]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - clvm_cmds.c
drawrotpic:
[xonotic/darkplaces.git] / clvm_cmds.c
index beb7db28125a2d16b8e2eff93523bf76597a1045..bf8ae0a176cca4951ccdbd731d27b596218f966b 100644 (file)
@@ -238,6 +238,9 @@ void CL_VM_SetTraceGlobals(const trace_t *trace, int svent)
                val->_float = svent;
 }
 
+#define CL_HitNetworkBrushModels(move) !((move) == MOVE_WORLDONLY)
+#define CL_HitNetworkPlayers(move)     !((move) == MOVE_WORLDONLY || (move) == MOVE_NOMONSTERS)
+
 // #16 float(vector v1, vector v2, float movetype, entity ignore) traceline
 static void VM_CL_traceline (void)
 {
@@ -255,10 +258,10 @@ static void VM_CL_traceline (void)
        move = (int)PRVM_G_FLOAT(OFS_PARM2);
        ent = PRVM_G_EDICT(OFS_PARM3);
 
-       if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v1[2]) || IS_NAN(v2[2]))
+       if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
                PRVM_ERROR("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
 
-       trace = CL_Move(v1, vec3_origin, vec3_origin, v2, move, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
+       trace = CL_Move(v1, vec3_origin, vec3_origin, v2, move, ent, CL_GenericHitSuperContentsMask(ent), CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true);
 
        CL_VM_SetTraceGlobals(&trace, svent);
 }
@@ -293,10 +296,10 @@ static void VM_CL_tracebox (void)
        move = (int)PRVM_G_FLOAT(OFS_PARM4);
        ent = PRVM_G_EDICT(OFS_PARM5);
 
-       if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v1[2]) || IS_NAN(v2[2]))
+       if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
                PRVM_ERROR("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
 
-       trace = CL_Move(v1, m1, m2, v2, move, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
+       trace = CL_Move(v1, m1, m2, v2, move, ent, CL_GenericHitSuperContentsMask(ent), CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true);
 
        CL_VM_SetTraceGlobals(&trace, svent);
 }
@@ -390,7 +393,7 @@ void VM_CL_precache_model (void)
                }
        }
        PRVM_G_FLOAT(OFS_RETURN) = 0;
-       m = Mod_ForName(name, false, false, false);
+       m = Mod_ForName(name, false, false, name[0] == '*' ? cl.model_name[1] : NULL);
        if(m && m->loaded)
        {
                for (i = 0;i < MAX_MODELS;i++)
@@ -432,8 +435,16 @@ static void VM_CL_findradius (void)
        vec3_t                  org, eorg, mins, maxs;
        int                             i, numtouchedicts;
        prvm_edict_t    *touchedicts[MAX_EDICTS];
+       int             chainfield;
+
+       VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_findradius);
 
-       VM_SAFEPARMCOUNT(2, VM_CL_findradius);
+       if(prog->argc == 3)
+               chainfield = PRVM_G_INT(OFS_PARM2);
+       else
+               chainfield = prog->fieldoffsets.chain;
+       if(chainfield < 0)
+               PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
 
        chain = (prvm_edict_t *)prog->edicts;
 
@@ -475,7 +486,7 @@ static void VM_CL_findradius (void)
                        VectorMAMAM(1, eorg, -0.5f, ent->fields.client->mins, -0.5f, ent->fields.client->maxs, eorg);
                if (DotProduct(eorg, eorg) < radius2)
                {
-                       ent->fields.client->chain = PRVM_EDICT_TO_PROG(chain);
+                       PRVM_EDICTFIELDVALUE(ent, chainfield)->edict = PRVM_EDICT_TO_PROG(chain);
                        chain = ent;
                }
        }
@@ -914,7 +925,8 @@ void VM_CL_R_AddDynamicLight (void)
        VectorScale(prog->globals.client->v_up, radius, up);
        Matrix4x4_FromVectors(&matrix, forward, left, up, org);
 
