X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=csprogs.c;h=0492d10c574f80383ec32ff3d6d3a53db9cd6eb9;hb=66d1df20a5ed5ff954d7bf9db2db23cbe304281a;hp=1ee20b6017214c909f87ed829bfae821e742a7f0;hpb=6661d4a6e250ded9d9c8e536d475f8cf157fbdcd;p=xonotic%2Fdarkplaces.git diff --git a/csprogs.c b/csprogs.c index 1ee20b60..0492d10c 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 @@ -16,6 +17,18 @@ 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; + CSQC_END +} + //[515]: these are required funcs static char *cl_required_func[] = { @@ -140,7 +153,8 @@ void CSQC_Think (prvm_edict_t *ed) } 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; @@ -154,9 +168,26 @@ qboolean CSQC_AddRenderEdict(prvm_edict_t *ed) if (!model) return false; - entrender = CL_NewTempEntity(0); - if (!entrender) - return false; + if (edictnum) + { + 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; + //entrender->shadertime = 0; // shadertime was set by spawn() + entrender->alpha = 1; + entrender->scale = 1; + VectorSet(entrender->colormod, 1, 1, 1); + VectorSet(entrender->glowmod, 1, 1, 1); + entrender->allowdecals = true; + } + else + { + entrender = CL_NewTempEntity(0); + if (!entrender) + return false; + } entrender->model = model; entrender->skinnum = (int)ed->fields.client->skin; @@ -167,6 +198,7 @@ qboolean CSQC_AddRenderEdict(prvm_edict_t *ed) 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.glowmod)) && VectorLength2(val->vector)) VectorCopy(val->vector, entrender->glowmod); 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) { @@ -179,6 +211,10 @@ qboolean CSQC_AddRenderEdict(prvm_edict_t *ed) } else Matrix4x4_CreateIdentity(&tagmatrix); + if (!VectorLength2(entrender->colormod)) + VectorSet(entrender->colormod, 1, 1, 1); + if (!VectorLength2(entrender->glowmod)) + VectorSet(entrender->glowmod, 1, 1, 1); if (renderflags & RF_USEAXIS) { @@ -200,38 +236,26 @@ qboolean CSQC_AddRenderEdict(prvm_edict_t *ed) } // 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; + 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 ((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); + // transparent offset + if ((renderflags & RF_USETRANSPARENTOFFSET) && (val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.transparent_offset))) + entrender->transparent_offset = val->_float; + if(renderflags) { - if(renderflags & RF_VIEWMODEL) entrender->flags |= RENDER_VIEWMODEL; + if(renderflags & RF_VIEWMODEL) entrender->flags |= RENDER_VIEWMODEL | RENDER_NODEPTHTEST; 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_NOCULL) entrender->flags |= RENDER_NOCULL; + if(renderflags & RF_DEPTHHACK) entrender->flags |= RENDER_NODEPTHTEST; + if(renderflags & RF_ADDITIVE) entrender->flags |= RENDER_ADDITIVE; + } c = (int)ed->fields.client->colormap; @@ -244,8 +268,13 @@ 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)) + 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) @@ -256,9 +285,22 @@ 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; } @@ -281,7 +323,7 @@ qboolean CL_VM_InputEvent (qboolean down, int key, int ascii) PRVM_G_FLOAT(OFS_PARM1) = key; PRVM_G_FLOAT(OFS_PARM2) = ascii; PRVM_ExecuteProgram(prog->funcoffsets.CSQC_InputEvent, "QC function CSQC_InputEvent is missing"); - r = CSQC_RETURNVAL; + r = CSQC_RETURNVAL != 0; } CSQC_END return r; @@ -332,7 +374,7 @@ qboolean CL_VM_ConsoleCommand (const char *cmd) PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(cmd); PRVM_ExecuteProgram(prog->funcoffsets.CSQC_ConsoleCommand, "QC function CSQC_ConsoleCommand is missing"); vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize; - r = CSQC_RETURNVAL; + r = CSQC_RETURNVAL != 0; } CSQC_END return r; @@ -351,7 +393,7 @@ qboolean CL_VM_Parse_TempEntity (void) 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"); - r = CSQC_RETURNVAL; + r = CSQC_RETURNVAL != 0; if(!r) { msg_readcount = t; @@ -550,7 +592,7 @@ qboolean CL_VM_Event_Sound(int sound_num, float volume, int channel, float atten 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"); - r = CSQC_RETURNVAL; + r = CSQC_RETURNVAL != 0; } CSQC_END } @@ -700,13 +742,27 @@ void CL_VM_CB_EndIncreaseEdicts(void) 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)); + VM_RemoveEdictSkeleton(ed); + World_Physics_RemoveFromEntity(&cl.world, ed); + World_Physics_RemoveJointFromEntity(&cl.world, ed); } void CL_VM_CB_CountEdicts(void) @@ -870,6 +926,7 @@ 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); @@ -968,7 +1025,7 @@ 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) {