Update:
I've implemented client side prediction to show how nice it is and how responsive the game will feel. I posted a video but will explain in text how it works (in case it's easier to understand). As I mentioned in the video, I'm happy to share the code or talk to the devs regarding the solution.
Explanation:
Let's say my my ping is 300. The client starts the cooldown immediately and sends a request to the server telling it that I activated my skill, the server receives the request after (roughly) 150ms and validates that it's not already on cooldown, that I'm in range, etc. and if it passes, it will activate the skill on the server and send a response back to the client telling it whether it was accepted or not.
Even if my client's cooldown is ahead by half of my ping, by the time I send another response, it takes another half of my ping (150ms) to reach the server, so by the time the second request reaches the server, the server's cooldown would have reached 0 and it would be allowed to activate again.
You may have noticed I used the word "roughly" above. This is because in the real world, your ping is never stable and one way ping is not guaranteed to be half of your overall ping (although it's a good enough approximation for most cases). Therefore, we need to handle jitter (ping fluctuation). So let's say my ping fluctuates or all of a sudden my request reaches the server in 100ms instead of 150ms (due to different routing). Well, in this case, the server still has 50ms remaining on the cooldown, so what should the server do? I decided to handle this in my code by have a configurable tolerance value which buffers/queues those skills so that they can be activated when the cooldown completes. If we set this jitter tolerance value to 100ms, then the server would realize that the client's request has come in 50ms too early and since that's below the threshold, it will queue the skill up so that after 50ms it can be activated. If on the other hand my request came in 150ms too early (or if the client is cheating and sends requests way too quickly), the server will simply reject them. This allows things to continue normally even in the face of jitter.
Another thing to point out is that everything on the client is visual - it doesn't need to be, the client can predict hp and mana etc. but this is good enough for now.
The server applies all the effects like healing, damage, etc. so that will still be delayed, but at least cooldowns aren't blocked and can go through.
Server can still reject skills if they're on cooldown, you're out of range, or whatever other reason. Stroke on skillbar slot 7 (in the video) is an example of what it looks like when the server rejects the skill. Only the client that used the skill will see the animation on their side, other clients will not see anything. For others, it's like nothing happened.
Everyone is going to benefit from this. Even for people playing under 100 ping, it's still going to feel a bit more responsive.
Amazing explanation.
Let's hope the devs get on to this right away.