You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1978 lines
47 KiB
1978 lines
47 KiB
/** |
|
* @file diablo.cpp |
|
* |
|
* Implementation of the main game initialization functions. |
|
*/ |
|
#include "all.h" |
|
#include "paths.h" |
|
#include "../3rdParty/Storm/Source/storm.h" |
|
#include "../DiabloUI/diabloui.h" |
|
#include <config.h> |
|
|
|
DEVILUTION_BEGIN_NAMESPACE |
|
|
|
bool allquests; |
|
SDL_Window *ghMainWnd; |
|
DWORD glSeedTbl[NUMLEVELS]; |
|
int gnLevelTypeTbl[NUMLEVELS]; |
|
int glEndSeed[NUMLEVELS]; |
|
int glMid1Seed[NUMLEVELS]; |
|
int glMid2Seed[NUMLEVELS]; |
|
int glMid3Seed[NUMLEVELS]; |
|
int MouseX; |
|
int MouseY; |
|
BOOL gbGameLoopStartup; |
|
BOOL gbRunGame; |
|
BOOL gbRunGameResult; |
|
BOOL zoomflag; |
|
/** Enable updating of player character, set to false once Diablo dies */ |
|
BOOL gbProcessPlayers; |
|
BOOL gbLoadGame; |
|
BOOLEAN cineflag; |
|
int force_redraw; |
|
BOOL light4flag; |
|
int setseed; |
|
int PauseMode; |
|
bool forceSpawn; |
|
bool forceDiablo; |
|
bool gbTheoQuest; |
|
bool gbCowQuest; |
|
bool gbNestArt; |
|
bool gbBard; |
|
bool gbBarbarian; |
|
int sgnTimeoutCurs; |
|
char sgbMouseDown; |
|
int color_cycle_timer; |
|
int gnTickRate; |
|
WORD gnTickDelay = 50; |
|
/** Game options */ |
|
Options sgOptions; |
|
|
|
/* rdata */ |
|
|
|
bool gbForceWindowed = false; |
|
bool gbShowIntro = true; |
|
BOOL leveldebug; |
|
#ifdef _DEBUG |
|
BOOL monstdebug; |
|
int DebugMonsters[10]; |
|
int debugmonsttypes; |
|
BOOL visiondebug; |
|
int questdebug = -1; |
|
int debug_mode_key_s; |
|
int debug_mode_key_w; |
|
int debug_mode_key_inverted_v; |
|
int debug_mode_dollar_sign; |
|
int debug_mode_key_d; |
|
int debug_mode_key_i; |
|
int dbgplr; |
|
int dbgqst; |
|
int dbgmon; |
|
int arrowdebug; |
|
#endif |
|
/** Specifies whether players are in non-PvP mode. */ |
|
BOOL FriendlyMode = TRUE; |
|
/** Default quick messages */ |
|
const char *const spszMsgTbl[4] = { |
|
"I need help! Come Here!", |
|
"Follow me.", |
|
"Here's something for you.", |
|
"Now you DIE!" |
|
}; |
|
/** INI files variable names for quick message keys */ |
|
const char *const spszMsgHotKeyTbl[4] = { "F9", "F10", "F11", "F12" }; |
|
|
|
/** To know if these things have been done when we get to the diablo_deinit() function */ |
|
BOOL was_archives_init = false; |
|
/** To know if surfaces have been initialized or not */ |
|
BOOL was_window_init = false; |
|
BOOL was_ui_init = false; |
|
BOOL was_snd_init = false; |
|
|
|
static void print_help_and_exit() |
|
{ |
|
printf("Options:\n"); |
|
printf(" %-20s %-30s\n", "-h, --help", "Print this message and exit"); |
|
printf(" %-20s %-30s\n", "--version", "Print the version and exit"); |
|
printf(" %-20s %-30s\n", "--data-dir", "Specify the folder of diabdat.mpq"); |
|
printf(" %-20s %-30s\n", "--save-dir", "Specify the folder of save files"); |
|
printf(" %-20s %-30s\n", "--config-dir", "Specify the location of diablo.ini"); |
|
printf(" %-20s %-30s\n", "-n", "Skip startup videos"); |
|
printf(" %-20s %-30s\n", "-f", "Display frames per second"); |
|
printf(" %-20s %-30s\n", "-x", "Run in windowed mode"); |
|
printf(" %-20s %-30s\n", "--spawn", "Force spawn mode even if diabdat.mpq is found"); |
|
printf(" %-20s %-30s\n", "--bardtest", "Enable the Bard class"); |
|
printf(" %-20s %-30s\n", "--barbariantest", "Enable the Barbarian class"); |
|
printf("\nHellfire options:\n"); |
|
printf(" %-20s %-30s\n", "--diablo", "Force diablo mode even if hellfire.mpq is found"); |
|
printf(" %-20s %-30s\n", "--nestart", "Use alternate nest palette"); |
|
#ifdef _DEBUG |
|
printf("\nDebug options:\n"); |
|
printf(" %-20s %-30s\n", "-d", "Increaased item drops"); |
|
printf(" %-20s %-30s\n", "-w", "Enable cheats"); |
|
printf(" %-20s %-30s\n", "-$", "Enable god mode"); |
|
printf(" %-20s %-30s\n", "-^", "Enable god mode and debug tools"); |
|
//printf(" %-20s %-30s\n", "-b", "Enable item drop log"); |
|
printf(" %-20s %-30s\n", "-v", "Highlight visibility"); |
|
printf(" %-20s %-30s\n", "-i", "Ignore network timeout"); |
|
//printf(" %-20s %-30s\n", "-j <##>", "Init trigger at level"); |
|
printf(" %-20s %-30s\n", "-l <##> <##>", "Start in level as type"); |
|
printf(" %-20s %-30s\n", "-m <##>", "Add debug monster, up to 10 allowed"); |
|
printf(" %-20s %-30s\n", "-q <#>", "Force a certain quest"); |
|
printf(" %-20s %-30s\n", "-r <##########>", "Set map seed"); |
|
printf(" %-20s %-30s\n", "-t <##>", "Set current quest level"); |
|
printf(" %-20s %-30s\n", "--allquests", "Force all quests to generate in a singleplayer game"); |
|
#endif |
|
printf("\nReport bugs at https://github.com/diasurgical/devilutionX/\n"); |
|
diablo_quit(0); |
|
} |
|
|
|
static void diablo_parse_flags(int argc, char **argv) |
|
{ |
|
for (int i = 1; i < argc; i++) { |
|
if (strcasecmp("-h", argv[i]) == 0 || strcasecmp("--help", argv[i]) == 0) { |
|
print_help_and_exit(); |
|
} else if (strcasecmp("--version", argv[i]) == 0) { |
|
printf("%s v%s\n", PROJECT_NAME, PROJECT_VERSION); |
|
diablo_quit(0); |
|
} else if (strcasecmp("--data-dir", argv[i]) == 0) { |
|
SetBasePath(argv[++i]); |
|
} else if (strcasecmp("--save-dir", argv[i]) == 0) { |
|
SetPrefPath(argv[++i]); |
|
} else if (strcasecmp("--config-dir", argv[i]) == 0) { |
|
SetConfigPath(argv[++i]); |
|
} else if (strcasecmp("-n", argv[i]) == 0) { |
|
gbShowIntro = false; |
|
} else if (strcasecmp("-f", argv[i]) == 0) { |
|
EnableFrameCount(); |
|
} else if (strcasecmp("-x", argv[i]) == 0) { |
|
gbForceWindowed = true; |
|
} else if (strcasecmp("--spawn", argv[i]) == 0) { |
|
forceSpawn = TRUE; |
|
} else if (strcasecmp("--diablo", argv[i]) == 0) { |
|
forceDiablo = TRUE; |
|
} else if (strcasecmp("--nestart", argv[i]) == 0) { |
|
gbNestArt = true; |
|
} else if (strcasecmp("--bardtest", argv[i]) == 0) { |
|
gbBard = true; |
|
} else if (strcasecmp("--barbariantest", argv[i]) == 0) { |
|
gbBarbarian = true; |
|
#ifdef _DEBUG |
|
} else if (strcasecmp("-^", argv[i]) == 0) { |
|
debug_mode_key_inverted_v = TRUE; |
|
} else if (strcasecmp("-$", argv[i]) == 0) { |
|
debug_mode_dollar_sign = TRUE; |
|
/* |
|
} else if (strcasecmp("-b", argv[i]) == 0) { |
|
debug_mode_key_b = 1; |
|
*/ |
|
} else if (strcasecmp("-d", argv[i]) == 0) { |
|
debug_mode_key_d = TRUE; |
|
} else if (strcasecmp("-i", argv[i]) == 0) { |
|
debug_mode_key_i = TRUE; |
|
/* |
|
} else if (strcasecmp("-j", argv[i]) == 0) { |
|
debug_mode_key_J_trigger = argv[++i]; |
|
*/ |
|
} else if (strcasecmp("-l", argv[i]) == 0) { |
|
setlevel = FALSE; |
|
leveldebug = TRUE; |
|
leveltype = SDL_atoi(argv[++i]); |
|
currlevel = SDL_atoi(argv[++i]); |
|
plr[0].plrlevel = currlevel; |
|
} else if (strcasecmp("-m", argv[i]) == 0) { |
|
monstdebug = TRUE; |
|
DebugMonsters[debugmonsttypes++] = SDL_atoi(argv[++i]); |
|
} else if (strcasecmp("-q", argv[i]) == 0) { |
|
questdebug = SDL_atoi(argv[++i]); |
|
} else if (strcasecmp("-r", argv[i]) == 0) { |
|
setseed = SDL_atoi(argv[++i]); |
|
} else if (strcasecmp("-s", argv[i]) == 0) { |
|
debug_mode_key_s = TRUE; |
|
} else if (strcasecmp("-t", argv[i]) == 0) { |
|
leveldebug = TRUE; |
|
setlevel = TRUE; |
|
setlvlnum = SDL_atoi(argv[++i]); |
|
} else if (strcasecmp("-v", argv[i]) == 0) { |
|
visiondebug = TRUE; |
|
} else if (strcasecmp("-w", argv[i]) == 0) { |
|
debug_mode_key_w = TRUE; |
|
} else if (strcasecmp("--allquests", argv[i]) == 0) { |
|
allquests = true; |
|
#endif |
|
} else { |
|
printf("unrecognized option '%s'\n", argv[i]); |
|
print_help_and_exit(); |
|
} |
|
} |
|
} |
|
|
|
void FreeGameMem() |
|
{ |
|
music_stop(); |
|
|
|
MemFreeDbg(pDungeonCels); |
|
MemFreeDbg(pMegaTiles); |
|
MemFreeDbg(pLevelPieces); |
|
MemFreeDbg(pSpecialCels); |
|
|
|
FreeMissiles(); |
|
FreeMonsters(); |
|
FreeObjectGFX(); |
|
FreeMonsterSnd(); |
|
FreeTownerGFX(); |
|
} |
|
|
|
static void start_game(unsigned int uMsg) |
|
{ |
|
zoomflag = TRUE; |
|
CalcViewportGeometry(); |
|
cineflag = FALSE; |
|
InitCursor(); |
|
InitLightTable(); |
|
#ifdef _DEBUG |
|
LoadDebugGFX(); |
|
#endif |
|
assert(ghMainWnd); |
|
music_stop(); |
|
ShowProgress(uMsg); |
|
gmenu_init_menu(); |
|
InitLevelCursor(); |
|
sgnTimeoutCurs = CURSOR_NONE; |
|
sgbMouseDown = CLICK_NONE; |
|
track_repeat_walk(FALSE); |
|
} |
|
|
|
static void free_game() |
|
{ |
|
int i; |
|
|
|
FreeControlPan(); |
|
FreeInvGFX(); |
|
FreeGMenu(); |
|
FreeQuestText(); |
|
FreeStoreMem(); |
|
|
|
for (i = 0; i < MAX_PLRS; i++) |
|
FreePlayerGFX(i); |
|
|
|
FreeItemGFX(); |
|
FreeCursor(); |
|
FreeLightTable(); |
|
#ifdef _DEBUG |
|
FreeDebugGFX(); |
|
#endif |
|
FreeGameMem(); |
|
} |
|
|
|
// Controller support: Actions to run after updating the cursor state. |
|
// Defined in SourceX/controls/plctrls.cpp. |
|
extern void finish_simulated_mouse_clicks(int current_mouse_x, int current_mouse_y); |
|
extern void plrctrls_after_check_curs_move(); |
|
|
|
static bool ProcessInput() |
|
{ |
|
if (PauseMode == 2) { |
|
return false; |
|
} |
|
if (!gbIsMultiplayer && gmenu_is_active()) { |
|
force_redraw |= 1; |
|
return false; |
|
} |
|
|
|
if (!gmenu_is_active() && sgnTimeoutCurs == CURSOR_NONE) { |
|
#ifndef USE_SDL1 |
|
finish_simulated_mouse_clicks(MouseX, MouseY); |
|
#endif |
|
CheckCursMove(); |
|
plrctrls_after_check_curs_move(); |
|
track_process(); |
|
} |
|
|
|
return true; |
|
} |
|
|
|
static void run_game_loop(unsigned int uMsg) |
|
{ |
|
WNDPROC saveProc; |
|
MSG msg; |
|
|
|
nthread_ignore_mutex(TRUE); |
|
start_game(uMsg); |
|
assert(ghMainWnd); |
|
saveProc = SetWindowProc(GM_Game); |
|
control_update_life_mana(); |
|
run_delta_info(); |
|
gbRunGame = TRUE; |
|
gbProcessPlayers = TRUE; |
|
gbRunGameResult = TRUE; |
|
force_redraw = 255; |
|
DrawAndBlit(); |
|
LoadPWaterPalette(); |
|
PaletteFadeIn(8); |
|
force_redraw = 255; |
|
gbGameLoopStartup = TRUE; |
|
nthread_ignore_mutex(FALSE); |
|
|
|
while (gbRunGame) { |
|
while (PeekMessage(&msg)) { |
|
if (msg.message == DVL_WM_QUIT) { |
|
gbRunGameResult = FALSE; |
|
gbRunGame = FALSE; |
|
break; |
|
} |
|
TranslateMessage(&msg); |
|
DispatchMessage(&msg); |
|
} |
|
if (!gbRunGame) |
|
break; |
|
if (!nthread_has_500ms_passed()) { |
|
ProcessInput(); |
|
force_redraw |= 1; |
|
DrawAndBlit(); |
|
continue; |
|
} |
|
diablo_color_cyc_logic(); |
|
multi_process_network_packets(); |
|
game_loop(gbGameLoopStartup); |
|
gbGameLoopStartup = FALSE; |
|
DrawAndBlit(); |
|
} |
|
|
|
if (gbIsMultiplayer) { |
|
pfile_write_hero(); |
|
} |
|
|
|
pfile_flush_W(); |
|
PaletteFadeOut(8); |
|
NewCursor(CURSOR_NONE); |
|
ClearScreenBuffer(); |
|
force_redraw = 255; |
|
scrollrt_draw_game_screen(TRUE); |
|
saveProc = SetWindowProc(saveProc); |
|
assert(saveProc == GM_Game); |
|
free_game(); |
|
|
|
if (cineflag) { |
|
cineflag = FALSE; |
|
DoEnding(); |
|
} |
|
} |
|
|
|
BOOL StartGame(BOOL bNewGame, BOOL bSinglePlayer) |
|
{ |
|
BOOL fExitProgram; |
|
unsigned int uMsg; |
|
|
|
gbSelectProvider = TRUE; |
|
|
|
do { |
|
fExitProgram = FALSE; |
|
gbLoadGame = FALSE; |
|
|
|
if (!NetInit(bSinglePlayer, &fExitProgram)) { |
|
gbRunGameResult = !fExitProgram; |
|
break; |
|
} |
|
|
|
gbSelectProvider = FALSE; |
|
|
|
if (bNewGame || !gbValidSaveFile) { |
|
InitLevels(); |
|
InitQuests(); |
|
InitPortals(); |
|
InitDungMsgs(myplr); |
|
} |
|
if (!gbValidSaveFile || !gbLoadGame) { |
|
uMsg = WM_DIABNEWGAME; |
|
} else { |
|
uMsg = WM_DIABLOADGAME; |
|
} |
|
run_game_loop(uMsg); |
|
NetClose(); |
|
pfile_create_player_description(NULL, 0); |
|
} while (gbRunGameResult); |
|
|
|
SNetDestroy(); |
|
return gbRunGameResult; |
|
} |
|
|
|
/** |
|
* @brief Save game configurations to ini file |
|
*/ |
|
static void SaveOptions() |
|
{ |
|
setIniInt("Audio", "Sound Volume", sgOptions.nSoundVolume); |
|
setIniInt("Audio", "Music Volume", sgOptions.nMusicVolume); |
|
setIniInt("Audio", "Walking Sound", sgOptions.bWalkingSound); |
|
|
|
#ifdef __vita__ |
|
setIniInt("Graphics", "Width", sgOptions.nWidth); |
|
setIniInt("Graphics", "Height", sgOptions.nHeight); |
|
#endif |
|
setIniInt("Graphics", "Fullscreen", sgOptions.bFullscreen); |
|
#ifdef __vita__ |
|
setIniInt("Graphics", "Upscale", sgOptions.bUpscale); |
|
#endif |
|
setIniInt("Graphics", "Fit to Screen", sgOptions.bFitToScreen); |
|
setIniValue("Graphics", "Scaling Quality", sgOptions.szScaleQuality); |
|
setIniInt("Graphics", "Integer Scaling", sgOptions.bIntegerScaling); |
|
setIniInt("Graphics", "Vertical Sync", sgOptions.bVSync); |
|
setIniInt("Graphics", "Blended Transparency", sgOptions.bBlendedTransparancy); |
|
setIniInt("Graphics", "Gamma Correction", sgOptions.nGammaCorrection); |
|
setIniInt("Graphics", "Color Cycling", sgOptions.bColorCycling); |
|
|
|
setIniInt("Game", "Speed", sgOptions.nTickRate); |
|
setIniInt("Game", "Fast Walk", sgOptions.bJogInTown); |
|
setIniInt("Game", "Grab Input", sgOptions.bGrabInput); |
|
setIniInt("Game", "Theo Quest", sgOptions.bTheoQuest); |
|
setIniInt("Game", "Cow Quest", sgOptions.bCowQuest); |
|
|
|
setIniValue("Network", "Bind Address", sgOptions.szBindAddress); |
|
} |
|
|
|
/** |
|
* @brief Load game configurations from ini file |
|
*/ |
|
static void LoadOptions() |
|
{ |
|
sgOptions.nSoundVolume = getIniInt("Audio", "Sound Volume", VOLUME_MAX); |
|
sgOptions.nMusicVolume = getIniInt("Audio", "Music Volume", VOLUME_MAX); |
|
sgOptions.bWalkingSound = getIniBool("Audio", "Walking Sound", true); |
|
|
|
#ifndef __vita__ |
|
sgOptions.nWidth = getIniInt("Graphics", "Width", DEFAULT_WIDTH); |
|
sgOptions.nHeight = getIniInt("Graphics", "Height", DEFAULT_HEIGHT); |
|
#else |
|
sgOptions.nWidth = DEFAULT_WIDTH; |
|
sgOptions.nHeight = DEFAULT_HEIGHT; |
|
#endif |
|
sgOptions.bFullscreen = getIniBool("Graphics", "Fullscreen", true); |
|
#if !defined(USE_SDL1) && !defined(__vita__) |
|
sgOptions.bUpscale = getIniBool("Graphics", "Upscale", true); |
|
#else |
|
sgOptions.bUpscale = false; |
|
#endif |
|
sgOptions.bFitToScreen = getIniBool("Graphics", "Fit to Screen", true); |
|
getIniValue("Graphics", "Scaling Quality", sgOptions.szScaleQuality, sizeof(sgOptions.szScaleQuality), "2"); |
|
sgOptions.bIntegerScaling = getIniBool("Graphics", "Integer Scaling", false); |
|
sgOptions.bVSync = getIniBool("Graphics", "Vertical Sync", true); |
|
sgOptions.bBlendedTransparancy = getIniBool("Graphics", "Blended Transparency", true); |
|
sgOptions.nGammaCorrection = getIniInt("Graphics", "Gamma Correction", 100); |
|
sgOptions.bColorCycling = getIniBool("Graphics", "Color Cycling", true); |
|
|
|
sgOptions.nTickRate = getIniInt("Game", "Speed", 20); |
|
sgOptions.bJogInTown = getIniBool("Game", "Fast Walk", false); |
|
sgOptions.bGrabInput = getIniBool("Game", "Grab Input", false); |
|
sgOptions.bTheoQuest = getIniBool("Game", "Theo Quest", false); |
|
sgOptions.bCowQuest = getIniBool("Game", "Cow Quest", false); |
|
|
|
getIniValue("Network", "Bind Address", sgOptions.szBindAddress, sizeof(sgOptions.szBindAddress), "0.0.0.0"); |
|
} |
|
|
|
static void diablo_init_screen() |
|
{ |
|
MouseX = SCREEN_WIDTH / 2; |
|
MouseY = SCREEN_HEIGHT / 2; |
|
if (!sgbControllerActive) |
|
SetCursorPos(MouseX, MouseY); |
|
ScrollInfo._sdx = 0; |
|
ScrollInfo._sdy = 0; |
|
ScrollInfo._sxoff = 0; |
|
ScrollInfo._syoff = 0; |
|
ScrollInfo._sdir = SDIR_NONE; |
|
|
|
ClrDiabloMsg(); |
|
} |
|
|
|
static void diablo_init() |
|
{ |
|
init_create_window(); |
|
was_window_init = true; |
|
|
|
SFileEnableDirectAccess(TRUE); |
|
init_archives(); |
|
was_archives_init = true; |
|
|
|
if (forceSpawn) |
|
gbIsSpawn = true; |
|
if (forceDiablo) |
|
gbIsHellfire = false; |
|
|
|
UiInitialize(); |
|
UiSetSpawned(gbIsSpawn); |
|
was_ui_init = true; |
|
|
|
ReadOnlyTest(); |
|
|
|
InitHash(); |
|
|
|
diablo_init_screen(); |
|
|
|
snd_init(); |
|
was_snd_init = true; |
|
|
|
ui_sound_init(); |
|
} |
|
|
|
static void diablo_splash() |
|
{ |
|
if (!gbShowIntro) |
|
return; |
|
|
|
play_movie("gendata\\logo.smk", TRUE); |
|
|
|
if (gbIsHellfire && getIniBool("Hellfire", "Intro", true)) { |
|
play_movie("gendata\\Hellfire.smk", TRUE); |
|
setIniValue("Hellfire", "Intro", "0"); |
|
} |
|
if (!gbIsHellfire && !gbIsSpawn && getIniBool("Diablo", "Intro", true)) { |
|
play_movie("gendata\\diablo1.smk", TRUE); |
|
setIniValue("Diablo", "Intro", "0"); |
|
} |
|
|
|
UiTitleDialog(); |
|
} |
|
|
|
static void diablo_deinit() |
|
{ |
|
if (was_snd_init) { |
|
effects_cleanup_sfx(); |
|
} |
|
if (was_ui_init) |
|
UiDestroy(); |
|
if (was_archives_init) |
|
init_cleanup(); |
|
if (was_window_init) |
|
dx_cleanup(); // Cleanup SDL surfaces stuff, so we have to do it before SDL_Quit(). |
|
if (was_fonts_init) |
|
FontsCleanup(); |
|
if (SDL_WasInit(SDL_INIT_EVERYTHING & ~SDL_INIT_HAPTIC)) |
|
SDL_Quit(); |
|
} |
|
|
|
void diablo_quit(int exitStatus) |
|
{ |
|
diablo_deinit(); |
|
exit(exitStatus); |
|
} |
|
|
|
int DiabloMain(int argc, char **argv) |
|
{ |
|
diablo_parse_flags(argc, argv); |
|
LoadOptions(); |
|
diablo_init(); |
|
diablo_splash(); |
|
mainmenu_loop(); |
|
SaveOptions(); |
|
diablo_deinit(); |
|
|
|
return 0; |
|
} |
|
|
|
static BOOL LeftMouseCmd(BOOL bShift) |
|
{ |
|
BOOL bNear; |
|
|
|
assert(MouseY < PANEL_TOP || MouseX < PANEL_LEFT || MouseX >= PANEL_LEFT + PANEL_WIDTH); |
|
|
|
if (leveltype == DTYPE_TOWN) { |
|
if (pcursitem != -1 && pcurs == CURSOR_HAND) |
|
NetSendCmdLocParam1(TRUE, invflag ? CMD_GOTOGETITEM : CMD_GOTOAGETITEM, cursmx, cursmy, pcursitem); |
|
if (pcursmonst != -1) |
|
NetSendCmdLocParam1(TRUE, CMD_TALKXY, cursmx, cursmy, pcursmonst); |
|
if (pcursitem == -1 && pcursmonst == -1 && pcursplr == -1) |
|
return TRUE; |
|
} else { |
|
bNear = abs(plr[myplr]._px - cursmx) < 2 && abs(plr[myplr]._py - cursmy) < 2; |
|
if (pcursitem != -1 && pcurs == CURSOR_HAND && !bShift) { |
|
NetSendCmdLocParam1(TRUE, invflag ? CMD_GOTOGETITEM : CMD_GOTOAGETITEM, cursmx, cursmy, pcursitem); |
|
} else if (pcursobj != -1 && (!bShift || bNear && object[pcursobj]._oBreak == 1)) { |
|
NetSendCmdLocParam1(TRUE, pcurs == CURSOR_DISARM ? CMD_DISARMXY : CMD_OPOBJXY, cursmx, cursmy, pcursobj); |
|
} else if (plr[myplr]._pwtype == WT_RANGED) { |
|
if (bShift) { |
|
NetSendCmdLoc(TRUE, CMD_RATTACKXY, cursmx, cursmy); |
|
} else if (pcursmonst != -1) { |
|
if (CanTalkToMonst(pcursmonst)) { |
|
NetSendCmdParam1(TRUE, CMD_ATTACKID, pcursmonst); |
|
} else { |
|
NetSendCmdParam1(TRUE, CMD_RATTACKID, pcursmonst); |
|
} |
|
} else if (pcursplr != -1 && !FriendlyMode) { |
|
NetSendCmdParam1(TRUE, CMD_RATTACKPID, pcursplr); |
|
} |
|
} else { |
|
if (bShift) { |
|
if (pcursmonst != -1) { |
|
if (CanTalkToMonst(pcursmonst)) { |
|
NetSendCmdParam1(TRUE, CMD_ATTACKID, pcursmonst); |
|
} else { |
|
NetSendCmdLoc(TRUE, CMD_SATTACKXY, cursmx, cursmy); |
|
} |
|
} else { |
|
NetSendCmdLoc(TRUE, CMD_SATTACKXY, cursmx, cursmy); |
|
} |
|
} else if (pcursmonst != -1) { |
|
NetSendCmdParam1(TRUE, CMD_ATTACKID, pcursmonst); |
|
} else if (pcursplr != -1 && !FriendlyMode) { |
|
NetSendCmdParam1(TRUE, CMD_ATTACKPID, pcursplr); |
|
} |
|
} |
|
if (!bShift && pcursitem == -1 && pcursobj == -1 && pcursmonst == -1 && pcursplr == -1) |
|
return TRUE; |
|
} |
|
|
|
return FALSE; |
|
} |
|
|
|
BOOL TryIconCurs() |
|
{ |
|
if (pcurs == CURSOR_RESURRECT) { |
|
NetSendCmdParam1(TRUE, CMD_RESURRECT, pcursplr); |
|
return TRUE; |
|
} |
|
|
|
if (pcurs == CURSOR_HEALOTHER) { |
|
NetSendCmdParam1(TRUE, CMD_HEALOTHER, pcursplr); |
|
return TRUE; |
|
} |
|
|
|
if (pcurs == CURSOR_TELEKINESIS) { |
|
DoTelekinesis(); |
|
return TRUE; |
|
} |
|
|
|
if (pcurs == CURSOR_IDENTIFY) { |
|
if (pcursinvitem != -1) |
|
CheckIdentify(myplr, pcursinvitem); |
|
else |
|
NewCursor(CURSOR_HAND); |
|
return TRUE; |
|
} |
|
|
|
if (pcurs == CURSOR_REPAIR) { |
|
if (pcursinvitem != -1) |
|
DoRepair(myplr, pcursinvitem); |
|
else |
|
NewCursor(CURSOR_HAND); |
|
return TRUE; |
|
} |
|
|
|
if (pcurs == CURSOR_RECHARGE) { |
|
if (pcursinvitem != -1) |
|
DoRecharge(myplr, pcursinvitem); |
|
else |
|
NewCursor(CURSOR_HAND); |
|
return TRUE; |
|
} |
|
|
|
if (pcurs == CURSOR_OIL) { |
|
if (pcursinvitem != -1) |
|
DoOil(myplr, pcursinvitem); |
|
else |
|
NewCursor(CURSOR_HAND); |
|
return TRUE; |
|
} |
|
|
|
if (pcurs == CURSOR_TELEPORT) { |
|
if (pcursmonst != -1) |
|
NetSendCmdParam3(TRUE, CMD_TSPELLID, pcursmonst, plr[myplr]._pTSpell, GetSpellLevel(myplr, plr[myplr]._pTSpell)); |
|
else if (pcursplr != -1) |
|
NetSendCmdParam3(TRUE, CMD_TSPELLPID, pcursplr, plr[myplr]._pTSpell, GetSpellLevel(myplr, plr[myplr]._pTSpell)); |
|
else |
|
NetSendCmdLocParam2(TRUE, CMD_TSPELLXY, cursmx, cursmy, plr[myplr]._pTSpell, GetSpellLevel(myplr, plr[myplr]._pTSpell)); |
|
NewCursor(CURSOR_HAND); |
|
return TRUE; |
|
} |
|
|
|
if (pcurs == CURSOR_DISARM && pcursobj == -1) { |
|
NewCursor(CURSOR_HAND); |
|
return TRUE; |
|
} |
|
|
|
return FALSE; |
|
} |
|
|
|
static BOOL LeftMouseDown(int wParam) |
|
{ |
|
if (gmenu_left_mouse(TRUE)) |
|
return FALSE; |
|
|
|
if (control_check_talk_btn()) |
|
return FALSE; |
|
|
|
if (sgnTimeoutCurs != CURSOR_NONE) |
|
return FALSE; |
|
|
|
if (deathflag) { |
|
control_check_btn_press(); |
|
return FALSE; |
|
} |
|
|
|
if (PauseMode == 2) { |
|
return FALSE; |
|
} |
|
if (doomflag) { |
|
doom_close(); |
|
return FALSE; |
|
} |
|
|
|
if (spselflag) { |
|
SetSpell(); |
|
return FALSE; |
|
} |
|
|
|
if (stextflag != STORE_NONE) { |
|
CheckStoreBtn(); |
|
return FALSE; |
|
} |
|
|
|
if (MouseY < PANEL_TOP || MouseX < PANEL_LEFT || MouseX >= PANEL_LEFT + PANEL_WIDTH) { |
|
if (!gmenu_is_active() && !TryIconCurs()) { |
|
if (questlog && MouseX > 32 && MouseX < 288 && MouseY > 32 && MouseY < 308) { |
|
QuestlogESC(); |
|
} else if (qtextflag) { |
|
qtextflag = FALSE; |
|
stream_stop(); |
|
} else if (chrflag && MouseX < SPANEL_WIDTH && MouseY < SPANEL_HEIGHT) { |
|
CheckChrBtns(); |
|
} else if (invflag && MouseX > RIGHT_PANEL && MouseY < SPANEL_HEIGHT) { |
|
if (!dropGoldFlag) |
|
CheckInvItem(); |
|
} else if (sbookflag && MouseX > RIGHT_PANEL && MouseY < SPANEL_HEIGHT) { |
|
CheckSBook(); |
|
} else if (pcurs >= CURSOR_FIRSTITEM) { |
|
if (TryInvPut()) { |
|
NetSendCmdPItem(TRUE, CMD_PUTITEM, cursmx, cursmy); |
|
NewCursor(CURSOR_HAND); |
|
} |
|
} else { |
|
if (plr[myplr]._pStatPts != 0 && !spselflag) |
|
CheckLvlBtn(); |
|
if (!lvlbtndown) |
|
return LeftMouseCmd(wParam == DVL_MK_SHIFT + DVL_MK_LBUTTON); |
|
} |
|
} |
|
} else { |
|
if (!talkflag && !dropGoldFlag && !gmenu_is_active()) |
|
CheckInvScrn(); |
|
DoPanBtn(); |
|
if (pcurs > CURSOR_HAND && pcurs < CURSOR_FIRSTITEM) |
|
NewCursor(CURSOR_HAND); |
|
} |
|
|
|
return FALSE; |
|
} |
|
|
|
static void LeftMouseUp(int wParam) |
|
{ |
|
gmenu_left_mouse(FALSE); |
|
control_release_talk_btn(); |
|
bool isShiftHeld = wParam & (DVL_MK_SHIFT | DVL_MK_LBUTTON); |
|
if (panbtndown) |
|
CheckBtnUp(); |
|
if (chrbtnactive) |
|
ReleaseChrBtns(isShiftHeld); |
|
if (lvlbtndown) |
|
ReleaseLvlBtn(); |
|
if (stextflag != STORE_NONE) |
|
ReleaseStoreBtn(); |
|
} |
|
|
|
static void RightMouseDown() |
|
{ |
|
if (!gmenu_is_active() && sgnTimeoutCurs == CURSOR_NONE && PauseMode != 2 && !plr[myplr]._pInvincible) { |
|
if (doomflag) { |
|
doom_close(); |
|
} else if (stextflag == STORE_NONE) { |
|
if (spselflag) { |
|
SetSpell(); |
|
} else if (MouseY >= SPANEL_HEIGHT |
|
|| (!sbookflag || MouseX <= RIGHT_PANEL) |
|
&& !TryIconCurs() |
|
&& (pcursinvitem == -1 || !UseInvItem(myplr, pcursinvitem))) { |
|
if (pcurs == CURSOR_HAND) { |
|
if (pcursinvitem == -1 || !UseInvItem(myplr, pcursinvitem)) |
|
CheckPlrSpell(); |
|
} else if (pcurs > CURSOR_HAND && pcurs < CURSOR_FIRSTITEM) { |
|
NewCursor(CURSOR_HAND); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
void diablo_pause_game() |
|
{ |
|
if (!gbIsMultiplayer) { |
|
if (PauseMode) { |
|
PauseMode = 0; |
|
} else { |
|
PauseMode = 2; |
|
sound_stop(); |
|
track_repeat_walk(FALSE); |
|
} |
|
force_redraw = 255; |
|
} |
|
} |
|
|
|
static void diablo_hotkey_msg(DWORD dwMsg) |
|
{ |
|
char szMsg[MAX_SEND_STR_LEN]; |
|
|
|
if (!gbIsMultiplayer) { |
|
return; |
|
} |
|
|
|
assert(dwMsg < sizeof(spszMsgTbl) / sizeof(spszMsgTbl[0])); |
|
if (!getIniValue("NetMsg", spszMsgHotKeyTbl[dwMsg], szMsg, MAX_SEND_STR_LEN)) { |
|
snprintf(szMsg, MAX_SEND_STR_LEN, "%s", spszMsgTbl[dwMsg]); |
|
setIniValue("NetMsg", spszMsgHotKeyTbl[dwMsg], szMsg); |
|
} |
|
|
|
NetSendCmdString(-1, szMsg); |
|
} |
|
|
|
static BOOL PressSysKey(int wParam) |
|
{ |
|
if (gmenu_is_active() || wParam != DVL_VK_F10) |
|
return FALSE; |
|
diablo_hotkey_msg(1); |
|
return TRUE; |
|
} |
|
|
|
static void ReleaseKey(int vkey) |
|
{ |
|
if (vkey == DVL_VK_SNAPSHOT) |
|
CaptureScreen(); |
|
} |
|
|
|
BOOL PressEscKey() |
|
{ |
|
BOOL rv = FALSE; |
|
|
|
if (doomflag) { |
|
doom_close(); |
|
rv = TRUE; |
|
} |
|
if (helpflag) { |
|
helpflag = FALSE; |
|
rv = TRUE; |
|
} |
|
|
|
if (qtextflag) { |
|
qtextflag = FALSE; |
|
stream_stop(); |
|
rv = TRUE; |
|
} else if (stextflag) { |
|
STextESC(); |
|
rv = TRUE; |
|
} |
|
|
|
if (msgflag) { |
|
msgdelay = 0; |
|
rv = TRUE; |
|
} |
|
if (talkflag) { |
|
control_reset_talk(); |
|
rv = TRUE; |
|
} |
|
if (dropGoldFlag) { |
|
control_drop_gold(DVL_VK_ESCAPE); |
|
rv = TRUE; |
|
} |
|
if (spselflag) { |
|
spselflag = FALSE; |
|
rv = TRUE; |
|
} |
|
|
|
return rv; |
|
} |
|
|
|
static void PressKey(int vkey) |
|
{ |
|
if (gmenu_presskeys(vkey) || control_presskeys(vkey)) { |
|
return; |
|
} |
|
|
|
if (deathflag) { |
|
if (sgnTimeoutCurs != CURSOR_NONE) { |
|
return; |
|
} |
|
if (vkey == DVL_VK_F9) { |
|
diablo_hotkey_msg(0); |
|
} |
|
if (vkey == DVL_VK_F10) { |
|
diablo_hotkey_msg(1); |
|
} |
|
if (vkey == DVL_VK_F11) { |
|
diablo_hotkey_msg(2); |
|
} |
|
if (vkey == DVL_VK_F12) { |
|
diablo_hotkey_msg(3); |
|
} |
|
if (vkey == DVL_VK_RETURN) { |
|
if (GetAsyncKeyState(DVL_VK_MENU) & 0x8000) |
|
dx_reinit(); |
|
else |
|
control_type_message(); |
|
} |
|
if (vkey != DVL_VK_ESCAPE) { |
|
return; |
|
} |
|
} |
|
if (vkey == DVL_VK_ESCAPE) { |
|
if (!PressEscKey()) { |
|
track_repeat_walk(FALSE); |
|
gamemenu_on(); |
|
} |
|
return; |
|
} |
|
|
|
if (sgnTimeoutCurs != CURSOR_NONE || dropGoldFlag) { |
|
return; |
|
} |
|
if (vkey == DVL_VK_PAUSE) { |
|
diablo_pause_game(); |
|
return; |
|
} |
|
if (PauseMode == 2) { |
|
if ((vkey == DVL_VK_RETURN) && (GetAsyncKeyState(DVL_VK_MENU) & 0x8000)) |
|
dx_reinit(); |
|
return; |
|
} |
|
|
|
if (vkey == DVL_VK_RETURN) { |
|
if (GetAsyncKeyState(DVL_VK_MENU) & 0x8000) { |
|
dx_reinit(); |
|
} else if (stextflag) { |
|
STextEnter(); |
|
} else if (questlog) { |
|
QuestlogEnter(); |
|
} else { |
|
control_type_message(); |
|
} |
|
} else if (vkey == DVL_VK_F1) { |
|
if (helpflag) { |
|
helpflag = FALSE; |
|
} else if (stextflag != STORE_NONE) { |
|
ClearPanel(); |
|
AddPanelString("No help available", TRUE); /// BUGFIX: message isn't displayed |
|
AddPanelString("while in stores", TRUE); |
|
track_repeat_walk(FALSE); |
|
} else { |
|
invflag = FALSE; |
|
chrflag = FALSE; |
|
sbookflag = FALSE; |
|
spselflag = FALSE; |
|
if (qtextflag && leveltype == DTYPE_TOWN) { |
|
qtextflag = FALSE; |
|
stream_stop(); |
|
} |
|
questlog = FALSE; |
|
automapflag = FALSE; |
|
msgdelay = 0; |
|
gamemenu_off(); |
|
DisplayHelp(); |
|
doom_close(); |
|
} |
|
} |
|
#ifdef _DEBUG |
|
else if (vkey == DVL_VK_F2) { |
|
} |
|
#endif |
|
#ifdef _DEBUG |
|
else if (vkey == DVL_VK_F3) { |
|
if (pcursitem != -1) { |
|
sprintf( |
|
tempstr, |
|
"IDX = %i : Seed = %i : CF = %i", |
|
item[pcursitem].IDidx, |
|
item[pcursitem]._iSeed, |
|
item[pcursitem]._iCreateInfo); |
|
NetSendCmdString(1 << myplr, tempstr); |
|
} |
|
sprintf(tempstr, "Numitems : %i", numitems); |
|
NetSendCmdString(1 << myplr, tempstr); |
|
} |
|
#endif |
|
#ifdef _DEBUG |
|
else if (vkey == DVL_VK_F4) { |
|
PrintDebugQuest(); |
|
} |
|
#endif |
|
else if (vkey == DVL_VK_F5) { |
|
if (spselflag) { |
|
SetSpeedSpell(0); |
|
return; |
|
} |
|
ToggleSpell(0); |
|
return; |
|
} else if (vkey == DVL_VK_F6) { |
|
if (spselflag) { |
|
SetSpeedSpell(1); |
|
return; |
|
} |
|
ToggleSpell(1); |
|
return; |
|
} else if (vkey == DVL_VK_F7) { |
|
if (spselflag) { |
|
SetSpeedSpell(2); |
|
return; |
|
} |
|
ToggleSpell(2); |
|
return; |
|
} else if (vkey == DVL_VK_F8) { |
|
if (spselflag) { |
|
SetSpeedSpell(3); |
|
return; |
|
} |
|
ToggleSpell(3); |
|
return; |
|
} else if (vkey == DVL_VK_F9) { |
|
diablo_hotkey_msg(0); |
|
} else if (vkey == DVL_VK_F10) { |
|
diablo_hotkey_msg(1); |
|
} else if (vkey == DVL_VK_F11) { |
|
diablo_hotkey_msg(2); |
|
} else if (vkey == DVL_VK_F12) { |
|
diablo_hotkey_msg(3); |
|
} else if (vkey == DVL_VK_UP) { |
|
if (stextflag) { |
|
STextUp(); |
|
} else if (questlog) { |
|
QuestlogUp(); |
|
} else if (helpflag) { |
|
HelpScrollUp(); |
|
} else if (automapflag) { |
|
AutomapUp(); |
|
} |
|
} else if (vkey == DVL_VK_DOWN) { |
|
if (stextflag) { |
|
STextDown(); |
|
} else if (questlog) { |
|
QuestlogDown(); |
|
} else if (helpflag) { |
|
HelpScrollDown(); |
|
} else if (automapflag) { |
|
AutomapDown(); |
|
} |
|
} else if (vkey == DVL_VK_PRIOR) { |
|
if (stextflag) { |
|
STextPrior(); |
|
} |
|
} else if (vkey == DVL_VK_NEXT) { |
|
if (stextflag) { |
|
STextNext(); |
|
} |
|
} else if (vkey == DVL_VK_LEFT) { |
|
if (automapflag && !talkflag) { |
|
AutomapLeft(); |
|
} |
|
} else if (vkey == DVL_VK_RIGHT) { |
|
if (automapflag && !talkflag) { |
|
AutomapRight(); |
|
} |
|
} else if (vkey == DVL_VK_TAB) { |
|
DoAutoMap(); |
|
} else if (vkey == DVL_VK_SPACE) { |
|
if (!chrflag && invflag && MouseX < 480 && MouseY < PANEL_TOP && PANELS_COVER) { |
|
SetCursorPos(MouseX + 160, MouseY); |
|
} |
|
if (!invflag && chrflag && MouseX > 160 && MouseY < PANEL_TOP && PANELS_COVER) { |
|
SetCursorPos(MouseX - 160, MouseY); |
|
} |
|
helpflag = FALSE; |
|
invflag = FALSE; |
|
chrflag = FALSE; |
|
sbookflag = FALSE; |
|
spselflag = FALSE; |
|
if (qtextflag && leveltype == DTYPE_TOWN) { |
|
qtextflag = FALSE; |
|
stream_stop(); |
|
} |
|
questlog = FALSE; |
|
automapflag = FALSE; |
|
msgdelay = 0; |
|
gamemenu_off(); |
|
doom_close(); |
|
} |
|
} |
|
|
|
/** |
|
* @internal `return` must be used instead of `break` to be bin exact as C++ |
|
*/ |
|
static void PressChar(WPARAM vkey) |
|
{ |
|
if (gmenu_is_active() || control_talk_last_key(vkey) || sgnTimeoutCurs != CURSOR_NONE || deathflag) { |
|
return; |
|
} |
|
if ((char)vkey == 'p' || (char)vkey == 'P') { |
|
diablo_pause_game(); |
|
return; |
|
} |
|
if (PauseMode == 2) { |
|
return; |
|
} |
|
if (doomflag) { |
|
doom_close(); |
|
return; |
|
} |
|
if (dropGoldFlag) { |
|
control_drop_gold(vkey); |
|
return; |
|
} |
|
|
|
switch (vkey) { |
|
case 'G': |
|
case 'g': |
|
DecreaseGamma(); |
|
return; |
|
case 'F': |
|
case 'f': |
|
IncreaseGamma(); |
|
return; |
|
case 'I': |
|
case 'i': |
|
if (stextflag == STORE_NONE) { |
|
sbookflag = FALSE; |
|
invflag = !invflag; |
|
if (!invflag || chrflag) { |
|
if (MouseX < 480 && MouseY < PANEL_TOP && PANELS_COVER) { |
|
SetCursorPos(MouseX + 160, MouseY); |
|
} |
|
} else { |
|
if (MouseX > 160 && MouseY < PANEL_TOP && PANELS_COVER) { |
|
SetCursorPos(MouseX - 160, MouseY); |
|
} |
|
} |
|
} |
|
return; |
|
case 'C': |
|
case 'c': |
|
if (stextflag == STORE_NONE) { |
|
questlog = FALSE; |
|
chrflag = !chrflag; |
|
if (!chrflag || invflag) { |
|
if (MouseX > 160 && MouseY < PANEL_TOP && PANELS_COVER) { |
|
SetCursorPos(MouseX - 160, MouseY); |
|
} |
|
} else { |
|
if (MouseX < 480 && MouseY < PANEL_TOP && PANELS_COVER) { |
|
SetCursorPos(MouseX + 160, MouseY); |
|
} |
|
} |
|
} |
|
return; |
|
case 'Q': |
|
case 'q': |
|
if (stextflag == STORE_NONE) { |
|
chrflag = FALSE; |
|
if (!questlog) { |
|
StartQuestlog(); |
|
} else { |
|
questlog = FALSE; |
|
} |
|
} |
|
return; |
|
case 'Z': |
|
case 'z': |
|
zoomflag = !zoomflag; |
|
CalcViewportGeometry(); |
|
return; |
|
case 'S': |
|
case 's': |
|
if (stextflag == STORE_NONE) { |
|
invflag = FALSE; |
|
if (!spselflag) { |
|
DoSpeedBook(); |
|
} else { |
|
spselflag = FALSE; |
|
} |
|
track_repeat_walk(FALSE); |
|
} |
|
return; |
|
case 'B': |
|
case 'b': |
|
if (stextflag == STORE_NONE) { |
|
invflag = FALSE; |
|
sbookflag = !sbookflag; |
|
} |
|
return; |
|
case '+': |
|
case '=': |
|
if (automapflag) { |
|
AutomapZoomIn(); |
|
} |
|
return; |
|
case '-': |
|
case '_': |
|
if (automapflag) { |
|
AutomapZoomOut(); |
|
} |
|
return; |
|
case 'v': { |
|
char pszStr[120]; |
|
const char *difficulties[3] = { |
|
"Normal", |
|
"Nightmare", |
|
"Hell", |
|
}; |
|
sprintf(pszStr, "%s, mode = %s", gszProductName, difficulties[gnDifficulty]); |
|
NetSendCmdString(1 << myplr, pszStr); |
|
return; |
|
} |
|
case 'V': |
|
NetSendCmdString(1 << myplr, gszVersionNumber); |
|
return; |
|
case '!': |
|
case '1': |
|
if (plr[myplr].SpdList[0]._itype != ITYPE_NONE && plr[myplr].SpdList[0]._itype != ITYPE_GOLD) { |
|
UseInvItem(myplr, INVITEM_BELT_FIRST); |
|
} |
|
return; |
|
case '@': |
|
case '2': |
|
if (plr[myplr].SpdList[1]._itype != ITYPE_NONE && plr[myplr].SpdList[1]._itype != ITYPE_GOLD) { |
|
UseInvItem(myplr, INVITEM_BELT_FIRST + 1); |
|
} |
|
return; |
|
case '#': |
|
case '3': |
|
if (plr[myplr].SpdList[2]._itype != ITYPE_NONE && plr[myplr].SpdList[2]._itype != ITYPE_GOLD) { |
|
UseInvItem(myplr, INVITEM_BELT_FIRST + 2); |
|
} |
|
return; |
|
case '$': |
|
case '4': |
|
if (plr[myplr].SpdList[3]._itype != ITYPE_NONE && plr[myplr].SpdList[3]._itype != ITYPE_GOLD) { |
|
UseInvItem(myplr, INVITEM_BELT_FIRST + 3); |
|
} |
|
return; |
|
case '%': |
|
case '5': |
|
if (plr[myplr].SpdList[4]._itype != ITYPE_NONE && plr[myplr].SpdList[4]._itype != ITYPE_GOLD) { |
|
UseInvItem(myplr, INVITEM_BELT_FIRST + 4); |
|
} |
|
return; |
|
case '^': |
|
case '6': |
|
if (plr[myplr].SpdList[5]._itype != ITYPE_NONE && plr[myplr].SpdList[5]._itype != ITYPE_GOLD) { |
|
UseInvItem(myplr, INVITEM_BELT_FIRST + 5); |
|
} |
|
return; |
|
case '&': |
|
case '7': |
|
if (plr[myplr].SpdList[6]._itype != ITYPE_NONE && plr[myplr].SpdList[6]._itype != ITYPE_GOLD) { |
|
UseInvItem(myplr, INVITEM_BELT_FIRST + 6); |
|
} |
|
return; |
|
case '*': |
|
case '8': |
|
#ifdef _DEBUG |
|
if (debug_mode_key_inverted_v || debug_mode_key_w) { |
|
NetSendCmd(TRUE, CMD_CHEAT_EXPERIENCE); |
|
return; |
|
} |
|
#endif |
|
if (plr[myplr].SpdList[7]._itype != ITYPE_NONE && plr[myplr].SpdList[7]._itype != ITYPE_GOLD) { |
|
UseInvItem(myplr, INVITEM_BELT_FIRST + 7); |
|
} |
|
return; |
|
#ifdef _DEBUG |
|
case ')': |
|
case '0': |
|
if (debug_mode_key_inverted_v) { |
|
if (arrowdebug > 2) { |
|
arrowdebug = 0; |
|
} |
|
if (arrowdebug == 0) { |
|
plr[myplr]._pIFlags &= ~ISPL_FIRE_ARROWS; |
|
plr[myplr]._pIFlags &= ~ISPL_LIGHT_ARROWS; |
|
} |
|
if (arrowdebug == 1) { |
|
plr[myplr]._pIFlags |= ISPL_FIRE_ARROWS; |
|
} |
|
if (arrowdebug == 2) { |
|
plr[myplr]._pIFlags |= ISPL_LIGHT_ARROWS; |
|
} |
|
arrowdebug++; |
|
} |
|
return; |
|
case ':': |
|
if (currlevel == 0 && debug_mode_key_w) { |
|
SetAllSpellsCheat(); |
|
} |
|
return; |
|
case '[': |
|
if (currlevel == 0 && debug_mode_key_w) { |
|
TakeGoldCheat(); |
|
} |
|
return; |
|
case ']': |
|
if (currlevel == 0 && debug_mode_key_w) { |
|
MaxSpellsCheat(); |
|
} |
|
return; |
|
case 'a': |
|
if (debug_mode_key_inverted_v) { |
|
spelldata[SPL_TELEPORT].sTownSpell = 1; |
|
plr[myplr]._pSplLvl[plr[myplr]._pSpell]++; |
|
} |
|
return; |
|
case 'D': |
|
PrintDebugPlayer(TRUE); |
|
return; |
|
case 'd': |
|
PrintDebugPlayer(FALSE); |
|
return; |
|
case 'L': |
|
case 'l': |
|
if (debug_mode_key_inverted_v) { |
|
ToggleLighting(); |
|
} |
|
return; |
|
case 'M': |
|
NextDebugMonster(); |
|
return; |
|
case 'm': |
|
GetDebugMonster(); |
|
return; |
|
case 'R': |
|
case 'r': |
|
sprintf(tempstr, "seed = %i", glSeedTbl[currlevel]); |
|
NetSendCmdString(1 << myplr, tempstr); |
|
sprintf(tempstr, "Mid1 = %i : Mid2 = %i : Mid3 = %i", glMid1Seed[currlevel], glMid2Seed[currlevel], glMid3Seed[currlevel]); |
|
NetSendCmdString(1 << myplr, tempstr); |
|
sprintf(tempstr, "End = %i", glEndSeed[currlevel]); |
|
NetSendCmdString(1 << myplr, tempstr); |
|
return; |
|
case 'T': |
|
case 't': |
|
if (debug_mode_key_inverted_v) { |
|
sprintf(tempstr, "PX = %i PY = %i", plr[myplr]._px, plr[myplr]._py); |
|
NetSendCmdString(1 << myplr, tempstr); |
|
sprintf(tempstr, "CX = %i CY = %i DP = %i", cursmx, cursmy, dungeon[cursmx][cursmy]); |
|
NetSendCmdString(1 << myplr, tempstr); |
|
} |
|
return; |
|
case '|': |
|
if (currlevel == 0 && debug_mode_key_w) { |
|
GiveGoldCheat(); |
|
} |
|
return; |
|
#endif |
|
} |
|
} |
|
|
|
static void GetMousePos(LPARAM lParam) |
|
{ |
|
MouseX = (short)(lParam & 0xffff); |
|
MouseY = (short)((lParam >> 16) & 0xffff); |
|
} |
|
|
|
void DisableInputWndProc(UINT uMsg, WPARAM wParam, LPARAM lParam) |
|
{ |
|
switch (uMsg) { |
|
case DVL_WM_KEYDOWN: |
|
case DVL_WM_KEYUP: |
|
case DVL_WM_CHAR: |
|
case DVL_WM_SYSKEYDOWN: |
|
case DVL_WM_SYSCOMMAND: |
|
case DVL_WM_MOUSEMOVE: |
|
GetMousePos(lParam); |
|
return; |
|
case DVL_WM_LBUTTONDOWN: |
|
if (sgbMouseDown != CLICK_NONE) |
|
return; |
|
sgbMouseDown = CLICK_LEFT; |
|
return; |
|
case DVL_WM_LBUTTONUP: |
|
if (sgbMouseDown != CLICK_LEFT) |
|
return; |
|
sgbMouseDown = CLICK_NONE; |
|
return; |
|
case DVL_WM_RBUTTONDOWN: |
|
if (sgbMouseDown != CLICK_NONE) |
|
return; |
|
sgbMouseDown = CLICK_RIGHT; |
|
return; |
|
case DVL_WM_RBUTTONUP: |
|
if (sgbMouseDown != CLICK_RIGHT) |
|
return; |
|
sgbMouseDown = CLICK_NONE; |
|
return; |
|
case DVL_WM_CAPTURECHANGED: |
|
sgbMouseDown = CLICK_NONE; |
|
return; |
|
} |
|
|
|
MainWndProc(uMsg, wParam, lParam); |
|
} |
|
|
|
void GM_Game(UINT uMsg, WPARAM wParam, LPARAM lParam) |
|
{ |
|
switch (uMsg) { |
|
case DVL_WM_KEYDOWN: |
|
PressKey(wParam); |
|
return; |
|
case DVL_WM_KEYUP: |
|
ReleaseKey(wParam); |
|
return; |
|
case DVL_WM_CHAR: |
|
PressChar(wParam); |
|
return; |
|
case DVL_WM_SYSKEYDOWN: |
|
if (PressSysKey(wParam)) |
|
return; |
|
break; |
|
case DVL_WM_SYSCOMMAND: |
|
if (wParam == DVL_SC_CLOSE) { |
|
gbRunGame = FALSE; |
|
gbRunGameResult = FALSE; |
|
return; |
|
} |
|
break; |
|
case DVL_WM_MOUSEMOVE: |
|
GetMousePos(lParam); |
|
gmenu_on_mouse_move(); |
|
return; |
|
case DVL_WM_LBUTTONDOWN: |
|
GetMousePos(lParam); |
|
if (sgbMouseDown == CLICK_NONE) { |
|
sgbMouseDown = CLICK_LEFT; |
|
track_repeat_walk(LeftMouseDown(wParam)); |
|
} |
|
return; |
|
case DVL_WM_LBUTTONUP: |
|
GetMousePos(lParam); |
|
if (sgbMouseDown == CLICK_LEFT) { |
|
sgbMouseDown = CLICK_NONE; |
|
LeftMouseUp(wParam); |
|
track_repeat_walk(FALSE); |
|
} |
|
return; |
|
case DVL_WM_RBUTTONDOWN: |
|
GetMousePos(lParam); |
|
if (sgbMouseDown == CLICK_NONE) { |
|
sgbMouseDown = CLICK_RIGHT; |
|
RightMouseDown(); |
|
} |
|
return; |
|
case DVL_WM_RBUTTONUP: |
|
GetMousePos(lParam); |
|
if (sgbMouseDown == CLICK_RIGHT) { |
|
sgbMouseDown = CLICK_NONE; |
|
} |
|
return; |
|
case DVL_WM_CAPTURECHANGED: |
|
sgbMouseDown = CLICK_NONE; |
|
track_repeat_walk(FALSE); |
|
break; |
|
case WM_DIABNEXTLVL: |
|
case WM_DIABPREVLVL: |
|
case WM_DIABRTNLVL: |
|
case WM_DIABSETLVL: |
|
case WM_DIABWARPLVL: |
|
case WM_DIABTOWNWARP: |
|
case WM_DIABTWARPUP: |
|
case WM_DIABRETOWN: |
|
if (gbIsMultiplayer) |
|
pfile_write_hero(); |
|
nthread_ignore_mutex(TRUE); |
|
PaletteFadeOut(8); |
|
sound_stop(); |
|
music_stop(); |
|
track_repeat_walk(FALSE); |
|
sgbMouseDown = CLICK_NONE; |
|
ShowProgress(uMsg); |
|
force_redraw = 255; |
|
DrawAndBlit(); |
|
LoadPWaterPalette(); |
|
if (gbRunGame) |
|
PaletteFadeIn(8); |
|
nthread_ignore_mutex(FALSE); |
|
gbGameLoopStartup = TRUE; |
|
return; |
|
} |
|
|
|
MainWndProc(uMsg, wParam, lParam); |
|
} |
|
|
|
void LoadLvlGFX() |
|
{ |
|
assert(!pDungeonCels); |
|
|
|
switch (leveltype) { |
|
case DTYPE_TOWN: |
|
if (gbIsHellfire) { |
|
pDungeonCels = LoadFileInMem("NLevels\\TownData\\Town.CEL", NULL); |
|
pMegaTiles = LoadFileInMem("NLevels\\TownData\\Town.TIL", NULL); |
|
pLevelPieces = LoadFileInMem("NLevels\\TownData\\Town.MIN", NULL); |
|
} else { |
|
pDungeonCels = LoadFileInMem("Levels\\TownData\\Town.CEL", NULL); |
|
pMegaTiles = LoadFileInMem("Levels\\TownData\\Town.TIL", NULL); |
|
pLevelPieces = LoadFileInMem("Levels\\TownData\\Town.MIN", NULL); |
|
} |
|
pSpecialCels = LoadFileInMem("Levels\\TownData\\TownS.CEL", NULL); |
|
break; |
|
case DTYPE_CATHEDRAL: |
|
if (currlevel < 21) { |
|
pDungeonCels = LoadFileInMem("Levels\\L1Data\\L1.CEL", NULL); |
|
pMegaTiles = LoadFileInMem("Levels\\L1Data\\L1.TIL", NULL); |
|
pLevelPieces = LoadFileInMem("Levels\\L1Data\\L1.MIN", NULL); |
|
pSpecialCels = LoadFileInMem("Levels\\L1Data\\L1S.CEL", NULL); |
|
} else { |
|
pDungeonCels = LoadFileInMem("NLevels\\L5Data\\L5.CEL", NULL); |
|
pMegaTiles = LoadFileInMem("NLevels\\L5Data\\L5.TIL", NULL); |
|
pLevelPieces = LoadFileInMem("NLevels\\L5Data\\L5.MIN", NULL); |
|
pSpecialCels = LoadFileInMem("NLevels\\L5Data\\L5S.CEL", NULL); |
|
} |
|
break; |
|
case DTYPE_CATACOMBS: |
|
pDungeonCels = LoadFileInMem("Levels\\L2Data\\L2.CEL", NULL); |
|
pMegaTiles = LoadFileInMem("Levels\\L2Data\\L2.TIL", NULL); |
|
pLevelPieces = LoadFileInMem("Levels\\L2Data\\L2.MIN", NULL); |
|
pSpecialCels = LoadFileInMem("Levels\\L2Data\\L2S.CEL", NULL); |
|
break; |
|
case DTYPE_CAVES: |
|
if (currlevel < 17) { |
|
pDungeonCels = LoadFileInMem("Levels\\L3Data\\L3.CEL", NULL); |
|
pMegaTiles = LoadFileInMem("Levels\\L3Data\\L3.TIL", NULL); |
|
pLevelPieces = LoadFileInMem("Levels\\L3Data\\L3.MIN", NULL); |
|
} else { |
|
pDungeonCels = LoadFileInMem("NLevels\\L6Data\\L6.CEL", NULL); |
|
pMegaTiles = LoadFileInMem("NLevels\\L6Data\\L6.TIL", NULL); |
|
pLevelPieces = LoadFileInMem("NLevels\\L6Data\\L6.MIN", NULL); |
|
} |
|
pSpecialCels = LoadFileInMem("Levels\\L1Data\\L1S.CEL", NULL); |
|
break; |
|
case DTYPE_HELL: |
|
pDungeonCels = LoadFileInMem("Levels\\L4Data\\L4.CEL", NULL); |
|
pMegaTiles = LoadFileInMem("Levels\\L4Data\\L4.TIL", NULL); |
|
pLevelPieces = LoadFileInMem("Levels\\L4Data\\L4.MIN", NULL); |
|
pSpecialCels = LoadFileInMem("Levels\\L2Data\\L2S.CEL", NULL); |
|
break; |
|
default: |
|
app_fatal("LoadLvlGFX"); |
|
break; |
|
} |
|
} |
|
|
|
void LoadAllGFX() |
|
{ |
|
IncProgress(); |
|
IncProgress(); |
|
InitObjectGFX(); |
|
IncProgress(); |
|
InitMissileGFX(); |
|
IncProgress(); |
|
} |
|
|
|
/** |
|
* @param lvldir method of entry |
|
*/ |
|
void CreateLevel(int lvldir) |
|
{ |
|
switch (leveltype) { |
|
case DTYPE_TOWN: |
|
CreateTown(lvldir); |
|
InitTownTriggers(); |
|
LoadRndLvlPal(0); |
|
break; |
|
case DTYPE_CATHEDRAL: |
|
CreateL5Dungeon(glSeedTbl[currlevel], lvldir); |
|
InitL1Triggers(); |
|
Freeupstairs(); |
|
if (currlevel < 21) { |
|
LoadRndLvlPal(1); |
|
} else { |
|
LoadRndLvlPal(5); |
|
} |
|
break; |
|
case DTYPE_CATACOMBS: |
|
CreateL2Dungeon(glSeedTbl[currlevel], lvldir); |
|
InitL2Triggers(); |
|
Freeupstairs(); |
|
LoadRndLvlPal(2); |
|
break; |
|
case DTYPE_CAVES: |
|
CreateL3Dungeon(glSeedTbl[currlevel], lvldir); |
|
InitL3Triggers(); |
|
Freeupstairs(); |
|
if (currlevel < 17) { |
|
LoadRndLvlPal(3); |
|
} else { |
|
LoadRndLvlPal(6); |
|
} |
|
break; |
|
case DTYPE_HELL: |
|
CreateL4Dungeon(glSeedTbl[currlevel], lvldir); |
|
InitL4Triggers(); |
|
Freeupstairs(); |
|
LoadRndLvlPal(4); |
|
break; |
|
default: |
|
app_fatal("CreateLevel"); |
|
break; |
|
} |
|
} |
|
|
|
static void UpdateMonsterLights() |
|
{ |
|
for (int i = 0; i < nummonsters; i++) { |
|
MonsterStruct *mon = &monster[monstactive[i]]; |
|
if (mon->mlid != NO_LIGHT) { |
|
if (mon->mlid == plr[myplr]._plid) { // Fix old saves where some monsters had 0 instead of NO_LIGHT |
|
mon->mlid = NO_LIGHT; |
|
continue; |
|
} |
|
|
|
LightListStruct *lid = &LightList[mon->mlid]; |
|
if (mon->_mx != lid->_lx || mon->_my != lid->_ly) { |
|
ChangeLightXY(mon->mlid, mon->_mx, mon->_my); |
|
} |
|
} |
|
} |
|
} |
|
|
|
void LoadGameLevel(BOOL firstflag, int lvldir) |
|
{ |
|
int i, j; |
|
BOOL visited; |
|
|
|
if (setseed) |
|
glSeedTbl[currlevel] = setseed; |
|
|
|
music_stop(); |
|
NewCursor(CURSOR_HAND); |
|
SetRndSeed(glSeedTbl[currlevel]); |
|
IncProgress(); |
|
MakeLightTable(); |
|
LoadLvlGFX(); |
|
IncProgress(); |
|
|
|
if (firstflag) { |
|
InitInv(); |
|
InitItemGFX(); |
|
InitQuestText(); |
|
|
|
int players = gbIsMultiplayer ? MAX_PLRS : 1; |
|
for (i = 0; i < players; i++) |
|
InitPlrGFXMem(i); |
|
|
|
InitStores(); |
|
InitAutomapOnce(); |
|
InitHelp(); |
|
} |
|
|
|
SetRndSeed(glSeedTbl[currlevel]); |
|
|
|
if (leveltype == DTYPE_TOWN) |
|
SetupTownStores(); |
|
|
|
IncProgress(); |
|
InitAutomap(); |
|
|
|
if (leveltype != DTYPE_TOWN && lvldir != ENTRY_LOAD) { |
|
InitLighting(); |
|
InitVision(); |
|
} |
|
|
|
InitLevelMonsters(); |
|
IncProgress(); |
|
|
|
if (!setlevel) { |
|
CreateLevel(lvldir); |
|
IncProgress(); |
|
FillSolidBlockTbls(); |
|
SetRndSeed(glSeedTbl[currlevel]); |
|
|
|
if (leveltype != DTYPE_TOWN) { |
|
GetLevelMTypes(); |
|
InitThemes(); |
|
LoadAllGFX(); |
|
} else { |
|
IncProgress(); |
|
IncProgress(); |
|
InitMissileGFX(); |
|
IncProgress(); |
|
IncProgress(); |
|
} |
|
|
|
IncProgress(); |
|
|
|
if (lvldir == ENTRY_RTNLVL) |
|
GetReturnLvlPos(); |
|
if (lvldir == ENTRY_WARPLVL) |
|
GetPortalLvlPos(); |
|
|
|
IncProgress(); |
|
|
|
for (i = 0; i < MAX_PLRS; i++) { |
|
if (plr[i].plractive && currlevel == plr[i].plrlevel) { |
|
InitPlayerGFX(i); |
|
if (lvldir != ENTRY_LOAD) |
|
InitPlayer(i, firstflag); |
|
} |
|
} |
|
|
|
PlayDungMsgs(); |
|
InitMultiView(); |
|
IncProgress(); |
|
|
|
visited = FALSE; |
|
int players = gbIsMultiplayer ? MAX_PLRS : 1; |
|
for (i = 0; i < players; i++) { |
|
if (plr[i].plractive) |
|
visited = visited || plr[i]._pLvlVisited[currlevel]; |
|
} |
|
|
|
SetRndSeed(glSeedTbl[currlevel]); |
|
|
|
if (leveltype != DTYPE_TOWN) { |
|
if (firstflag || lvldir == ENTRY_LOAD || !plr[myplr]._pLvlVisited[currlevel] || gbIsMultiplayer) { |
|
HoldThemeRooms(); |
|
glMid1Seed[currlevel] = GetRndSeed(); |
|
InitMonsters(); |
|
glMid2Seed[currlevel] = GetRndSeed(); |
|
IncProgress(); |
|
InitObjects(); |
|
InitItems(); |
|
if (currlevel < 17) |
|
CreateThemeRooms(); |
|
IncProgress(); |
|
glMid3Seed[currlevel] = GetRndSeed(); |
|
InitMissiles(); |
|
InitDead(); |
|
glEndSeed[currlevel] = GetRndSeed(); |
|
|
|
if (gbIsMultiplayer) |
|
DeltaLoadLevel(); |
|
|
|
IncProgress(); |
|
SavePreLighting(); |
|
} else { |
|
HoldThemeRooms(); |
|
InitMonsters(); |
|
InitMissiles(); |
|
InitDead(); |
|
IncProgress(); |
|
LoadLevel(); |
|
IncProgress(); |
|
} |
|
} else { |
|
for (i = 0; i < MAXDUNX; i++) { |
|
for (j = 0; j < MAXDUNY; j++) |
|
dFlags[i][j] |= BFLAG_LIT; |
|
} |
|
|
|
InitTowners(); |
|
InitItems(); |
|
InitMissiles(); |
|
IncProgress(); |
|
|
|
if (!firstflag && lvldir != ENTRY_LOAD && plr[myplr]._pLvlVisited[currlevel] && !gbIsMultiplayer) |
|
LoadLevel(); |
|
if (gbIsMultiplayer) |
|
DeltaLoadLevel(); |
|
|
|
IncProgress(); |
|
} |
|
if (!gbIsMultiplayer) |
|
ResyncQuests(); |
|
else |
|
ResyncMPQuests(); |
|
} else { |
|
LoadSetMap(); |
|
IncProgress(); |
|
GetLevelMTypes(); |
|
IncProgress(); |
|
InitMonsters(); |
|
IncProgress(); |
|
InitMissileGFX(); |
|
IncProgress(); |
|
InitDead(); |
|
IncProgress(); |
|
FillSolidBlockTbls(); |
|
IncProgress(); |
|
|
|
if (lvldir == ENTRY_WARPLVL) |
|
GetPortalLvlPos(); |
|
IncProgress(); |
|
|
|
for (i = 0; i < MAX_PLRS; i++) { |
|
if (plr[i].plractive && currlevel == plr[i].plrlevel) { |
|
InitPlayerGFX(i); |
|
if (lvldir != ENTRY_LOAD) |
|
InitPlayer(i, firstflag); |
|
} |
|
} |
|
IncProgress(); |
|
|
|
InitMultiView(); |
|
IncProgress(); |
|
|
|
if (firstflag || lvldir == ENTRY_LOAD || !plr[myplr]._pSLvlVisited[setlvlnum]) { |
|
InitItems(); |
|
SavePreLighting(); |
|
} else { |
|
LoadLevel(); |
|
} |
|
|
|
InitMissiles(); |
|
IncProgress(); |
|
} |
|
|
|
SyncPortals(); |
|
|
|
for (i = 0; i < MAX_PLRS; i++) { |
|
if (plr[i].plractive && plr[i].plrlevel == currlevel && (!plr[i]._pLvlChanging || i == myplr)) { |
|
if (plr[i]._pHitPoints > 0) { |
|
if (!gbIsMultiplayer) |
|
dPlayer[plr[i]._px][plr[i]._py] = i + 1; |
|
else |
|
SyncInitPlrPos(i); |
|
} else { |
|
dFlags[plr[i]._px][plr[i]._py] |= BFLAG_DEAD_PLAYER; |
|
} |
|
} |
|
} |
|
|
|
SetDungeonMicros(); |
|
|
|
InitLightMax(); |
|
IncProgress(); |
|
IncProgress(); |
|
|
|
if (firstflag) { |
|
InitControlPan(); |
|
} |
|
IncProgress(); |
|
UpdateMonsterLights(); |
|
if (leveltype != DTYPE_TOWN) { |
|
ProcessLightList(); |
|
ProcessVisionList(); |
|
} |
|
|
|
if (currlevel >= 21) { |
|
if (currlevel == 21) { |
|
items_427ABA(CornerStone.x, CornerStone.y); |
|
} |
|
if (quests[Q_NAKRUL]._qactive == QUEST_DONE && currlevel == 24) { |
|
objects_454BA8(); |
|
} |
|
} |
|
|
|
if (currlevel >= 17) |
|
music_start(currlevel > 20 ? TMUSIC_L5 : TMUSIC_L6); |
|
else |
|
music_start(leveltype); |
|
|
|
while (!IncProgress()) |
|
; |
|
|
|
if (gbIsSpawn && setlevel && setlvlnum == SL_SKELKING && quests[Q_SKELKING]._qactive == QUEST_ACTIVE) |
|
PlaySFX(USFX_SKING1); |
|
} |
|
|
|
// Controller support: |
|
extern void plrctrls_after_game_logic(); |
|
|
|
static void game_logic() |
|
{ |
|
if (!ProcessInput()) { |
|
return; |
|
} |
|
if (gbProcessPlayers) { |
|
ProcessPlayers(); |
|
} |
|
if (leveltype != DTYPE_TOWN) { |
|
ProcessMonsters(); |
|
ProcessObjects(); |
|
ProcessMissiles(); |
|
ProcessItems(); |
|
ProcessLightList(); |
|
ProcessVisionList(); |
|
} else { |
|
ProcessTowners(); |
|
ProcessItems(); |
|
ProcessMissiles(); |
|
} |
|
|
|
#ifdef _DEBUG |
|
if (debug_mode_key_inverted_v && GetAsyncKeyState(DVL_VK_SHIFT) & 0x8000) { |
|
ScrollView(); |
|
} |
|
#endif |
|
|
|
sound_update(); |
|
ClearPlrMsg(); |
|
CheckTriggers(); |
|
CheckQuests(); |
|
force_redraw |= 1; |
|
pfile_update(FALSE); |
|
|
|
plrctrls_after_game_logic(); |
|
} |
|
|
|
static void timeout_cursor(BOOL bTimeout) |
|
{ |
|
if (bTimeout) { |
|
if (sgnTimeoutCurs == CURSOR_NONE && sgbMouseDown == CLICK_NONE) { |
|
sgnTimeoutCurs = pcurs; |
|
multi_net_ping(); |
|
ClearPanel(); |
|
AddPanelString("-- Network timeout --", TRUE); |
|
AddPanelString("-- Waiting for players --", TRUE); |
|
NewCursor(CURSOR_HOURGLASS); |
|
force_redraw = 255; |
|
} |
|
scrollrt_draw_game_screen(TRUE); |
|
} else if (sgnTimeoutCurs != CURSOR_NONE) { |
|
NewCursor(sgnTimeoutCurs); |
|
sgnTimeoutCurs = CURSOR_NONE; |
|
ClearPanel(); |
|
force_redraw = 255; |
|
} |
|
} |
|
|
|
/** |
|
* @param bStartup Process additional ticks before returning |
|
*/ |
|
void game_loop(BOOL bStartup) |
|
{ |
|
int i; |
|
|
|
i = bStartup ? gnTickRate * 3 : 3; |
|
|
|
while (i--) { |
|
if (!multi_handle_delta()) { |
|
timeout_cursor(TRUE); |
|
break; |
|
} else { |
|
timeout_cursor(FALSE); |
|
game_logic(); |
|
} |
|
if (!gbRunGame || !gbIsMultiplayer || !nthread_has_500ms_passed()) |
|
break; |
|
} |
|
} |
|
|
|
void diablo_color_cyc_logic() |
|
{ |
|
if (!sgOptions.bColorCycling) |
|
return; |
|
|
|
if (leveltype == DTYPE_HELL) { |
|
lighting_color_cycling(); |
|
} else if (currlevel >= 21) { |
|
palette_update_crypt(); |
|
} else if (currlevel >= 17) { |
|
palette_update_hive(); |
|
} else if (leveltype == DTYPE_CAVES) { |
|
palette_update_caves(); |
|
} |
|
} |
|
|
|
DEVILUTION_END_NAMESPACE
|
|
|