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), CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true);
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), CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true);
vec3_t org, eorg, mins, maxs;
int i, numtouchedicts;
prvm_edict_t *touchedicts[MAX_EDICTS];
+ int chainfield;
- VM_SAFEPARMCOUNT(2, VM_CL_findradius);
+ VM_SAFEPARMCOUNTRANGE(2, 3, 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;
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;
}
}
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++];
}
//============================================================================
// 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;
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;
+
+ 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
+ Matrix4x4_CreateFromQuakeEntity(out, 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);
+}
+
+
+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
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
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);
/*
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)
{
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, 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);