1 (* Copyright (C) DooM 2D:Forever Developers
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 {$INCLUDE ../shared/a_modes.inc}
23 g_textures
, g_basic
, e_graphics
, g_phys
, g_grid
, g_player
, g_monsters
,
24 g_window
, g_map
, g_triggers
, g_items
, g_game
, g_panel
, g_console
,
32 // both for but and for bstate
45 kind
: Byte; // motion, press, release
47 dx
, dy
: Integer; // for wheel this is wheel motion, otherwise this is relative mouse motion
48 but
: Word; // current pressed/released button, or 0 for motion
49 bstate
: Word; // button state
50 kstate
: Word; // keyboard state (see THKeyEvent);
67 scan
: Word; // SDL_SCANCODE_XXX
68 sym
: Word; // SDLK_XXX
69 bstate
: Word; // button state
70 kstate
: Word; // keyboard state
74 procedure g_Holmes_VidModeChanged ();
75 procedure g_Holmes_WindowFocused ();
76 procedure g_Holmes_WindowBlured ();
78 procedure g_Holmes_Draw ();
80 function g_Holmes_mouseEvent (var ev
: THMouseEvent
): Boolean; // returns `true` if event was eaten
81 function g_Holmes_KeyEvent (var ev
: THKeyEvent
): Boolean; // returns `true` if event was eaten
84 procedure g_Holmes_plrView (viewPortX
, viewPortY
, viewPortW
, viewPortH
: Integer);
85 procedure g_Holmes_plrLaser (ax0
, ay0
, ax1
, ay1
: Integer);
89 g_holmes_enabled
: Boolean = {$IF DEFINED(D2F_DEBUG)}true{$ELSE}false{$ENDIF};
100 //globalInited: Boolean = false;
103 msB
: Word = 0; // button state
104 kbS
: Word = 0; // keyboard modifiers state
105 showMonsInfo
: Boolean = false;
106 showMonsLOS2Plr
: Boolean = false;
107 showAllMonsCells
: Boolean = false;
110 // ////////////////////////////////////////////////////////////////////////// //
111 {$INCLUDE g_holmes.inc}
113 // ////////////////////////////////////////////////////////////////////////// //
114 procedure g_Holmes_VidModeChanged ();
116 e_WriteLog(Format('Inspector: videomode changed: %dx%d', [gScreenWidth
, gScreenHeight
]), MSG_NOTIFY
);
117 // texture space is possibly lost here, idc
123 //createCursorTexture();
126 procedure g_Holmes_WindowFocused ();
132 procedure g_Holmes_WindowBlured ();
137 // ////////////////////////////////////////////////////////////////////////// //
139 vpSet
: Boolean = false;
142 laserSet
: Boolean = false;
143 laserX0
, laserY0
, laserX1
, laserY1
: Integer;
144 monMarkedUID
: Integer = -1;
146 procedure g_Holmes_plrView (viewPortX
, viewPortY
, viewPortW
, viewPortH
: Integer);
155 procedure g_Holmes_plrLaser (ax0
, ay0
, ax1
, ay1
: Integer);
165 function pmsCurMapX (): Integer; inline; begin result
:= msX
+vpx
; end;
166 function pmsCurMapY (): Integer; inline; begin result
:= msY
+vpy
; end;
169 procedure plrDebugMouse (var ev
: THMouseEvent
);
171 function wallToggle (pan
: TPanel
; tag
: Integer): Boolean;
173 result
:= false; // don't stop
174 if pan
.Enabled
then g_Map_DisableWall(pan
.arrIdx
) else g_Map_EnableWall(pan
.arrIdx
);
177 function monsAtDump (mon
: TMonster
; tag
: Integer): Boolean;
179 result
:= false; // don't stop
180 e_WriteLog(Format('monster #%d; UID=%d', [mon
.arrIdx
, mon
.UID
]), MSG_NOTIFY
);
181 monMarkedUID
:= mon
.UID
;
182 //if pan.Enabled then g_Map_DisableWall(pan.arrIdx) else g_Map_EnableWall(pan.arrIdx);
185 function monsInCell (mon
: TMonster
; tag
: Integer): Boolean;
187 result
:= false; // don't stop
188 e_WriteLog(Format('monster #%d (UID:%u) (proxyid:%d)', [mon
.arrIdx
, mon
.UID
, mon
.proxyId
]), MSG_NOTIFY
);
192 //e_WriteLog(Format('mouse: x=%d; y=%d; but=%d; bstate=%d', [msx, msy, but, bstate]), MSG_NOTIFY);
193 if (gPlayer1
= nil) then exit
;
194 if (ev
.kind
<> THMouseEvent
.Press
) then exit
;
196 if (ev
.but
= THMouseEvent
.Left
) then
198 if ((kbS
and THKeyEvent
.ModShift
) <> 0) then
200 // dump monsters in cell
201 e_WriteLog('===========================', MSG_NOTIFY
);
202 monsGrid
.forEachInCell(pmsCurMapX
, pmsCurMapY
, monsInCell
);
203 e_WriteLog('---------------------------', MSG_NOTIFY
);
208 mapGrid
.forEachAtPoint(pmsCurMapX
, pmsCurMapY
, wallToggle
, (GridTagWall
or GridTagDoor
));
213 if (ev
.but
= THMouseEvent
.Right
) then
216 e_WriteLog('===========================', MSG_NOTIFY
);
217 monsGrid
.forEachAtPoint(pmsCurMapX
, pmsCurMapY
, monsAtDump
);
218 e_WriteLog('---------------------------', MSG_NOTIFY
);
224 procedure plrDebugDraw ();
226 procedure drawTileGrid ();
231 while (y
< mapGrid
.gridY0
+mapGrid
.gridHeight
) do
234 while (x
< mapGrid
.gridX0
+mapGrid
.gridWidth
) do
236 if (x
+mapGrid
.tileSize
> vpx
) and (y
+mapGrid
.tileSize
> vpy
) and
237 (x
< vpx
+vpw
) and (y
< vpy
+vph
) then
239 //e_DrawQuad(x, y, x+mapGrid.tileSize-1, y+mapGrid.tileSize-1, 96, 96, 96, 96);
240 drawRect(x
, y
, mapGrid
.tileSize
, mapGrid
.tileSize
, 96, 96, 96, 255);
242 Inc(x
, mapGrid
.tileSize
);
244 Inc(y
, mapGrid
.tileSize
);
248 procedure hilightCell (cx
, cy
: Integer);
250 fillRect(cx
, cy
, monsGrid
.tileSize
, monsGrid
.tileSize
, 0, 128, 0, 64);
253 procedure hilightCell1 (cx
, cy
: Integer);
255 //e_WriteLog(Format('h1: (%d,%d)', [cx, cy]), MSG_NOTIFY);
256 fillRect(cx
, cy
, monsGrid
.tileSize
, monsGrid
.tileSize
, 255, 255, 0, 92);
259 function hilightWallTrc (pan
: TPanel
; tag
: Integer; x
, y
, prevx
, prevy
: Integer): Boolean;
261 result
:= false; // don't stop
262 if (pan
= nil) then exit
; // cell completion, ignore
263 //e_WriteLog(Format('h1: (%d,%d)', [cx, cy]), MSG_NOTIFY);
264 fillRect(pan
.X
, pan
.Y
, pan
.Width
, pan
.Height
, 0, 128, 128, 64);
267 function monsCollector (mon
: TMonster
; tag
: Integer): Boolean;
270 mx
, my
, mw
, mh
: Integer;
273 mon
.getMapBox(mx
, my
, mw
, mh
);
274 e_DrawQuad(mx
, my
, mx
+mw
-1, my
+mh
-1, 255, 255, 0, 96);
275 if lineAABBIntersects(laserX0
, laserY0
, laserX1
, laserY1
, mx
, my
, mw
, mh
, ex
, ey
) then
277 e_DrawPoint(8, ex
, ey
, 0, 255, 0);
281 procedure drawMonsterInfo (mon
: TMonster
);
283 mx
, my
, mw
, mh
: Integer;
285 procedure drawMonsterTargetLine ();
287 emx
, emy
, emw
, emh
: Integer;
292 if (g_GetUIDType(mon
.MonsterTargetUID
) = UID_PLAYER
) then
294 eplr
:= g_Player_Get(mon
.MonsterTargetUID
);
295 if (eplr
<> nil) then eplr
.getMapBox(emx
, emy
, emw
, emh
) else exit
;
297 else if (g_GetUIDType(mon
.MonsterTargetUID
) = UID_MONSTER
) then
299 enemy
:= g_Monsters_ByUID(mon
.MonsterTargetUID
);
300 if (enemy
<> nil) then enemy
.getMapBox(emx
, emy
, emw
, emh
) else exit
;
306 mon
.getMapBox(mx
, my
, mw
, mh
);
307 drawLine(mx
+mw
div 2, my
+mh
div 2, emx
+emw
div 2, emy
+emh
div 2, 255, 0, 0, 255);
308 if (g_Map_traceToNearestWall(mx
+mw
div 2, my
+mh
div 2, emx
+emw
div 2, emy
+emh
div 2, @ex
, @ey
) <> nil) then
310 drawLine(mx
+mw
div 2, my
+mh
div 2, ex
, ey
, 0, 255, 0, 255);
314 procedure drawLOS2Plr ();
316 emx
, emy
, emw
, emh
: Integer;
321 if (eplr
= nil) then exit
;
322 eplr
.getMapBox(emx
, emy
, emw
, emh
);
323 mon
.getMapBox(mx
, my
, mw
, mh
);
324 drawLine(mx
+mw
div 2, my
+mh
div 2, emx
+emw
div 2, emy
+emh
div 2, 255, 0, 0, 255);
325 {$IF DEFINED(D2F_DEBUG)}
326 //mapGrid.dbgRayTraceTileHitCB := hilightCell1;
328 if (g_Map_traceToNearestWall(mx
+mw
div 2, my
+mh
div 2, emx
+emw
div 2, emy
+emh
div 2, @ex
, @ey
) <> nil) then
329 //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
331 drawLine(mx
+mw
div 2, my
+mh
div 2, ex
, ey
, 0, 255, 0, 255);
333 {$IF DEFINED(D2F_DEBUG)}
334 //mapGrid.dbgRayTraceTileHitCB := nil;
339 if (mon
= nil) then exit
;
340 mon
.getMapBox(mx
, my
, mw
, mh
);
343 monsGrid
.forEachBodyCell(mon
.proxyId
, hilightCell
);
347 //fillRect(mx-4, my-7*8-6, 110, 7*8+6, 0, 0, 94, 250);
348 shadeRect(mx
-4, my
-7*8-6, 110, 7*8+6, 128);
353 drawText6(mx
, my
, Format('%s(U:%u)', [monsTypeToString(mon
.MonsterType
), mon
.UID
]), 255, 127, 0); my
-= 8;
355 drawText6(mx
, my
, Format('Beh: %s', [monsBehToString(mon
.MonsterBehaviour
)]), 255, 127, 0); my
-= 8;
357 drawText6(mx
, my
, Format('State:%s (%d)', [monsStateToString(mon
.MonsterState
), mon
.MonsterSleep
]), 255, 127, 0); my
-= 8;
359 drawText6(mx
, my
, Format('Health:%d', [mon
.MonsterHealth
]), 255, 127, 0); my
-= 8;
361 drawText6(mx
, my
, Format('Ammo:%d', [mon
.MonsterAmmo
]), 255, 127, 0); my
-= 8;
363 drawText6(mx
, my
, Format('TgtUID:%u', [mon
.MonsterTargetUID
]), 255, 127, 0); my
-= 8;
364 drawText6(mx
, my
, Format('TgtTime:%d', [mon
.MonsterTargetTime
]), 255, 127, 0); my
-= 8;
367 drawMonsterTargetLine();
368 if showMonsLOS2Plr
then drawLOS2Plr();
370 property MonsterRemoved: Boolean read FRemoved write FRemoved;
371 property MonsterPain: Integer read FPain write FPain;
372 property MonsterAnim: Byte read FCurAnim write FCurAnim;
376 function highlightAllMonsterCells (mon
: TMonster
): Boolean;
378 result
:= false; // don't stop
379 monsGrid
.forEachBodyCell(mon
.proxyId
, hilightCell
);
384 mx
, my
, mw
, mh
: Integer;
386 //e_DrawPoint(4, plrMouseX, plrMouseY, 255, 0, 255);
387 if (gPlayer1
= nil) then exit
;
389 //e_WriteLog(Format('(%d,%d)-(%d,%d)', [laserX0, laserY0, laserX1, laserY1]), MSG_NOTIFY);
392 glTranslatef(-vpx
, -vpy
, 0);
396 g_Mons_AlongLine(laserX0
, laserY0
, laserX1
, laserY1
, monsCollector
, true);
398 if (monMarkedUID
<> -1) then
400 mon
:= g_Monsters_ByUID(monMarkedUID
);
403 mon
.getMapBox(mx
, my
, mw
, mh
);
404 e_DrawQuad(mx
, my
, mx
+mw
-1, my
+mh
-1, 255, 0, 0, 30);
405 drawMonsterInfo(mon
);
409 if showAllMonsCells
then g_Mons_ForEach(highlightAllMonsterCells
);
411 //e_DrawPoint(16, laserX0, laserY0, 255, 255, 255);
417 // ////////////////////////////////////////////////////////////////////////// //
418 function g_Holmes_mouseEvent (var ev
: THMouseEvent
): Boolean;
429 function g_Holmes_KeyEvent (var ev
: THKeyEvent
): Boolean;
437 SDL_SCANCODE_LCTRL
, SDL_SCANCODE_RCTRL
,
438 SDL_SCANCODE_LALT
, SDL_SCANCODE_RALT
,
439 SDL_SCANCODE_LSHIFT
, SDL_SCANCODE_RSHIFT
:
443 if (ev
.kind
= THKeyEvent
.Press
) then
445 // M-M: one monster think step
446 if (ev
.scan
= SDL_SCANCODE_M
) and ((ev
.kstate
and THKeyEvent
.ModAlt
) <> 0) then
449 gmon_debug_think
:= false;
450 gmon_debug_one_think_step
:= true; // do one step
453 // M-I: toggle monster info
454 if (ev
.scan
= SDL_SCANCODE_I
) and ((ev
.kstate
and THKeyEvent
.ModAlt
) <> 0) then
457 showMonsInfo
:= not showMonsInfo
;
460 // M-L: toggle monster LOS to player
461 if (ev
.scan
= SDL_SCANCODE_L
) and ((ev
.kstate
and THKeyEvent
.ModAlt
) <> 0) then
464 showMonsLOS2Plr
:= not showMonsLOS2Plr
;
467 // M-G: toggle "show all cells occupied by monsters"
468 if (ev
.scan
= SDL_SCANCODE_G
) and ((ev
.kstate
and THKeyEvent
.ModAlt
) <> 0) then
471 showAllMonsCells
:= not showAllMonsCells
;
474 // M-A: wake up monster
475 if (ev
.scan
= SDL_SCANCODE_A
) and ((ev
.kstate
and THKeyEvent
.ModAlt
) <> 0) then
478 if (monMarkedUID
<> -1) then
480 mon
:= g_Monsters_ByUID(monMarkedUID
);
481 if (mon
<> nil) then mon
.WakeUp();
489 // ////////////////////////////////////////////////////////////////////////// //
490 procedure g_Holmes_Draw ();
492 glColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
); // modify color buffer
493 glDisable(GL_STENCIL_TEST
);
495 glDisable(GL_SCISSOR_TEST
);
496 glDisable(GL_TEXTURE_2D
);
503 //drawText6Prop(10, 10, 'Hi there, I''m Holmes!', 255, 255, 0);
504 //drawText8Prop(10, 20, 'Hi there, I''m Holmes!', 255, 255, 0);