]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - csprogs.c
turn font size snapping into a float
[xonotic/darkplaces.git] / csprogs.c
index 67a7aee18ba562cc00ab17acdb7e84963273ac8c..0492d10c574f80383ec32ff3d6d3a53db9cd6eb9 100644 (file)
--- 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
 
 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[] =
 {
@@ -106,7 +119,7 @@ static void CSQC_SetGlobals (void)
                // 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.velocity, prog->globals.client->pmove_vel);
+               VectorCopy(cl.movement_velocity, prog->globals.client->pmove_vel);
 
                if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.view_angles)))
                        VectorCopy(cl.viewangles, val->vector);
@@ -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,26 +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
-       entrender->frame1 = entrender->frame2 = (int) ed->fields.client->frame;
-       if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.frame2))) entrender->frame2 = (int) val->_float;
-       if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.frame1time))) entrender->frame2time = val->_float;
-       if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.frame2time))) entrender->frame1time = val->_float;
-       if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.lerpfrac))) entrender->framelerp = 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;
 
        // 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;
@@ -232,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)
@@ -244,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;
 }
@@ -269,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;
@@ -320,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;
@@ -339,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;
@@ -538,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
        }
@@ -688,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)
@@ -858,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);
 
@@ -949,18 +1018,21 @@ qboolean CL_VM_GetEntitySoundOrigin(int entnum, vec3_t out)
 {
        prvm_edict_t *ed;
        dp_model_t *mod;
+       matrix4x4_t matrix;
        qboolean r = 0;
 
        CSQC_BEGIN;
 
        // 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);
+               if(CL_GetTagMatrix (&matrix, ed, 0) == 0)
+                       Matrix4x4_OriginFromMatrix(&matrix, out);
                if (mod && mod->soundfromcenter)
                        VectorMAMAM(1.0f, out, 0.5f, mod->normalmins, 0.5f, mod->normalmaxs, out);
                r = 1;