+ ATTRIB(DebugText3d, draw2d, void(DebugText3d), DebugText3d_draw2d);
+ENDCLASS(DebugText3d)
+
+NET_HANDLE(debug_text_3d, bool is_new) {
+ vector pos = ReadVector();
+ string msg = ReadString();
+ float align = ReadFloat();
+ float duration = ReadFloat();
+ vector vel = ReadVector();
+ make_impure(NEW(DebugText3d, pos, msg, align, 1 / duration, vel));
+ return true;
+}
+
+#endif // CSQC
+
+#ifdef SVQC
+
+// can't use autocvars because they give unused warning unless the macros are expanded
+#define debug_text_3d(...) EVAL(OVERLOAD(debug_text_3d, __VA_ARGS__))
+#define debug_text_3d_2(pos, msg) debug_text_3d_3(pos, msg, cvar("debug_text_3d_default_align"))
+#define debug_text_3d_3(pos, msg, align) debug_text_3d_4(pos, msg, align, cvar("debug_text_3d_default_duration"))
+#define debug_text_3d_4(pos, msg, align, dur) debug_text_3d_5(pos, msg, align, dur, stov(cvar_string("debug_text_3d_default_velocity")))
+#define debug_text_3d_5(pos, msg, align, dur, vel) debug_text_3d_fn(pos, msg, align, dur, vel)
+
+ERASEABLE
+void debug_text_3d_fn(vector pos, string msg, float align, float duration, vector velocity) {
+ WriteHeader(MSG_BROADCAST, debug_text_3d);
+ WriteVector(MSG_BROADCAST, pos);
+ WriteString(MSG_BROADCAST, msg);
+ WriteFloat(MSG_BROADCAST, align);
+ WriteFloat(MSG_BROADCAST, duration);
+ WriteVector(MSG_BROADCAST, velocity);