X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_game.pas;h=05b824ac9f1f9814b59f80fd244e7436b037c116;hb=7a37d93e41daf0b467ff616e493db79d90882085;hp=1cf480864080a2c4115db2cae221b07de7e16299;hpb=6d6df4e3427cd01e03e172984c9d0d391ff38032;p=d2df-sdl.git diff --git a/src/game/g_game.pas b/src/game/g_game.pas index 1cf4808..05b824a 100644 --- a/src/game/g_game.pas +++ b/src/game/g_game.pas @@ -70,7 +70,7 @@ function g_Game_IsNet(): Boolean; function g_Game_IsServer(): Boolean; function g_Game_IsClient(): Boolean; procedure g_Game_Init(); -procedure g_Game_Free(); +procedure g_Game_Free (freeTextures: Boolean=true); procedure g_Game_LoadData(); procedure g_Game_FreeData(); procedure g_Game_Update(); @@ -95,9 +95,9 @@ procedure g_Game_RestartLevel(); procedure g_Game_RestartRound(NoMapRestart: Boolean = False); procedure g_Game_ClientWAD(NewWAD: String; WHash: TMD5Digest); procedure g_Game_SaveOptions(); -function g_Game_StartMap(Map: String; Force: Boolean = False): Boolean; -procedure g_Game_ChangeMap(MapPath: String); -procedure g_Game_ExitLevel(Map: Char16); +function g_Game_StartMap(Map: String; Force: Boolean = False; const oldMapPath: AnsiString=''): Boolean; +procedure g_Game_ChangeMap(const MapPath: String); +procedure g_Game_ExitLevel(const Map: AnsiString); function g_Game_GetFirstMap(WAD: String): String; function g_Game_GetNextMap(): String; procedure g_Game_NextLevel(); @@ -335,7 +335,7 @@ function conIsCheatsEnabled (): Boolean; implementation uses - g_textures, g_main, g_window, g_menu, + e_texture, g_textures, g_main, g_window, g_menu, e_input, e_log, g_console, g_items, g_map, g_panel, g_playermodel, g_gfx, g_options, g_weapons, Math, g_triggers, g_monsters, e_sound, CONFIG, @@ -792,7 +792,7 @@ begin {$IF DEFINED(D2F_DEBUG)} if gPlayer1 <> nil then gPlayer1.NoTarget := True; - gAimLine := true; + gAimLine := g_dbg_aimline_on; {$ENDIF} end; @@ -1297,12 +1297,12 @@ begin end; end; -procedure g_Game_Free(); +procedure g_Game_Free(freeTextures: Boolean=true); begin if NetMode = NET_CLIENT then g_Net_Disconnect(); if NetMode = NET_SERVER then g_Net_Host_Die(); - g_Map_Free(); + g_Map_Free(freeTextures); g_Player_Free(); g_Player_RemoveAllCorpses(); @@ -1485,20 +1485,30 @@ var function sendMonsPos (mon: TMonster): Boolean; begin result := false; // don't stop - if (mon.MonsterType = MONSTER_BARREL) then + // this will also reset "need-send" flag + if mon.gncNeedSend then + begin + MH_SEND_MonsterPos(mon.UID); + end + else if (mon.MonsterType = MONSTER_BARREL) then begin if (mon.GameVelX <> 0) or (mon.GameVelY <> 0) then MH_SEND_MonsterPos(mon.UID); end - else - if (mon.MonsterState <> MONSTATE_SLEEP) then - begin - if (mon.MonsterState <> MONSTATE_DEAD) or (mon.GameVelX <> 0) or (mon.GameVelY <> 0) then - begin - MH_SEND_MonsterPos(mon.UID); - end; - end; + else if (mon.MonsterState <> MONSTATE_SLEEP) then + begin + if (mon.MonsterState <> MONSTATE_DEAD) or (mon.GameVelX <> 0) or (mon.GameVelY <> 0) then MH_SEND_MonsterPos(mon.UID); + end; + end; + + function sendMonsPosUnexpected (mon: TMonster): Boolean; + begin + result := false; // don't stop + // this will also reset "need-send" flag + if mon.gncNeedSend then MH_SEND_MonsterPos(mon.UID); end; +var + reliableUpdate: Boolean; begin g_ResetDynlights(); // Ïîðà âûêëþ÷àòü èãðó: @@ -1842,13 +1852,16 @@ begin g_GFX_Update(); g_Player_UpdateAll(); g_Player_UpdatePhysicalObjects(); - if gGameSettings.GameType = GT_SERVER then - if Length(gMonstersSpawned) > 0 then + + // server: send newly spawned monsters unconditionally + if (gGameSettings.GameType = GT_SERVER) then + begin + if (Length(gMonstersSpawned) > 0) then begin - for I := 0 to High(gMonstersSpawned) do - MH_SEND_MonsterSpawn(gMonstersSpawned[I]); + for I := 0 to High(gMonstersSpawned) do MH_SEND_MonsterSpawn(gMonstersSpawned[I]); SetLength(gMonstersSpawned, 0); end; + end; if (gSoundTriggerTime > 8) then begin @@ -1856,49 +1869,65 @@ begin gSoundTriggerTime := 0; end else + begin Inc(gSoundTriggerTime); + end; if (NetMode = NET_SERVER) then begin Inc(NetTimeToUpdate); Inc(NetTimeToReliable); - if NetTimeToReliable >= NetRelupdRate then + + // send monster updates + if (NetTimeToReliable >= NetRelupdRate) or (NetTimeToUpdate >= NetUpdateRate) then begin + // send all monsters (periodic sync) + reliableUpdate := (NetTimeToReliable >= NetRelupdRate); + for I := 0 to High(gPlayers) do - if gPlayers[I] <> nil then - MH_SEND_PlayerPos(True, gPlayers[I].UID); + begin + if (gPlayers[I] <> nil) then MH_SEND_PlayerPos(reliableUpdate, gPlayers[I].UID); + end; g_Mons_ForEach(sendMonsPos); - NetTimeToReliable := 0; - NetTimeToUpdate := NetUpdateRate; + if reliableUpdate then + begin + NetTimeToReliable := 0; + NetTimeToUpdate := NetUpdateRate; + end + else + begin + NetTimeToUpdate := 0; + end; end - else if NetTimeToUpdate >= NetUpdateRate then + else begin - if gPlayers <> nil then - for I := 0 to High(gPlayers) do - if gPlayers[I] <> nil then - MH_SEND_PlayerPos(False, gPlayers[I].UID); - - g_Mons_ForEach(sendMonsPos); - - NetTimeToUpdate := 0; + // send only mosters with some unexpected changes + g_Mons_ForEach(sendMonsPosUnexpected); end; + // send unexpected platform changes + g_Map_NetSendInterestingPanels(); + if NetUseMaster then + begin if gTime >= NetTimeToMaster then begin if (NetMHost = nil) or (NetMPeer = nil) then - if not g_Net_Slist_Connect then - g_Console_Add(_lc[I_NET_MSG_ERROR] + _lc[I_NET_SLIST_ERROR]); + begin + if not g_Net_Slist_Connect then g_Console_Add(_lc[I_NET_MSG_ERROR] + _lc[I_NET_SLIST_ERROR]); + end; g_Net_Slist_Update; NetTimeToMaster := gTime + NetMasterRate; end; + end; end - else - if NetMode = NET_CLIENT then - MC_SEND_PlayerPos(); + else if (NetMode = NET_CLIENT) then + begin + MC_SEND_PlayerPos(); + end; end; // if gameOn ... // Àêòèâíî îêíî èíòåðôåéñà - ïåðåäàåì êëàâèøè åìó: @@ -2009,12 +2038,12 @@ begin g_Texture_CreateWADEx('TEXTURE_PLAYER_HUDJET', GameWAD+':TEXTURES\JETBAR'); g_Texture_CreateWADEx('TEXTURE_PLAYER_HUDBG', GameWAD+':TEXTURES\HUDBG'); g_Texture_CreateWADEx('TEXTURE_PLAYER_ARMORHUD', GameWAD+':TEXTURES\ARMORHUD'); - g_Texture_CreateWADEx('TEXTURE_PLAYER_REDFLAG', GameWAD+':TEXTURES\FLAGHUD_RB'); - g_Texture_CreateWADEx('TEXTURE_PLAYER_REDFLAG_S', GameWAD+':TEXTURES\FLAGHUD_RS'); - g_Texture_CreateWADEx('TEXTURE_PLAYER_REDFLAG_D', GameWAD+':TEXTURES\FLAGHUD_RD'); - g_Texture_CreateWADEx('TEXTURE_PLAYER_BLUEFLAG', GameWAD+':TEXTURES\FLAGHUD_BB'); - g_Texture_CreateWADEx('TEXTURE_PLAYER_BLUEFLAG_S', GameWAD+':TEXTURES\FLAGHUD_BS'); - g_Texture_CreateWADEx('TEXTURE_PLAYER_BLUEFLAG_D', GameWAD+':TEXTURES\FLAGHUD_BD'); + g_Texture_CreateWADEx('TEXTURE_PLAYER_REDFLAG', GameWAD+':TEXTURES\FLAGHUD_RB', GameWAD+':TEXTURES\FLAGHUD_R_BASE'); + g_Texture_CreateWADEx('TEXTURE_PLAYER_REDFLAG_S', GameWAD+':TEXTURES\FLAGHUD_RS', GameWAD+':TEXTURES\FLAGHUD_R_STOLEN'); + g_Texture_CreateWADEx('TEXTURE_PLAYER_REDFLAG_D', GameWAD+':TEXTURES\FLAGHUD_RD', GameWAD+':TEXTURES\FLAGHUD_R_DROP'); + g_Texture_CreateWADEx('TEXTURE_PLAYER_BLUEFLAG', GameWAD+':TEXTURES\FLAGHUD_BB', GameWAD+':TEXTURES\FLAGHUD_B_BASE'); + g_Texture_CreateWADEx('TEXTURE_PLAYER_BLUEFLAG_S', GameWAD+':TEXTURES\FLAGHUD_BS', GameWAD+':TEXTURES\FLAGHUD_B_STOLEN'); + g_Texture_CreateWADEx('TEXTURE_PLAYER_BLUEFLAG_D', GameWAD+':TEXTURES\FLAGHUD_BD', GameWAD+':TEXTURES\FLAGHUD_B_DROP'); g_Texture_CreateWADEx('TEXTURE_PLAYER_TALKBUBBLE', GameWAD+':TEXTURES\TALKBUBBLE'); g_Texture_CreateWADEx('TEXTURE_PLAYER_INVULPENTA', GameWAD+':TEXTURES\PENTA'); g_Frames_CreateWAD(nil, 'FRAMES_TELEPORT', GameWAD+':TEXTURES\TELEPORT', 64, 64, 10, False); @@ -2493,7 +2522,7 @@ var result := false; // don't stop with mon do begin - if Live then + if alive then begin // Ëåâûé âåðõíèé óãîë aX := Obj.X div ScaleSz + 1; @@ -2656,7 +2685,7 @@ begin // Ðèñóåì èãðîêîâ: for a := 0 to High(gPlayers) do if gPlayers[a] <> nil then with gPlayers[a] do - if Live then begin + if alive then begin // Ëåâûé âåðõíèé óãîë: aX := Obj.X div ScaleSz + 1; aY := Obj.Y div ScaleSz + 1; @@ -2683,15 +2712,57 @@ begin end; +procedure renderAmbientQuad (hasAmbient: Boolean; constref ambColor: TDFColor); +begin + if not hasAmbient then exit; + e_AmbientQuad(sX, sY, sWidth, sHeight, ambColor.r, ambColor.g, ambColor.b, ambColor.a); +end; + + // setup sX, sY, sWidth, sHeight, and transformation matrix before calling this! +//FIXME: broken for splitscreen mode procedure renderDynLightsInternal (); var + //hasAmbient: Boolean; + //ambColor: TDFColor; lln: Integer; lx, ly, lrad: Integer; + scxywh: array[0..3] of GLint; + wassc: Boolean; begin + if e_NoGraphics then exit; + //TODO: lights should be in separate grid, i think // but on the other side: grid may be slower for dynlights, as their lifetime is short - if not gwin_has_stencil or (g_dynLightCount < 1) then exit; + if (not g_playerLight) or (not gwin_has_stencil) or (g_dynLightCount < 1) then exit; + + // rendering mode + //ambColor := gCurrentMap['light_ambient'].rgba; + //hasAmbient := (not ambColor.isOpaque) or (not ambColor.isBlack); + + { // this will multiply incoming color to alpha from framebuffer + glEnable(GL_BLEND); + glBlendFunc(GL_DST_ALPHA, GL_ONE); + } + + (* + * light rendering: (INVALID!) + * glStencilFunc(GL_EQUAL, 0, $ff); + * for each light: + * glClear(GL_STENCIL_BUFFER_BIT); + * glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); + * draw shadow volume into stencil buffer + * glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // modify color buffer + * glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // don't modify stencil buffer + * turn off blending + * draw color-less quad with light alpha (WARNING! don't touch color!) + * glEnable(GL_BLEND); + * glBlendFunc(GL_DST_ALPHA, GL_ONE); + * draw all geometry up to and including walls (with alpha-testing, probably) -- this does lighting + *) + + wassc := (glIsEnabled(GL_SCISSOR_TEST) <> 0); + if wassc then glGetIntegerv(GL_SCISSOR_BOX, @scxywh[0]) else glGetIntegerv(GL_VIEWPORT, @scxywh[0]); // setup OpenGL parameters glStencilMask($FFFFFFFF); @@ -2706,17 +2777,24 @@ begin lx := g_dynLights[lln].x; ly := g_dynLights[lln].y; lrad := g_dynLights[lln].radius; - if lrad < 3 then continue; + if (lrad < 3) then continue; - if lx-sX+lrad < 0 then continue; - if ly-sY+lrad < 0 then continue; - if lx-sX-lrad >= gPlayerScreenSize.X then continue; - if ly-sY-lrad >= gPlayerScreenSize.Y then continue; + if (lx-sX+lrad < 0) then continue; + if (ly-sY+lrad < 0) then continue; + if (lx-sX-lrad >= gPlayerScreenSize.X) then continue; + if (ly-sY-lrad >= gPlayerScreenSize.Y) then continue; // set scissor to optimize drawing - //FIXME: broken for splitscreen mode - glScissor((lx-sX)-lrad+2, gPlayerScreenSize.Y-(ly-sY)-lrad-1+2, lrad*2-4, lrad*2-4); - // no need to clear stencil buffer, light blitting will do it for us + if (g_dbg_scale = 1.0) then + begin + glScissor((lx-sX)-lrad+2, gPlayerScreenSize.Y-(ly-sY)-lrad-1+2, lrad*2-4, lrad*2-4); + end + else + begin + glScissor(0, 0, gWinSizeX, gWinSizeY); + end; + // no need to clear stencil buffer, light blitting will do it for us... but only for normal scale + if (g_dbg_scale <> 1.0) then glClear(GL_STENCIL_BUFFER_BIT); glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); // draw extruded panels glDisable(GL_TEXTURE_2D); @@ -2745,16 +2823,44 @@ begin glDisable(GL_STENCIL_TEST); glDisable(GL_BLEND); glDisable(GL_SCISSOR_TEST); - glScissor(0, 0, sWidth, sHeight); + //glScissor(0, 0, sWidth, sHeight); + + glScissor(scxywh[0], scxywh[1], scxywh[2], scxywh[3]); + if wassc then glEnable(GL_SCISSOR_TEST) else glDisable(GL_SCISSOR_TEST); +end; + + +function fixViewportForScale (): Boolean; +var + nx0, ny0, nw, nh: Integer; +begin + result := false; + if (g_dbg_scale <> 1.0) then + begin + result := true; + nx0 := round(sX-(gPlayerScreenSize.X-(sWidth*g_dbg_scale))/2/g_dbg_scale); + ny0 := round(sY-(gPlayerScreenSize.Y-(sHeight*g_dbg_scale))/2/g_dbg_scale); + nw := round(sWidth/g_dbg_scale); + nh := round(sHeight/g_dbg_scale); + sX := nx0; + sY := ny0; + sWidth := nw; + sHeight := nh; + end; end; // setup sX, sY, sWidth, sHeight, and transformation matrix before calling this! // WARNING! this WILL CALL `glTranslatef()`, but won't restore matrices! -procedure renderMapInternal (backXOfs, backYOfs: Integer; transX, transY: Integer; setTransMatrix: Boolean); +procedure renderMapInternal (backXOfs, backYOfs: Integer; setTransMatrix: Boolean); type TDrawCB = procedure (); +var + hasAmbient: Boolean; + ambColor: TDFColor; + doAmbient: Boolean = false; + procedure drawPanelType (profname: AnsiString; panType: DWord; doDraw: Boolean); var tagmask: Integer; @@ -2768,13 +2874,13 @@ type begin pan := TPanel(gDrawPanelList.front()); if ((pan.tag and tagmask) = 0) then break; - if doDraw then pan.Draw(); + if doDraw then pan.Draw(doAmbient, ambColor); gDrawPanelList.popFront(); end; end else begin - if doDraw then g_Map_DrawPanels(panType); + if doDraw then g_Map_DrawPanels(panType, hasAmbient, ambColor); end; profileFrameDraw.sectionEnd(); end; @@ -2802,7 +2908,27 @@ begin g_Map_DrawBack(backXOfs, backYOfs); profileFrameDraw.sectionEnd(); - if (setTransMatrix) then glTranslatef(transX, transY, 0); + if setTransMatrix then + begin + //if (g_dbg_scale <> 1.0) then glTranslatef(0.0, -0.375/2, 0); + glScalef(g_dbg_scale, g_dbg_scale, 1.0); + glTranslatef(-sX, -sY, 0); + end; + + // rendering mode + ambColor := gCurrentMap['light_ambient'].rgba; + hasAmbient := (not ambColor.isOpaque) or (not ambColor.isBlack); + + { + if hasAmbient then + begin + //writeln('color: (', ambColor.r, ',', ambColor.g, ',', ambColor.b, ',', ambColor.a, ')'); + glColor4ub(ambColor.r, ambColor.g, ambColor.b, ambColor.a); + glClear(GL_COLOR_BUFFER_BIT); + end; + } + //writeln('color: (', ambColor.r, ',', ambColor.g, ',', ambColor.b, ',', ambColor.a, ')'); + drawPanelType('*back', PANEL_BACK, g_rlayer_back); drawPanelType('*step', PANEL_STEP, g_rlayer_step); @@ -2820,8 +2946,16 @@ begin drawPanelType('*acid2', PANEL_ACID2, g_rlayer_acid2); drawPanelType('*water', PANEL_WATER, g_rlayer_water); drawOther('dynlights', @renderDynLightsInternal); + + if hasAmbient {and ((not g_playerLight) or (not gwin_has_stencil) or (g_dynLightCount < 1))} then + begin + renderAmbientQuad(hasAmbient, ambColor); + end; + + doAmbient := true; drawPanelType('*fore', PANEL_FORE, g_rlayer_fore); + if g_debug_HealthBar then begin g_Monsters_DrawHealth(); @@ -2847,7 +2981,8 @@ begin sWidth := w; sHeight := h; - renderMapInternal(-bx, -by, -x, -y, true); + fixViewportForScale(); + renderMapInternal(-bx, -by, true); glPopMatrix(); end; @@ -2857,7 +2992,6 @@ procedure DrawPlayer(p: TPlayer); var px, py, a, b, c, d: Integer; //R: TRect; - begin if (p = nil) or (p.FDummy) then begin @@ -2875,26 +3009,35 @@ begin glPushMatrix(); px := p.GameX + PLAYER_RECT_CX; - py := p.GameY + PLAYER_RECT_CY; + py := p.GameY + PLAYER_RECT_CY+p.Obj.slopeUpLeft; - if px > (gPlayerScreenSize.X div 2) then a := -px+(gPlayerScreenSize.X div 2) else a := 0; - if py > (gPlayerScreenSize.Y div 2) then b := -py+(gPlayerScreenSize.Y div 2) else b := 0; + if (g_dbg_scale = 1.0) then + begin + if (px > (gPlayerScreenSize.X div 2)) then a := -px+(gPlayerScreenSize.X div 2) else a := 0; + if (py > (gPlayerScreenSize.Y div 2)) then b := -py+(gPlayerScreenSize.Y div 2) else b := 0; - if px > gMapInfo.Width-(gPlayerScreenSize.X div 2) then a := -gMapInfo.Width+gPlayerScreenSize.X; - if py > gMapInfo.Height-(gPlayerScreenSize.Y div 2) then b := -gMapInfo.Height+gPlayerScreenSize.Y; + if (px > gMapInfo.Width-(gPlayerScreenSize.X div 2)) then a := -gMapInfo.Width+gPlayerScreenSize.X; + if (py > gMapInfo.Height-(gPlayerScreenSize.Y div 2)) then b := -gMapInfo.Height+gPlayerScreenSize.Y; - if (gMapInfo.Width = gPlayerScreenSize.X) then a := 0 - else if (gMapInfo.Width < gPlayerScreenSize.X) then - begin - // hcenter - a := (gPlayerScreenSize.X-gMapInfo.Width) div 2; - end; + if (gMapInfo.Width = gPlayerScreenSize.X) then a := 0 + else if (gMapInfo.Width < gPlayerScreenSize.X) then + begin + // hcenter + a := (gPlayerScreenSize.X-gMapInfo.Width) div 2; + end; - if (gMapInfo.Height = gPlayerScreenSize.Y) then b := 0 - else if (gMapInfo.Height < gPlayerScreenSize.Y) then + if (gMapInfo.Height = gPlayerScreenSize.Y) then b := 0 + else if (gMapInfo.Height < gPlayerScreenSize.Y) then + begin + // vcenter + b := (gPlayerScreenSize.Y-gMapInfo.Height) div 2; + end; + end + else begin - // vcenter - b := (gPlayerScreenSize.Y-gMapInfo.Height) div 2; + // scaled, ignore level bounds + a := -px+(gPlayerScreenSize.X div 2); + b := -py+(gPlayerScreenSize.Y div 2); end; if p.IncCam <> 0 then @@ -2941,17 +3084,17 @@ begin //glTranslatef(a, b+p.IncCam, 0); + if (p = gPlayer1) then g_Holmes_plrViewSize(sWidth, sHeight); + + fixViewportForScale(); p.viewPortX := sX; p.viewPortY := sY; p.viewPortW := sWidth; p.viewPortH := sHeight; - if (p = gPlayer1) then - begin - g_Holmes_plrView(p.viewPortX, p.viewPortY, p.viewPortW, p.viewPortH); - end; + if (p = gPlayer1) then g_Holmes_plrViewPos(sX, sY); - renderMapInternal(-c, -d, a, b+p.IncCam, true); + renderMapInternal(-c, -d, true); if p.FSpectator then e_TextureFontPrintEx(p.GameX + PLAYER_RECT_CX - 4, @@ -3211,16 +3354,26 @@ begin begin if (gState = STATE_MENU) then begin - if ((g_ActiveWindow = nil) or (g_ActiveWindow.BackTexture = '')) then + if (g_ActiveWindow = nil) or (g_ActiveWindow.BackTexture = '') then begin - if g_Texture_Get('MENU_BACKGROUND', ID) then - e_DrawSize(ID, 0, 0, 0, False, False, gScreenWidth, gScreenHeight) + if g_Texture_Get('MENU_BACKGROUND', ID) then e_DrawSize(ID, 0, 0, 0, False, False, gScreenWidth, gScreenHeight) else e_Clear(GL_COLOR_BUFFER_BIT, 0, 0, 0); end; - if g_ActiveWindow <> nil then + // F3 at menu will show game loading dialog + if e_KeyPressed(IK_F3) then g_Menu_Show_LoadMenu(true); + if (g_ActiveWindow <> nil) then begin //e_DrawFillQuad(0, 0, gScreenWidth-1, gScreenHeight-1, 48, 48, 48, 180); e_DarkenQuadWH(0, 0, gScreenWidth, gScreenHeight, 150); + end + else + begin + // F3 at titlepic will show game loading dialog + if e_KeyPressed(IK_F3) then + begin + g_Menu_Show_LoadMenu(true); + if (g_ActiveWindow <> nil) then e_DarkenQuadWH(0, 0, gScreenWidth, gScreenHeight, 150); + end; end; end; @@ -3971,7 +4124,7 @@ begin end; end; - ProcessLoading(); + ProcessLoading(true); e_PollInput(); @@ -4003,7 +4156,7 @@ begin g_Options_Write_Video(GameDir+'/'+CONFIG_FILENAME); end; -procedure g_Game_ChangeMap(MapPath: String); +procedure g_Game_ChangeMap(const MapPath: String); var Force: Boolean; begin @@ -4031,15 +4184,15 @@ begin MessageTime := 0; gGameOn := False; g_Game_ClearLoading(); - g_Game_StartMap(Map, True); + g_Game_StartMap(Map, True, gCurrentMapFileName); end; -function g_Game_StartMap(Map: String; Force: Boolean = False): Boolean; +function g_Game_StartMap(Map: String; Force: Boolean = False; const oldMapPath: AnsiString=''): Boolean; var NewWAD, ResName: String; I: Integer; begin - g_Map_Free(); + g_Map_Free((Map <> gCurrentMapFileName) and (oldMapPath <> gCurrentMapFileName)); g_Player_RemoveAllCorpses(); if (not g_Game_IsClient) and @@ -4055,7 +4208,7 @@ begin g_Player_ResetTeams(); - if Pos(':\', Map) > 0 then + if isWadPath(Map) then begin NewWAD := g_ExtractWadName(Map); ResName := g_ExtractFileName(Map); @@ -4187,7 +4340,7 @@ begin MapList := nil; end; -procedure g_Game_ExitLevel(Map: Char16); +procedure g_Game_ExitLevel(const Map: AnsiString); begin gNextMap := Map; @@ -4422,7 +4575,7 @@ end; procedure g_Game_DeleteTestMap(); var a: Integer; - MapName: Char16; + //MapName: AnsiString; WadName: string; { WAD: TWADFile; @@ -4430,16 +4583,16 @@ var time: Integer; } begin - a := Pos('.wad:\', gMapToDelete); - if a = 0 then - Exit; + a := Pos('.wad:\', toLowerCase1251(gMapToDelete)); + if (a = 0) then a := Pos('.wad:/', toLowerCase1251(gMapToDelete)); + if (a = 0) then exit; -// Âûäåëÿåì èìÿ wad-ôàéëà è èìÿ êàðòû: - WadName := Copy(gMapToDelete, 1, a + 3); - Delete(gMapToDelete, 1, a + 5); + // Âûäåëÿåì èìÿ wad-ôàéëà è èìÿ êàðòû + WadName := Copy(gMapToDelete, 1, a+3); + Delete(gMapToDelete, 1, a+5); gMapToDelete := UpperCase(gMapToDelete); - MapName := ''; - CopyMemory(@MapName[0], @gMapToDelete[1], Min(16, Length(gMapToDelete))); + //MapName := ''; + //CopyMemory(@MapName[0], @gMapToDelete[1], Min(16, Length(gMapToDelete))); { // Èìÿ êàðòû íå ñòàíäàðòíîå òåñòîâîå: @@ -5078,18 +5231,18 @@ begin end else if cmd = 'd_monster' then begin - if gGameOn and (gPlayer1 <> nil) and (gPlayer1.Live) and (not g_Game_IsNet) then + if gGameOn and (gPlayer1 <> nil) and (gPlayer1.alive) and (not g_Game_IsNet) then if Length(P) < 2 then begin g_Console_Add(cmd + ' [ID | Name] [behaviour]'); g_Console_Add('ID | Name'); for b := MONSTER_DEMON to MONSTER_MAN do - g_Console_Add(Format('%2d | %s', [b, g_Monsters_GetNameByID(b)])); + g_Console_Add(Format('%2d | %s', [b, g_Mons_NameByTypeId(b)])); end else begin a := StrToIntDef(P[1], 0); if (a < MONSTER_DEMON) or (a > MONSTER_MAN) then - a := g_Monsters_GetIDByName(P[1]); + a := g_Mons_TypeIdByName(P[1]); if (a < MONSTER_DEMON) or (a > MONSTER_MAN) then g_Console_Add(Format(_lc[I_MSG_NO_MONSTER], [P[1]])) @@ -5179,7 +5332,8 @@ begin begin g_Console_Add('player left the map'); gExitByTrigger := True; - g_Game_ExitLevel(gTriggers[a].Data.MapName); + //g_Game_ExitLevel(gTriggers[a].Data.MapName); + g_Game_ExitLevel(gTriggers[a].tgcMap); break; end; end; @@ -6048,14 +6202,15 @@ begin if gTriggers[a].TriggerType = TRIGGER_EXIT then begin gExitByTrigger := True; - gNextMap := gTriggers[a].Data.MapName; + //gNextMap := gTriggers[a].Data.MapName; + gNextMap := gTriggers[a].tgcMap; Break; end; // Èùåì ñëåäóþùóþ êàðòó â WAD ôàéëå if gNextMap = '' then gNextMap := g_Game_GetNextMap(); // Ïðîâåðÿåì, íå çàäàí ëè WAD ôàéë ðåñóðñíîé ñòðîêîé - if Pos(':\', gNextMap) = 0 then + if not isWadPath(gNextMap) then s := gGameSettings.WAD + ':\' + gNextMap else s := gNextMap; @@ -6101,6 +6256,21 @@ begin Exit; end; end + else if cmd = 'suicide' then + begin + if gGameOn then + begin + if g_Game_IsClient then + MC_SEND_CheatRequest(NET_CHEAT_SUICIDE) + else + begin + if gPlayer1 <> nil then + gPlayer1.Damage(SUICIDE_DAMAGE, gPlayer1.UID, 0, 0, HIT_SELF); + if gPlayer2 <> nil then + gPlayer2.Damage(SUICIDE_DAMAGE, gPlayer2.UID, 0, 0, HIT_SELF); + end; + end; + end // Êîìàíäû Ñâîåé èãðû: else if gGameSettings.GameType in [GT_CUSTOM, GT_SERVER, GT_CLIENT] then begin @@ -6118,21 +6288,6 @@ begin else g_Bot_Add(TEAM_BLUE, 2); end - else if cmd = 'suicide' then - begin - if gGameOn then - begin - if g_Game_IsClient then - MC_SEND_CheatRequest(NET_CHEAT_SUICIDE) - else - begin - if gPlayer1 <> nil then - gPlayer1.Damage(SUICIDE_DAMAGE, gPlayer1.UID, 0, 0, HIT_SELF); - if gPlayer2 <> nil then - gPlayer2.Damage(SUICIDE_DAMAGE, gPlayer2.UID, 0, 0, HIT_SELF); - end; - end; - end else if cmd = 'spectate' then begin if not gGameOn then @@ -6439,17 +6594,17 @@ begin with gTriggers[i] do if (TriggerType = TRIGGER_SOUND) and (Sound <> nil) and - (Data.Local) and + (tgcLocal) and Sound.IsPlaying() then begin if ((gPlayer1 <> nil) and g_CollidePoint(gPlayer1.GameX, gPlayer1.GameY, X, Y, Width, Height)) or ((gPlayer2 <> nil) and g_CollidePoint(gPlayer2.GameX, gPlayer2.GameY, X, Y, Width, Height)) then begin - Sound.SetPan(0.5 - Data.Pan/255.0); - Sound.SetVolume(Data.Volume/255.0); + Sound.SetPan(0.5 - tgcPan/255.0); + Sound.SetVolume(tgcVolume/255.0); end else - Sound.SetCoords(X+(Width div 2), Y+(Height div 2), Data.Volume/255.0); + Sound.SetCoords(X+(Width div 2), Y+(Height div 2), tgcVolume/255.0); end; end; @@ -6737,7 +6892,7 @@ begin g_ActiveWindow := nil; - ProcessLoading; + ProcessLoading(true); end; procedure g_Game_StepLoading(); @@ -6749,7 +6904,7 @@ begin if (ShowCount > LOADING_SHOW_STEP) then begin ShowCount := 0; - ProcessLoading; + ProcessLoading(); end; end; end; @@ -6956,7 +7111,7 @@ begin s := Find_Param_Value(pars, '-exec'); if s <> '' then begin - if Pos(':\', s) = 0 then + if not isWadPath(s) then s := GameDir + '/' + s; {$I-} @@ -7011,4 +7166,6 @@ begin conRegVar('mon_think', @gmon_debug_think, 'enable/disable monster thinking', 'monster thinking', true); conRegVar('dbg_holmes', @g_holmes_enabled, 'enable/disable Holmes', 'Holmes', true); + + conRegVar('dbg_scale', @g_dbg_scale, 0.01, 100.0, 'experimental deBUG scale mode', '', false); end.