DEADSOFTWARE

add stub opengl wrapper and remove nanogl wrapper.
[d2df-sdl.git] / src / game / g_gfx.pas
index 01ada5245edcbb7606cfd4ffdd3f12af364719b6..8094c4e4e1af00e578f2f6d82d70340e75c565f0 100644 (file)
@@ -2,8 +2,7 @@
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * the Free Software Foundation, version 3 of the License ONLY.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -26,6 +25,8 @@ uses
 const
   BLOOD_NORMAL = 0;
   BLOOD_SPARKS = 1;
+  BLOOD_CSPARKS = 2;
+  BLOOD_COMBINE = 3;
 
   ONCEANIM_NONE  = 0;
   ONCEANIM_SMOKE = 1;
@@ -78,11 +79,7 @@ function awmIsSetHolmes (x, y: Integer): Boolean; inline;
 implementation
 
 uses
-{$IFDEF USE_NANOGL}
-  nanoGL,
-{$ELSE}
-  GL, GLExt,
-{$ENDIF}
+  {$INCLUDE ../nogl/noGLuses.inc}
   g_map, g_panel, g_basic, Math, e_graphics,
   g_options, g_console, SysUtils, g_triggers, MAPDEF,
   g_game, g_language, g_net, utils, xprofiler;
@@ -112,7 +109,7 @@ type
     particleType: TPartType;
     red, green, blue: Byte;
     alpha: Byte;
-    time, liveTime: Word;
+    time, liveTime, waitTime: Word;
     stickDX: Integer; // STATE_STICK: -1,1: stuck to a wall; 0: stuck to ceiling
     justSticked: Boolean; // not used
     floorY: Integer; // actually, floor-1; `Unknown`: unknown
@@ -336,31 +333,38 @@ end;
 function TParticle.checkAirStreams (): Boolean;
 var
   pan: TPanel;
+  r: Integer;
 begin
   pan := g_Map_PanelAtPoint(x, y, GridTagLift);
-  result := (pan <> nil);
+  result := (pan <> nil) and WordBool(pan.PanelType and (PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT));
+  r := Random(3);
   if result then
   begin
-    if ((pan.PanelType and PANEL_LIFTUP) <> 0) then
-    begin
-      if (velY > -4-Random(3)) then velY -= 0.8;
-      if (abs(velX) > 0.1) then velX -= velX/10.0;
-      velX += (Random-Random)*0.2;
-      accelY := 0.15;
-    end
-    else if ((pan.PanelType and PANEL_LIFTLEFT) <> 0) then
-    begin
-      if (velX > -8-Random(3)) then velX -= 0.8;
-      accelY := 0.15;
-    end
-    else if ((pan.PanelType and PANEL_LIFTRIGHT) <> 0) then
-    begin
-      if (velX < 8+Random(3)) then velX += 0.8;
-      accelY := 0.15;
-    end
-    else
-    begin
-      result := false;
+    case pan.LiftType of
+      LIFTTYPE_UP:
+      begin
+        if (velY > -1-r) then velY -= 0.8;
+        if (abs(velX) > 0.1) then velX -= velX/10.0;
+        velX += (Random-Random)*0.2;
+        accelY := 0.15;
+      end;
+      LIFTTYPE_DOWN:
+      begin
+        if (velY < 1+r) then velY += 0.8;
+        accelY := 0.15;
+      end;
+      LIFTTYPE_LEFT:
+      begin
+        if (velX > -8-r) then velX -= (8+r) div 2;
+        accelY := 0.15;
+      end;
+      LIFTTYPE_RIGHT:
+      begin
+        if (velX < 8+r) then velX += (8+r) div 2;
+        accelY := 0.15;
+      end;
+      else
+        result := false;
     end;
     // awake
     if result and (state = TPartState.Sleeping) then state := TPartState.Normal;
@@ -452,7 +456,7 @@ var
   ex: Integer;
 begin
   if (not force) and (ceilingY <> Unknown) then exit;
