I consider GM's particle system pretty limited. For instance, if you change the wind direction while rain is falling, the particles already spawned won't be effected. Sure rain particles don't stick around long, but it is noticeable, and just one of many downsides to use the particle system. If you plan to implement slow-motion to the game, you also can't effect particles in any way, unless you manually step them less, which will make them jumpy.
However objects are bloated with tons of built-in variables and take long to create. I'm currently using objects for the rain in my game, and I'm going to change it to use my own particle system that I have yet to make, but maybe you can make it, and see if it works, lol.
So if particles are limited, and objects are slow, what do we do?
Basically just use one rain controller object that handles all the rain. Create a list/array and populate it with information on every rain particle
ex. x, y, xspeed, yspeed, duration
So like, an array would be rain[0] = x, rain[1] = y... etc
Then once it gets to rain[5], we're looking at a different rain drop.
So you can loop through the drops like: for (var i = 0; i < array_length_1d(rain); i += 5)
In the step event, loop through the drops and update their position. Efficient way to do wind would be to check if the wind has changed from last frame, and only update the particles xspeed/yspeed if it has. Also, decrease their duration by 1.
In the draw event, loop through the drops and use the data to call a draw_sprite function.
If you want to have splashes when they hit the ground, you could use the same draw loop as above, and just check if the duration is <= 0 and draw a different sprite at that location. You would also have to keep it from moving, so in the step event, stop having it increment the x and y.
If the splashes do some kind of animation, which they probably should, you gotta be an extra smarty pants.
If the particles hit the ground, it's duration is 0. But as long as you're still decreasing the duration value, it will go into the negatives. You can then use this value to tell the particle which image index to use when it draws the spash.
Creating new drops would basically mean just recycling drops that are done splashing. When it's done with the splash animation, reset it's duration/x/y.
Hopefully this makes sense. If it doesn't, I'll be happy to clarify.