Hamilton is coming to town
Perl 6, 198 bytes (264 bytes - 25% bonus)

Managed to actually get this sucker into a Whatever block by inlining the helper functions from the original version. 



*.permutations.map({([+] -1,5*@_,|(for (0,0),|@_ Z |@_,(0,0) -&gt;((\i,\j),(\x,\y)){my ($s,\p)=0,i.Rat.nude[1]*j.Rat.nude[1]*abs(i -x).Rat.nude[0];(i+(x -i)*$_/p)%%1&amp;&amp;(j+(y -j)*$_/p)%%1&amp;&amp;$s++ for ^p;sqrt(abs(i -x)²+abs(j -y)²)+(p??$s!!abs(j.Int -y.Int))})),@_}).min


Try it online!

No doubt there are still a few little improvements that can be made.  Trickiest part was figuring out how to calculate the number of lattice points crossed.  The solution I went with uses the denominators of each X coordinate to calculate an iteration interval that is guaranteed to hit each whole number along with X axis, thus allowing a check for landing on a lattice point.  There is a catch, of course, that if there is no movement along X then the lattice points crossed will be the absolute value of the floor value of each Y coordinate.

This will be, nonetheless, very tricky for languages that don't have built in rationals, because of floating point errors (I can already see the .1 + .2 = .3 issue cropping up if any two X or Y coordinates are 10 apart).

Ungolfed version:

*                           #  Whatever block, takes a list of coordinates
.permutations.map({         #  Get all combinations and to each of them ... 
 (                          #   Implicitly return a list consisting of 
  [+]                       #    The sum of
   -1,                      #     -1 (to discount lattice +1 on return to origin)
   5*@_,                    #     5 * number of coordinates (or stops)
   |(for                    #     each value in the loop across 
    (0,0),|@_ Z |@_,(0,0)   #      the coordinates (zipping with the origin 
                            #        first/last for the return)
    -&gt;((\i,\j),(\x,\y)) {   #      deconstructing into i,j,x,y
     my ($s,\p)=0,          #      set S (lattice stops) to 0
       i.Rat.nude[1]        #      set P (x check interval) to denominator of i
       *j.Rat.nude[1]       #       times denominator of p (psuedo lcm)
       *abs(i -x).Rat.nude[0]; #    times x-diff numerator (bc Rat simplification) 
     (i+(x -i)*$_/p)%%1&amp;&amp;   #      check X is whole, if so,
      (j+(y -j)*$_/p)%%1&amp;&amp;  #       check Y is whole, if so,
      $s++                  #        increment S (trip crossed a lattice point)           
     for ^p;                #      do the checks for 0 to P
     sqrt(                  #      implicitly return
      abs(i -x)²+abs(j -y)² #       the distance
     )+(p                   #        plus, if X values were different,
      ??$s                  #         S value, else
      !!abs(j.Int -y.Int)   #         Y difference = vertical lattice crossings
     )
    }                            
   )                        #     
   ,@_)                     #   And the permutation
.min                        #  Find best (smallest) time 


I'll probably add a more readable version because this golfing got unreadable fast.