-  if (nil = g_Map_traceToNearest(x, y, x, g_Map_MinY, GridTagObstacle, @ex, @ceilingY)) then
+  if (nil = g_Map_traceToNearest(x, y, x, g_Map_MinY, GridTagSolid, @ex, @ceilingY)) then
   begin
     ceilingY := g_Map_MinY-2;
   end;
@@ -594,7 +598,7 @@ var
   pan: TPanel;
   dx, dy: SmallInt;
   ex, ey: Integer;
-  checkEnv: Boolean;
+  checkEnv, inAir, inStep: Boolean;
   floorJustTraced: Boolean;
   {$IF DEFINED(D2F_DEBUG_FALL_MPLAT)}
   oldFloorY: Integer;
@@ -690,7 +694,7 @@ begin
     dx := round(velX);
     dy := round(velY);
 
-    if (state = TPartState.Normal) then checkAirStreams();
+    inAir := checkAirStreams();
 
     // gravity, if not stuck
     if (state <> TPartState.Stuck) and (abs(velX) < 0.1) and (abs(velY) < 0.1) then
@@ -738,7 +742,24 @@ begin
     if (dx <> 0) then
     begin
       // has some horizontal velocity
-      pan := g_Map_traceToNearest(x, y, x+dx, y+dy, GridTagObstacle, @ex, @ey);
+      inStep := False;
+      pan := g_Map_traceToNearest(x, y, x+dx, y+dy, GridTagSolid, @ex, @ey);
+      if (pan = nil) and (dy >= 0) then
+      begin
+        // do not stuck inside step
+        if g_Map_traceToNearest(x, y, x, y, GridTagStep, nil, nil) = nil then
+          // check for step panel below
+          pan := g_Map_traceToNearest(x, y, x, y+dy, GridTagStep, nil, @ey);
+        inStep := pan <> nil;
+        if inStep then
+        begin
+          // stick to panel edges
+          if ex < pan.X then
+            ex := pan.X
+          else if ex > pan.X + pan.Width - 1 then
+            ex := pan.X + pan.Width - 1;
+        end;
+      end;
       checkEnv := (x <> ex);
       x := ex;
       y := ey;
@@ -752,19 +773,24 @@ begin
       end;
       if (pan <> nil) then
       begin
-        // we stuck
-        // the only case when we can have both ceiling and wall is corner; stick to wall in this case
-        // check if we stuck to a wall
-        if (dx < 0) then dx := -1 else dx := 1;
-        if (g_Map_PanelAtPoint(x+dx, y, GridTagObstacle) <> nil) then
-        begin
-          // stuck to a wall
-          stickToWall(dx);
-        end
+        if inStep then
+          stickToWall(dx)
         else
         begin
-          // stuck to a ceiling
-          stickToCeiling();
+          // we stuck
+          // the only case when we can have both ceiling and wall is corner; stick to wall in this case
+          // check if we stuck to a wall
+          if (dx < 0) then dx := -1 else dx := 1;
+          if (g_Map_PanelAtPoint(x+dx, y, GridTagSolid) <> nil) then
+          begin
+            // stuck to a wall
+            stickToWall(dx);
+          end
+          else
+          begin
+            // stuck to a ceiling
+            stickToCeiling();
+          end;
         end;
       end;
     end
@@ -815,7 +841,7 @@ begin
                     if (y <> floorY) then continue;
                   end;
                   // environment didn't changed
-                  hitAFloor();
+                  if not inAir then hitAFloor();
                   break; // done with vertical movement
                 end;
               TFloorType.LiquidIn: // entering the liquid
@@ -833,7 +859,7 @@ begin
                   findFloor(true); // force rescan
                   if (floorType = TFloorType.Wall) and (floorY = y) then
                   begin
-                    hitAFloor();
+                    if not inAir then hitAFloor();
                     break; // done with vertical movement
                   end;
                 end;
@@ -868,7 +894,10 @@ _done:
   begin
     if (env = TEnvType.ELiquid) then
     begin
