The on JOIN won't work exactly like that. If you put the code you currently have it inside a timer to let the rest of the process finish, it will work just fine. Here's the order of events for a channel that already exists:
  1. /JOIN #Channel (typed by the user) { on INPUT }
  2. :MyNick!userid@host.com JOIN :#Channel (everything else if from the server) { on JOIN }
  3. MODE #Channel { done for you by the IRCd (server software) }
  4. 332 MyNick #Channel :www.mirc.com rox! (Topic)
  5. 333 MyNick #Channel MyNick 1040582330 (set by nick and set by ctime)
  6. 353 MyNick = #Channel :MyNick @Op1 @Op2 +Voice1 @Op3 Regular1 Regular2 +Voice2 @Op4 (/NAMES List.)
  7. 366 MyNick #Channel :End of /NAMES list.
  8. 324 MyNick #Channel +stn (channel modes) { on RAWMODE }
  9. 329 MyNick #Channel 991047639 (channel creation ctime)
For an empty channel, 332 and 333 are omitted. From the above list, you can see that on JOIN occurs when mIRC receives #2; therefore, you couldn't possibly tell how many nicks were on the channel since you haven't gotten the nick list in #6 yet.

Probably the best place to check would be when #9 fires, the raw 329. You are unlikely to get this numeric unless it is you joining a channel. You could also set a variable with the channel that you're joining on JOIN and subtract that channel from the variable in the 329. You could check 353 for $4- being equal to $+(:@,$me) or, more precisely, $1 being equal to $me, $2 being equal to =, and $4- being equal to $+(:@,$me). ($2 cannot be * (private channel) or @ (secret channel) yet since it's a brand new channel; it must be = (normal -ps channel).) Thus, your revised code might look like this:
Code:

on !*:PART:#:{
  if (%pchan) echo $color(ctcp) -esti2 * Couldn't cycle $chan to get ops (cycle in progress ( $+ %pchan $+ )). /SaveChan $chan *
  elseif (($nick($chan,0) == 2) && ($me !isop $chan)) SaveChan $chan
}
on *:QUIT:{
  var %i = 1
  while ($comchan($nick,%i)) {
    var %chan = $ifmatch
    if (%pchan) echo $color(ctcp) -esti2 * Couldn't cycle %chan to get ops (cycle in progress ( $+ %pchan $+ )). /SaveChan %chan *
    elseif (($nick(%chan,0) == 2) && ($me !isop %chan)) SaveChan %chan
    inc %i
  }
}
raw 353:*:{
  if (($2 == $chr(61)) && ($3 == %pchan) && ($4- == $+(:@,$me))) {
    MODE %pchan %pchan.mode %pchan.limit %pchan.key
    TOPIC %pchan %pchan.topic)
    unset %pchan*
  }
}
alias SaveChan {
    set -u300 %pchan #$1
    set -u300 %pchan.mode $chan(#$1).mode
    set -u300 %pchan.topic $chan(#$1).topic
    set -u300 %pchan.limit $chan(#$1).limit
    set -u300 %pchan.key $chan(#$1).key
    .raw $+(PART #$1,$crlf,JOIN #$1)
}

Note that it's quite possible to have 2 channels come "empty" at once; it can occur if you and someone else are waiting for 2 or more common channels and they /join 0 or /partall or /quit.

Since I don't think this will really be all that much of a problem, I did not include a queuing mechanism (other than a manual one in the on PART). It wouldn't be difficult; all you'd have to do is save a list of channels that need to be cycled and then SaveChan the next channel inside the previous channel's 353, deleting the new channel from the queue variable.

Note: Another channel setting that might you might want to retain is the banlist prior to leaving the channel and recreating it.


DALnet: #HelpDesk and #m[color:#FF0000]IR[color:#EEEE00]C