-       R_RTLight_Update(&r_refdef.scene.lights[r_refdef.scene.numlights++], false, &matrix, col, style, cubemapname, castshadow, coronaintensity, coronasizescale, ambientscale, diffusescale, specularscale, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+       R_RTLight_Update(&r_refdef.scene.templights[r_refdef.scene.numlights], false, &matrix, col, style, cubemapname, castshadow, coronaintensity, coronasizescale, ambientscale, diffusescale, specularscale, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+       r_refdef.scene.lights[r_refdef.scene.numlights] = &r_refdef.scene.templights[r_refdef.scene.numlights++];
 }
 
 //============================================================================
@@ -1147,6 +1159,7 @@ static void VM_CL_getinputstate (void)
        int i, frame;
        VM_SAFEPARMCOUNT(1, VM_CL_getinputstate);
        frame = (int)PRVM_G_FLOAT(OFS_PARM0);
+       PRVM_G_FLOAT(OFS_RETURN) = false;
        for (i = 0;i < CL_MAX_USERCMDS;i++)
        {
                if (cl.movecmd[i].sequence == frame)
@@ -1167,6 +1180,7 @@ static void VM_CL_getinputstate (void)
                                VectorCopy(cl.playerstandmins, prog->globals.client->pmove_mins);
                                VectorCopy(cl.playerstandmaxs, prog->globals.client->pmove_maxs);
                        }
+                       PRVM_G_FLOAT(OFS_RETURN) = true;
                }
        }
 }
@@ -1362,7 +1376,7 @@ static void VM_CL_ReadPicture (void)
                {
                        // texture not found
                        // use the attached jpeg as texture
-                       buf = Mem_Alloc(tempmempool, size);
+                       buf = (unsigned char *) Mem_Alloc(tempmempool, size);
                        MSG_ReadBytes(size, buf);
                        data = JPEG_LoadImage_BGRA(buf, size);
                        Mem_Free(buf);
@@ -1403,10 +1417,10 @@ static void VM_CL_makestatic (void)
                // copy it to the current state
                memset(staticent, 0, sizeof(*staticent));
                staticent->render.model = CL_GetModelByIndex((int)ent->fields.client->modelindex);
-               staticent->render.frame1 = staticent->render.frame2 = (int)ent->fields.client->frame;
-               staticent->render.framelerp = 0;
+               staticent->render.framegroupblend[0].frame = (int)ent->fields.client->frame;
+               staticent->render.framegroupblend[0].lerp = 1;
                // make torchs play out of sync
-               staticent->render.frame1time = staticent->render.frame2time = lhrandom(-10, -1);
+               staticent->render.framegroupblend[0].start = lhrandom(-10, -1);
                staticent->render.skinnum = (int)ent->fields.client->skin;
                staticent->render.effects = (int)ent->fields.client->effects;
                staticent->render.alpha = 1;
@@ -2170,6 +2184,78 @@ int CL_GetTagIndex (prvm_edict_t *e, const char *tagname)
                return -1;
 };
 
+int CL_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
+{
+       int r;
+       dp_model_t *model;
+       int frame;
+
+       *tagname = NULL;
+       *parentindex = 0;
+       Matrix4x4_CreateIdentity(tag_localmatrix);
+
+       if (tagindex >= 0
+        && (model = CL_GetModelFromEdict(e))
+        && model->animscenes)
+       {
+               frame = (int)e->fields.client->frame;
+               if (frame < 0 || frame >= model->numframes)
+                       frame = 0;
+
+               r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)e->fields.client->skin, model->animscenes[frame].firstframe, tagindex - 1, parentindex, tagname, tag_localmatrix);
+
+               if(!r) // success?
+                       *parentindex += 1;
+
+               return r;
+       }
+
+       return 1;
+}
+
+void CL_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
+{
+       prvm_eval_t *val;
+       float scale;
+       float pitchsign;
+       dp_model_t *model;
+
+       scale = 1;
+       val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
+       if (val && val->_float != 0)
+               scale = val->_float;
+
+       // TODO do we need the same weird angle inverting logic here as in the server side case?
+       if(viewmatrix)
+               Matrix4x4_CreateFromQuakeEntity(out, cl.csqc_origin[0], cl.csqc_origin[1], cl.csqc_origin[2], cl.csqc_angles[0], cl.csqc_angles[1], cl.csqc_angles[2], scale * cl_viewmodel_scale.value);
+       else
+       {
+               pitchsign = 1;
+               if ((model = CL_GetModelFromEdict(ent)) && model->type == mod_alias)
+                       pitchsign = -1;
+               Matrix4x4_CreateFromQuakeEntity(out, ent->fields.client->origin[0], ent->fields.client->origin[1], ent->fields.client->origin[2], pitchsign * ent->fields.client->angles[0], ent->fields.client->angles[1], ent->fields.client->angles[2], scale);
+       }
+}
+
+
+int CL_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
+{
+       int frame;
+       dp_model_t *model;
+       if (tagindex >= 0
+        && (model = CL_GetModelFromEdict(ent))
+        && model->animscenes)
+       {
+               // if model has wrong frame, engine automatically switches to model first frame
+               frame = (int)ent->fields.client->frame;
+               if (frame < 0 || frame >= model->numframes)
+                       frame = 0;
+               return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
+       }
+       *out = identitymatrix;
+       return 0;
+}
+
 // Warnings/errors code:
 // 0 - normal (everything all-right)
 // 1 - world entity