-      time += 1;
+      if waitTime > 0 then
+        waitTime -= 1
+      else
+        time += 1;
       if (liveTime <= 0) then begin die(); exit; end;
       ex := 255-trunc(255.0*time/liveTime);
       if (ex <= 10) then begin die(); exit; end;
@@ -880,7 +909,10 @@ _done:
   begin
     // water will disappear in any liquid
     if (env = TEnvType.ELiquid) then begin die(); exit; end;
-    time += 1;
+    if waitTime > 0 then
+      waitTime -= 1
+    else
+      time += 1;
     // dry water
     if (liveTime <= 0) then begin die(); exit; end;
     ex := 255-trunc(255.0*time/liveTime);
@@ -925,6 +957,11 @@ begin
   begin
     g_GFX_SparkVel(fX, fY, 2+Random(2), -vx div 2, -vy div 2, devX, devY);
     exit;
+  end
+  else if (kind = BLOOD_CSPARKS) OR (kind = BLOOD_COMBINE) then
+  begin
+    g_GFX_SparkVel(fX, fY, count, -vx div 2, -vy div 2, devX, devY);
+    if kind <> BLOOD_COMBINE then exit
   end;
 
   l := Length(Particles);
@@ -947,11 +984,11 @@ begin
       if (x < g_Map_MinX) or (y < g_Map_MinY) or (x > g_Map_MaxX) or (y > g_Map_MaxY) then continue;
 
       // in what environment we are starting in?
-      pan := g_Map_PanelAtPoint(x, y, (GridTagObstacle or GridTagLiquid));
+      pan := g_Map_PanelAtPoint(x, y, (GridTagSolid or GridTagLiquid));
       if (pan <> nil) then
       begin
         // either in a wall, or in a liquid
-        if ((pan.tag and GridTagObstacle) <> 0) then continue; // don't spawn in walls
+        if ((pan.tag and GridTagSolid) <> 0) then continue; // don't spawn in walls
         env := TEnvType.ELiquid;
       end
       else
@@ -981,6 +1018,7 @@ begin
       state := TPartState.Normal;
       time := 0;
       liveTime := 120+Random(40);
+      waitTime := 20;
       floorY := Unknown;
       ceilingY := Unknown;
     end;
@@ -1107,6 +1145,7 @@ begin
       state := TPartState.Normal;
       time := 0;
       liveTime := 60+Random(60);
+      waitTime := 120;
       floorY := Unknown;
       ceilingY := Unknown;
     end;
@@ -1145,7 +1184,10 @@ begin
 
   if (velY > -4) then velY += accelY;
 
-  time += 1;
+  if waitTime > 0 then
+    waitTime -= 1
+  else
+    time += 1;
 end;
 
 
@@ -1220,6 +1262,7 @@ begin
       particleType := TPartType.Bubbles;
       time := 0;
       liveTime := 65535;
+      waitTime := 0;
     end;
 
     if (CurrentParticle >= MaxParticles-1) then CurrentParticle := 0 else CurrentParticle += 1;
@@ -1254,7 +1297,7 @@ begin
   if (dx <> 0) then
   begin
     // has some horizontal velocity
-    pan := g_Map_traceToNearest(x, y, x+dx, y+dy, (GridTagObstacle or GridTagLiquid), @ex, @ey);
+    pan := g_Map_traceToNearest(x, y, x+dx, y+dy, (GridTagSolid or GridTagLiquid), @ex, @ey);
     if (x <> ex) then begin floorY := Unknown; ceilingY := Unknown; end; // dunno yet
     x := ex;
     y := ey;
@@ -1313,7 +1356,10 @@ _done:
 
   //writeln('spark1: pos=(', x, ',', y, '); delta=(', velX:6:3, ',', velY:6:3, '); state=', state, '; ceilingY=', ceilingY, '; floorY=', floorY);
 
-  time += 1;
+  if waitTime > 0 then
+    waitTime -= 1
+  else
+    time += 1;
 end;
 
 
