V1:
%next is set to be greater than $ctime, so the conditional "%next < $ctime" is never going to be $true

V2:
If %next is $null, the conditional "%next < $ctime" cannot be $true because $null is neither less than or greater than any number. If %next is initialized with 0, it can execute the V2 code, but instead of showing the message 15 seconds later, what is happening instead is that the message displays immediately, but only if there has been at least 15 seconds since someone joined the channel.

If you want to display a message after a 15 seconds delay, you would use a timer. As long as your timer is not given an $identifier as part of its command line and is not using text supplied by another nick, you shouldn't have to worry about unpleasant evaluation results. You can send a message 15 seconds after join like:

Code:
ON *:JOIN:#: {
  timer 1 15 msg $nick Hello
}

In this case, giving $nick as part of the /timer's command line is ok, as long as you're not on a non-standard network which permits a nick to begin with % or $. If you use this script, you will find yourself banned from many channels for spamming a query to everyone who joins that channel, so you should change :#: into :#channelname: so it triggers only at your channel. You may also wish to use /notice instead of /msg.

There are also ways to verify that the nick has not left or changed to a different nick within those 15 seconds, but that's probably beyond what you're looking for.

Without a timer, the only way to have the /msg be performed within the :JOIN: event is to have a loop that freezes your mIRC for 15 seconds, making it non-responsive to the keyboard or screen during that period. Using a /timer allows the message to happen 15 seconds after it exits the JOIN event.