@@ -2182,12 +2268,11 @@ extern cvar_t cl_bobcycle;
 extern cvar_t cl_bobup;
 int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
 {
+       int ret;
        prvm_eval_t *val;
-       int reqframe, attachloop;
+       int attachloop;
        matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
-       prvm_edict_t *attachent;
        dp_model_t *model;
-       float scale;
 
        *out = identitymatrix; // warnings and errors return identical matrix
 
@@ -2197,80 +2282,40 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
                return 2;
 
        model = CL_GetModelFromEdict(ent);
-
        if(!model)
                return 3;
 
-       if (ent->fields.client->frame >= 0 && ent->fields.client->frame < model->numframes && model->animscenes)
-               reqframe = model->animscenes[(int)ent->fields.client->frame].firstframe;
-       else
-               reqframe = 0; // if model has wrong frame, engine automatically switches to model first frame
-
-       // get initial tag matrix
-       if (tagindex)
+       tagmatrix = identitymatrix;
+       attachloop = 0;
+       for(;;)
        {
-               int ret = Mod_Alias_GetTagMatrix(model, reqframe, tagindex - 1, &tagmatrix);
-               if (ret)
+               if(attachloop >= 256)
+                       return 5;
+               // apply transformation by child's tagindex on parent entity and then
+               // by parent entity itself
+               ret = CL_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
+               if(ret && attachloop == 0)
                        return ret;
-       }
-       else
-               tagmatrix = identitymatrix;
-
-       if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
-       { // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
-               attachloop = 0;
-               do
+               CL_GetEntityMatrix(ent, &entitymatrix, false);
+               Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
+               Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
+               // next iteration we process the parent entity
+               if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
                {
-                       attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached
-                       val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index);
-
-                       model = CL_GetModelFromEdict(attachent);
-
-                       if (model && val->_float >= 1 && model->animscenes && attachent->fields.client->frame >= 0 && attachent->fields.client->frame < model->numframes)
-                               Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.client->frame].firstframe, (int)val->_float - 1, &attachmatrix);
-                       else
-                               attachmatrix = identitymatrix;
-
-                       // apply transformation by child entity matrix
-                       scale = 1;
-                       val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
-                       if (val && val->_float != 0)
-                               scale = val->_float;
-                       Matrix4x4_CreateFromQuakeEntity(&entitymatrix, ent->fields.client->origin[0], ent->fields.client->origin[1], ent->fields.client->origin[2], -ent->fields.client->angles[0], ent->fields.client->angles[1], ent->fields.client->angles[2], scale);
-                       Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
-                       Matrix4x4_Copy(&tagmatrix, out);
-
-                       // finally transformate by matrix of tag on parent entity
-                       Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
-                       Matrix4x4_Copy(&tagmatrix, out);
-
-                       ent = attachent;
-                       attachloop += 1;
-                       if (attachloop > 255) // prevent runaway looping
-                               return 5;
+                       tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
+                       ent = PRVM_EDICT_NUM(val->edict);
                }
-               while ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict);
+               else
+                       break;
+               attachloop++;
        }
 
-       // normal or RENDER_VIEWMODEL entity (or main parent entity on attach chain)
-       scale = 1;
-       val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
-       if (val && val->_float != 0)
-               scale = val->_float;
-       // Alias models have inverse pitch, bmodels can't have tags, so don't check for modeltype...
-       Matrix4x4_CreateFromQuakeEntity(&entitymatrix, ent->fields.client->origin[0], ent->fields.client->origin[1], ent->fields.client->origin[2], -ent->fields.client->angles[0], ent->fields.client->angles[1], ent->fields.client->angles[2], scale);
-       Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
-
+       // RENDER_VIEWMODEL magic
        if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.renderflags)) && (RF_VIEWMODEL & (int)val->_float))
