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
93 //k8: sorry, i have to emulate virtual methods this way, 'cause i haet `Object`
111 const
120 var
127 // ////////////////////////////////////////////////////////////////////////// //
132 begin
142 // ////////////////////////////////////////////////////////////////////////// //
144 begin
149 // ???
151 begin
157 begin
163 begin
169 begin
175 begin
181 begin
187 begin
189 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));
194 {$IF not DEFINED(HAS_COLLIDE_BITMAP)}
195 begin
197 {$ELSE}
198 var
200 begin
202 begin
208 Exit;
211 begin
217 Exit;
220 Exit;
222 Exit;
237 end
238 else
246 {$ENDIF}
249 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
251 var
253 begin
260 begin
268 begin
276 begin
284 begin
288 begin
303 begin
306 begin
308 begin
309 // Çàêðûòàÿ äâåðü:
317 end
324 {$ENDIF}
328 begin
329 //CreateCollideMap();
330 {$IFDEF HEADLESS}
332 {$ENDIF}
337 var
339 begin
346 begin
355 {
356 procedure CorrectOffsets(id: Integer); inline;
357 var
358 part: PParticle;
359 begin
360 part := @Particles[id];
361 part.offsetX := 0;
362 part.offsetY := 0;
363 // check for upper wall
364 if isBlockedAt(part.X, part.Y-1) then part.offsetY := 1;
365 // check for left wall
366 if isBlockedAt(part.X-1, part.Y) then part.offsetX := 1;
367 end;
368 }
371 // ////////////////////////////////////////////////////////////////////////// //
373 var
376 {$IF not DEFINED(D2F_NEW_SPARK_THINKER)}
379 {$ELSE}
382 {$ENDIF}
383 begin
388 begin
390 begin
391 {$IF not DEFINED(D2F_NEW_SPARK_THINKER)}
392 {
393 if (not ByteBool(gCollideMap[Y-1, X] and MARK_BLOCKED)) and
394 (not ByteBool(gCollideMap[Y+1, X] and MARK_BLOCKED)) and
395 (not ByteBool(gCollideMap[Y, X-1] and MARK_BLOCKED)) and
396 (not ByteBool(gCollideMap[Y, X+1] and MARK_BLOCKED))
397 then
398 }
403 {$ELSE}
404 if not g_Map_CollidePanel(X-1, Y-1, 3, 3, (PANEL_STEP or PANEL_WALL or PANEL_OPENDOOR or PANEL_CLOSEDOOR))
405 {$ENDIF}
406 then
411 end
416 exit;
420 {$IF not DEFINED(D2F_NEW_SPARK_THINKER)}
422 begin
441 {$ELSE}
444 begin
446 begin
453 begin
458 begin
463 {$ENDIF}
468 {$IF not DEFINED(D2F_NEW_SPARK_THINKER)}
470 begin
481 {$ELSE}
483 begin
484 // Âèñèò â âîçäóõå - êàïàåò
485 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
486 begin
492 {$ENDIF}
494 {$IF DEFINED(D2F_NEW_SPARK_THINKER)}
495 // horizontal
497 begin
498 pan := g_Map_traceToNearest(X, Y, X+dX, Y, (GridTagWall or GridTagDoor or GridTagStep), @ex, @ey);
500 // free to ride?
502 begin
503 // Ñòåíà/äâåðü
513 // vertical
515 begin
516 pan := g_Map_traceToNearest(X, Y, X, Y+dY, (GridTagWall or GridTagDoor or GridTagStep), @ex, @ey);
518 // free to ride?
520 begin
521 // Ñòåíà/äâåðü
527 begin
529 end
530 else
531 begin
533 if (g_Map_PanelAtPoint(X-1, Y, (GridTagWall or GridTagDoor or GridTagStep)) <> nil) then stickDX := -1
534 else if (g_Map_PanelAtPoint(X+1, Y, (GridTagWall or GridTagDoor or GridTagStep)) <> nil) then stickDX := 1
540 {$ELSE}
541 // horizontal
543 begin
547 begin
549 //c := gCollideMap[Y, X+s];
557 break;
562 // vertical
564 begin
568 begin
570 //c := gCollideMap[Y+s, X];
578 break;
583 {$ENDIF}
585 else
586 begin
589 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
592 exit;
593 //VelX := 0;
594 //VelY := 0;
595 end
596 else
597 begin
606 // Êðîâü ðàñòâîðÿåòñÿ â æèäêîñòè:
608 begin
616 // ////////////////////////////////////////////////////////////////////////// //
618 var
620 {$IF not DEFINED(D2F_NEW_SPARK_THINKER)}
624 {$ELSE}
627 {$ENDIF}
628 begin
629 {$IF not DEFINED(D2F_NEW_SPARK_THINKER)}
632 {$ENDIF}
634 //TODO: trace wall end when water becomes stick
639 {$IF not DEFINED(D2F_NEW_SPARK_THINKER)}
643 {$ELSE}
645 begin
646 // no walls around, drop
648 end
649 else
650 begin
651 if (g_Map_PanelAtPoint(X+stickDX, Y, (GridTagWall or GridTagDoor or GridTagStep)) = nil) then State := STATE_NORMAL;
653 {$ENDIF}
654 exit;
657 {$IF not DEFINED(D2F_NEW_SPARK_THINKER)}
659 begin
682 {$ELSE}
685 begin
686 if ((pan.tag and (GridTagAcid1 or GridTagAcid2 or GridTagWater)) <> 0) then begin die(); exit; end;
688 begin
695 begin
700 begin
705 {$ENDIF}
710 {$IF not DEFINED(D2F_NEW_SPARK_THINKER)}
712 begin
723 {$ELSE}
725 begin
726 // Âèñèò â âîçäóõå - êàïàåò
727 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
728 begin
734 {$ENDIF}
736 {$IF DEFINED(D2F_NEW_SPARK_THINKER)}
737 // horizontal
739 begin
740 pan := g_Map_traceToNearest(X, Y, X+dX, Y, (GridTagWall or GridTagDoor or GridTagStep or GridTagAcid1 or GridTagAcid2 or GridTagWater), @ex, @ey);
742 // free to ride?
744 begin
745 // nope
746 if (dY > 0) and ((pan.tag and (GridTagAcid1 or GridTagAcid2 or GridTagWater)) <> 0) then begin die(); exit; end;
747 // Ñòåíà/äâåðü?
749 begin
760 // vertical
762 begin
763 pan := g_Map_traceToNearest(X, Y, X, Y+dY, (GridTagWall or GridTagDoor or GridTagStep or GridTagAcid1 or GridTagAcid2 or GridTagWater), @ex, @ey);
765 // free to ride?
767 begin
768 // nope
769 if (dY > 0) and ((pan.tag and (GridTagAcid1 or GridTagAcid2 or GridTagWater)) <> 0) then begin die(); exit; end;
770 // Ñòåíà/äâåðü?
772 begin
778 begin
780 end
781 else
782 begin
784 if (g_Map_PanelAtPoint(X-1, Y, (GridTagWall or GridTagDoor or GridTagStep)) <> nil) then stickDX := -1
785 else if (g_Map_PanelAtPoint(X+1, Y, (GridTagWall or GridTagDoor or GridTagStep)) <> nil) then stickDX := 1
792 {$ELSE}
793 // horizontal
795 begin
798 begin
799 // Ñáîêó ãðàíèöà?
801 //c := gCollideMap[Y, X+s];
802 // Ñáîêó æèäêîñòü, à ÷àñòèöà óæå ïàäàåò?
811 Break;
816 // vertical
818 begin
821 begin
822 // Ñíèçó/ñâåðõó ãðàíèöà
824 //c := gCollideMap[Y+s, X];
825 // Ñíèçó æèäêîñòü, à ÷àñòèöà óæå ïàäàåò
834 break;
839 {$ENDIF}
848 // ////////////////////////////////////////////////////////////////////////// //
850 var
852 {$IF not DEFINED(D2F_NEW_SPARK_THINKER)}
855 {$ELSE}
858 {$ENDIF}
859 begin
863 {$IF DEFINED(D2F_NEW_SPARK_THINKER)}
865 begin
866 pan := g_Map_traceToNearest(X, Y-1, X, Y+1, (GridTagWall or GridTagDoor or GridTagStep or GridTagAcid1 or GridTagAcid2 or GridTagWater), @ex, @ey);
868 {$ELSE}
877 {$ENDIF}
880 begin
881 {$IF DEFINED(D2F_NEW_SPARK_THINKER)}
882 pan := g_Map_traceToNearest(X, Y, X+dX, Y, (GridTagWall or GridTagDoor or GridTagStep or GridTagAcid1 or GridTagAcid2 or GridTagWater), @ex, @ey);
883 //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);
885 // free to ride?
887 begin
888 // nope
889 if ((pan.tag and (GridTagAcid1 or GridTagAcid2 or GridTagWater)) <> 0) then begin die(); exit; end;
894 {$ELSE}
898 begin
900 //c := gCollideMap[Y, X+s];
905 Break;
906 end
911 begin
913 break;
916 {$ENDIF}
920 begin
921 {$IF DEFINED(D2F_NEW_SPARK_THINKER)}
922 pan := g_Map_traceToNearest(X, Y, X, Y+dY, (GridTagWall or GridTagDoor or GridTagStep or GridTagAcid1 or GridTagAcid2 or GridTagWater), @ex, @ey);
923 //e_WriteLog(Format('spark y-trace: (%d,%d)-(%d,%d); dy=%d; end=(%d,%d); hit=%d', [X, Y, X, Y+dY, dY, ex, ey, Integer(pan <> nil)]), MSG_NOTIFY);
924 (*
925 if (pan <> nil) then
926 begin
927 e_WriteLog(Format('spark y-trace: %08x (%d,%d)-(%d,%d); dy=%d; end=(%d,%d); hittag=%04x', [LongWord(@self), X, Y, X, Y+dY, dY, ex, ey, pan.tag]), MSG_NOTIFY);
928 end
929 else
930 begin
931 e_WriteLog(Format('spark y-trace: %08x (%d,%d)-(%d,%d); dy=%d; end=(%d,%d); hit=%d', [LongWord(@self), X, Y, X, Y+dY, dY, ex, ey, Integer(pan <> nil)]), MSG_NOTIFY);
932 end;
933 *)
935 // free to ride?
937 begin
938 //die(); exit;
939 // nope
940 if ((pan.tag and (GridTagAcid1 or GridTagAcid2 or GridTagWater)) <> 0) then begin die(); exit; end;
942 begin
945 end
946 else
947 begin
955 {$ELSE}
959 begin
961 //c := gCollideMap[Y+s, X];
965 begin
968 end
970 begin
977 Break;
978 end
983 begin
985 break;
988 {$ENDIF}
994 begin
1002 // ////////////////////////////////////////////////////////////////////////// //
1004 var
1009 begin
1015 begin
1018 else
1022 begin
1025 (*
1026 if not isLiquidAt(X, Y+s) {ByteBool(gCollideMap[Y+s, X] and MARK_LIQUID)} then
1027 begin // Óæå íå æèäêîñòü
1028 State := STATE_FREE;
1029 Break;
1030 end;
1031 *)
1032 // we traced liquid before, so don't bother checking
1046 // ////////////////////////////////////////////////////////////////////////// //
1048 var
1053 begin
1065 begin
1067 begin
1077 else
1093 {CorrectOffsets(CurrentParticle);}
1098 else
1106 var
1113 begin
1116 begin
1118 Exit;
1122 Exit;
1132 begin
1134 begin
1138 {
1139 if (X < 0) or (X > gMapInfo.Width-1) or
1140 (Y < 0) or (Y > gMapInfo.Height-1) or
1141 ByteBool(gCollideMap[Y, X] and MARK_WALL) then
1142 Continue;
1143 }
1152 else
1160 begin
1165 end else
1168 begin
1173 end else
1176 begin
1181 end else
1191 {CorrectOffsets(CurrentParticle);}
1196 else
1203 var
1210 begin
1214 Exit;
1233 begin
1235 begin
1254 {CorrectOffsets(CurrentParticle);}
1259 else
1264 procedure g_GFX_Water(fX, fY: Integer; Count: Word; fVelX, fVelY: Single; DevX, DevY, Color: Byte);
1265 var
1270 begin
1274 Exit;
1287 begin
1289 begin
1295 else
1305 begin
1311 begin
1317 begin
1323 begin
1337 {CorrectOffsets(CurrentParticle);}
1342 else
1347 procedure g_GFX_SimpleWater(fX, fY: Integer; Count: Word; fVelX, fVelY: Single; DefColor, CR, CG, CB: Byte);
1348 var
1351 begin
1355 Exit;
1360 begin
1362 begin
1373 begin
1379 begin
1385 begin
1391 begin
1400 begin
1409 begin
1423 {CorrectOffsets(CurrentParticle);}
1428 else
1435 var
1440 begin
1444 Exit;
1454 begin
1456 begin
1462 Continue;
1464 (*
1465 // don't spawn bubbles outside of the liquid
1466 if not isLiquidAt(X, Y) {ByteBool(gCollideMap[Y, X] and MARK_LIQUID)} then
1467 Continue;
1468 *)
1470 // trace liquid, so we'll know where it ends; do it in 8px steps for speed
1471 // tracer will return `false` if we started outside of the liquid
1489 {CorrectOffsets(CurrentParticle);}
1494 else
1500 var
1502 begin
1509 //if CurrentParticle >= Count then
1514 begin
1519 var
1521 begin
1525 begin
1527 Exit;
1531 begin
1534 end
1535 else
1536 begin
1543 var
1545 begin
1548 Exit;
1561 var
1565 begin
1568 begin
1575 begin
1577 begin
1579 begin
1582 //if not alive then Continue;
1583 //e_WriteLog(Format('particle #%d: %d', [State, ParticleType]), MSG_NOTIFY);
1585 {CorrectOffsets(a);}
1592 begin
1595 begin
1597 ONCEANIM_SMOKE:
1598 begin
1607 begin
1610 end
1611 else
1618 var
1620 begin
1622 begin
1636 begin