1 (* Copyright (C) DooM 2D:Forever Developers
2 *
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.
7 *
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.
12 *
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/>.
15 *)
16 {$INCLUDE ../shared/a_modes.inc}
17 {$DEFINE D2F_NEW_SPARK_THINKER}
20 interface
22 uses
25 const
49 procedure g_GFX_Water(fX, fY: Integer; Count: Word; fVelX, fVelY: Single; DevX, DevY, Color: Byte);
50 procedure g_GFX_SimpleWater(fX, fY: Integer; Count: Word; fVelX, fVelY: Single; DefColor, CR, CG, CB: Byte);
63 var
68 implementation
70 uses
75 type
88 // for bubbles
90 // for water
92 // for blood
95 // for all
99 //k8: sorry, i have to emulate virtual methods this way, 'cause i haet `Object`
117 const
126 var
133 // ////////////////////////////////////////////////////////////////////////// //
138 begin
148 // ////////////////////////////////////////////////////////////////////////// //
150 begin
155 // ???
157 begin
163 begin
169 begin
175 begin
181 begin
187 begin
193 begin
195 result := g_Map_HasAnyPanelAtPoint(x, y, (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_OPENDOOR or PANEL_WATER or PANEL_ACID1 or PANEL_ACID2 or PANEL_STEP or PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT));
200 {$IF not DEFINED(HAS_COLLIDE_BITMAP)}
201 var
204 begin
206 begin
210 begin
211 // wakup this particle
212 {
213 if (part.ParticleType = PARTICLE_SPARK) then
214 begin
215 e_LogWritefln('waking up particle of type %s; justSticked=%s; onGround=%s; VelY=%s; AccelY=%s', [part.ParticleType, part.justSticked, part.onGround, part.VelY, part.AccelY]);
216 end;
217 }
220 begin
229 {$ELSE}
230 var
232 begin
234 begin
240 Exit;
243 begin
249 Exit;
252 Exit;
254 Exit;
269 end
270 else
278 {$ENDIF}
281 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
283 var
285 begin
292 begin
300 begin
308 begin
316 begin
320 begin
335 begin
338 begin
340 begin
341 // Çàêðûòàÿ äâåðü:
349 end
356 {$ENDIF}
360 begin
361 //CreateCollideMap();
362 {$IFDEF HEADLESS}
364 {$ENDIF}
369 var
371 begin
378 begin
387 // ////////////////////////////////////////////////////////////////////////// //
389 var
392 {$IF not DEFINED(D2F_NEW_SPARK_THINKER)}
395 {$ELSE}
398 {$ENDIF}
399 begin
404 begin
406 begin
407 {$IF not DEFINED(D2F_NEW_SPARK_THINKER)}
408 {
409 if (not ByteBool(gCollideMap[Y-1, X] and MARK_BLOCKED)) and
410 (not ByteBool(gCollideMap[Y+1, X] and MARK_BLOCKED)) and
411 (not ByteBool(gCollideMap[Y, X-1] and MARK_BLOCKED)) and
412 (not ByteBool(gCollideMap[Y, X+1] and MARK_BLOCKED))
413 then
414 }
419 {$ELSE}
421 begin
422 if not mapGrid.traceOrthoRayWhileIn(ex, ey, X+stickDX, Y, X+stickDX, mapGrid.gridY0+mapGrid.gridHeight, GridTagWall or GridTagDoor or GridTagStep) then
423 begin
424 // îòëèïëà
426 //e_LogWritefln('juststicked unsticked: X=%s; X+stickDX=%s; stickDX=%s; Y=%s', [X, X+stickDX, stickDX, Y]);
427 end
428 else
429 begin
431 if (nil <> g_Map_traceToNearest(X, Y, X, stickEY, (GridTagWall or GridTagDoor or GridTagStep or GridTagAcid1 or GridTagAcid2 or GridTagWater), @ex, @ey)) then
432 begin
436 //e_LogWritefln('juststicked: X=%s; X+stickDX=%s; stickDX=%s; Y=%s; stickEY=%s', [X, X+stickDX, stickDX, Y, stickEY]);
440 //if not g_Map_CollidePanel(X-1, Y-1, 3, 3, (PANEL_STEP or PANEL_WALL or PANEL_OPENDOOR or PANEL_CLOSEDOOR))
441 {$ENDIF}
442 then
447 end
452 exit;
456 {$IF not DEFINED(D2F_NEW_SPARK_THINKER)}
458 begin
477 {$ELSE}
480 begin
482 begin
489 begin
494 begin
499 {$ENDIF}
504 {$IF not DEFINED(D2F_NEW_SPARK_THINKER)}
506 begin
517 {$ELSE}
519 begin
520 // Âèñèò â âîçäóõå - êàïàåò
521 if (nil = g_Map_traceToNearest(X, Y-1, X, Y+1, (GridTagWall or GridTagDoor or GridTagStep or GridTagAcid1 or GridTagAcid2 or GridTagWater), @ex, @ey)) then
522 begin
528 {$ENDIF}
530 {$IF DEFINED(D2F_NEW_SPARK_THINKER)}
531 // horizontal
533 begin
534 pan := g_Map_traceToNearest(X, Y, X+dX, Y, (GridTagWall or GridTagDoor or GridTagStep), @ex, @ey);
536 // free to ride?
538 begin
539 // Ñòåíà/äâåðü
550 // vertical
552 begin
554 begin
555 pan := g_Map_traceToNearest(X, Y, X, Y+dY, (GridTagWall or GridTagDoor or GridTagStep), @ex, @ey);
557 // free to ride?
559 begin
560 // Ñòåíà/äâåðü
566 begin
568 end
569 else
570 begin
572 if (g_Map_PanelAtPoint(X-1, Y, (GridTagWall or GridTagDoor or GridTagStep)) <> nil) then stickDX := -1
573 else if (g_Map_PanelAtPoint(X+1, Y, (GridTagWall or GridTagDoor or GridTagStep)) <> nil) then stickDX := 1
578 onGround := (VelY >= 0) and g_Map_HasAnyPanelAtPoint(X, Y+1, (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_STEP));
582 {$ELSE}
583 // horizontal
585 begin
589 begin
591 //c := gCollideMap[Y, X+s];
600 break;
605 // vertical
607 begin
611 begin
613 //c := gCollideMap[Y+s, X];
622 break;
627 {$ENDIF}
629 else
630 begin
633 if (X+dX >= w) or (Y+dY >= h) or (X+dX <= 0) or (Y+dY <= 0) or isBlockedAt(X+dX, Y+dY) {ByteBool(gCollideMap[Y+dY, X+dX] and MARK_BLOCKED)} then
636 exit;
637 //VelX := 0;
638 //VelY := 0;
639 end
640 else
641 begin
650 // Êðîâü ðàñòâîðÿåòñÿ â æèäêîñòè:
652 begin
660 // ////////////////////////////////////////////////////////////////////////// //
662 var
664 {$IF not DEFINED(D2F_NEW_SPARK_THINKER)}
668 {$ELSE}
671 {$ENDIF}
672 begin
673 {$IF not DEFINED(D2F_NEW_SPARK_THINKER)}
676 {$ENDIF}
678 //TODO: trace wall end when water becomes stick
683 {$IF not DEFINED(D2F_NEW_SPARK_THINKER)}
687 {$ELSE}
689 begin
690 // no walls around, drop
692 end
693 else
694 begin
696 begin
697 if not mapGrid.traceOrthoRayWhileIn(ex, ey, X+stickDX, Y, X+stickDX, mapGrid.gridY0+mapGrid.gridHeight, GridTagWall or GridTagDoor or GridTagStep) then
698 begin
699 // îòëèïëà
701 //e_LogWritefln('juststicked unsticked: X=%s; X+stickDX=%s; stickDX=%s; Y=%s', [X, X+stickDX, stickDX, Y]);
702 end
703 else
704 begin
707 if (nil <> g_Map_traceToNearest(X, Y, X, stickEY, (GridTagWall or GridTagDoor or GridTagStep or GridTagAcid1 or GridTagAcid2 or GridTagWater), @ex, @ey)) then
708 begin
711 //e_LogWritefln('juststicked: X=%s; X+stickDX=%s; stickDX=%s; Y=%s; stickEY=%s', [X, X+stickDX, stickDX, Y, stickEY]);
713 end
714 else
715 begin
718 //if not g_Map_CollidePanel(X-1, Y-1, 3, 3, (PANEL_STEP or PANEL_WALL or PANEL_OPENDOOR or PANEL_CLOSEDOOR))
720 {$ENDIF}
721 exit;
724 {$IF not DEFINED(D2F_NEW_SPARK_THINKER)}
726 begin
749 {$ELSE}
752 begin
753 if ((pan.tag and (GridTagAcid1 or GridTagAcid2 or GridTagWater)) <> 0) then begin die(); exit; end;
755 begin
762 begin
767 begin
772 {$ENDIF}
777 {$IF not DEFINED(D2F_NEW_SPARK_THINKER)}
779 begin
790 {$ELSE}
792 begin
793 // Âèñèò â âîçäóõå - êàïàåò
794 if (nil = g_Map_traceToNearest(X, Y-1, X, Y+1, (GridTagWall or GridTagDoor or GridTagStep or GridTagAcid1 or GridTagAcid2 or GridTagWater), @ex, @ey)) then
795 begin
801 {$ENDIF}
803 {$IF DEFINED(D2F_NEW_SPARK_THINKER)}
804 // horizontal
806 begin
807 pan := g_Map_traceToNearest(X, Y, X+dX, Y, (GridTagWall or GridTagDoor or GridTagStep or GridTagAcid1 or GridTagAcid2 or GridTagWater), @ex, @ey);
809 // free to ride?
811 begin
812 // nope
813 if (dY > 0) and ((pan.tag and (GridTagAcid1 or GridTagAcid2 or GridTagWater)) <> 0) then begin die(); exit; end;
814 // Ñòåíà/äâåðü?
816 begin
828 // vertical
830 begin
832 begin
833 pan := g_Map_traceToNearest(X, Y, X, Y+dY, (GridTagWall or GridTagDoor or GridTagStep or GridTagAcid1 or GridTagAcid2 or GridTagWater), @ex, @ey);
835 // free to ride?
837 begin
838 // nope
839 if (dY > 0) and ((pan.tag and (GridTagAcid1 or GridTagAcid2 or GridTagWater)) <> 0) then begin die(); exit; end;
840 // Ñòåíà/äâåðü?
842 begin
848 begin
850 end
851 else
852 begin
854 if (g_Map_PanelAtPoint(X-1, Y, (GridTagWall or GridTagDoor or GridTagStep)) <> nil) then stickDX := -1
855 else if (g_Map_PanelAtPoint(X+1, Y, (GridTagWall or GridTagDoor or GridTagStep)) <> nil) then stickDX := 1
861 onGround := (VelY >= 0) and g_Map_HasAnyPanelAtPoint(X, Y+1, (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_STEP));
865 {$ELSE}
866 // horizontal
868 begin
871 begin
872 // Ñáîêó ãðàíèöà?
874 //c := gCollideMap[Y, X+s];
875 // Ñáîêó æèäêîñòü, à ÷àñòèöà óæå ïàäàåò?
885 Break;
890 // vertical
892 begin
895 begin
896 // Ñíèçó/ñâåðõó ãðàíèöà
898 //c := gCollideMap[Y+s, X];
899 // Ñíèçó æèäêîñòü, à ÷àñòèöà óæå ïàäàåò
909 break;
914 {$ENDIF}
923 // ////////////////////////////////////////////////////////////////////////// //
925 var
927 {$IF not DEFINED(D2F_NEW_SPARK_THINKER)}
930 {$ELSE}
933 {$ENDIF}
934 begin
938 {$IF DEFINED(D2F_NEW_SPARK_THINKER)}
940 begin
941 pan := g_Map_traceToNearest(X, Y-1, X, Y+1, (GridTagWall or GridTagDoor or GridTagStep or GridTagAcid1 or GridTagAcid2 or GridTagWater), @ex, @ey);
943 {$ELSE}
952 {$ENDIF}
955 begin
956 {$IF DEFINED(D2F_NEW_SPARK_THINKER)}
957 pan := g_Map_traceToNearest(X, Y, X+dX, Y, (GridTagWall or GridTagDoor or GridTagStep or GridTagAcid1 or GridTagAcid2 or GridTagWater), @ex, @ey);
958 //e_WriteLog(Format('spark h-trace: (%d,%d)-(%d,%d); dx=%d; end=(%d,%d); hit=%d', [X, Y, X+dX, Y, dX, ex, ey, Integer(pan <> nil)]), MSG_NOTIFY);
960 // free to ride?
962 begin
963 // nope
964 if ((pan.tag and (GridTagAcid1 or GridTagAcid2 or GridTagWater)) <> 0) then begin die(); exit; end;
969 {$ELSE}
973 begin
975 //c := gCollideMap[Y, X+s];
980 Break;
981 end
986 begin
988 break;
991 {$ENDIF}
995 begin
996 {$IF DEFINED(D2F_NEW_SPARK_THINKER)}
998 begin
999 pan := g_Map_traceToNearest(X, Y, X, Y+dY, (GridTagWall or GridTagDoor or GridTagStep or GridTagAcid1 or GridTagAcid2 or GridTagWater), @ex, @ey);
1001 {
1002 if awaken then
1003 begin
1004 awaken := false;
1005 e_LogWritefln('AWAKEN particle of type %s; justSticked=%s; onGround=%s; VelY=%s; AccelY=%s; Y=%s; ey=%s', [ParticleType, justSticked, onGround, VelY, AccelY, Y, ey]);
1006 end;
1007 }
1008 // free to ride?
1010 begin
1011 // nope
1012 if ((pan.tag and (GridTagAcid1 or GridTagAcid2 or GridTagWater)) <> 0) then begin die(); exit; end;
1014 begin
1017 end
1018 else
1019 begin
1026 onGround := (VelY >= 0) and g_Map_HasAnyPanelAtPoint(X, Y+1, (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_STEP));
1029 {$ELSE}
1033 begin
1035 //c := gCollideMap[Y+s, X];
1039 begin
1042 end
1044 begin
1051 Break;
1052 end
1057 begin
1059 break;
1062 {$ENDIF}
1068 begin
1076 // ////////////////////////////////////////////////////////////////////////// //
1078 var
1083 begin
1089 begin
1092 else
1096 begin
1099 (*
1100 if not isLiquidAt(X, Y+s) {ByteBool(gCollideMap[Y+s, X] and MARK_LIQUID)} then
1101 begin // Óæå íå æèäêîñòü
1102 State := STATE_FREE;
1103 Break;
1104 end;
1105 *)
1106 // we traced liquid before, so don't bother checking
1120 // ////////////////////////////////////////////////////////////////////////// //
1122 var
1127 begin
1139 begin
1141 begin
1151 else
1167 onGround := (VelY >= 0) and g_Map_HasAnyPanelAtPoint(X, Y+1, (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_STEP));
1173 else
1181 var
1188 begin
1191 begin
1193 Exit;
1197 Exit;
1207 begin
1209 begin
1213 {
1214 if (X < 0) or (X > gMapInfo.Width-1) or
1215 (Y < 0) or (Y > gMapInfo.Height-1) or
1216 ByteBool(gCollideMap[Y, X] and MARK_WALL) then
1217 Continue;
1218 }
1227 else
1235 begin
1240 end else
1243 begin
1248 end else
1251 begin
1256 end else
1266 onGround := (VelY >= 0) and g_Map_HasAnyPanelAtPoint(X, Y+1, (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_STEP));
1268 //stickEY := 0;
1273 else
1280 var
1287 begin
1291 Exit;
1310 begin
1312 begin
1331 onGround := (VelY >= 0) and g_Map_HasAnyPanelAtPoint(X, Y+1, (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_STEP));
1337 else
1342 procedure g_GFX_Water(fX, fY: Integer; Count: Word; fVelX, fVelY: Single; DevX, DevY, Color: Byte);
1343 var
1348 begin
1352 Exit;
1365 begin
1367 begin
1373 else
1383 begin
1389 begin
1395 begin
1401 begin
1415 onGround := (VelY >= 0) and g_Map_HasAnyPanelAtPoint(X, Y+1, (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_STEP));
1421 else
1426 procedure g_GFX_SimpleWater(fX, fY: Integer; Count: Word; fVelX, fVelY: Single; DefColor, CR, CG, CB: Byte);
1427 var
1430 begin
1434 Exit;
1439 begin
1441 begin
1452 begin
1458 begin
1464 begin
1470 begin
1479 begin
1488 begin
1502 onGround := (VelY >= 0) and g_Map_HasAnyPanelAtPoint(X, Y+1, (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_STEP));
1508 else
1514 {.$DEFINE D2F_DEBUG_BUBBLES}
1516 var
1521 {$IF DEFINED(D2F_DEBUG_BUBBLES)}
1524 {$ENDIF}
1525 begin
1529 Exit;
1539 begin
1541 begin
1547 Continue;
1549 (*
1550 // don't spawn bubbles outside of the liquid
1551 if not isLiquidAt(X, Y) {ByteBool(gCollideMap[Y, X] and MARK_LIQUID)} then
1552 Continue;
1553 *)
1555 // trace liquid, so we'll know where it ends; do it in 8px steps for speed
1556 // tracer will return `false` if we started outside of the liquid
1558 {$IF DEFINED(D2F_DEBUG_BUBBLES)}
1560 ptr := mapGrid.traceOrthoRayWhileIn(liquidx, liquidTopY, X, Y, X, 0, GridTagWater or GridTagAcid1 or GridTagAcid2);
1562 e_LogWritefln('traceOrthoRayWhileIn: time=%s (%s); liquidTopY=%s', [Integer(stt), ptr, liquidTopY]);
1563 //
1567 e_LogWritefln('g_Map_TraceLiquidNonPrecise: time=%s (%s); liquidTopY=%s', [Integer(stt), nptr, liquidTopY]);
1569 {$ELSE}
1571 {$ENDIF}
1588 onGround := (VelY >= 0) and g_Map_HasAnyPanelAtPoint(X, Y+1, (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_STEP));
1594 else
1600 var
1602 begin
1609 //if CurrentParticle >= Count then
1614 begin
1619 var
1621 begin
1625 begin
1627 Exit;
1631 begin
1634 end
1635 else
1636 begin
1643 var
1645 begin
1648 Exit;
1661 var
1665 begin
1668 begin
1675 begin
1677 begin
1679 begin
1682 //if not alive then Continue;
1683 //e_WriteLog(Format('particle #%d: %d', [State, ParticleType]), MSG_NOTIFY);
1691 begin
1694 begin
1696 ONCEANIM_SMOKE:
1697 begin
1706 begin
1709 end
1710 else
1717 var
1719 begin
1721 begin
1735 begin