-       {// RENDER_VIEWMODEL magic
+       {
                Matrix4x4_Copy(&tagmatrix, out);
 
-               scale = 1;
-               val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
-               if (val && val->_float != 0)
-                       scale = val->_float;
-
-               Matrix4x4_CreateFromQuakeEntity(&entitymatrix, cl.csqc_origin[0], cl.csqc_origin[1], cl.csqc_origin[2], cl.csqc_angles[0], cl.csqc_angles[1], cl.csqc_angles[2], scale);
+               CL_GetEntityMatrix(prog->edicts, &entitymatrix, true);
                Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
 
                /*
@@ -2340,14 +2385,35 @@ void VM_CL_gettaginfo (void)
        prvm_edict_t *e;
        int tagindex;
        matrix4x4_t tag_matrix;
+       matrix4x4_t tag_localmatrix;
+       int parentindex;
+       const char *tagname;
        int returncode;
+       prvm_eval_t *val;
+       vec3_t fo, le, up, trans;
 
        VM_SAFEPARMCOUNT(2, VM_CL_gettaginfo);
 
        e = PRVM_G_EDICT(OFS_PARM0);
        tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
        returncode = CL_GetTagMatrix(&tag_matrix, e, tagindex);
-       Matrix4x4_ToVectors(&tag_matrix, prog->globals.client->v_forward, prog->globals.client->v_right, prog->globals.client->v_up, PRVM_G_VECTOR(OFS_RETURN));
+       Matrix4x4_ToVectors(&tag_matrix, prog->globals.client->v_forward, le, prog->globals.client->v_up, PRVM_G_VECTOR(OFS_RETURN));
+       VectorScale(le, -1, prog->globals.client->v_right);
+       CL_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
+       Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
+
+       if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_parent)))
+               val->_float = parentindex;
+       if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_name)))
+               val->string = tagname ? PRVM_SetTempString(tagname) : 0;
+       if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_offset)))
+               VectorCopy(trans, val->vector);
+       if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_forward)))
+               VectorCopy(fo, val->vector);
+       if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_right)))
+               VectorScale(le, -1, val->vector);
+       if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_up)))
+               VectorCopy(up, val->vector);
 
        switch(returncode)
        {
@@ -2798,7 +2864,7 @@ realcheck:
        start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
        start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
        stop[2] = start[2] - 2*sv_stepheight.value;
-       trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
+       trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, false, NULL, true);
 
        if (trace.fraction == 1.0)
                return false;
@@ -2811,7 +2877,7 @@ realcheck:
                        start[0] = stop[0] = x ? maxs[0] : mins[0];
                        start[1] = stop[1] = y ? maxs[1] : mins[1];
 
-                       trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true);
+                       trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, false, NULL, true);
 
                        if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
                                bottom = trace.endpos[2];
@@ -3358,7 +3424,7 @@ VM_drawresetcliparea,                     // #325 void(void) drawresetcliparea
 VM_drawcolorcodedstring,               // #326 float drawcolorcodedstring(vector position, string text, vector scale, vector rgb, float alpha, float flag) (EXT_CSQC)
 VM_stringwidth,                 // #327 // FIXME is this okay?
 VM_drawsubpic,                                 // #328 // FIXME is this okay?
-NULL,                                                  // #329
+VM_drawrotpic,                                 // #329 // FIXME is this okay?
 VM_CL_getstatf,                                        // #330 float(float stnum) getstatf (EXT_CSQC)
 VM_CL_getstati,                                        // #331 float(float stnum) getstati (EXT_CSQC)
 VM_CL_getstats,                                        // #332 string(float firststnum) getstats (EXT_CSQC)
@@ -3547,11 +3613,22 @@ VM_uri_get,                                             // #513 float(string uril, float id) uri_get = #512; (DP_QC_URI
 VM_tokenize_console,                                   // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
 VM_argv_start_index,                                   // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
 VM_argv_end_index,                                             // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
-VM_buf_cvarlist,                                               // #517 void(float buf, string prefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
+VM_buf_cvarlist,                                               // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
 VM_cvar_description,                                   // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
-NULL,                                                  // #519
+VM_gettime,                                            // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
 VM_keynumtostring,                             // #520 string keynumtostring(float keynum)
 VM_findkeysforcommand,         // #521 string findkeysforcommand(string command)
+NULL,                                                  // #522
+NULL,                                                  // #523
+NULL,                                                  // #524
+NULL,                                                  // #525
+NULL,                                                  // #526
+NULL,                                                  // #527
+NULL,                                                  // #528
+NULL,                                                  // #529
+NULL,                                                  // #530
+NULL,                                  // #531
+NULL,                                                  // #532
 };
 
 const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);