X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=csprogs.c;h=51253f3b59899b1ac1ca5d1c95344f65ee9dd216;hp=b4e62c980d40626d2349e5fb59a2daf4fe7320cf;hb=4134bf6102c7d2c50c55658757a7e43cee244cb3;hpb=d79bf352070fe96997e0622c73019a08cb67fff9 diff --git a/csprogs.c b/csprogs.c index b4e62c98..51253f3b 100644 --- a/csprogs.c +++ b/csprogs.c @@ -5,6 +5,7 @@ #include "cl_collision.h" #include "snd_main.h" #include "clvm_cmds.h" +#include "prvm_cmds.h" //============================================================================ // Client prog handling @@ -18,18 +19,16 @@ static prvm_prog_t *csqc_tmpprog; void CL_VM_PreventInformationLeaks(void) { - prvm_eval_t *val; if(!cl.csqc_loaded) return; CSQC_BEGIN VM_ClearTraceGlobals(); - if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_networkentity))) - val->_float = 0; + PRVM_clientglobalfloat(trace_networkentity) = 0; CSQC_END } //[515]: these are required funcs -static char *cl_required_func[] = +static const char *cl_required_func[] = { "CSQC_Init", "CSQC_InputEvent", @@ -39,6 +38,164 @@ static char *cl_required_func[] = static int cl_numrequiredfunc = sizeof(cl_required_func) / sizeof(char*); +#define CL_REQFIELDS (sizeof(cl_reqfields) / sizeof(prvm_required_field_t)) + +prvm_required_field_t cl_reqfields[] = +{ +#define PRVM_DECLARE_serverglobalfloat(x) +#define PRVM_DECLARE_serverglobalvector(x) +#define PRVM_DECLARE_serverglobalstring(x) +#define PRVM_DECLARE_serverglobaledict(x) +#define PRVM_DECLARE_serverglobalfunction(x) +#define PRVM_DECLARE_clientglobalfloat(x) +#define PRVM_DECLARE_clientglobalvector(x) +#define PRVM_DECLARE_clientglobalstring(x) +#define PRVM_DECLARE_clientglobaledict(x) +#define PRVM_DECLARE_clientglobalfunction(x) +#define PRVM_DECLARE_menuglobalfloat(x) +#define PRVM_DECLARE_menuglobalvector(x) +#define PRVM_DECLARE_menuglobalstring(x) +#define PRVM_DECLARE_menuglobaledict(x) +#define PRVM_DECLARE_menuglobalfunction(x) +#define PRVM_DECLARE_serverfieldfloat(x) +#define PRVM_DECLARE_serverfieldvector(x) +#define PRVM_DECLARE_serverfieldstring(x) +#define PRVM_DECLARE_serverfieldedict(x) +#define PRVM_DECLARE_serverfieldfunction(x) +#define PRVM_DECLARE_clientfieldfloat(x) {ev_float, #x }, +#define PRVM_DECLARE_clientfieldvector(x) {ev_vector, #x }, +#define PRVM_DECLARE_clientfieldstring(x) {ev_string, #x }, +#define PRVM_DECLARE_clientfieldedict(x) {ev_entity, #x }, +#define PRVM_DECLARE_clientfieldfunction(x) {ev_function, #x }, +#define PRVM_DECLARE_menufieldfloat(x) +#define PRVM_DECLARE_menufieldvector(x) +#define PRVM_DECLARE_menufieldstring(x) +#define PRVM_DECLARE_menufieldedict(x) +#define PRVM_DECLARE_menufieldfunction(x) +#define PRVM_DECLARE_serverfunction(x) +#define PRVM_DECLARE_clientfunction(x) +#define PRVM_DECLARE_menufunction(x) +#define PRVM_DECLARE_field(x) +#define PRVM_DECLARE_global(x) +#define PRVM_DECLARE_function(x) +#include "prvm_offsets.h" +#undef PRVM_DECLARE_serverglobalfloat +#undef PRVM_DECLARE_serverglobalvector +#undef PRVM_DECLARE_serverglobalstring +#undef PRVM_DECLARE_serverglobaledict +#undef PRVM_DECLARE_serverglobalfunction +#undef PRVM_DECLARE_clientglobalfloat +#undef PRVM_DECLARE_clientglobalvector +#undef PRVM_DECLARE_clientglobalstring +#undef PRVM_DECLARE_clientglobaledict +#undef PRVM_DECLARE_clientglobalfunction +#undef PRVM_DECLARE_menuglobalfloat +#undef PRVM_DECLARE_menuglobalvector +#undef PRVM_DECLARE_menuglobalstring +#undef PRVM_DECLARE_menuglobaledict +#undef PRVM_DECLARE_menuglobalfunction +#undef PRVM_DECLARE_serverfieldfloat +#undef PRVM_DECLARE_serverfieldvector +#undef PRVM_DECLARE_serverfieldstring +#undef PRVM_DECLARE_serverfieldedict +#undef PRVM_DECLARE_serverfieldfunction +#undef PRVM_DECLARE_clientfieldfloat +#undef PRVM_DECLARE_clientfieldvector +#undef PRVM_DECLARE_clientfieldstring +#undef PRVM_DECLARE_clientfieldedict +#undef PRVM_DECLARE_clientfieldfunction +#undef PRVM_DECLARE_menufieldfloat +#undef PRVM_DECLARE_menufieldvector +#undef PRVM_DECLARE_menufieldstring +#undef PRVM_DECLARE_menufieldedict +#undef PRVM_DECLARE_menufieldfunction +#undef PRVM_DECLARE_serverfunction +#undef PRVM_DECLARE_clientfunction +#undef PRVM_DECLARE_menufunction +#undef PRVM_DECLARE_field +#undef PRVM_DECLARE_global +#undef PRVM_DECLARE_function +}; + +#define CL_REQGLOBALS (sizeof(cl_reqglobals) / sizeof(prvm_required_field_t)) + +prvm_required_field_t cl_reqglobals[] = +{ +#define PRVM_DECLARE_serverglobalfloat(x) +#define PRVM_DECLARE_serverglobalvector(x) +#define PRVM_DECLARE_serverglobalstring(x) +#define PRVM_DECLARE_serverglobaledict(x) +#define PRVM_DECLARE_serverglobalfunction(x) +#define PRVM_DECLARE_clientglobalfloat(x) {ev_float, #x}, +#define PRVM_DECLARE_clientglobalvector(x) {ev_vector, #x}, +#define PRVM_DECLARE_clientglobalstring(x) {ev_string, #x}, +#define PRVM_DECLARE_clientglobaledict(x) {ev_entity, #x}, +#define PRVM_DECLARE_clientglobalfunction(x) {ev_function, #x}, +#define PRVM_DECLARE_menuglobalfloat(x) +#define PRVM_DECLARE_menuglobalvector(x) +#define PRVM_DECLARE_menuglobalstring(x) +#define PRVM_DECLARE_menuglobaledict(x) +#define PRVM_DECLARE_menuglobalfunction(x) +#define PRVM_DECLARE_serverfieldfloat(x) +#define PRVM_DECLARE_serverfieldvector(x) +#define PRVM_DECLARE_serverfieldstring(x) +#define PRVM_DECLARE_serverfieldedict(x) +#define PRVM_DECLARE_serverfieldfunction(x) +#define PRVM_DECLARE_clientfieldfloat(x) +#define PRVM_DECLARE_clientfieldvector(x) +#define PRVM_DECLARE_clientfieldstring(x) +#define PRVM_DECLARE_clientfieldedict(x) +#define PRVM_DECLARE_clientfieldfunction(x) +#define PRVM_DECLARE_menufieldfloat(x) +#define PRVM_DECLARE_menufieldvector(x) +#define PRVM_DECLARE_menufieldstring(x) +#define PRVM_DECLARE_menufieldedict(x) +#define PRVM_DECLARE_menufieldfunction(x) +#define PRVM_DECLARE_serverfunction(x) +#define PRVM_DECLARE_clientfunction(x) +#define PRVM_DECLARE_menufunction(x) +#define PRVM_DECLARE_field(x) +#define PRVM_DECLARE_global(x) +#define PRVM_DECLARE_function(x) +#include "prvm_offsets.h" +#undef PRVM_DECLARE_serverglobalfloat +#undef PRVM_DECLARE_serverglobalvector +#undef PRVM_DECLARE_serverglobalstring +#undef PRVM_DECLARE_serverglobaledict +#undef PRVM_DECLARE_serverglobalfunction +#undef PRVM_DECLARE_clientglobalfloat +#undef PRVM_DECLARE_clientglobalvector +#undef PRVM_DECLARE_clientglobalstring +#undef PRVM_DECLARE_clientglobaledict +#undef PRVM_DECLARE_clientglobalfunction +#undef PRVM_DECLARE_menuglobalfloat +#undef PRVM_DECLARE_menuglobalvector +#undef PRVM_DECLARE_menuglobalstring +#undef PRVM_DECLARE_menuglobaledict +#undef PRVM_DECLARE_menuglobalfunction +#undef PRVM_DECLARE_serverfieldfloat +#undef PRVM_DECLARE_serverfieldvector +#undef PRVM_DECLARE_serverfieldstring +#undef PRVM_DECLARE_serverfieldedict +#undef PRVM_DECLARE_serverfieldfunction +#undef PRVM_DECLARE_clientfieldfloat +#undef PRVM_DECLARE_clientfieldvector +#undef PRVM_DECLARE_clientfieldstring +#undef PRVM_DECLARE_clientfieldedict +#undef PRVM_DECLARE_clientfieldfunction +#undef PRVM_DECLARE_menufieldfloat +#undef PRVM_DECLARE_menufieldvector +#undef PRVM_DECLARE_menufieldstring +#undef PRVM_DECLARE_menufieldedict +#undef PRVM_DECLARE_menufieldfunction +#undef PRVM_DECLARE_serverfunction +#undef PRVM_DECLARE_clientfunction +#undef PRVM_DECLARE_menufunction +#undef PRVM_DECLARE_field +#undef PRVM_DECLARE_global +#undef PRVM_DECLARE_function +}; + void CL_VM_Error (const char *format, ...) DP_FUNC_PRINTF(1); void CL_VM_Error (const char *format, ...) //[515]: hope it will be never executed =) { @@ -61,192 +218,177 @@ void CL_VM_Error (const char *format, ...) //[515]: hope it will be never execut } void CL_VM_UpdateDmgGlobals (int dmg_take, int dmg_save, vec3_t dmg_origin) { - prvm_eval_t *val; if(cl.csqc_loaded) { CSQC_BEGIN - val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.dmg_take); - if(val) - val->_float = dmg_take; - val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.dmg_save); - if(val) - val->_float = dmg_save; - val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.dmg_origin); - if(val) - { - val->vector[0] = dmg_origin[0]; - val->vector[1] = dmg_origin[1]; - val->vector[2] = dmg_origin[2]; - } + PRVM_clientglobalfloat(dmg_take) = dmg_take; + PRVM_clientglobalfloat(dmg_save) = dmg_save; + VectorCopy(dmg_origin, PRVM_clientglobalvector(dmg_origin)); CSQC_END } } void CSQC_UpdateNetworkTimes(double newtime, double oldtime) { - prvm_eval_t *val; if(!cl.csqc_loaded) return; CSQC_BEGIN - if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.servertime))) - val->_float = newtime; - if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.serverprevtime))) - val->_float = oldtime; - if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.serverdeltatime))) - val->_float = newtime - oldtime; + PRVM_clientglobalfloat(servertime) = newtime; + PRVM_clientglobalfloat(serverprevtime) = oldtime; + PRVM_clientglobalfloat(serverdeltatime) = newtime - oldtime; CSQC_END } //[515]: set globals before calling R_UpdateView, WEIRD CRAP +void CSQC_R_RecalcView (void); static void CSQC_SetGlobals (void) { - prvm_eval_t *val; CSQC_BEGIN - prog->globals.client->time = cl.time; - prog->globals.client->frametime = max(0, cl.time - cl.oldtime); - prog->globals.client->servercommandframe = cls.servermovesequence; - prog->globals.client->clientcommandframe = cl.movecmd[0].sequence; - VectorCopy(cl.viewangles, prog->globals.client->input_angles); - VectorCopy(cl.viewangles, cl.csqc_angles); + PRVM_clientglobalfloat(time) = cl.time; + PRVM_clientglobalfloat(frametime) = max(0, cl.time - cl.oldtime); + PRVM_clientglobalfloat(servercommandframe) = cls.servermovesequence; + PRVM_clientglobalfloat(clientcommandframe) = cl.movecmd[0].sequence; + VectorCopy(cl.viewangles, PRVM_clientglobalvector(input_angles)); // // FIXME: this actually belongs into getinputstate().. [12/17/2007 Black] - prog->globals.client->input_buttons = cl.movecmd[0].buttons; - VectorSet(prog->globals.client->input_movevalues, cl.movecmd[0].forwardmove, cl.movecmd[0].sidemove, cl.movecmd[0].upmove); - //VectorCopy(cl.movement_origin, cl.csqc_origin); - Matrix4x4_OriginFromMatrix(&cl.entities[cl.viewentity].render.matrix, cl.csqc_origin); + PRVM_clientglobalfloat(input_buttons) = cl.movecmd[0].buttons; + VectorSet(PRVM_clientglobalvector(input_movevalues), cl.movecmd[0].forwardmove, cl.movecmd[0].sidemove, cl.movecmd[0].upmove); + VectorCopy(cl.csqc_vieworiginfromengine, cl.csqc_vieworigin); + VectorCopy(cl.csqc_viewanglesfromengine, cl.csqc_viewangles); // LordHavoc: Spike says not to do this, but without pmove_org the // CSQC is useless as it can't alter the view origin without // completely replacing it - VectorCopy(cl.csqc_origin, prog->globals.client->pmove_org); - VectorCopy(cl.movement_velocity, prog->globals.client->pmove_vel); + Matrix4x4_OriginFromMatrix(&cl.entities[cl.viewentity].render.matrix, PRVM_clientglobalvector(pmove_org)); + VectorCopy(cl.movement_velocity, PRVM_clientglobalvector(pmove_vel)); + PRVM_clientglobalfloat(pmove_onground) = cl.onground; + PRVM_clientglobalfloat(pmove_inwater) = cl.inwater; + + VectorCopy(cl.viewangles, PRVM_clientglobalvector(view_angles)); + VectorCopy(cl.punchangle, PRVM_clientglobalvector(view_punchangle)); + VectorCopy(cl.punchvector, PRVM_clientglobalvector(view_punchvector)); + PRVM_clientglobalfloat(maxclients) = cl.maxclients; - if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.view_angles))) - VectorCopy(cl.viewangles, val->vector); - prog->globals.client->maxclients = cl.maxclients; + CSQC_R_RecalcView(); CSQC_END } void CSQC_Predraw (prvm_edict_t *ed) { int b; - if(!ed->fields.client->predraw) + if(!PRVM_clientedictfunction(ed, predraw)) return; - b = prog->globals.client->self; - prog->globals.client->self = PRVM_EDICT_TO_PROG(ed); - PRVM_ExecuteProgram(ed->fields.client->predraw, "CSQC_Predraw: NULL function\n"); - prog->globals.client->self = b; + b = PRVM_clientglobaledict(self); + PRVM_clientglobaledict(self) = PRVM_EDICT_TO_PROG(ed); + PRVM_ExecuteProgram(PRVM_clientedictfunction(ed, predraw), "CSQC_Predraw: NULL function\n"); + PRVM_clientglobaledict(self) = b; } void CSQC_Think (prvm_edict_t *ed) { int b; - if(ed->fields.client->think) - if(ed->fields.client->nextthink && ed->fields.client->nextthink <= prog->globals.client->time) + if(PRVM_clientedictfunction(ed, think)) + if(PRVM_clientedictfloat(ed, nextthink) && PRVM_clientedictfloat(ed, nextthink) <= PRVM_clientglobalfloat(time)) { - ed->fields.client->nextthink = 0; - b = prog->globals.client->self; - prog->globals.client->self = PRVM_EDICT_TO_PROG(ed); - PRVM_ExecuteProgram(ed->fields.client->think, "CSQC_Think: NULL function\n"); - prog->globals.client->self = b; + PRVM_clientedictfloat(ed, nextthink) = 0; + b = PRVM_clientglobaledict(self); + PRVM_clientglobaledict(self) = PRVM_EDICT_TO_PROG(ed); + PRVM_ExecuteProgram(PRVM_clientedictfunction(ed, think), "CSQC_Think: NULL function\n"); + PRVM_clientglobaledict(self) = b; } } extern cvar_t cl_noplayershadow; -qboolean CSQC_AddRenderEdict(prvm_edict_t *ed) +extern cvar_t r_equalize_entities_fullbright; +qboolean CSQC_AddRenderEdict(prvm_edict_t *ed, int edictnum) { int renderflags; int c; float scale; - prvm_eval_t *val; entity_render_t *entrender; dp_model_t *model; - matrix4x4_t tagmatrix, matrix2; model = CL_GetModelFromEdict(ed); if (!model) return false; - entrender = CL_NewTempEntity(0); - if (!entrender) - return false; - - entrender->model = model; - entrender->skinnum = (int)ed->fields.client->skin; - entrender->effects |= entrender->model->effects; - scale = 1; - renderflags = 0; - if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.renderflags)) && val->_float) renderflags = (int)val->_float; - if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.alpha)) && val->_float) entrender->alpha = val->_float; - if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.scale)) && val->_float) entrender->scale = scale = val->_float; - if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.colormod)) && VectorLength2(val->vector)) VectorCopy(val->vector, entrender->colormod); - if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.effects)) && val->_float) entrender->effects |= (int)val->_float; - if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.tag_entity)) && val->edict) - { - int tagentity; - int tagindex = 0; - tagentity = val->edict; - if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.tag_index)) && val->_float) - tagindex = (int)val->_float; - CL_GetTagMatrix (&tagmatrix, PRVM_PROG_TO_EDICT(tagentity), tagindex); - } - else - Matrix4x4_CreateIdentity(&tagmatrix); - - if (renderflags & RF_USEAXIS) + if (edictnum) { - vec3_t left; - VectorNegate(prog->globals.client->v_right, left); - Matrix4x4_FromVectors(&matrix2, prog->globals.client->v_forward, left, prog->globals.client->v_up, ed->fields.client->origin); - Matrix4x4_Scale(&matrix2, scale, 1); + if (r_refdef.scene.numentities >= r_refdef.scene.maxentities) + return false; + entrender = cl.csqcrenderentities + edictnum; + r_refdef.scene.entities[r_refdef.scene.numentities++] = entrender; + entrender->entitynumber = edictnum + MAX_EDICTS; + //entrender->shadertime = 0; // shadertime was set by spawn() + entrender->flags = 0; + entrender->alpha = 1; + entrender->scale = 1; + VectorSet(entrender->colormod, 1, 1, 1); + VectorSet(entrender->glowmod, 1, 1, 1); + entrender->allowdecals = true; } else { - vec3_t angles; - VectorCopy(ed->fields.client->angles, angles); - // if model is alias, reverse pitch direction - if (entrender->model->type == mod_alias) - angles[0] = -angles[0]; - - // set up the render matrix - Matrix4x4_CreateFromQuakeEntity(&matrix2, ed->fields.client->origin[0], ed->fields.client->origin[1], ed->fields.client->origin[2], angles[0], angles[1], angles[2], scale); + entrender = CL_NewTempEntity(0); + if (!entrender) + return false; } + entrender->userwavefunc_param[0] = PRVM_clientedictfloat(ed, userwavefunc_param0); + entrender->userwavefunc_param[1] = PRVM_clientedictfloat(ed, userwavefunc_param1); + entrender->userwavefunc_param[2] = PRVM_clientedictfloat(ed, userwavefunc_param2); + entrender->userwavefunc_param[3] = PRVM_clientedictfloat(ed, userwavefunc_param3); + + entrender->model = model; + entrender->skinnum = (int)PRVM_clientedictfloat(ed, skin); + entrender->effects |= entrender->model->effects; + renderflags = (int)PRVM_clientedictfloat(ed, renderflags); + entrender->alpha = PRVM_clientedictfloat(ed, alpha); + entrender->scale = scale = PRVM_clientedictfloat(ed, scale); + VectorCopy(PRVM_clientedictvector(ed, colormod), entrender->colormod); + VectorCopy(PRVM_clientedictvector(ed, glowmod), entrender->glowmod); + if(PRVM_clientedictfloat(ed, effects)) entrender->effects |= (int)PRVM_clientedictfloat(ed, effects); + if (!entrender->alpha) + entrender->alpha = 1.0f; + if (!entrender->scale) + entrender->scale = scale = 1.0f; + if (!VectorLength2(entrender->colormod)) + VectorSet(entrender->colormod, 1, 1, 1); + if (!VectorLength2(entrender->glowmod)) + VectorSet(entrender->glowmod, 1, 1, 1); + + // LordHavoc: use the CL_GetTagMatrix function on self to ensure consistent behavior (duplicate code would be bad) + CL_GetTagMatrix(&entrender->matrix, ed, 0); + // set up the animation data - // self.frame is the interpolation target (new frame) - // self.frame1time is the animation base time for the interpolation target - // self.frame2 is the interpolation start (previous frame) - // self.frame2time is the animation base time for the interpolation start - // self.lerpfrac is the interpolation strength for self.frame - // 3+ are for additional blends (the main use for this feature is lerping - // pitch angle on a player model where the animator set up 5 sets of - // animations and the csqc simply lerps between sets) - entrender->framegroupblend[0].frame = entrender->framegroupblend[1].frame = (int) ed->fields.client->frame; - if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.frame2))) entrender->framegroupblend[1].frame = (int) val->_float; - if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.frame3))) entrender->framegroupblend[2].frame = (int) val->_float; - if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.frame4))) entrender->framegroupblend[3].frame = (int) val->_float; - if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.frame1time))) entrender->framegroupblend[0].start = val->_float; - if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.frame2time))) entrender->framegroupblend[1].start = val->_float; - if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.frame3time))) entrender->framegroupblend[2].start = val->_float; - if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.frame4time))) entrender->framegroupblend[3].start = val->_float; - if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.lerpfrac))) entrender->framegroupblend[0].lerp = val->_float; - if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.lerpfrac3))) entrender->framegroupblend[2].lerp = val->_float; - if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.lerpfrac4))) entrender->framegroupblend[3].lerp = val->_float; - if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.shadertime))) entrender->shadertime = val->_float; - // assume that the (missing) lerpfrac2 is whatever remains after lerpfrac+lerpfrac3+lerpfrac4 are summed - entrender->framegroupblend[1].lerp = 1 - entrender->framegroupblend[0].lerp - entrender->framegroupblend[2].lerp - entrender->framegroupblend[3].lerp; - - // concat the matrices to make the entity relative to its tag - Matrix4x4_Concat(&entrender->matrix, &tagmatrix, &matrix2); + VM_GenerateFrameGroupBlend(ed->priv.server->framegroupblend, ed); + VM_FrameBlendFromFrameGroupBlend(ed->priv.server->frameblend, ed->priv.server->framegroupblend, model); + VM_UpdateEdictSkeleton(ed, model, ed->priv.server->frameblend); + if (PRVM_clientedictfloat(ed, shadertime)) // hack for csprogs.dat files that do not set shadertime, leaves the value at entity spawn time + entrender->shadertime = PRVM_clientedictfloat(ed, shadertime); + + // transparent offset + if (renderflags & RF_USETRANSPARENTOFFSET) + entrender->transparent_offset = PRVM_clientglobalfloat(transparent_offset); + + // model light + if (renderflags & RF_MODELLIGHT) + { + if(PRVM_clientedictvector(ed, modellight_ambient)) VectorCopy(PRVM_clientedictvector(ed, modellight_ambient), entrender->modellight_ambient); + if(PRVM_clientedictvector(ed, modellight_diffuse)) VectorCopy(PRVM_clientedictvector(ed, modellight_diffuse), entrender->modellight_diffuse); + if(PRVM_clientedictvector(ed, modellight_dir)) VectorCopy(PRVM_clientedictvector(ed, modellight_dir), entrender->modellight_lightdir); + entrender->flags |= RENDER_CUSTOMIZEDMODELLIGHT; + } if(renderflags) { - if(renderflags & RF_VIEWMODEL) entrender->flags |= RENDER_VIEWMODEL; - if(renderflags & RF_EXTERNALMODEL)entrender->flags |= RENDER_EXTERIORMODEL; - if(renderflags & RF_DEPTHHACK) entrender->effects |= EF_NODEPTHTEST; - if(renderflags & RF_ADDITIVE) entrender->effects |= EF_ADDITIVE; + if(renderflags & RF_VIEWMODEL) entrender->flags |= RENDER_VIEWMODEL | RENDER_NODEPTHTEST; + if(renderflags & RF_EXTERNALMODEL) entrender->flags |= RENDER_EXTERIORMODEL; + if(renderflags & RF_WORLDOBJECT) entrender->flags |= RENDER_WORLDOBJECT; + if(renderflags & RF_DEPTHHACK) entrender->flags |= RENDER_NODEPTHTEST; + if(renderflags & RF_ADDITIVE) entrender->flags |= RENDER_ADDITIVE; } - c = (int)ed->fields.client->colormap; + c = (int)PRVM_clientedictfloat(ed, colormap); if (c <= 0) CL_SetEntityColormapColors(entrender, -1); else if (c <= cl.maxclients && cl.scores != NULL) @@ -256,11 +398,17 @@ qboolean CSQC_AddRenderEdict(prvm_edict_t *ed) entrender->flags &= ~(RENDER_SHADOW | RENDER_LIGHT | RENDER_NOSELFSHADOW); // either fullbright or lit - if (!(entrender->effects & EF_FULLBRIGHT) && !r_fullbright.integer) - entrender->flags |= RENDER_LIGHT; + if(!r_fullbright.integer) + { + if (!(entrender->effects & EF_FULLBRIGHT) && !(renderflags & RF_FULLBRIGHT)) + entrender->flags |= RENDER_LIGHT; + else if(r_equalize_entities_fullbright.integer) + entrender->flags |= RENDER_LIGHT | RENDER_EQUALIZE; + } // hide player shadow during intermission or nehahra movie if (!(entrender->effects & (EF_NOSHADOW | EF_ADDITIVE | EF_NODEPTHTEST)) && (entrender->alpha >= 1) + && !(renderflags & RF_NOSHADOW) && !(entrender->flags & RENDER_VIEWMODEL) && (!(entrender->flags & RENDER_EXTERIORMODEL) || (!cl.intermission && cls.protocol != PROTOCOL_NEHAHRAMOVIE && !cl_noplayershadow.integer))) entrender->flags |= RENDER_SHADOW; @@ -268,14 +416,31 @@ qboolean CSQC_AddRenderEdict(prvm_edict_t *ed) entrender->flags |= RENDER_NOSELFSHADOW; if (entrender->effects & EF_NOSELFSHADOW) entrender->flags |= RENDER_NOSELFSHADOW; + if (entrender->effects & EF_NODEPTHTEST) + entrender->flags |= RENDER_NODEPTHTEST; + if (entrender->effects & EF_ADDITIVE) + entrender->flags |= RENDER_ADDITIVE; + if (entrender->effects & EF_DOUBLESIDED) + entrender->flags |= RENDER_DOUBLESIDED; // make the other useful stuff + memcpy(entrender->framegroupblend, ed->priv.server->framegroupblend, sizeof(ed->priv.server->framegroupblend)); CL_UpdateRenderEntity(entrender); + // override animation data with full control + memcpy(entrender->frameblend, ed->priv.server->frameblend, sizeof(ed->priv.server->frameblend)); + if (ed->priv.server->skeleton.relativetransforms) + entrender->skeleton = &ed->priv.server->skeleton; + else + entrender->skeleton = NULL; return true; } -qboolean CL_VM_InputEvent (qboolean down, int key, int ascii) +// 0 = keydown, key, character (EXT_CSQC) +// 1 = keyup, key, character (EXT_CSQC) +// 2 = mousemove relative, x, y (EXT_CSQC) +// 3 = mousemove absolute, x, y (DP_CSQC) +qboolean CL_VM_InputEvent (int eventtype, int x, int y) { qboolean r; @@ -283,16 +448,16 @@ qboolean CL_VM_InputEvent (qboolean down, int key, int ascii) return false; CSQC_BEGIN - if (!prog->funcoffsets.CSQC_InputEvent) + if (!PRVM_clientfunction(CSQC_InputEvent)) r = false; else { - prog->globals.client->time = cl.time; - prog->globals.client->self = cl.csqc_server2csqcentitynumber[cl.playerentity]; - PRVM_G_FLOAT(OFS_PARM0) = !down; // 0 is down, 1 is up - PRVM_G_FLOAT(OFS_PARM1) = key; - PRVM_G_FLOAT(OFS_PARM2) = ascii; - PRVM_ExecuteProgram(prog->funcoffsets.CSQC_InputEvent, "QC function CSQC_InputEvent is missing"); + PRVM_clientglobalfloat(time) = cl.time; + PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[cl.playerentity]; + PRVM_G_FLOAT(OFS_PARM0) = eventtype; + PRVM_G_FLOAT(OFS_PARM1) = x; // key or x + PRVM_G_FLOAT(OFS_PARM2) = y; // ascii or y + PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_InputEvent), "QC function CSQC_InputEvent is missing"); r = CSQC_RETURNVAL != 0; } CSQC_END @@ -308,10 +473,11 @@ qboolean CL_VM_UpdateView (void) // vec3_t oldangles; if(!cl.csqc_loaded) return false; + R_TimeReport("pre-UpdateView"); CSQC_BEGIN //VectorCopy(cl.viewangles, oldangles); - prog->globals.client->time = cl.time; - prog->globals.client->self = cl.csqc_server2csqcentitynumber[cl.playerentity]; + PRVM_clientglobalfloat(time) = cl.time; + PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[cl.playerentity]; CSQC_SetGlobals(); // clear renderable entity and light lists to prevent crashes if the // CSQC_UpdateView function does not call R_ClearScene as it should @@ -320,11 +486,12 @@ qboolean CL_VM_UpdateView (void) // pass in width and height as parameters (EXT_CSQC_1) PRVM_G_FLOAT(OFS_PARM0) = vid.width; PRVM_G_FLOAT(OFS_PARM1) = vid.height; - PRVM_ExecuteProgram(prog->funcoffsets.CSQC_UpdateView, "QC function CSQC_UpdateView is missing"); + PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_UpdateView), "QC function CSQC_UpdateView is missing"); //VectorCopy(oldangles, cl.viewangles); // Dresk : Reset Dmg Globals Here CL_VM_UpdateDmgGlobals(0, 0, emptyvector); CSQC_END + R_TimeReport("UpdateView"); return true; } @@ -336,13 +503,13 @@ qboolean CL_VM_ConsoleCommand (const char *cmd) if(!cl.csqc_loaded) return false; CSQC_BEGIN - if (prog->funcoffsets.CSQC_ConsoleCommand) + if (PRVM_clientfunction(CSQC_ConsoleCommand)) { - prog->globals.client->time = cl.time; - prog->globals.client->self = cl.csqc_server2csqcentitynumber[cl.playerentity]; + PRVM_clientglobalfloat(time) = cl.time; + PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[cl.playerentity]; restorevm_tempstringsbuf_cursize = vm_tempstringsbuf.cursize; PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(cmd); - PRVM_ExecuteProgram(prog->funcoffsets.CSQC_ConsoleCommand, "QC function CSQC_ConsoleCommand is missing"); + PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_ConsoleCommand), "QC function CSQC_ConsoleCommand is missing"); vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize; r = CSQC_RETURNVAL != 0; } @@ -357,12 +524,12 @@ qboolean CL_VM_Parse_TempEntity (void) if(!cl.csqc_loaded) return false; CSQC_BEGIN - if(prog->funcoffsets.CSQC_Parse_TempEntity) + if(PRVM_clientfunction(CSQC_Parse_TempEntity)) { t = msg_readcount; - prog->globals.client->time = cl.time; - prog->globals.client->self = cl.csqc_server2csqcentitynumber[cl.playerentity]; - PRVM_ExecuteProgram(prog->funcoffsets.CSQC_Parse_TempEntity, "QC function CSQC_Parse_TempEntity is missing"); + PRVM_clientglobalfloat(time) = cl.time; + PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[cl.playerentity]; + PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_Parse_TempEntity), "QC function CSQC_Parse_TempEntity is missing"); r = CSQC_RETURNVAL != 0; if(!r) { @@ -440,13 +607,13 @@ void CL_VM_Parse_StuffCmd (const char *msg) return; } CSQC_BEGIN - if(prog->funcoffsets.CSQC_Parse_StuffCmd) + if(PRVM_clientfunction(CSQC_Parse_StuffCmd)) { - prog->globals.client->time = cl.time; - prog->globals.client->self = cl.csqc_server2csqcentitynumber[cl.playerentity]; + PRVM_clientglobalfloat(time) = cl.time; + PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[cl.playerentity]; restorevm_tempstringsbuf_cursize = vm_tempstringsbuf.cursize; PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(msg); - PRVM_ExecuteProgram(prog->funcoffsets.CSQC_Parse_StuffCmd, "QC function CSQC_Parse_StuffCmd is missing"); + PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_Parse_StuffCmd), "QC function CSQC_Parse_StuffCmd is missing"); vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize; } else @@ -457,11 +624,11 @@ void CL_VM_Parse_StuffCmd (const char *msg) static void CL_VM_Parse_Print (const char *msg) { int restorevm_tempstringsbuf_cursize; - prog->globals.client->time = cl.time; - prog->globals.client->self = cl.csqc_server2csqcentitynumber[cl.playerentity]; + PRVM_clientglobalfloat(time) = cl.time; + PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[cl.playerentity]; restorevm_tempstringsbuf_cursize = vm_tempstringsbuf.cursize; PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(msg); - PRVM_ExecuteProgram(prog->funcoffsets.CSQC_Parse_Print, "QC function CSQC_Parse_Print is missing"); + PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_Parse_Print), "QC function CSQC_Parse_Print is missing"); vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize; } @@ -474,7 +641,7 @@ void CSQC_AddPrintText (const char *msg) return; } CSQC_BEGIN - if(prog->funcoffsets.CSQC_Parse_Print) + if(PRVM_clientfunction(CSQC_Parse_Print)) { // FIXME: is this bugged? i = strlen(msg)-1; @@ -507,13 +674,13 @@ void CL_VM_Parse_CenterPrint (const char *msg) return; } CSQC_BEGIN - if(prog->funcoffsets.CSQC_Parse_CenterPrint) + if(PRVM_clientfunction(CSQC_Parse_CenterPrint)) { - prog->globals.client->time = cl.time; - prog->globals.client->self = cl.csqc_server2csqcentitynumber[cl.playerentity]; + PRVM_clientglobalfloat(time) = cl.time; + PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[cl.playerentity]; restorevm_tempstringsbuf_cursize = vm_tempstringsbuf.cursize; PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(msg); - PRVM_ExecuteProgram(prog->funcoffsets.CSQC_Parse_CenterPrint, "QC function CSQC_Parse_CenterPrint is missing"); + PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_Parse_CenterPrint), "QC function CSQC_Parse_CenterPrint is missing"); vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize; } else @@ -523,45 +690,41 @@ void CL_VM_Parse_CenterPrint (const char *msg) void CL_VM_UpdateIntermissionState (int intermission) { - prvm_eval_t *val; if(cl.csqc_loaded) { CSQC_BEGIN - val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.intermission); - if(val) - val->_float = intermission; + PRVM_clientglobalfloat(intermission) = intermission; CSQC_END } } void CL_VM_UpdateShowingScoresState (int showingscores) { - prvm_eval_t *val; if(cl.csqc_loaded) { CSQC_BEGIN - val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.sb_showscores); - if(val) - val->_float = showingscores; + PRVM_clientglobalfloat(sb_showscores) = showingscores; CSQC_END } } -qboolean CL_VM_Event_Sound(int sound_num, float volume, int channel, float attenuation, int ent, vec3_t pos) +qboolean CL_VM_Event_Sound(int sound_num, float volume, int channel, float attenuation, int ent, vec3_t pos, float speed) { qboolean r = false; if(cl.csqc_loaded) { CSQC_BEGIN - if(prog->funcoffsets.CSQC_Event_Sound) + if(PRVM_clientfunction(CSQC_Event_Sound)) { - prog->globals.client->time = cl.time; - prog->globals.client->self = cl.csqc_server2csqcentitynumber[cl.playerentity]; + PRVM_clientglobalfloat(time) = cl.time; + PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[cl.playerentity]; PRVM_G_FLOAT(OFS_PARM0) = ent; - PRVM_G_FLOAT(OFS_PARM1) = channel; + PRVM_G_FLOAT(OFS_PARM1) = CHAN_ENGINE2USER(channel); PRVM_G_INT(OFS_PARM2) = PRVM_SetTempString(cl.sound_name[sound_num] ); PRVM_G_FLOAT(OFS_PARM3) = volume; PRVM_G_FLOAT(OFS_PARM4) = attenuation; VectorCopy(pos, PRVM_G_VECTOR(OFS_PARM5) ); - PRVM_ExecuteProgram(prog->funcoffsets.CSQC_Event_Sound, "QC function CSQC_Event_Sound is missing"); + PRVM_G_FLOAT(OFS_PARM6) = speed * 100.0f; + PRVM_G_FLOAT(OFS_PARM7) = 0; // flags - none can come in at this point yet + PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_Event_Sound), "QC function CSQC_Event_Sound is missing"); r = CSQC_RETURNVAL != 0; } CSQC_END @@ -575,7 +738,6 @@ void CL_VM_UpdateCoopDeathmatchGlobals (int gametype) int localcoop; int localdeathmatch; - prvm_eval_t *val; if(cl.csqc_loaded) { if(gametype == GAME_COOP) @@ -597,12 +759,8 @@ void CL_VM_UpdateCoopDeathmatchGlobals (int gametype) localdeathmatch = 0; } CSQC_BEGIN - val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.coop); - if(val) - val->_float = localcoop; - val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.deathmatch); - if(val) - val->_float = localdeathmatch; + PRVM_clientglobalfloat(coop) = localcoop; + PRVM_clientglobalfloat(deathmatch) = localdeathmatch; CSQC_END } } @@ -612,12 +770,12 @@ float CL_VM_Event (float event) //[515]: needed ? I'd say "YES", but don't know if(!cl.csqc_loaded) return 0; CSQC_BEGIN - if(prog->funcoffsets.CSQC_Event) + if(PRVM_clientfunction(CSQC_Event)) { - prog->globals.client->time = cl.time; - prog->globals.client->self = cl.csqc_server2csqcentitynumber[cl.playerentity]; + PRVM_clientglobalfloat(time) = cl.time; + PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[cl.playerentity]; PRVM_G_FLOAT(OFS_PARM0) = event; - PRVM_ExecuteProgram(prog->funcoffsets.CSQC_Event, "QC function CSQC_Event is missing"); + PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_Event), "QC function CSQC_Event is missing"); r = CSQC_RETURNVAL; } CSQC_END @@ -634,20 +792,20 @@ void CSQC_ReadEntities (void) } CSQC_BEGIN - prog->globals.client->time = cl.time; - oldself = prog->globals.client->self; + PRVM_clientglobalfloat(time) = cl.time; + oldself = PRVM_clientglobaledict(self); while(1) { entnum = MSG_ReadShort(); if(!entnum || msg_badread) - return; + break; realentnum = entnum & 0x7FFF; - prog->globals.client->self = cl.csqc_server2csqcentitynumber[realentnum]; + PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[realentnum]; if(entnum & 0x8000) { - if(prog->globals.client->self) + if(PRVM_clientglobaledict(self)) { - PRVM_ExecuteProgram(prog->funcoffsets.CSQC_Ent_Remove, "QC function CSQC_Ent_Remove is missing"); + PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_Ent_Remove), "QC function CSQC_Ent_Remove is missing"); cl.csqc_server2csqcentitynumber[realentnum] = 0; } else @@ -661,14 +819,14 @@ void CSQC_ReadEntities (void) } else { - if(!prog->globals.client->self) + if(!PRVM_clientglobaledict(self)) { - if(!prog->funcoffsets.CSQC_Ent_Spawn) + if(!PRVM_clientfunction(CSQC_Ent_Spawn)) { prvm_edict_t *ed; ed = PRVM_ED_Alloc(); - ed->fields.client->entnum = realentnum; - prog->globals.client->self = cl.csqc_server2csqcentitynumber[realentnum] = PRVM_EDICT_TO_PROG(ed); + PRVM_clientedictfloat(ed, entnum) = realentnum; + PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[realentnum] = PRVM_EDICT_TO_PROG(ed); } else { @@ -676,20 +834,20 @@ void CSQC_ReadEntities (void) // the qc function should set entnum, too (this way it also can return world [2/1/2008 Andreas] PRVM_G_FLOAT(OFS_PARM0) = (float) realentnum; // make sure no one gets wrong ideas - prog->globals.client->self = 0; - PRVM_ExecuteProgram(prog->funcoffsets.CSQC_Ent_Spawn, "QC function CSQC_Ent_Spawn is missing"); - prog->globals.client->self = cl.csqc_server2csqcentitynumber[realentnum] = PRVM_EDICT( PRVM_G_INT( OFS_RETURN ) ); + PRVM_clientglobaledict(self) = 0; + PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_Ent_Spawn), "QC function CSQC_Ent_Spawn is missing"); + PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[realentnum] = PRVM_EDICT( PRVM_G_INT( OFS_RETURN ) ); } PRVM_G_FLOAT(OFS_PARM0) = 1; - PRVM_ExecuteProgram(prog->funcoffsets.CSQC_Ent_Update, "QC function CSQC_Ent_Update is missing"); + PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_Ent_Update), "QC function CSQC_Ent_Update is missing"); } else { PRVM_G_FLOAT(OFS_PARM0) = 0; - PRVM_ExecuteProgram(prog->funcoffsets.CSQC_Ent_Update, "QC function CSQC_Ent_Update is missing"); + PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_Ent_Update), "QC function CSQC_Ent_Update is missing"); } } } - prog->globals.client->self = oldself; + PRVM_clientglobaledict(self) = oldself; CSQC_END } @@ -705,20 +863,34 @@ void CL_VM_CB_EndIncreaseEdicts(void) prvm_edict_t *ent; // link every entity except world - for (i = 1, ent = prog->edicts;i < prog->max_edicts;i++, ent++) + for (i = 1, ent = prog->edicts;i < prog->num_edicts;i++, ent++) if (!ent->priv.server->free) CL_LinkEdict(ent); } void CL_VM_CB_InitEdict(prvm_edict_t *e) { + int edictnum = PRVM_NUM_FOR_EDICT(e); + entity_render_t *entrender; + CL_ExpandCSQCRenderEntities(edictnum); + entrender = cl.csqcrenderentities + edictnum; e->priv.server->move = false; // don't move on first frame + memset(entrender, 0, sizeof(*entrender)); + entrender->shadertime = cl.time; } +extern void R_DecalSystem_Reset(decalsystem_t *decalsystem); + void CL_VM_CB_FreeEdict(prvm_edict_t *ed) { + entity_render_t *entrender = cl.csqcrenderentities + PRVM_NUM_FOR_EDICT(ed); + R_DecalSystem_Reset(&entrender->decalsystem); + memset(entrender, 0, sizeof(*entrender)); World_UnlinkEdict(ed); - memset(ed->fields.client, 0, sizeof(*ed->fields.client)); + memset(ed->fields.vp, 0, prog->entityfields * 4); + VM_RemoveEdictSkeleton(ed); + World_Physics_RemoveFromEntity(&cl.world, ed); + World_Physics_RemoveJointFromEntity(&cl.world, ed); } void CL_VM_CB_CountEdicts(void) @@ -733,9 +905,9 @@ void CL_VM_CB_CountEdicts(void) if (ent->priv.server->free) continue; active++; - if (ent->fields.client->solid) + if (PRVM_clientedictfloat(ent, solid)) solid++; - if (ent->fields.client->model) + if (PRVM_clientedictstring(ent, model)) models++; } @@ -754,7 +926,7 @@ void Cmd_ClearCsqcFuncs (void); // returns true if the packet is valid, false if end of file is reached // used for dumping the CSQC download into demo files -qboolean MakeDownloadPacket(const char *filename, unsigned char *data, unsigned long len, int crc, int cnt, sizebuf_t *buf, int protocol) +qboolean MakeDownloadPacket(const char *filename, unsigned char *data, size_t len, int crc, int cnt, sizebuf_t *buf, int protocol) { int packetsize = buf->maxsize - 7; // byte short long int npackets = (len + packetsize - 1) / (packetsize); @@ -766,7 +938,7 @@ qboolean MakeDownloadPacket(const char *filename, unsigned char *data, unsigned if(cnt == 0) { MSG_WriteByte(buf, svc_stufftext); - MSG_WriteString(buf, va("\ncl_downloadbegin %lu %s\n", len, filename)); + MSG_WriteString(buf, va("\ncl_downloadbegin %lu %s\n", (unsigned long)len, filename)); return true; } else if(cnt >= 1 && cnt <= npackets) @@ -786,20 +958,20 @@ qboolean MakeDownloadPacket(const char *filename, unsigned char *data, unsigned else if(cnt == npackets + 1) { MSG_WriteByte(buf, svc_stufftext); - MSG_WriteString(buf, va("\ncl_downloadfinished %lu %d\n", len, crc)); + MSG_WriteString(buf, va("\ncl_downloadfinished %lu %d\n", (unsigned long)len, crc)); return true; } return false; } +extern cvar_t csqc_usedemoprogs; void CL_VM_Init (void) { const char* csprogsfn; - unsigned char *csprogsdata; + unsigned char *csprogsdata = NULL; fs_offset_t csprogsdatasize; int csprogsdatacrc, requiredcrc; int requiredsize; - prvm_eval_t *val; // reset csqc_progcrc after reading it, so that changing servers doesn't // expect csqc on the next server @@ -814,8 +986,11 @@ void CL_VM_Init (void) // see if the requested csprogs.dat file matches the requested crc csprogsdatacrc = -1; - csprogsfn = va("dlcache/%s.%i.%i", csqc_progname.string, requiredsize, requiredcrc); - csprogsdata = FS_LoadFile(csprogsfn, tempmempool, true, &csprogsdatasize); + if (!cls.demoplayback || csqc_usedemoprogs.integer) + { + csprogsfn = va("dlcache/%s.%i.%i", csqc_progname.string, requiredsize, requiredcrc); + csprogsdata = FS_LoadFile(csprogsfn, tempmempool, true, &csprogsdatasize); + } if (!csprogsdata) { csprogsfn = csqc_progname.string; @@ -823,7 +998,7 @@ void CL_VM_Init (void) } if (csprogsdata) { - csprogsdatacrc = CRC_Block(csprogsdata, csprogsdatasize); + csprogsdatacrc = CRC_Block(csprogsdata, (size_t)csprogsdatasize); if (csprogsdatacrc != requiredcrc || csprogsdatasize != requiredsize) { if (cls.demoplayback) @@ -861,7 +1036,6 @@ void CL_VM_Init (void) // allocate the mempools prog->progs_mempool = Mem_AllocPool(csqc_progname.string, 0, NULL); - prog->headercrc = CL_PROGHEADER_CRC; prog->edictprivate_size = 0; // no private struct used prog->name = CL_NAME; prog->num_edicts = 1; @@ -882,8 +1056,9 @@ void CL_VM_Init (void) prog->init_cmd = VM_CL_Cmd_Init; prog->reset_cmd = VM_CL_Cmd_Reset; prog->error_cmd = CL_VM_Error; + prog->ExecuteProgram = CLVM_ExecuteProgram; - PRVM_LoadProgs(csprogsfn, cl_numrequiredfunc, cl_required_func, 0, NULL, 0, NULL); + PRVM_LoadProgs(csprogsfn, cl_numrequiredfunc, cl_required_func, CL_REQFIELDS, cl_reqfields, CL_REQGLOBALS, cl_reqglobals); if (!prog->loaded) { @@ -894,14 +1069,14 @@ void CL_VM_Init (void) return; } - Con_Printf("CSQC %s ^5loaded (crc=%i, size=%i)\n", csprogsfn, csprogsdatacrc, (int)csprogsdatasize); + Con_DPrintf("CSQC %s ^5loaded (crc=%i, size=%i)\n", csprogsfn, csprogsdatacrc, (int)csprogsdatasize); if(cls.demorecording) { if(cls.demo_lastcsprogssize != csprogsdatasize || cls.demo_lastcsprogscrc != csprogsdatacrc) { int i; - char buf[NET_MAXMESSAGE]; + static char buf[NET_MAXMESSAGE]; sizebuf_t sb; unsigned char *demobuf; fs_offset_t demofilesize; @@ -910,7 +1085,7 @@ void CL_VM_Init (void) i = 0; CL_CutDemo(&demobuf, &demofilesize); - while(MakeDownloadPacket(csqc_progname.string, csprogsdata, csprogsdatasize, csprogsdatacrc, i++, &sb, cls.protocol)) + while(MakeDownloadPacket(csqc_progname.string, csprogsdata, (size_t)csprogsdatasize, csprogsdatacrc, i++, &sb, cls.protocol)) CL_WriteDemoMessage(&sb); CL_PasteDemo(&demobuf, &demofilesize); @@ -925,21 +1100,19 @@ void CL_VM_Init (void) prog->flag |= PRVM_OP_STATE; // set time - prog->globals.client->time = cl.time; - prog->globals.client->self = 0; + PRVM_clientglobalfloat(time) = cl.time; + PRVM_clientglobaledict(self) = 0; - prog->globals.client->mapname = cl.worldmodel ? PRVM_SetEngineString(cl.worldmodel->name) : PRVM_SetEngineString(""); - prog->globals.client->player_localentnum = cl.playerentity; + PRVM_clientglobalstring(mapname) = PRVM_SetEngineString(cl.worldname); + PRVM_clientglobalfloat(player_localentnum) = cl.playerentity; // set map description (use world entity 0) - val = PRVM_EDICTFIELDVALUE(prog->edicts, prog->fieldoffsets.message); - if(val) - val->string = PRVM_SetEngineString(cl.levelname); - VectorCopy(cl.world.mins, prog->edicts->fields.client->mins); - VectorCopy(cl.world.maxs, prog->edicts->fields.client->maxs); + PRVM_clientedictstring(prog->edicts, message) = PRVM_SetEngineString(cl.worldmessage); + VectorCopy(cl.world.mins, PRVM_clientedictvector(prog->edicts, mins)); + VectorCopy(cl.world.maxs, PRVM_clientedictvector(prog->edicts, maxs)); // call the prog init - PRVM_ExecuteProgram(prog->funcoffsets.CSQC_Init, "QC function CSQC_Init is missing"); + PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_Init), "QC function CSQC_Init is missing"); PRVM_End; cl.csqc_loaded = true; @@ -959,13 +1132,13 @@ void CL_VM_ShutDown (void) if(!cl.csqc_loaded) return; CSQC_BEGIN - prog->globals.client->time = cl.time; - prog->globals.client->self = 0; - if (prog->funcoffsets.CSQC_Shutdown) - PRVM_ExecuteProgram(prog->funcoffsets.CSQC_Shutdown, "QC function CSQC_Shutdown is missing"); + PRVM_clientglobalfloat(time) = cl.time; + PRVM_clientglobaledict(self) = 0; + if (PRVM_clientfunction(CSQC_Shutdown)) + PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_Shutdown), "QC function CSQC_Shutdown is missing"); PRVM_ResetProg(); CSQC_END - Con_Print("CSQC ^1unloaded\n"); + Con_DPrint("CSQC ^1unloaded\n"); cl.csqc_loaded = false; } @@ -980,12 +1153,12 @@ qboolean CL_VM_GetEntitySoundOrigin(int entnum, vec3_t out) // FIXME consider attachments here! - ed = PRVM_EDICT_NUM(entnum - 32768); + ed = PRVM_EDICT_NUM(entnum - MAX_EDICTS); if(!ed->priv.required->free) { mod = CL_GetModelFromEdict(ed); - VectorCopy(ed->fields.client->origin, out); + VectorCopy(PRVM_clientedictvector(ed, origin), out); if(CL_GetTagMatrix (&matrix, ed, 0) == 0) Matrix4x4_OriginFromMatrix(&matrix, out); if (mod && mod->soundfromcenter) @@ -997,3 +1170,46 @@ qboolean CL_VM_GetEntitySoundOrigin(int entnum, vec3_t out) return r; } + +qboolean CL_VM_TransformView(int entnum, matrix4x4_t *viewmatrix, mplane_t *clipplane, vec3_t visorigin) +{ + qboolean ret = false; + prvm_edict_t *ed; + vec3_t forward, left, up, origin, ang; + matrix4x4_t mat, matq; + + CSQC_BEGIN + ed = PRVM_EDICT_NUM(entnum); + // camera: + // camera_transform + if(PRVM_clientedictfunction(ed, camera_transform)) + { + ret = true; + if(viewmatrix || clipplane || visorigin) + { + Matrix4x4_ToVectors(viewmatrix, forward, left, up, origin); + AnglesFromVectors(ang, forward, up, false); + PRVM_clientglobalfloat(time) = cl.time; + PRVM_clientglobaledict(self) = entnum; + VectorCopy(origin, PRVM_G_VECTOR(OFS_PARM0)); + VectorCopy(ang, PRVM_G_VECTOR(OFS_PARM1)); + VectorCopy(forward, PRVM_clientglobalvector(v_forward)); + VectorScale(left, -1, PRVM_clientglobalvector(v_right)); + VectorCopy(up, PRVM_clientglobalvector(v_up)); + VectorCopy(origin, PRVM_clientglobalvector(trace_endpos)); + PRVM_ExecuteProgram(PRVM_clientedictfunction(ed, camera_transform), "QC function e.camera_transform is missing"); + VectorCopy(PRVM_G_VECTOR(OFS_RETURN), origin); + VectorCopy(PRVM_clientglobalvector(v_forward), forward); + VectorScale(PRVM_clientglobalvector(v_right), -1, left); + VectorCopy(PRVM_clientglobalvector(v_up), up); + VectorCopy(PRVM_clientglobalvector(trace_endpos), visorigin); + Matrix4x4_Invert_Full(&mat, viewmatrix); + Matrix4x4_FromVectors(viewmatrix, forward, left, up, origin); + Matrix4x4_Concat(&matq, viewmatrix, &mat); + Matrix4x4_TransformPositivePlane(&matq, clipplane->normal[0], clipplane->normal[1], clipplane->normal[2], clipplane->dist, &clipplane->normal[0]); + } + } + CSQC_END + + return ret; +}