Okay, so I tried a hybrid approach here - keeping the existing code for rendering the blocks (and cracks on them etc), but using Z buffer for sprites. Although it does have the "sprite partially disappears into deflector / slope" issue, this is not too severe and I think it's better than the downright odd stuff that was happening with the existing code.
The code for blocks seems to mostly get things right - it's when sprites (which can be taller than blocks) get thrown into the mix that things get weird, generally. However if there are still issues, I can look at going into a full BSP tree approach for the blocks.
There's also one special case, to avoid Z-fighting - when hatch flaps are completely closed, they get treated as block faces rather than sprites. Similar special cases need to be added for a few other things too; namely teleporters, spring landing pads, and trampolines; but this is trickier to do as they'd need to be seperated out from other objects during the rendering.