593613e79e07c3f636746a793f63606c3761d859
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 // in what environment we are starting in?
863 begin
864 // either in a wall, or in a liquid
865 //if ((pan.tag and GridTagObstacle) <> 0) then continue; // don't spawn in walls
866 //env := TEnvType.ELiquid;
867 //continue;
869 end
870 else
871 begin
875 // color
878 begin
884 begin
890 begin
896 begin
905 begin
914 begin
935 procedure g_GFX_SimpleWater (fX, fY: Integer; count: Word; fVelX, fVelY: Single; defColor, cr, cg, cb: Byte);
936 begin
941 // ////////////////////////////////////////////////////////////////////////// //
943 var
945 begin
949 begin
952 begin
954 end
955 else
956 begin
968 {.$DEFINE D2F_DEBUG_BUBBLES}
970 var
974 {$IF DEFINED(D2F_DEBUG_BUBBLES)}
977 {$ENDIF}
978 begin
991 begin
993 begin
997 // check for level bounds
1000 (*
1001 // don't spawn bubbles outside of the liquid
1002 if not isLiquidAt(X, Y) {ByteBool(gCollideMap[Y, X] and MARK_LIQUID)} then
1003 Continue;
1004 *)
1006 // trace liquid, so we'll know where it ends; do it in 8px steps for speed
1007 // tracer will return `false` if we started outside of the liquid
1009 {$IF DEFINED(D2F_DEBUG_BUBBLES)}
1011 ptr := mapGrid.traceOrthoRayWhileIn(liquidx, liquidTopY, x, y, x, 0, GridTagWater or GridTagAcid1 or GridTagAcid2);
1013 e_LogWritefln('traceOrthoRayWhileIn: time=%s (%s); liquidTopY=%s', [Integer(stt), ptr, liquidTopY]);
1014 //
1018 e_LogWritefln('g_Map_TraceLiquidNonPrecise: time=%s (%s); liquidTopY=%s', [Integer(stt), nptr, liquidTopY]);
1020 {$ELSE}
1023 {$ENDIF}
1046 // ////////////////////////////////////////////////////////////////////////// //
1048 label
1049 _done;
1050 var
1054 begin
1060 // apply gravity
1062 begin
1067 // flying
1069 begin
1070 // has some horizontal velocity
1076 begin
1078 // hit the wall; falling down vertically
1082 end
1084 begin
1085 // has some vertical velocity
1087 begin
1088 // flying up
1092 begin
1093 // oops, hit a ceiling
1098 // environment didn't changed
1099 end
1100 else
1101 begin
1102 // falling down
1106 begin
1107 // hit something except a floor?
1109 // otherwise, go to sleep
1112 // environment didn't changed
1117 _done:
1118 if (x < g_Map_MinX) or (y < g_Map_MinY) or (x > g_Map_MaxX) or (y > g_Map_MaxY) then begin die(); end;
1123 begin
1132 // ////////////////////////////////////////////////////////////////////////// //
1134 var
1139 begin
1152 begin
1154 begin
1158 // check for level bounds
1161 // in what environment we are starting in?
1164 begin
1165 // either in a wall, or in a liquid
1166 //if ((pan.tag and GridTagObstacle) <> 0) then continue; // don't spawn in walls
1167 //env := TEnvType.ELiquid;
1168 continue;
1169 end
1170 else
1171 begin
1179 begin
1205 var
1212 begin
1233 begin
1235 begin
1239 // check for level bounds
1242 // in what environment we are starting in?
1245 begin
1246 // either in a wall, or in a liquid
1247 //if ((pan.tag and GridTagObstacle) <> 0) then continue; // don't spawn in walls
1248 //env := TEnvType.ELiquid;
1249 continue;
1250 end
1251 else
1252 begin
1279 // ////////////////////////////////////////////////////////////////////////// //
1281 var
1283 begin
1294 begin
1300 var
1302 begin
1306 begin
1308 Exit;
1312 begin
1315 end
1316 else
1317 begin
1325 var
1327 begin
1343 // ////////////////////////////////////////////////////////////////////////// //
1344 // st: set mark
1345 // t: mark type
1346 // currently unused
1348 var
1351 begin
1355 // make some border, so we'll hit particles lying around the panel
1362 begin
1365 begin
1374 // ////////////////////////////////////////////////////////////////////////// //
1376 begin
1377 //g_Game_SetLoadingText(_lc[I_LOAD_COLLIDE_MAP]+' 1/6', 0, False);
1378 //SetLength(gCollideMap, gMapInfo.Height+1);
1379 //for a := 0 to High(gCollideMap) do SetLength(gCollideMap[a], gMapInfo.Width+1);
1381 {$IFDEF HEADLESS}
1383 {$ENDIF}
1388 var
1390 begin
1397 begin
1403 // why not?
1409 // ////////////////////////////////////////////////////////////////////////// //
1411 var
1415 begin
1419 begin
1426 begin
1428 begin
1430 begin
1439 // clear awake map
1443 begin
1446 begin
1448 ONCEANIM_SMOKE:
1449 begin
1458 begin
1461 end
1462 else
1470 var
1472 begin
1476 begin
1487 begin
1489 begin
1491 begin
1504 begin
1507 begin
1509 begin