anchor.diff:    CornerY := Loc.Y + (BA.MoveY + R.Pivot[ID].Y + R.Size[ID].Y) / CELL_SIZE_PX - 1
                      - fTerrain.Land[Loc.Y + 1, Loc.X].Height / CELL_HEIGHT_DIV;
     fRenderList.AddSprite(aRX, ID, CornerX, CornerY);
  +end;
  +
  +
  +//aRenderPos has fTerrain.HeightAt factored in already, aTilePos is on tile coordinates for Z ordering
  +procedure TRenderPool.AddProjectile(aProj: TProjectileType; aRenderPos, aTilePos: TKMPointF; aDir: TKMDirection; aFlight: Single);
  +var
  +  FOW: Byte;
  +  ID: Integer;
  +  R: TRXData;
  +  CornerX,CornerY: Single;
  +  Ground: Single;
  +begin
  +  //We don't care about off-map arrows, but still we get TKMPoint error if X/Y gets negative
  +  if not fTerrain.TileInMapCoords(Round(aRenderPos.X), Round(aRenderPos.Y)) then Exit;
  +
  +  FOW := MyPlayer.FogOfWar.CheckTileRevelation(Round(aRenderPos.X), Round(aRenderPos.Y), True);
  +  if FOW <= 128 then Exit; //Don't render objects which are behind FOW
  +
  +  case aProj of
  +    pt_Arrow:     with fResource.UnitDat[ut_Bowman].UnitAnim[ua_Spec, aDir] do
  +                    ID := Step[Round(Min(aFlight, 1) * Count) + 1] + 1;
  +    pt_Bolt:      with fResource.UnitDat[ut_Arbaletman].UnitAnim[ua_Spec, aDir] do
  +                    ID := Step[Round(Min(aFlight, 1) * Count) + 1] + 1;
  +    pt_SlingRock: with fResource.UnitDat[ut_Slingshot].UnitAnim[ua_Spec, aDir] do
  +                    ID := Step[Round(Min(aFlight, 1) * Count) + 1] + 1;
  +    pt_TowerRock: ID := ProjectileBounds[aProj, 1] + 1;
  +    else          ID := 1; //Nothing?
  +  end;
  +
  +  R := fRXData[rxUnits];
  +
  +  CornerX := R.Pivot[ID].X / CELL_SIZE_PX - 1;
  +  CornerY := (R.Pivot[ID].Y + R.Size[ID].Y) / CELL_SIZE_PX - 1;
  +
  +  case aProj of
  +    pt_Arrow, pt_Bolt, pt_SlingRock:  Ground := aTilePos.Y + (0.5 - Abs(Min(aFlight, 1) - 0.5)) - 0.5;
  +    pt_TowerRock:                     Ground := aTilePos.Y + Min(aFlight, 1)/5 - 0.4;
  +    else                              Ground := aTilePos.Y - 1; //Nothing?
  +  end;
  +
  +  fRenderList.AddSprite(rxUnits, ID, aRenderPos.X + CornerX, aRenderPos.Y + CornerY, aTilePos.X - 1, Ground);
   end;
   
   
  
positive.code:     if fTerrain.Land[I, K].Obj <> 255 then
        RenderObjectOrQuad(fTerrain.Land[I, K].Obj + 1, AnimStep, K, I);
  
    with fTerrain do
      for I := 0 to FallingTrees.Count - 1 do
      begin
        RenderObject(FallingTrees.Tag[I] + 1, AnimStep - FallingTrees.Tag2[I], FallingTrees[I].X, FallingTrees[I].Y);
        Assert(AnimStep - FallingTrees.Tag2[I] <= 100, 'Falling tree overrun?');
      end;
  end;
  
  
  //aRenderPos has fTerrain.HeightAt factored in already, aTilePos is on tile coordinates for Z ordering
  procedure TRenderPool.AddProjectile(aProj: TProjectileType; aRenderPos, aTilePos: TKMPointF; aDir: TKMDirection; aFlight: Single);
  var
    FOW: Byte;
    ID: Integer;
    R: TRXData;
    CornerX,CornerY: Single;
    Ground: Single;
  begin
    //We don't care about off-map arrows, but still we get TKMPoint error if X/Y gets negative
    if not fTerrain.TileInMapCoords(Round(aRenderPos.X), Round(aRenderPos.Y)) then Exit;
  
    FOW := MyPlayer.FogOfWar.CheckTileRevelation(Round(aRenderPos.X), Round(aRenderPos.Y), True);
    if FOW <= 128 then Exit; //Don't render objects which are behind FOW
  
    case aProj of
      pt_Arrow:     with fResource.UnitDat[ut_Bowman].UnitAnim[ua_Spec, aDir] do
                      ID := Step[Round(Min(aFlight, 1) * Count) + 1] + 1;
      pt_Bolt:      with fResource.UnitDat[ut_Arbaletman].UnitAnim[ua_Spec, aDir] do
                      ID := Step[Round(Min(aFlight, 1) * Count) + 1] + 1;
      pt_SlingRock: with fResource.UnitDat[ut_Slingshot].UnitAnim[ua_Spec, aDir] do
                      ID := Step[Round(Min(aFlight, 1) * Count) + 1] + 1;
      pt_TowerRock: ID := ProjectileBounds[aProj, 1] + 1;
      else          ID := 1; //Nothing?
    end;
  
    R := fRXData[rxUnits];
  
    CornerX := R.Pivot[ID].X / CELL_SIZE_PX - 1;
    CornerY := (R.Pivot[ID].Y + R.Size[ID].Y) / CELL_SIZE_PX - 1;
  
    case aProj of
      pt_Arrow, pt_Bolt, pt_SlingRock:  Ground := aTilePos.Y + (0.5 - Abs(Min(aFlight, 1) - 0.5)) - 0.5;
      pt_TowerRock:                     Ground := aTilePos.Y + Min(aFlight, 1)/5 - 0.4;
      else                              Ground := aTilePos.Y - 1; //Nothing?
    end;
  
    fRenderList.AddSprite(rxUnits, ID, aRenderPos.X + CornerX, aRenderPos.Y + CornerY, aTilePos.X - 1, Ground);
  end;
  
  
  
negative.code:     glLineWidth(fGame.Viewport.Zoom * 2);
      glPointSize(fGame.Viewport.Zoom * 5);
  
      //Background
      RenderTerrain;
  
      //Sprites are added by Terrain/Players/Projectiles, then sorted by position
      RenderSprites;
  
      //Cursor overlays (including wire plans)
      RenderCursors;
  
      if DISPLAY_SOUNDS then fSoundLib.Paint;
    glPopAttrib;
  end;
  
  
  procedure TRenderPool.RenderTerrainTiles(aRect: TKMRect; AnimStep: Integer);
  