d3cc071ad5f4a0a4c1598884ad276bb2176ac699
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`
136 var
141 // awakeMap has one bit for each map grid cell; on g_Mark,
142 // corresponding bits will be set, and in `think()` all particles
143 // in marked cells will be awaken
151 // ////////////////////////////////////////////////////////////////////////// //
152 // HACK! using mapgrid
154 begin
156 begin
164 begin
172 {$IF DEFINED(D2F_DEBUG)}
173 e_LogWritefln('particle awake map: %sx%s (for grid of size %sx%s)', [awakeMapW, awakeMapH, mapGrid.gridWidth, mapGrid.gridHeight]);
174 {$ENDIF}
181 begin
185 begin
186 {$IF DEFINED(D2F_DEBUG)}
188 {$ENDIF}
190 end
191 else
192 begin
199 var
201 begin
205 begin
206 {$IF DEFINED(D2F_DEBUG)}
208 {$ENDIF}
216 // ////////////////////////////////////////////////////////////////////////// //
220 // remove velocities and acceleration
222 begin
223 // stop right there, you criminal scum!
231 // switch to sleep mode
233 begin
240 var
243 begin
245 // stuck in the wall? rescan, 'cause it can be mplat
247 begin
250 begin
251 // either in a wall, or in a liquid
253 begin
254 // we are in the wall, wtf?!
259 exit;
261 // we are in liquid, trace to liquid end
265 // are we in a liquid?
267 begin
268 // trace out of the liquid
269 //env := TEnvType.ELiquid;
271 //e_LogWritefln('tracing out of a liquid; floorY=%s; y=%s', [floorY, y]);
274 //e_LogWritefln(' traced out of a liquid; floorY=%s; y=%s', [floorY, y]);
275 end
276 else
277 begin
278 // in the air
280 //env := TEnvType.EAir;
281 pan := g_Map_traceToNearest(x, y, x, g_Map_MaxY, (GridTagObstacle or GridTagLiquid), @ex, @floorY);
283 begin
284 // wall or liquid
286 begin
287 // wall
289 end
290 else
291 begin
292 // liquid
296 end
297 else
298 begin
299 // out of the level; assume wall, but it doesn't really matter
308 var
310 begin
313 begin
320 begin
321 // awake sleeping particle, if necessary
323 begin
327 begin
344 // ////////////////////////////////////////////////////////////////////////// //
347 begin
355 var
357 begin
361 // find next floor transition
363 // find `wallEndY`
364 mapGrid.traceOrthoRayWhileIn(ex, wallEndY, x+stickDX, y, x+stickDX, floorY+1, (GridTagWall or GridTagDoor or GridTagStep));
368 begin
375 // `true`: didn't, get outa thinker
377 begin
386 // `true`: affected by air stream
388 var
390 begin
394 begin
396 begin
401 end
403 begin
406 end
408 begin
411 end
412 else
413 begin
416 // awake
421 // switch to freefall mode
423 begin
430 begin
433 begin
436 end
437 else
438 begin
444 label
445 _done;
446 var
450 begin
454 begin
455 // still check for air streams when sleeping
456 if (state = TPartState.Sleeping) then begin checkAirStreams(); goto _done; end; // so blood will dissolve
458 // process stuck particles
460 begin
461 // stuck to a ceiling?
463 begin
464 // yeah, stuck to a ceiling
466 // dropped from a ceiling?
468 begin
469 // yep
473 end
474 else
475 begin
476 // otherwise, try to drip
479 end
480 else
481 begin
482 // stuck to a wall
484 // floor transition?
486 begin
490 begin
495 begin
496 // rescan, so we'll know when we'll exit the liquid
500 begin
501 // rescan, so we'll know when we'll enter something interesting
507 // wall transition?
509 begin
510 // just unstuck from the wall, switch to freefall mode
513 end
514 else
515 begin
516 // otherwise, try to drip
520 // nope, process as usual
523 // it is important to have it here
527 // gravity, if not stuck
529 begin
531 // floor transition?
533 begin
536 begin
537 // nothing to do
540 begin
541 // rescan, so we'll know when we'll exit the liquid
546 begin
547 // rescan, so we'll know when we'll enter something interesting
549 if (floorType <> TFloorType.Wall) or (floorY <> y) then applyGravity(floorType = TFloorType.LiquidIn);
552 end
553 else
554 begin
555 // looks like we're in the air
560 // trace movement
562 begin
563 // has some horizontal velocity
569 begin
570 // we stuck
571 // the only case when we can have both ceiling and wall is corner; stick to wall in this case
572 // check environment (air/liquid)
573 if (g_Map_PanelAtPoint(x, y, GridTagLiquid) <> nil) then env := TEnvType.ELiquid else env := TEnvType.EAir;
574 // check if we stuck to a wall
577 begin
578 // stuck to a wall
580 end
581 else
582 begin
583 // stuck to a ceiling
587 end
589 begin
590 // has only vertical velocity
592 begin
593 // flying up
597 // environment didn't changed
598 end
599 else
600 begin
602 begin
603 // falling down
606 //e_LogWritefln('floorY=%s; newy=%s; dY=%s; floorType=%s', [floorY, y, dY, floorType]);
608 begin
609 // floor transition
612 //e_LogWritefln(' HIT FLOORY: floorY=%s; newy=%s; dY=%s; floorType=%s', [floorY, y, dY, floorType]);
615 begin
616 // environment didn't changed
621 begin
622 // we're entered the liquid
624 // rescan, so we'll know when we'll exit the liquid
628 begin
629 // we're exited the liquid
631 // rescan, so we'll know when we'll enter something interesting
634 begin
640 end
641 else
642 begin
649 else
650 begin
651 // simple blood
659 _done:
660 if (x < g_Map_MinX) or (y < g_Map_MinY) or (x > g_Map_MaxX) or (y > g_Map_MaxY) then begin die(); end;
665 // blood will dissolve in other liquids
667 begin
669 begin
677 end
678 else
679 begin
680 // water will disappear in water (?)
687 // ////////////////////////////////////////////////////////////////////////// //
688 procedure g_GFX_SparkVel (fX, fY: Integer; count: Word; vx, vy: Integer; devX, devY: Byte); forward;
694 begin
696 begin
701 end
702 else
703 begin
708 var
714 begin
718 begin
720 exit;
733 begin
735 begin
739 // check for level bounds
742 // in what environment we are starting in?
745 begin
746 // either in a wall, or in a liquid
749 end
750 else
751 begin
759 begin
786 procedure g_GFX_Water (fX, fY: Integer; count: Word; fVelX, fVelY: Single; devX, devY, color: Byte;
788 var
793 begin
810 begin
812 begin
814 begin
823 end
824 else
825 begin
835 // check for level bounds
838 // in what environment we are starting in?
841 begin
842 // either in a wall, or in a liquid
843 //if ((pan.tag and GridTagObstacle) <> 0) then continue; // don't spawn in walls
844 //env := TEnvType.ELiquid;
845 continue;
846 end
847 else
848 begin
852 // color
855 begin
861 begin
867 begin
873 begin
882 begin
891 begin
912 procedure g_GFX_SimpleWater (fX, fY: Integer; count: Word; fVelX, fVelY: Single; defColor, cr, cg, cb: Byte);
913 begin
918 // ////////////////////////////////////////////////////////////////////////// //
920 var
922 begin
926 begin
929 begin
931 end
932 else
933 begin
945 {.$DEFINE D2F_DEBUG_BUBBLES}
947 var
951 {$IF DEFINED(D2F_DEBUG_BUBBLES)}
954 {$ENDIF}
955 begin
968 begin
970 begin
974 // check for level bounds
977 (*
978 // don't spawn bubbles outside of the liquid
979 if not isLiquidAt(X, Y) {ByteBool(gCollideMap[Y, X] and MARK_LIQUID)} then
980 Continue;
981 *)
983 // trace liquid, so we'll know where it ends; do it in 8px steps for speed
984 // tracer will return `false` if we started outside of the liquid
986 {$IF DEFINED(D2F_DEBUG_BUBBLES)}
988 ptr := mapGrid.traceOrthoRayWhileIn(liquidx, liquidTopY, x, y, x, 0, GridTagWater or GridTagAcid1 or GridTagAcid2);
990 e_LogWritefln('traceOrthoRayWhileIn: time=%s (%s); liquidTopY=%s', [Integer(stt), ptr, liquidTopY]);
991 //
995 e_LogWritefln('g_Map_TraceLiquidNonPrecise: time=%s (%s); liquidTopY=%s', [Integer(stt), nptr, liquidTopY]);
997 {$ELSE}
1000 {$ENDIF}
1023 // ////////////////////////////////////////////////////////////////////////// //
1025 label
1026 _done;
1027 var
1031 begin
1037 // apply gravity
1039 begin
1044 // flying
1046 begin
1047 // has some horizontal velocity
1053 begin
1054 // hit the wall; falling down vertically
1058 end
1060 begin
1061 // has some vertical velocity
1063 begin
1064 // flying up
1068 begin
1069 // oops, hit a ceiling
1074 // environment didn't changed
1075 end
1076 else
1077 begin
1078 // falling down
1082 begin
1083 // hit something except a floor?
1085 // otherwise, go to sleep
1088 // environment didn't changed
1093 _done:
1094 if (x < g_Map_MinX) or (y < g_Map_MinY) or (x > g_Map_MaxX) or (y > g_Map_MaxY) then begin die(); end;
1099 begin
1108 // ////////////////////////////////////////////////////////////////////////// //
1110 var
1115 begin
1128 begin
1130 begin
1134 // check for level bounds
1137 // in what environment we are starting in?
1140 begin
1141 // either in a wall, or in a liquid
1142 //if ((pan.tag and GridTagObstacle) <> 0) then continue; // don't spawn in walls
1143 //env := TEnvType.ELiquid;
1144 continue;
1145 end
1146 else
1147 begin
1155 begin
1181 var
1188 begin
1209 begin
1211 begin
1215 // check for level bounds
1218 // in what environment we are starting in?
1221 begin
1222 // either in a wall, or in a liquid
1223 //if ((pan.tag and GridTagObstacle) <> 0) then continue; // don't spawn in walls
1224 //env := TEnvType.ELiquid;
1225 continue;
1226 end
1227 else
1228 begin
1255 // ////////////////////////////////////////////////////////////////////////// //
1257 var
1259 begin
1270 begin
1276 var
1278 begin
1282 begin
1284 Exit;
1288 begin
1291 end
1292 else
1293 begin
1301 var
1303 begin
1319 // ////////////////////////////////////////////////////////////////////////// //
1320 // st: set mark
1321 // t: mark type
1322 // currently unused
1324 var
1327 begin
1331 // make some border, so we'll hit particles lying around the panel
1338 begin
1341 begin
1350 // ////////////////////////////////////////////////////////////////////////// //
1352 begin
1353 //g_Game_SetLoadingText(_lc[I_LOAD_COLLIDE_MAP]+' 1/6', 0, False);
1354 //SetLength(gCollideMap, gMapInfo.Height+1);
1355 //for a := 0 to High(gCollideMap) do SetLength(gCollideMap[a], gMapInfo.Width+1);
1357 {$IFDEF HEADLESS}
1359 {$ENDIF}
1364 var
1366 begin
1373 begin
1379 // why not?
1385 // ////////////////////////////////////////////////////////////////////////// //
1387 var
1391 begin
1395 begin
1402 begin
1404 begin
1406 begin
1415 // clear awake map
1419 begin
1422 begin
1424 ONCEANIM_SMOKE:
1425 begin
1434 begin
1437 end
1438 else
1446 var
1448 begin
1452 begin
1463 begin
1465 begin
1467 begin
1480 begin
1483 begin
1485 begin