@@ -1347,11 +1393,11 @@ begin
       if (x < g_Map_MinX) or (y < g_Map_MinY) or (x > g_Map_MaxX) or (y > g_Map_MaxY) then continue;
 
       // in what environment we are starting in?
-      pan := g_Map_PanelAtPoint(x, y, (GridTagObstacle or GridTagLiquid));
+      pan := g_Map_PanelAtPoint(x, y, (GridTagSolid or GridTagLiquid));
       if (pan <> nil) then
       begin
         // either in a wall, or in a liquid
-        //if ((pan.tag and GridTagObstacle) <> 0) then continue; // don't spawn in walls
+        //if ((pan.tag and GridTagSolid) <> 0) then continue; // don't spawn in walls
         //env := TEnvType.ELiquid;
         continue;
       end
@@ -1380,6 +1426,7 @@ begin
       state := TPartState.Normal;
       time := 0;
       liveTime := 30+Random(60);
+      waitTime := 0;
       floorY := Unknown;
       ceilingY := Unknown;
     end;
@@ -1428,11 +1475,11 @@ begin
       if (x < g_Map_MinX) or (y < g_Map_MinY) or (x > g_Map_MaxX) or (y > g_Map_MaxY) then continue;
 
       // in what environment we are starting in?
-      pan := g_Map_PanelAtPoint(x, y, (GridTagObstacle or GridTagLiquid));
+      pan := g_Map_PanelAtPoint(x, y, (GridTagSolid or GridTagLiquid));
       if (pan <> nil) then
       begin
         // either in a wall, or in a liquid
-        //if ((pan.tag and GridTagObstacle) <> 0) then continue; // don't spawn in walls
+        //if ((pan.tag and GridTagSolid) <> 0) then continue; // don't spawn in walls
         //env := TEnvType.ELiquid;
         continue;
       end
@@ -1455,6 +1502,7 @@ begin
       state := TPartState.Normal;
       time := 0;
       liveTime := 30+Random(60);
+      waitTime := 0;
       floorY := Unknown;
       ceilingY := Unknown;
     end;
@@ -1626,17 +1674,6 @@ end;
 procedure g_GFX_Draw ();
   var
     a, len: Integer;
-{$IFDEF USE_NANOGL}
-  type
-    PVertex = ^Vertex;
-    Vertex = record
-      x, y: GLfloat;
-      r, g, b, a: GLfloat;
-    end;
-  var
-    count: Integer;
-    v: PVertex;
-{$ENDIF}
 begin
   if not gpart_dbg_enabled then exit;
 
@@ -1651,37 +1688,6 @@ begin
     glEnable(GL_BLEND);
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
-{$IFDEF USE_NANOGL}
-    len := High(Particles);
-    v := GetMem(len * SizeOf(Vertex) + 1);
-    count := 0;
-    for a := 0 to len do
-    begin
-      with Particles[a] do
-      begin
-        if alive and (x >= sX) and (y >= sY) and (x <= sX + sWidth) and (sY <= sY + sHeight) then
-        begin
-          v[count].x := x + 0.37;
-          v[count].y := y + 0.37;
-          v[count].r := red / 255;
-          v[count].g := green / 255;
-          v[count].b := blue / 255;
-          v[count].a := alpha / 255;
-          Inc(count);
-        end;
-      end;
-    end;
-
-    glVertexPointer(2, GL_FLOAT, SizeOf(Vertex), @v.x);
-    glColorPointer(4, GL_FLOAT, SizeOf(Vertex), @v.r);
-    glEnableClientState(GL_VERTEX_ARRAY);
-    glEnableClientState(GL_COLOR_ARRAY);
-    glDisableClientState(GL_NORMAL_ARRAY);
-    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-    glDrawArrays(GL_POINTS, 0, count - 1);
-
-    Dispose(v);
-{$ELSE}
     glBegin(GL_POINTS);
 
     len := High(Particles);
@@ -1699,7 +1705,6 @@ begin
     end;
 
     glEnd();
-{$ENDIF}
 
     glDisable(GL_BLEND);
   end;