+static void VM_CL_RotateMoves(prvm_prog_t *prog)
+{
+ /*
+ * Obscure builtin used by GAME_XONOTIC.
+ *
+ * Edits the input history of cl_movement by rotating all move commands
+ * currently in the queue using the given transform.
+ *
+ * The vector passed is an "angles transform" as used by warpzonelib, i.e.
+ * v_angle-like (non-inverted) euler angles that perform the rotation
+ * of the space that is to be done.
+ *
+ * This is meant to be used as a fixangle replacement after passing
+ * through a warpzone/portal: the client is told about the warp transform,
+ * and calls this function in the same frame as the one on which the
+ * client's origin got changed by the serverside teleport. Then this code
+ * transforms the pre-warp input (which matches the empty space behind
+ * the warp plane) into post-warp input (which matches the target area
+ * of the warp). Also, at the same time, the client has to use
+ * R_SetView to adjust VF_CL_VIEWANGLES according to the same transform.
+ *
+ * This together allows warpzone motion to be perfectly predicted by
+ * the client!
+ *
+ * Furthermore, for perfect warpzone behaviour, the server side also
+ * has to detect input the client sent before it received the origin
+ * update, but after the warp occurred on the server, and has to adjust
+ * input appropriately.
+ */
+ matrix4x4_t m;
+ vec3_t v = {0, 0, 0};
+ vec3_t a, x, y, z;
+ VM_SAFEPARMCOUNT(1, VM_CL_RotateMoves);
+ VectorCopy(PRVM_G_VECTOR(OFS_PARM0), a);
+ AngleVectorsFLU(a, x, y, z);
+ Matrix4x4_FromVectors(&m, x, y, z, v);
+ CL_RotateMoves(&m);
+}
+
+// #358 void(string cubemapname) loadcubemap
+static void VM_CL_loadcubemap(prvm_prog_t *prog)
+{
+ const char *name;
+
+ VM_SAFEPARMCOUNT(1, VM_CL_loadcubemap);
+ name = PRVM_G_STRING(OFS_PARM0);
+ R_GetCubemap(name);
+}
+
+#define REFDEFFLAG_TELEPORTED 1
+#define REFDEFFLAG_JUMPING 2
+#define REFDEFFLAG_DEAD 4
+#define REFDEFFLAG_INTERMISSION 8
+static void VM_CL_V_CalcRefdef(prvm_prog_t *prog)
+{
+ matrix4x4_t entrendermatrix;
+ vec3_t clviewangles;
+ vec3_t clvelocity;
+ qboolean teleported;
+ qboolean clonground;
+ qboolean clcmdjump;
+ qboolean cldead;
+ qboolean clintermission;
+ float clstatsviewheight;
+ prvm_edict_t *ent;
+ int flags;
+
+ VM_SAFEPARMCOUNT(2, VM_CL_V_CalcRefdef);
+ ent = PRVM_G_EDICT(OFS_PARM0);
+ flags = PRVM_G_FLOAT(OFS_PARM1);
+
+ // use the CL_GetTagMatrix function on self to ensure consistent behavior (duplicate code would be bad)
+ CL_GetTagMatrix(prog, &entrendermatrix, ent, 0);
+
+ VectorCopy(cl.csqc_viewangles, clviewangles);
+ teleported = (flags & REFDEFFLAG_TELEPORTED) != 0;
+ clonground = ((int)PRVM_clientedictfloat(ent, pmove_flags) & PMF_ONGROUND) != 0;
+ clcmdjump = (flags & REFDEFFLAG_JUMPING) != 0;
+ clstatsviewheight = PRVM_clientedictvector(ent, view_ofs)[2];
+ cldead = (flags & REFDEFFLAG_DEAD) != 0;
+ clintermission = (flags & REFDEFFLAG_INTERMISSION) != 0;
+ VectorCopy(PRVM_clientedictvector(ent, velocity), clvelocity);
+
+ V_CalcRefdefUsing(&entrendermatrix, clviewangles, teleported, clonground, clcmdjump, clstatsviewheight, cldead, clintermission, clvelocity);
+
+ VectorCopy(cl.csqc_vieworiginfromengine, cl.csqc_vieworigin);
+ VectorCopy(cl.csqc_viewanglesfromengine, cl.csqc_viewangles);
+ CSQC_R_RecalcView();
+}
+