DEADSOFTWARE

GFX: Properly check for lift direction
[d2df-sdl.git] / src / game / g_gfx.pas
index cbb1c9783f85d0fac4606c479a008da95994f0e1..64b62e8d7682fdbc14f270b7dd01dc4c2645f3a6 100644 (file)
@@ -26,6 +26,8 @@ uses
 const
   BLOOD_NORMAL = 0;
   BLOOD_SPARKS = 1;
+  BLOOD_CSPARKS = 2;
+  BLOOD_COMBINE = 3;
 
   ONCEANIM_NONE  = 0;
   ONCEANIM_SMOKE = 1;
@@ -78,7 +80,8 @@ function awmIsSetHolmes (x, y: Integer): Boolean; inline;
 implementation
 
 uses
-  g_map, g_panel, g_basic, Math, e_graphics, GL, GLExt,
+  {$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;
 
@@ -107,7 +110,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
@@ -331,31 +334,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;
@@ -589,7 +599,7 @@ var
   pan: TPanel;
   dx, dy: SmallInt;
   ex, ey: Integer;
-  checkEnv: Boolean;
+  checkEnv, inAir: Boolean;
   floorJustTraced: Boolean;
   {$IF DEFINED(D2F_DEBUG_FALL_MPLAT)}
   oldFloorY: Integer;
@@ -685,7 +695,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
@@ -810,7 +820,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
@@ -828,7 +838,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;
@@ -863,7 +873,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;
@@ -875,7 +888,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);
@@ -920,6 +936,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);
@@ -976,6 +997,7 @@ begin
       state := TPartState.Normal;
       time := 0;
       liveTime := 120+Random(40);
+      waitTime := 20;
       floorY := Unknown;
       ceilingY := Unknown;
     end;
@@ -1102,6 +1124,7 @@ begin
       state := TPartState.Normal;
       time := 0;
       liveTime := 60+Random(60);
+      waitTime := 120;
       floorY := Unknown;
       ceilingY := Unknown;
     end;
@@ -1140,7 +1163,10 @@ begin
 
   if (velY > -4) then velY += accelY;
 
-  time += 1;
+  if waitTime > 0 then
+    waitTime -= 1
+  else
+    time += 1;
 end;
 
 
@@ -1215,6 +1241,7 @@ begin
       particleType := TPartType.Bubbles;
       time := 0;
       liveTime := 65535;
+      waitTime := 0;
     end;
 
     if (CurrentParticle >= MaxParticles-1) then CurrentParticle := 0 else CurrentParticle += 1;
@@ -1308,7 +1335,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;
 
 
@@ -1375,6 +1405,7 @@ begin
       state := TPartState.Normal;
       time := 0;
       liveTime := 30+Random(60);
+      waitTime := 0;
       floorY := Unknown;
       ceilingY := Unknown;
     end;
@@ -1450,6 +1481,7 @@ begin
       state := TPartState.Normal;
       time := 0;
       liveTime := 30+Random(60);
+      waitTime := 0;
       floorY := Unknown;
       ceilingY := Unknown;
     end;
@@ -1619,8 +1651,18 @@ end;
 
 
 procedure g_GFX_Draw ();
-var
-  a, len: Integer;
+  var
+    a, len: Integer;
+{$IFDEF USE_NANOGL}
+  type
+    Vertex = record
+      x, y: GLfloat;
+      r, g, b, a: GLfloat;
+    end;
+  var
+    count: Integer;
+    v: array of Vertex;
+{$ENDIF}
 begin
   if not gpart_dbg_enabled then exit;
 
@@ -1635,6 +1677,34 @@ begin
     glEnable(GL_BLEND);
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
+{$IFDEF USE_NANOGL}
+    count := 0;
+    SetLength(v, Length(Particles));
+    for a := 0 to High(Particles) 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[0].x);
+    glColorPointer(4, GL_FLOAT, SizeOf(Vertex), @v[0].r);
+    glEnableClientState(GL_VERTEX_ARRAY);
+    glEnableClientState(GL_COLOR_ARRAY);
+    glDisableClientState(GL_NORMAL_ARRAY);
+    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+    glDrawArrays(GL_POINTS, 0, count);
+{$ELSE}
     glBegin(GL_POINTS);
 
     len := High(Particles);
@@ -1652,6 +1722,7 @@ begin
     end;
 
     glEnd();
+{$ENDIF}
 
     glDisable(GL_BLEND);
   end;