e49a72cdaf286758c9a048d96a40b7e26259f3bd
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}
19 interface
21 uses
24 const
51 procedure g_GFX_Water (fX, fY: Integer; count: Word; fVelX, fVelY: Single; devX, devY, color: Byte;
53 procedure g_GFX_SimpleWater (fX, fY: Integer; count: Word; fVelX, fVelY: Single; defColor, cr, cg, cb: Byte);
67 var
72 implementation
74 uses
80 const
84 type
88 // Wall: floorY is just before floor
89 // LiquidIn: floorY is liquid *start* (i.e. just in a liquid)
90 // LiquidOut: floorY is liquid *end* (i.e. just out of a liquid)
93 // note: this MUST be record, so we can keep it in
94 // dynamic array and has sequential memory access pattern
113 //k8: sorry, i have to emulate virtual methods this way, 'cause i haet `Object`
138 var
143 // awakeMap has one bit for each map grid cell; on g_Mark,
144 // corresponding bits will be set, and in `think()` all particles
145 // in marked cells will be awaken
153 // ////////////////////////////////////////////////////////////////////////// //
154 // HACK! using mapgrid
156 begin
158 begin
166 begin
174 {$IF DEFINED(D2F_DEBUG)}
175 e_LogWritefln('particle awake map: %sx%s (for grid of size %sx%s)', [awakeMapW, awakeMapH, mapGrid.gridWidth, mapGrid.gridHeight]);
176 {$ENDIF}
183 begin
187 begin
188 {$IF DEFINED(D2F_DEBUG)}
190 {$ENDIF}
192 end
193 else
194 begin
201 var
203 begin
207 begin
208 {$IF DEFINED(D2F_DEBUG)}
210 {$ENDIF}
218 // ////////////////////////////////////////////////////////////////////////// //
222 // remove velocities and acceleration
224 begin
225 // stop right there, you criminal scum!
233 // `true`: affected by air stream
235 var
237 begin
241 begin
243 begin
248 end
250 begin
253 end
255 begin
258 end
259 else
260 begin
263 // awake
269 // switch to sleep mode
271 begin
273 begin
281 var
284 begin
286 // stuck in the wall? rescan, 'cause it can be mplat
288 begin
291 begin
292 // either in a wall, or in a liquid
294 begin
295 // we are in the wall, wtf?!
300 exit;
302 // we are in liquid, trace to liquid end
306 // are we in a liquid?
308 begin
309 // trace out of the liquid
310 //env := TEnvType.ELiquid;
312 //e_LogWritefln('tracing out of a liquid; floorY=%s; y=%s', [floorY, y]);
315 //e_LogWritefln(' traced out of a liquid; floorY=%s; y=%s', [floorY, y]);
316 end
317 else
318 begin
319 // in the air
321 //env := TEnvType.EAir;
322 pan := g_Map_traceToNearest(x, y, x, g_Map_MaxY, (GridTagObstacle or GridTagLiquid), @ex, @floorY);
324 begin
325 // wall or liquid
327 begin
328 // wall
330 end
331 else
332 begin
333 // liquid
337 end
338 else
339 begin
340 // out of the level; assume wall, but it doesn't really matter
349 var
351 begin
354 begin
361 begin
362 // awake sleeping particle, if necessary
364 begin
368 begin
385 // ////////////////////////////////////////////////////////////////////////// //
388 begin
396 var
398 begin
402 // find next floor transition
404 // find `wallEndY`
405 mapGrid.traceOrthoRayWhileIn(ex, wallEndY, x+stickDX, y, x+stickDX, floorY+1, (GridTagWall or GridTagDoor or GridTagStep));
409 begin
416 // `true`: didn't, get outa thinker
418 begin
427 // switch to freefall mode
429 begin
436 begin
439 begin
442 end
443 else
444 begin
450 label
451 _done;
452 var
457 begin
461 begin
462 // still check for air streams when sleeping (no)
463 if (state = TPartState.Sleeping) then begin {checkAirStreams();} goto _done; end; // so blood will dissolve
465 // process stuck particles
467 begin
468 // stuck to a ceiling?
470 begin
471 // yeah, stuck to a ceiling
473 // dropped from a ceiling?
475 begin
476 // yep
480 end
481 else
482 begin
483 // otherwise, try to drip
486 end
487 else
488 begin
489 // stuck to a wall
491 // floor transition?
493 begin
497 begin
502 begin
503 // rescan, so we'll know when we'll exit the liquid
507 begin
508 // rescan, so we'll know when we'll enter something interesting
514 // wall transition?
516 begin
517 // just unstuck from the wall, switch to freefall mode
520 end
521 else
522 begin
523 // otherwise, try to drip
527 // nope, process as usual
530 // it is important to have it here
536 // gravity, if not stuck
538 begin
540 // floor transition?
542 begin
545 begin
546 // nothing to do
549 begin
550 // rescan, so we'll know when we'll exit the liquid
555 begin
556 // rescan, so we'll know when we'll enter something interesting
558 if (floorType <> TFloorType.Wall) or (floorY <> y) then applyGravity(floorType = TFloorType.LiquidIn);
561 end
562 else
563 begin
564 // looks like we're in the air
569 // trace movement
571 begin
572 // has some horizontal velocity
578 begin
579 // dunno yet
582 // check environment (air/liquid)
583 if (g_Map_PanelAtPoint(x, y, GridTagLiquid) <> nil) then env := TEnvType.ELiquid else env := TEnvType.EAir;
586 begin
587 // we stuck
588 // the only case when we can have both ceiling and wall is corner; stick to wall in this case
589 // check if we stuck to a wall
592 begin
593 // stuck to a wall
595 end
596 else
597 begin
598 // stuck to a ceiling
602 end
604 begin
605 // has only vertical velocity
607 begin
608 // flying up
612 // environment didn't changed
613 end
614 else
615 begin
617 begin
618 // falling down
622 //e_LogWritefln('floorY=%s; newy=%s; dY=%s; floorType=%s', [floorY, y, dY, floorType]);
624 begin
625 // floor transition
628 //e_LogWritefln(' HIT FLOORY: floorY=%s; newy=%s; dY=%s; floorType=%s', [floorY, y, dY, floorType]);
631 begin
632 // environment didn't changed
637 begin
638 // we're entered the liquid
640 // rescan, so we'll know when we'll exit the liquid
644 begin
645 // we're exited the liquid
647 // rescan, so we'll know when we'll enter something interesting
650 begin
656 end
657 else
658 begin
665 else
666 begin
667 // simple blood
675 _done:
676 if (x < g_Map_MinX) or (y < g_Map_MinY) or (x > g_Map_MaxX) or (y > g_Map_MaxY) then begin die(); end;
681 // blood will dissolve in other liquids
683 begin
685 begin
693 end
694 else
695 begin
696 // water will disappear in any liquid
699 // dry water
709 // ////////////////////////////////////////////////////////////////////////// //
710 procedure g_GFX_SparkVel (fX, fY: Integer; count: Word; vx, vy: Integer; devX, devY: Byte); forward;
716 begin
718 begin
723 end
724 else
725 begin
730 var
736 begin
740 begin
742 exit;
755 begin
757 begin
761 // check for level bounds
764 // in what environment we are starting in?
767 begin
768 // either in a wall, or in a liquid
771 end
772 else
773 begin
781 begin
808 procedure g_GFX_Water (fX, fY: Integer; count: Word; fVelX, fVelY: Single; devX, devY, color: Byte;
810 var
815 begin
832 begin
834 begin
836 begin
845 end
846 else
847 begin
857 // check for level bounds
860 // this hack will allow water spawned in water to fly out
861 // it can happen when player fell from a huge height (see "DOOM2D.WAD:\MAP03", for example)
863 begin
864 // in what environment we are starting in?
866 end
867 else
868 begin
874 // color
877 begin
883 begin
889 begin
895 begin
904 begin
913 begin
934 procedure g_GFX_SimpleWater (fX, fY: Integer; count: Word; fVelX, fVelY: Single; defColor, cr, cg, cb: Byte);
935 begin
940 // ////////////////////////////////////////////////////////////////////////// //
942 var
944 begin
948 begin
951 begin
953 end
954 else
955 begin
967 {.$DEFINE D2F_DEBUG_BUBBLES}
969 var
973 {$IF DEFINED(D2F_DEBUG_BUBBLES)}
976 {$ENDIF}
977 begin
990 begin
992 begin
996 // check for level bounds
999 (*
1000 // don't spawn bubbles outside of the liquid
1001 if not isLiquidAt(X, Y) {ByteBool(gCollideMap[Y, X] and MARK_LIQUID)} then
1002 Continue;
1003 *)
1005 // trace liquid, so we'll know where it ends; do it in 8px steps for speed
1006 // tracer will return `false` if we started outside of the liquid
1008 {$IF DEFINED(D2F_DEBUG_BUBBLES)}
1010 ptr := mapGrid.traceOrthoRayWhileIn(liquidx, liquidTopY, x, y, x, 0, GridTagWater or GridTagAcid1 or GridTagAcid2);
1012 e_LogWritefln('traceOrthoRayWhileIn: time=%s (%s); liquidTopY=%s', [Integer(stt), ptr, liquidTopY]);
1013 //
1017 e_LogWritefln('g_Map_TraceLiquidNonPrecise: time=%s (%s); liquidTopY=%s', [Integer(stt), nptr, liquidTopY]);
1019 {$ELSE}
1022 {$ENDIF}
1045 // ////////////////////////////////////////////////////////////////////////// //
1047 label
1048 _done;
1049 var
1053 begin
1059 // apply gravity
1061 begin
1066 // flying
1068 begin
1069 // has some horizontal velocity
1075 begin
1077 // hit the wall; falling down vertically
1081 end
1083 begin
1084 // has some vertical velocity
1086 begin
1087 // flying up
1091 begin
1092 // oops, hit a ceiling
1097 // environment didn't changed
1098 end
1099 else
1100 begin
1101 // falling down
1105 begin
1106 // hit something except a floor?
1108 // otherwise, go to sleep
1111 // environment didn't changed
1116 _done:
1117 if (x < g_Map_MinX) or (y < g_Map_MinY) or (x > g_Map_MaxX) or (y > g_Map_MaxY) then begin die(); end;
1122 begin
1131 // ////////////////////////////////////////////////////////////////////////// //
1133 var
1138 begin
1151 begin
1153 begin
1157 // check for level bounds
1160 // in what environment we are starting in?
1163 begin
1164 // either in a wall, or in a liquid
1165 //if ((pan.tag and GridTagObstacle) <> 0) then continue; // don't spawn in walls
1166 //env := TEnvType.ELiquid;
1167 continue;
1168 end
1169 else
1170 begin
1178 begin
1204 var
1211 begin
1232 begin
1234 begin
1238 // check for level bounds
1241 // in what environment we are starting in?
1244 begin
1245 // either in a wall, or in a liquid
1246 //if ((pan.tag and GridTagObstacle) <> 0) then continue; // don't spawn in walls
1247 //env := TEnvType.ELiquid;
1248 continue;
1249 end
1250 else
1251 begin
1278 // ////////////////////////////////////////////////////////////////////////// //
1280 var
1282 begin
1293 begin
1299 var
1301 begin
1305 begin
1307 Exit;
1311 begin
1314 end
1315 else
1316 begin
1324 var
1326 begin
1342 // ////////////////////////////////////////////////////////////////////////// //
1343 // st: set mark
1344 // t: mark type
1345 // currently unused
1347 var
1350 begin
1354 // make some border, so we'll hit particles lying around the panel
1361 begin
1364 begin
1373 // ////////////////////////////////////////////////////////////////////////// //
1375 begin
1376 //g_Game_SetLoadingText(_lc[I_LOAD_COLLIDE_MAP]+' 1/6', 0, False);
1377 //SetLength(gCollideMap, gMapInfo.Height+1);
1378 //for a := 0 to High(gCollideMap) do SetLength(gCollideMap[a], gMapInfo.Width+1);
1380 {$IFDEF HEADLESS}
1382 {$ENDIF}
1387 var
1389 begin
1396 begin
1402 // why not?
1408 // ////////////////////////////////////////////////////////////////////////// //
1410 var
1414 begin
1418 begin
1425 begin
1427 begin
1429 begin
1438 // clear awake map
1442 begin
1445 begin
1447 ONCEANIM_SMOKE:
1448 begin
1457 begin
1460 end
1461 else
1469 var
1471 begin
1475 begin
1486 begin
1488 begin
1490 begin
1503 begin
1506 begin
1508 begin