"You must construct additional pylons!"

Python 3, 207*.9 == 186.3 bytes.

Implements the nexus bonus.
Saved 26 bytes thanks to DSM.
Saved 2 bytes thanks to Tim Pederick

x,*l=input().split()
d=-((int(x)*8-sum((('vexuobcl'+2*'clsuie'+4*'Ratahoiesuhihi').count(q[-3:-1])*(1-12*(q[0]>'w'))or 2)for q in l))//8)
print((1,"You must construct %s additional pylon"%d+'s!'[d<2:])[d>0])

JavaScript, 274 265 bytes (no bonuses) 281 - 10% = 252.9 bytes

s=>(c=eval(s[a="replace"](" ","-(")[a](/ /g,"+")[a](/\w+/g,m=>m[b="match"](/^(Pr|Ob)/g)?1:m[b](/^([ZSHDWP]|M\w+C)/g)?2:m[b](/^O/g)?3:m[b](/^[IAVT]/g)?4:m[b](/^N/g)?-11:m[b](/^C/g)?6:+m!=m?8:m*8)+")"))>0?true:`You must construct ${Math.ceil(-c/8)} additional pylon${c/8<-1?"s":""}!`

This appears to be pretty lengthy...

Demo + explanation:

p = s => (c = eval(
  s[a = "replace"](" ", "-(")         //replace the first space (after the number of pylons) with "-" and open the bracket
   [a](/ /g, "+")                       //replace all the remaining spaces with "+"
   [a](/\w+/g, m =>                     //replace any sequence of characters with...
    m[b = "match"](/^(Pr|Ob)/g) ? 1 :   //with 1, if matches "Probe" or "Observer"
    m[b](/^([ZSHDWP]|M\w+C)/g) ? 2 :    //with 2, if it matches bunch of the units with cost 2. "Probe" didn't match already, so it's safe to catch "Phoenix" by only the first letter.
    m[b](/^O/g) ? 3 :                   //with 3, if match is "Oracle"
    m[b](/^[IAVT]/g) ? 4 :              //with 4, if matches "Immortal", "Archon", "VoidRay" or "Tempest"
    m[b](/^C/g) ? 6 :                   //with 6, if it's "Carrier" or "Colossus"
    m[b](/^N/g) ? -11 :                 //don't forget nexuses!
    +m != m ? 8 : m * 8                 //and if's not a number, then it's "Mothership", so with 8. If it's number, it can only be the number of pylons, replace it with itself multiplied by 8.
  ) + ")"                             //close the opened bracket
)) > 0 ? true : `You must construct ${Math.ceil(-c/8)} additional pylon${c/8<-1?"s":""}!`

document.write(
  p("2 Probe Probe Probe Probe Stalker Zealot Carrier Probe Zealot") + "<br>" +
  p("5 Mothership Carrier Probe Tempest HighTemplar") + "<br>" +
  p("0 Mothership Colossus Zealot") + "<br>" +
  p("0 Probe Nexus Probe")
)


Python 3, 293 − 30% = 205.1 bytes

Implements both bonuses. Prints 1 as its truthy value, and either 0 or an empty string as its falsey value.

s='5N 8O5P bDbHeM7P6S7S9W6Z 6O 6A8I7T7V . 7C8C . aM'.split()
m=M=n=o=0
p,*u=input().split()
for v in u:
 S=0
 while'%x'%len(v)+v[0]not in s[S]:S+=1
 n+=S or-11;M+=S>7;m+='pC'in v;o+=m>1or M>1or m<1<=M
q=int(p)+n//-8
print([1,'You must construct %d additional pylon'%-q+'s!'[q>-2:]][q<0]*(o<1))

Credit to Dom Hastings' solution for helping me shave off a good few bytes with a "poor man's ceil" of my own, and Morgan Thrapp's for the idea underlying 's!'[q>-2:], which saved me six bytes—not to mention pointing out, in the comments, how to save another byte on that bit.


Explanations

The string in line 1 encodes all of the units and their supply requirements. Each unit is represented as two characters: a hexadecimal digit giving the length of the unit's name, and the first character of the name (e.g. 8O is the Observer; aM is the Mothership). The supply requirement is the index of the encoded unit within the sequence s, formed by splitting the string on the spaces. Full stops mark unused amounts of supply (no unit needs 5 or 7 supply), and as a special case, the Nexus (5N) is at index 0.

Line 2 initialises values: m is the number of mothership cores, M is the number of motherships, n is the total supply cost, and o indicates whether or not the mothership build conditions have been violated. Line 3 takes the input, putting the number of pylons into p and the list of units into u.

Within the loop that starts at line 4, S is an index into s and, thus, also the amount of supply needed for the current unit, v. In line 6, the while statement steps through s until the unit is found. ('%x'%len(v) turns the length of the unit's name into a hex digit.)

Line 7 updates the total supply cost n (note the special case, -11, if S is zero). It then increments the counts of motherships M (identified by the supply cost being over 7) and mothership cores m (identified by the substring pC in the unit's name). Then, if either of these is greater than 1, or if M is at least one while m is still zero, the flag o is set. (Actually, it's incremented, but later on we only care if it's zero or non-zero.)

The pylon deficit q is calculated, a little oddly, in line 8. Naively, it should be n // 8 - int(p) (i.e. one eighth of the supply cost, minus any pylons we already have). But that would round down, when we need to round up. Integer division (//) rounds towards negative infinity, though, so we just work everything in negatives: int(p) - -(n // -8), which simplifies to the form actually used.

Lastly, the output. If we're just one pylon short, q will be -1, hence the test q>-2 (which slices the s out of the string s! if true, and keeps it otherwise). If there's no pylon deficit, q will be zero or positive, hence q<0 to select between the truthy value 1 or the output string. Lastly, if the flag o isn't zero, multiplying either result (1 or a string) by Boolean False (handled as numeric 0) will give a falsey value (0 or the empty string).