1. the TEXT is one of the events not triggered by anything you type into a channel or query window, so the "!" prefix has no effect and can be removed.

2. *karp* matches those 4 letters anywhere in the line, but in this case i doubt it would ever be part of a normal word.

3. This is the way I often see these delays used, but often I see 2 kinds of delays, where there's 1 cooldown delay for the entire channel as a whole, and a different cooldown delay for each nick. Rather than creating dynamic variables, you can avoid that by using them in a hash table:
on *:TEXT:*karp*:#:{
  if ($hget(karp,$nick) || $hget(karp,$chan)) { echo $chan karp thief cooldown time is in session. No stealing yet. | return }
  hadd -mu30 karp $chan $chan
  hadd -mu60 karp $chan $nick
  describe $chan steals the karp and brings it to PP!

4. The hash table disappears from memory, and can only be saved, by saving it to a disk file with the /hsave command or then retrieved from disk with the /hload command. This also avoids the small chance that your temporary variable gets saved to disk when mIRC saves the variables list to disk, but then your computer crashes before it can be unset 60 seconds later. Then the next time you restart mIRC, the %comwait variable will be there without knowing the variable should be unset. If you'll use global variables, you'd want to have an ON START event to unset any such variables.