X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_holmes.pas;h=3a50ffaba189b0355483ab7aa86d5eb26f4a009a;hb=9ab8e0d74b399aad6fd4793f427503bb857a4236;hp=39669fa1d8dd922c7a08c7cc2ed3080993c94137;hpb=966e88968e6a2ba968187fe82144874aae35d02a;p=d2df-sdl.git diff --git a/src/game/g_holmes.pas b/src/game/g_holmes.pas index 39669fa..3a50ffa 100644 --- a/src/game/g_holmes.pas +++ b/src/game/g_holmes.pas @@ -76,8 +76,9 @@ procedure g_Holmes_WindowFocused (); procedure g_Holmes_WindowBlured (); procedure g_Holmes_Draw (); +procedure g_Holmes_DrawUI (); -function g_Holmes_mouseEvent (var ev: THMouseEvent): Boolean; // returns `true` if event was eaten +function g_Holmes_MouseEvent (var ev: THMouseEvent): Boolean; // returns `true` if event was eaten function g_Holmes_KeyEvent (var ev: THKeyEvent): Boolean; // returns `true` if event was eaten // hooks for player @@ -102,11 +103,93 @@ var msY: Integer = -666; msB: Word = 0; // button state kbS: Word = 0; // keyboard modifiers state + showGrid: Boolean = true; showMonsInfo: Boolean = false; + showMonsLOS2Plr: Boolean = false; + showAllMonsCells: Boolean = false; + showMapCurPos: Boolean = false; // ////////////////////////////////////////////////////////////////////////// // {$INCLUDE g_holmes.inc} +{$INCLUDE g_holmes_ui.inc} + + +// ////////////////////////////////////////////////////////////////////////// // +var + g_ol_nice: Boolean = false; + g_ol_rlayer_back: Boolean = false; + g_ol_rlayer_step: Boolean = false; + g_ol_rlayer_wall: Boolean = false; + g_ol_rlayer_door: Boolean = false; + g_ol_rlayer_acid1: Boolean = false; + g_ol_rlayer_acid2: Boolean = false; + g_ol_rlayer_water: Boolean = false; + g_ol_rlayer_fore: Boolean = false; + + +// ////////////////////////////////////////////////////////////////////////// // +var + winOptions: THTopWindow = nil; + winLayers: THTopWindow = nil; + winOutlines: THTopWindow = nil; + + +procedure createOptionsWindow (); +var + llb: THCtlCBListBox; +begin + llb := THCtlCBListBox.Create(0, 0); + llb.appendItem('map grid', @showGrid); + llb.appendItem('cursor position on map', @showMapCurPos); + llb.appendItem('monster info', @showMonsInfo); + llb.appendItem('monster LOS to player', @showMonsLOS2Plr); + llb.appendItem('monster cells (SLOW!)', @showAllMonsCells); + winOptions := THTopWindow.Create('Holmes Options', 100, 100); + winOptions.escClose := true; + winOptions.appendChild(llb); +end; + + +procedure createLayersWindow (); +var + llb: THCtlCBListBox; +begin + llb := THCtlCBListBox.Create(0, 0); + llb.appendItem('background', @g_rlayer_back); + llb.appendItem('steps', @g_rlayer_step); + llb.appendItem('walls', @g_rlayer_wall); + llb.appendItem('doors', @g_rlayer_door); + llb.appendItem('acid1', @g_rlayer_acid1); + llb.appendItem('acid2', @g_rlayer_acid2); + llb.appendItem('water', @g_rlayer_water); + llb.appendItem('foreground', @g_rlayer_fore); + winLayers := THTopWindow.Create('visible', 10, 10); + winLayers.escClose := true; + winLayers.appendChild(llb); +end; + + +procedure createOutlinesWindow (); +var + llb: THCtlCBListBox; +begin + llb := THCtlCBListBox.Create(0, 0); + llb.appendItem('background', @g_ol_rlayer_back); + llb.appendItem('steps', @g_ol_rlayer_step); + llb.appendItem('walls', @g_ol_rlayer_wall); + llb.appendItem('doors', @g_ol_rlayer_door); + llb.appendItem('acid1', @g_ol_rlayer_acid1); + llb.appendItem('acid2', @g_ol_rlayer_acid2); + llb.appendItem('water', @g_ol_rlayer_water); + llb.appendItem('foreground', @g_ol_rlayer_fore); + llb.appendItem('', nil); + llb.appendItem('slow''n''nice', @g_ol_nice); + winOutlines := THTopWindow.Create('outlines', 100, 10); + winOutlines.escClose := true; + winOutlines.appendChild(llb); +end; + // ////////////////////////////////////////////////////////////////////////// // procedure g_Holmes_VidModeChanged (); @@ -141,6 +224,7 @@ var laserX0, laserY0, laserX1, laserY1: Integer; monMarkedUID: Integer = -1; + procedure g_Holmes_plrView (viewPortX, viewPortY, viewPortW, viewPortH: Integer); begin vpSet := true; @@ -157,6 +241,7 @@ begin laserY0 := ay0; laserX1 := ax1; laserY1 := ay1; + laserSet := laserSet; // shut up, fpc! end; @@ -169,7 +254,11 @@ procedure plrDebugMouse (var ev: THMouseEvent); function wallToggle (pan: TPanel; tag: Integer): Boolean; begin result := false; // don't stop - if pan.Enabled then g_Map_DisableWall(pan.arrIdx) else g_Map_EnableWall(pan.arrIdx); + e_WriteLog(Format('wall #%d(%d); enabled=%d (%d); (%d,%d)-(%d,%d)', [pan.arrIdx, pan.proxyId, Integer(pan.Enabled), Integer(mapGrid.proxyEnabled[pan.proxyId]), pan.X, pan.Y, pan.Width, pan.Height]), MSG_NOTIFY); + if ((kbS and THKeyEvent.ModAlt) <> 0) then + begin + if pan.Enabled then g_Map_DisableWall(pan.arrIdx) else g_Map_EnableWall(pan.arrIdx); + end; end; function monsAtDump (mon: TMonster; tag: Integer): Boolean; @@ -188,9 +277,11 @@ procedure plrDebugMouse (var ev: THMouseEvent); begin //e_WriteLog(Format('mouse: x=%d; y=%d; but=%d; bstate=%d', [msx, msy, but, bstate]), MSG_NOTIFY); - if (gPlayer1 = nil) then exit; + if (gPlayer1 = nil) or not vpSet then exit; if (ev.kind <> THMouseEvent.Press) then exit; + e_WriteLog(Format('mev: %d', [Integer(ev.kind)]), MSG_NOTIFY); + if (ev.but = THMouseEvent.Left) then begin if ((kbS and THKeyEvent.ModShift) <> 0) then @@ -203,7 +294,9 @@ begin else begin // toggle wall + e_WriteLog('=== TOGGLE WALL ===', MSG_NOTIFY); mapGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY, wallToggle, (GridTagWall or GridTagDoor)); + e_WriteLog('--- toggle wall ---', MSG_NOTIFY); end; exit; end; @@ -219,27 +312,31 @@ begin end; +var + olEdgeL: array of Boolean = nil; + olEdgeR: array of Boolean = nil; + olEdgeU: array of Boolean = nil; + olEdgeD: array of Boolean = nil; + +procedure drawOutlines (); +begin +end; + + procedure plrDebugDraw (); procedure drawTileGrid (); var x, y: Integer; begin - y := mapGrid.gridY0; - while (y < mapGrid.gridY0+mapGrid.gridHeight) do + for y := 0 to (mapGrid.gridHeight div mapGrid.tileSize) do begin - x := mapGrid.gridX0; - while (x < mapGrid.gridX0+mapGrid.gridWidth) do - begin - if (x+mapGrid.tileSize > vpx) and (y+mapGrid.tileSize > vpy) and - (x < vpx+vpw) and (y < vpy+vph) then - begin - //e_DrawQuad(x, y, x+mapGrid.tileSize-1, y+mapGrid.tileSize-1, 96, 96, 96, 96); - drawRect(x, y, mapGrid.tileSize, mapGrid.tileSize, 96, 96, 96, 255); - end; - Inc(x, mapGrid.tileSize); - end; - Inc(y, mapGrid.tileSize); + drawLine(mapGrid.gridX0, mapGrid.gridY0+y*mapGrid.tileSize, mapGrid.gridX0+mapGrid.gridWidth, mapGrid.gridY0+y*mapGrid.tileSize, 96, 96, 96, 255); + end; + + for x := 0 to (mapGrid.gridWidth div mapGrid.tileSize) do + begin + drawLine(mapGrid.gridX0+x*mapGrid.tileSize, mapGrid.gridY0, mapGrid.gridX0+x*mapGrid.tileSize, mapGrid.gridY0+y*mapGrid.gridHeight, 96, 96, 96, 255); end; end; @@ -248,6 +345,20 @@ procedure plrDebugDraw (); fillRect(cx, cy, monsGrid.tileSize, monsGrid.tileSize, 0, 128, 0, 64); end; + procedure hilightCell1 (cx, cy: Integer); + begin + //e_WriteLog(Format('h1: (%d,%d)', [cx, cy]), MSG_NOTIFY); + fillRect(cx, cy, monsGrid.tileSize, monsGrid.tileSize, 255, 255, 0, 92); + end; + + function hilightWallTrc (pan: TPanel; tag: Integer; x, y, prevx, prevy: Integer): Boolean; + begin + result := false; // don't stop + if (pan = nil) then exit; // cell completion, ignore + //e_WriteLog(Format('h1: (%d,%d)', [cx, cy]), MSG_NOTIFY); + fillRect(pan.X, pan.Y, pan.Width, pan.Height, 0, 128, 128, 64); + end; + function monsCollector (mon: TMonster; tag: Integer): Boolean; var ex, ey: Integer; @@ -288,13 +399,37 @@ procedure plrDebugDraw (); exit; end; mon.getMapBox(mx, my, mw, mh); - drawLine(mx+mw div 2, my+mh div 2, emx+emw div 2, emy+emh div 2, 255, 0, 0, 128); + drawLine(mx+mw div 2, my+mh div 2, emx+emw div 2, emy+emh div 2, 255, 0, 0, 255); if (g_Map_traceToNearestWall(mx+mw div 2, my+mh div 2, emx+emw div 2, emy+emh div 2, @ex, @ey) <> nil) then begin - drawLine(mx+mw div 2, my+mh div 2, ex, ey, 0, 255, 0, 128); + drawLine(mx+mw div 2, my+mh div 2, ex, ey, 0, 255, 0, 255); end; end; + procedure drawLOS2Plr (); + var + emx, emy, emw, emh: Integer; + eplr: TPlayer; + ex, ey: Integer; + begin + eplr := gPlayers[0]; + if (eplr = nil) then exit; + eplr.getMapBox(emx, emy, emw, emh); + mon.getMapBox(mx, my, mw, mh); + drawLine(mx+mw div 2, my+mh div 2, emx+emw div 2, emy+emh div 2, 255, 0, 0, 255); + {$IF DEFINED(D2F_DEBUG)} + //mapGrid.dbgRayTraceTileHitCB := hilightCell1; + {$ENDIF} + if (g_Map_traceToNearestWall(mx+mw div 2, my+mh div 2, emx+emw div 2, emy+emh div 2, @ex, @ey) <> nil) then + //if (mapGrid.traceRay(ex, ey, mx+mw div 2, my+mh div 2, emx+emw div 2, emy+emh div 2, hilightWallTrc, (GridTagWall or GridTagDoor)) <> nil) then + begin + drawLine(mx+mw div 2, my+mh div 2, ex, ey, 0, 255, 0, 255); + end; + {$IF DEFINED(D2F_DEBUG)} + //mapGrid.dbgRayTraceTileHitCB := nil; + {$ENDIF} + end; + begin if (mon = nil) then exit; mon.getMapBox(mx, my, mw, mh); @@ -305,7 +440,7 @@ procedure plrDebugDraw (); if showMonsInfo then begin //fillRect(mx-4, my-7*8-6, 110, 7*8+6, 0, 0, 94, 250); - shadeRect(mx-4, my-7*8-6, 110, 7*8+6, 128); + darkenRect(mx-4, my-7*8-6, 110, 7*8+6, 128); my -= 8; my -= 2; @@ -325,6 +460,7 @@ procedure plrDebugDraw (); end; drawMonsterTargetLine(); + if showMonsLOS2Plr then drawLOS2Plr(); { property MonsterRemoved: Boolean read FRemoved write FRemoved; property MonsterPain: Integer read FPain write FPain; @@ -332,21 +468,29 @@ procedure plrDebugDraw (); } end; + function highlightAllMonsterCells (mon: TMonster): Boolean; + begin + result := false; // don't stop + monsGrid.forEachBodyCell(mon.proxyId, hilightCell); + end; + var mon: TMonster; mx, my, mw, mh: Integer; begin - //e_DrawPoint(4, plrMouseX, plrMouseY, 255, 0, 255); if (gPlayer1 = nil) then exit; - //e_WriteLog(Format('(%d,%d)-(%d,%d)', [laserX0, laserY0, laserX1, laserY1]), MSG_NOTIFY); + glEnable(GL_SCISSOR_TEST); + glScissor(0, gWinSizeY-gPlayerScreenSize.Y-1, vpw, vph); glPushMatrix(); glTranslatef(-vpx, -vpy, 0); - drawTileGrid(); + drawOutlines(); - g_Mons_AlongLine(laserX0, laserY0, laserX1, laserY1, monsCollector, true); + if (showGrid) then drawTileGrid(); + + if (laserSet) then g_Mons_AlongLine(laserX0, laserY0, laserX1, laserY1, monsCollector, true); if (monMarkedUID <> -1) then begin @@ -359,25 +503,41 @@ begin end; end; - //e_DrawPoint(16, laserX0, laserY0, 255, 255, 255); + if showAllMonsCells then g_Mons_ForEach(highlightAllMonsterCells); glPopMatrix(); + + glDisable(GL_SCISSOR_TEST); + + if showMapCurPos then drawText8(4, gWinSizeY-10, Format('mappos:(%d,%d)', [pmsCurMapX, pmsCurMapY]), 255, 255, 0); end; // ////////////////////////////////////////////////////////////////////////// // -function g_Holmes_mouseEvent (var ev: THMouseEvent): Boolean; +function g_Holmes_MouseEvent (var ev: THMouseEvent): Boolean; begin result := true; msX := ev.x; msY := ev.y; msB := ev.bstate; kbS := ev.kstate; - plrDebugMouse(ev); + msB := msB; + if not uiMouseEvent(ev) then plrDebugMouse(ev); end; function g_Holmes_KeyEvent (var ev: THKeyEvent): Boolean; +var + mon: TMonster; + pan: TPanel; + x, y, w, h: Integer; + ex, ey: Integer; + dx, dy: Integer; + + procedure dummyWallTrc (cx, cy: Integer); + begin + end; + begin result := false; msB := ev.bstate; @@ -388,6 +548,7 @@ begin SDL_SCANCODE_LSHIFT, SDL_SCANCODE_RSHIFT: result := true; end; + if uiKeyEvent(ev) then begin result := true; exit; end; // press if (ev.kind = THKeyEvent.Press) then begin @@ -406,6 +567,106 @@ begin showMonsInfo := not showMonsInfo; exit; end; + // M-L: toggle monster LOS to player + if (ev.scan = SDL_SCANCODE_L) and ((ev.kstate and THKeyEvent.ModAlt) <> 0) then + begin + result := true; + showMonsLOS2Plr := not showMonsLOS2Plr; + exit; + end; + // M-G: toggle "show all cells occupied by monsters" + if (ev.scan = SDL_SCANCODE_G) and ((ev.kstate and THKeyEvent.ModAlt) <> 0) then + begin + result := true; + showAllMonsCells := not showAllMonsCells; + exit; + end; + // M-A: wake up monster + if (ev.scan = SDL_SCANCODE_A) and ((ev.kstate and THKeyEvent.ModAlt) <> 0) then + begin + result := true; + if (monMarkedUID <> -1) then + begin + mon := g_Monsters_ByUID(monMarkedUID); + if (mon <> nil) then mon.WakeUp(); + end; + exit; + end; + // C-T: teleport player + if (ev.scan = SDL_SCANCODE_T) and ((ev.kstate and THKeyEvent.ModCtrl) <> 0) then + begin + result := true; + //e_WriteLog(Format('TELEPORT: (%d,%d)', [pmsCurMapX, pmsCurMapY]), MSG_NOTIFY); + if (gPlayers[0] <> nil) then + begin + gPlayers[0].getMapBox(x, y, w, h); + gPlayers[0].TeleportTo(pmsCurMapX-w div 2, pmsCurMapY-h div 2, true, 69); // 69: don't change dir + end; + exit; + end; + // C-P: show cursor position on the map + if (ev.scan = SDL_SCANCODE_P) and ((ev.kstate and THKeyEvent.ModCtrl) <> 0) then + begin + result := true; + showMapCurPos := not showMapCurPos; + exit; + end; + // C-G: toggle grid + if (ev.scan = SDL_SCANCODE_G) and ((ev.kstate and THKeyEvent.ModCtrl) <> 0) then + begin + result := true; + showGrid := not showGrid; + exit; + end; + // C-L: toggle layers window + if (ev.scan = SDL_SCANCODE_L) and ((ev.kstate and THKeyEvent.ModCtrl) <> 0) then + begin + result := true; + if (winLayers = nil) then createLayersWindow(); + if not uiVisibleWindow(winLayers) then uiAddWindow(winLayers) else uiRemoveWindow(winLayers); + exit; + end; + // C-O: toggle outlines window + if (ev.scan = SDL_SCANCODE_O) and ((ev.kstate and THKeyEvent.ModCtrl) <> 0) then + begin + result := true; + if (winOutlines = nil) then createOutlinesWindow(); + if not uiVisibleWindow(winOutlines) then uiAddWindow(winOutlines) else uiRemoveWindow(winOutlines); + exit; + end; + // F1: toggle options window + if (ev.scan = SDL_SCANCODE_F1) and (ev.kstate = 0) then + begin + result := true; + if (winOptions = nil) then createOptionsWindow(); + if not uiVisibleWindow(winOptions) then uiAddWindow(winOptions) else uiRemoveWindow(winOptions); + exit; + end; + // C-UP, C-DOWN, C-LEFT, C-RIGHT: trace 10 pixels from cursor in the respective direction + if ((ev.scan = SDL_SCANCODE_UP) or (ev.scan = SDL_SCANCODE_DOWN) or (ev.scan = SDL_SCANCODE_LEFT) or (ev.scan = SDL_SCANCODE_RIGHT)) and + ((ev.kstate and THKeyEvent.ModCtrl) <> 0) then + begin + result := true; + dx := pmsCurMapX; + dy := pmsCurMapY; + case ev.scan of + SDL_SCANCODE_UP: dy -= 120; + SDL_SCANCODE_DOWN: dy += 120; + SDL_SCANCODE_LEFT: dx -= 120; + SDL_SCANCODE_RIGHT: dx += 120; + end; + {$IF DEFINED(D2F_DEBUG)} + //mapGrid.dbgRayTraceTileHitCB := dummyWallTrc; + mapGrid.dbgShowTraceLog := true; + {$ENDIF} + pan := g_Map_traceToNearest(pmsCurMapX, pmsCurMapY, dx, dy, (GridTagWall or GridTagDoor or GridTagStep or GridTagAcid1 or GridTagAcid2 or GridTagWater), @ex, @ey); + {$IF DEFINED(D2F_DEBUG)} + //mapGrid.dbgRayTraceTileHitCB := nil; + mapGrid.dbgShowTraceLog := false; + {$ENDIF} + e_LogWritefln('v-trace: (%d,%d)-(%d,%d); end=(%d,%d); hit=%d', [pmsCurMapX, pmsCurMapY, dx, dy, ex, ey, (pan <> nil)]); + exit; + end; end; end; @@ -424,9 +685,13 @@ begin plrDebugDraw(); end; - //drawText6Prop(10, 10, 'Hi there, I''m Holmes!', 255, 255, 0); - //drawText8Prop(10, 20, 'Hi there, I''m Holmes!', 255, 255, 0); + laserSet := false; +end; + +procedure g_Holmes_DrawUI (); +begin + uiDraw(); drawCursor(); end;