]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - svvm_cmds.c
logarithm
[xonotic/darkplaces.git] / svvm_cmds.c
index 9bb99eb8dd0c1a08a1a784bcad9443bf51a54776..030bb92bf3bdc6ff478ea24f78de3cce97de2dd7 100644 (file)
@@ -19,6 +19,7 @@ char *vm_sv_extensions =
 "DP_CON_SET "
 "DP_CON_SETA "
 "DP_CON_STARTMAP "
+"DP_CSQC_MULTIFRAME_INTERPOLATION "
 "DP_EF_ADDITIVE "
 "DP_EF_BLUE "
 "DP_EF_DOUBLESIDED "
@@ -31,11 +32,13 @@ char *vm_sv_extensions =
 "DP_EF_NOSHADOW "
 "DP_EF_RED "
 "DP_EF_STARDUST "
+"DP_EF_TELEPORT_BIT "
 "DP_ENT_ALPHA "
 "DP_ENT_COLORMOD "
 "DP_ENT_CUSTOMCOLORMAP "
 "DP_ENT_EXTERIORMODELTOCLIENT "
 "DP_ENT_GLOW "
+"DP_ENT_GLOWMOD "
 "DP_ENT_LOWPRECISION "
 "DP_ENT_SCALE "
 "DP_ENT_VIEWMODEL "
@@ -46,6 +49,7 @@ char *vm_sv_extensions =
 "DP_GFX_QUAKE3MODELTAGS "
 "DP_GFX_SKINFILES "
 "DP_GFX_SKYBOX "
+"DP_GFX_MODEL_INTERPOLATION "
 "DP_HALFLIFE_MAP "
 "DP_HALFLIFE_MAP_CVAR "
 "DP_HALFLIFE_SPRITE "
@@ -62,12 +66,16 @@ char *vm_sv_extensions =
 "DP_QC_COPYENTITY "
 "DP_QC_CRC16 "
 "DP_QC_CVAR_DEFSTRING "
+"DP_QC_CVAR_DESCRIPTION "
 "DP_QC_CVAR_STRING "
 "DP_QC_CVAR_TYPE "
 "DP_QC_EDICT_NUM "
 "DP_QC_ENTITYDATA "
+"DP_QC_ENTITYSTRING "
 "DP_QC_ETOS "
+"DP_QC_EXTRESPONSEPACKET "
 "DP_QC_FINDCHAIN "
+"DP_QC_FINDCHAIN_TOFIELD "
 "DP_QC_FINDCHAINFLAGS "
 "DP_QC_FINDCHAINFLOAT "
 "DP_QC_FINDFLAGS "
@@ -77,6 +85,10 @@ char *vm_sv_extensions =
 "DP_QC_GETSURFACE "
 "DP_QC_GETSURFACEPOINTATTRIBUTE "
 "DP_QC_GETTAGINFO "
+"DP_QC_GETTAGINFO_BONEPROPERTIES "
+"DP_QC_GETTIME "
+"DP_QC_GETTIME_CDTRACK "
+"DP_QC_LOG "
 "DP_QC_MINMAXBOUND "
 "DP_QC_MULTIPLETEMPSTRINGS "
 "DP_QC_NUM_FOR_EDICT "
@@ -84,6 +96,7 @@ char *vm_sv_extensions =
 "DP_QC_SINCOSSQRTPOW "
 "DP_QC_STRFTIME "
 "DP_QC_STRINGBUFFERS "
+"DP_QC_STRINGBUFFERS_CVARLIST "
 "DP_QC_STRINGCOLORFUNCTIONS "
 "DP_QC_STRING_CASE_FUNCTIONS "
 "DP_QC_STRREPLACE "
@@ -111,6 +124,7 @@ char *vm_sv_extensions =
 "DP_SOLIDCORPSE "
 "DP_SPRITE32 "
 "DP_SV_BOTCLIENT "
+"DP_SV_BOUNCEFACTOR "
 "DP_SV_CLIENTCOLORS "
 "DP_SV_CLIENTNAME "
 "DP_SV_CMD "
@@ -124,6 +138,7 @@ char *vm_sv_extensions =
 "DP_SV_NETADDRESS "
 "DP_SV_NODRAWTOCLIENT "
 "DP_SV_ONENTITYNOSPAWNFUNCTION "
+"DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
 "DP_SV_PING "
 "DP_SV_PLAYERPHYSICS "
 "DP_SV_POINTPARTICLES "
@@ -154,8 +169,10 @@ char *vm_sv_extensions =
 "DP_TE_STANDARDEFFECTBUILTINS "
 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
 "DP_VIEWZOOM "
+"DP_LIGHTSTYLE_STATICVALUE "
 "EXT_BITSHIFT "
 "FRIK_FILE "
+"FTE_QC_CHECKPVS "
 "FTE_STRINGS "
 "KRIMZON_SV_PARSECLIENTCOMMAND "
 "NEH_CMD_PLAY2 "
@@ -165,6 +182,10 @@ char *vm_sv_extensions =
 "PRYDON_CLIENTCURSOR "
 "TENEBRAE_GFX_DLIGHTS "
 "TW_SV_STEPCONTROL "
+"ZQ_PAUSE "
+"DP_CSQC_SPAWNPARTICLE "
+"DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
+"DP_CSQC_ENTITYNOCULL "
 //"EXT_CSQC " // not ready yet
 ;
 
@@ -197,7 +218,7 @@ static void VM_SV_setorigin (void)
        }
        org = PRVM_G_VECTOR(OFS_PARM1);
        VectorCopy (org, e->fields.server->origin);
-       SV_LinkEdict (e, false);
+       SV_LinkEdict(e);
 }
 
 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
@@ -214,7 +235,7 @@ static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rot
        VectorCopy (max, e->fields.server->maxs);
        VectorSubtract (max, min, e->fields.server->size);
 
-       SV_LinkEdict (e, false);
+       SV_LinkEdict(e);
 }
 
 /*
@@ -565,10 +586,10 @@ static void VM_SV_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 = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
+       trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
 
        VM_SetTraceGlobals(&trace);
 }
@@ -604,10 +625,10 @@ static void VM_SV_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 = SV_Move (v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
+       trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
 
        VM_SetTraceGlobals(&trace);
 }
@@ -634,7 +655,7 @@ static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
                gravity = val->_float;
        else
                gravity = 1.0;
-       gravity *= sv_gravity.value * 0.05;
+       gravity *= sv_gravity.value * 0.025;
 
        for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
        {
@@ -643,8 +664,9 @@ static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
                VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles);
                VectorScale (tossent->fields.server->velocity, 0.05, move);
                VectorAdd (tossent->fields.server->origin, move, end);
-               trace = SV_Move (tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
+               trace = SV_TraceBox(tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
                VectorCopy (trace.endpos, tossent->fields.server->origin);
+               tossent->fields.server->velocity[2] -= gravity;
 
                if (trace.fraction < 1)
                        break;
@@ -780,6 +802,72 @@ static void VM_SV_checkclient (void)
 
 //============================================================================
 
+/*
+=================
+VM_SV_checkpvs
+
+Checks if an entity is in a point's PVS.
+Should be fast but can be inexact.
+
+float checkpvs(vector viewpos, entity viewee) = #240;
+=================
+*/
+static void VM_SV_checkpvs (void)
+{
+       vec3_t viewpos;
+       prvm_edict_t *viewee;
+#if 1
+       unsigned char *pvs;
+#else
+       static int fatpvsbytes;
+       static unsigned char fatpvs[MAX_MAP_LEAFS/8];
+#endif
+
+       VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
+       viewee = PRVM_G_EDICT(OFS_PARM1);
+
+       if(viewee->priv.server->free)
+       {
+               VM_Warning("checkpvs: can not check free entity\n");
+               PRVM_G_FLOAT(OFS_RETURN) = 4;
+               return;
+       }
+
+#if 1
+       if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
+       {
+               // no PVS support on this worldmodel... darn
+               PRVM_G_FLOAT(OFS_RETURN) = 3;
+               return;
+       }
+       pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
+       if(!pvs)
+       {
+               // viewpos isn't in any PVS... darn
+               PRVM_G_FLOAT(OFS_RETURN) = 2;
+               return;
+       }
+       PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
+#else
+       // using fat PVS like FTEQW does (slow)
+       if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
+       {
+               // no PVS support on this worldmodel... darn
+               PRVM_G_FLOAT(OFS_RETURN) = 3;
+               return;
+       }
+       fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
+       if(!fatpvsbytes)
+       {
+               // viewpos isn't in any PVS... darn
+               PRVM_G_FLOAT(OFS_RETURN) = 2;
+               return;
+       }
+       PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
+#endif
+}
+
 
 /*
 =================
@@ -830,8 +918,16 @@ static void VM_SV_findradius (void)
        int i;
        int numtouchedicts;
        prvm_edict_t *touchedicts[MAX_EDICTS];
+       int chainfield;
 
-       VM_SAFEPARMCOUNT(2, VM_SV_findradius);
+       VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_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;
 
@@ -874,7 +970,7 @@ static void VM_SV_findradius (void)
                        VectorMAMAM(1, eorg, -0.5f, ent->fields.server->mins, -0.5f, ent->fields.server->maxs, eorg);
                if (DotProduct(eorg, eorg) < radius2)
                {
-                       ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
+                       PRVM_EDICTFIELDVALUE(ent,chainfield)->edict = PRVM_EDICT_TO_PROG(chain);
                        chain = ent;
                }
        }
@@ -988,19 +1084,19 @@ static void VM_SV_droptofloor (void)
        if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
                SV_UnstickEntity(ent);
 
-       trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
+       trace = SV_TraceBox(ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
        if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
        {
                vec3_t offset, org;
                VectorSet(offset, 0.5f * (ent->fields.server->mins[0] + ent->fields.server->maxs[0]), 0.5f * (ent->fields.server->mins[1] + ent->fields.server->maxs[1]), ent->fields.server->mins[2]);
                VectorAdd(ent->fields.server->origin, offset, org);
-               trace = SV_Move (org, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
+               trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
                VectorSubtract(trace.endpos, offset, trace.endpos);
                if (trace.startsolid)
                {
                        Con_DPrintf("droptofloor at %f %f %f - COULD NOT FIX BADLY PLACED ENTITY\n", ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2]);
                        SV_UnstickEntity(ent);
-                       SV_LinkEdict (ent, false);
+                       SV_LinkEdict(ent);
                        ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
                        ent->fields.server->groundentity = 0;
                        PRVM_G_FLOAT(OFS_RETURN) = 1;
@@ -1010,7 +1106,7 @@ static void VM_SV_droptofloor (void)
                        Con_DPrintf("droptofloor at %f %f %f - FIXED BADLY PLACED ENTITY\n", ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2]);
                        VectorCopy (trace.endpos, ent->fields.server->origin);
                        SV_UnstickEntity(ent);
-                       SV_LinkEdict (ent, false);
+                       SV_LinkEdict(ent);
                        ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
                        ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
                        PRVM_G_FLOAT(OFS_RETURN) = 1;
@@ -1024,7 +1120,7 @@ static void VM_SV_droptofloor (void)
                {
                        if (trace.fraction < 1)
                                VectorCopy (trace.endpos, ent->fields.server->origin);
-                       SV_LinkEdict (ent, false);
+                       SV_LinkEdict(ent);
                        ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
                        ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
                        PRVM_G_FLOAT(OFS_RETURN) = 1;
@@ -1141,7 +1237,7 @@ static void VM_SV_aim (void)
 // try sending a trace straight
        VectorCopy (prog->globals.server->v_forward, dir);
        VectorMA (start, 2048, dir, end);
-       tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
+       tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
        if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
        && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
        {
@@ -1173,7 +1269,7 @@ static void VM_SV_aim (void)
                dist = DotProduct (dir, prog->globals.server->v_forward);
                if (dist < bestdist)
                        continue;       // to far to turn
-               tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
+               tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
                if (tr.ent == check)
                {       // can shoot at this one
                        bestdist = dist;
@@ -1318,7 +1414,7 @@ static void VM_SV_WritePicture (void)
        VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
 
        imgname = PRVM_G_STRING(OFS_PARM1);
-       size = PRVM_G_FLOAT(OFS_PARM2);
+       size = (int) PRVM_G_FLOAT(OFS_PARM2);
        if(size > 65535)
                size = 65535;
 
@@ -1327,7 +1423,7 @@ static void VM_SV_WritePicture (void)
        {
                // actual picture
                MSG_WriteShort(WriteDest(), size);
-               SZ_Write(WriteDest(), buf, size);
+               SZ_Write(WriteDest(), (unsigned char *) buf, size);
        }
        else
        {
@@ -1593,7 +1689,7 @@ static void VM_SV_copyentity (void)
                return;
        }
        memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
-       SV_LinkEdict(out, false);
+       SV_LinkEdict(out);
 }
 
 
@@ -2489,17 +2585,57 @@ int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
        model = sv.models[i];
 
        return Mod_Alias_GetTagIndexForName(model, (int)e->fields.server->skin, tagname);
-};
+}
+
+int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
+{
+       int r;
+       dp_model_t *model;
+       int frame;
+       int modelindex;
+
+       *tagname = NULL;
+       *parentindex = 0;
+       Matrix4x4_CreateIdentity(tag_localmatrix);
+
+       if (tagindex >= 0
+        && (modelindex = (int)e->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
+        && (model = sv.models[(int)e->fields.server->modelindex])
+        && model->animscenes)
+       {
+               frame = (int)e->fields.server->frame;
+               if (frame < 0 || frame >= model->numframes)
+                       frame = 0;
+
+               r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)e->fields.server->skin, model->animscenes[frame].firstframe, tagindex - 1, parentindex, tagname, tag_localmatrix);
+
+               if(!r) // success?
+                       *parentindex += 1;
+
+               return r;
+       }
+
+       return 1;
+}
 
 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
 {
-       float scale = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale)->_float;
-       if (scale == 0)
-               scale = 1;
+       prvm_eval_t *val;
+       float scale;
+       float pitchsign = 1;
+
+       scale = 1;
+       val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
+       if (val && val->_float != 0)
+               scale = val->_float;
+       
        if (viewmatrix)
-               Matrix4x4_CreateFromQuakeEntity(out, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2] + ent->fields.server->view_ofs[2], ent->fields.server->v_angle[0], ent->fields.server->v_angle[1], ent->fields.server->v_angle[2], scale);
+               Matrix4x4_CreateFromQuakeEntity(out, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2] + ent->fields.server->view_ofs[2], ent->fields.server->v_angle[0], ent->fields.server->v_angle[1], ent->fields.server->v_angle[2], scale * cl_viewmodel_scale.value);
        else
-               Matrix4x4_CreateFromQuakeEntity(out, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2], -ent->fields.server->angles[0], ent->fields.server->angles[1], ent->fields.server->angles[2], scale * cl_viewmodel_scale.value);
+       {
+               pitchsign = SV_GetPitchSign(ent);
+               Matrix4x4_CreateFromQuakeEntity(out, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2], pitchsign * ent->fields.server->angles[0], ent->fields.server->angles[1], ent->fields.server->angles[2], scale);
+       }
 }
 
 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
@@ -2548,7 +2684,7 @@ int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
                return 2;
 
        modelindex = (int)ent->fields.server->modelindex;
-       if (modelindex <= 0 || modelindex > MAX_MODELS)
+       if (modelindex <= 0 || modelindex >= MAX_MODELS)
                return 3;
 
        model = sv.models[modelindex];
@@ -2565,9 +2701,9 @@ int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
                ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
                if (ret && attachloop == 0)
                        return ret;
-               Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
                SV_GetEntityMatrix(ent, &entitymatrix, false);
-               Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
+               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)
                {
@@ -2640,7 +2776,7 @@ static void VM_SV_gettagindex (void)
 
        modelindex = (int)ent->fields.server->modelindex;
        tag_index = 0;
-       if (modelindex <= 0 || modelindex > MAX_MODELS)
+       if (modelindex <= 0 || modelindex >= MAX_MODELS)
                Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
        else
        {
@@ -2650,7 +2786,7 @@ static void VM_SV_gettagindex (void)
                                Con_Printf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
        }
        PRVM_G_FLOAT(OFS_RETURN) = tag_index;
-};
+}
 
 //vector(entity ent, float tagindex) gettaginfo;
 static void VM_SV_gettaginfo (void)
@@ -2658,7 +2794,12 @@ static void VM_SV_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_SV_gettaginfo);
 
@@ -2666,7 +2807,23 @@ static void VM_SV_gettaginfo (void)
        tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
 
        returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
-       Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
+       Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, le, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
+       VectorScale(le, -1, prog->globals.server->v_right);
+       SV_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)
        {
@@ -2786,7 +2943,7 @@ static void VM_SV_setmodelindex (void)
                return;
        }
        i = (int)PRVM_G_FLOAT(OFS_PARM1);
-       if (i <= 0 || i > MAX_MODELS)
+       if (i <= 0 || i >= MAX_MODELS)
        {
                VM_Warning("setmodelindex: invalid modelindex\n");
                return;
@@ -2822,7 +2979,7 @@ static void VM_SV_modelnameforindex (void)
        PRVM_G_INT(OFS_RETURN) = OFS_NULL;
 
        i = (int)PRVM_G_FLOAT(OFS_PARM0);
-       if (i <= 0 || i > MAX_MODELS)
+       if (i <= 0 || i >= MAX_MODELS)
        {
                VM_Warning("modelnameforindex: invalid modelindex\n");
                return;
@@ -2897,6 +3054,24 @@ static void VM_SV_pointparticles (void)
        SV_FlushBroadcastMessages();
 }
 
+//PF_setpause,    // void(float pause) setpause        = #531;
+static void VM_SV_setpause(void) {
+       int pauseValue;
+       pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
+       if (pauseValue != 0) { //pause the game
+               sv.paused = 1;
+               sv.pausedstart = Sys_DoubleTime();
+       } else { //disable pause, in case it was enabled
+               if (sv.paused != 0) {
+                       sv.paused = 0;
+                       sv.pausedstart = 0;
+               }
+       }
+       // send notification to all clients
+       MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
+       MSG_WriteByte(&sv.reliable_datagram, sv.paused);
+}
+
 prvm_builtin_t vm_sv_builtins[] = {
 NULL,                                                  // #0 NULL function (not callable) (QUAKE)
 VM_makevectors,                                        // #1 void(vector ang) makevectors (QUAKE)
@@ -2914,7 +3089,7 @@ VM_vlen,                                          // #12 float(vector v) vlen (QUAKE)
 VM_vectoyaw,                                   // #13 float(vector v) vectoyaw (QUAKE)
 VM_spawn,                                              // #14 entity() spawn (QUAKE)
 VM_remove,                                             // #15 void(entity e) remove (QUAKE)
-VM_SV_traceline,                               // #16 float(vector v1, vector v2, float tryents) traceline (QUAKE)
+VM_SV_traceline,                               // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
 VM_SV_checkclient,                             // #17 entity() checkclient (QUAKE)
 VM_find,                                               // #18 entity(entity start, .string fld, string match) find (QUAKE)
 VM_SV_precache_sound,                  // #19 void(string s) precache_sound (QUAKE)
@@ -3140,7 +3315,7 @@ NULL,                                                     // #236
 NULL,                                                  // #237
 NULL,                                                  // #238
 NULL,                                                  // #239
-NULL,                                                  // #240
+VM_SV_checkpvs,                                        // #240 float(vector viewpos, entity viewee) checkpvs;
 NULL,                                                  // #241
 NULL,                                                  // #242
 NULL,                                                  // #243
@@ -3419,9 +3594,115 @@ VM_uri_get,                                             // #513 float(string uril, float id) uri_get = #513; (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)
-NULL,                                                  // #517
-NULL,                                                  // #518
-NULL,                                                  // #519
+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)
+VM_gettime,                                            // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
+NULL,                                                  // #520
+NULL,                                                  // #521
+NULL,                                                  // #522
+NULL,                                                  // #523
+NULL,                                                  // #524
+NULL,                                                  // #525
+NULL,                                                  // #526
+NULL,                                                  // #527
+NULL,                                                  // #528
+VM_loadfromdata,                               // #529
+VM_loadfromfile,                               // #530
+VM_SV_setpause,                                        // #531 void(float pause) setpause = #531;
+VM_log,                                                        // #532
+NULL,                                                  // #533
+NULL,                                                  // #534
+NULL,                                                  // #535
+NULL,                                                  // #536
+NULL,                                                  // #537
+NULL,                                                  // #538
+NULL,                                                  // #539
+NULL,                                                  // #540
+NULL,                                                  // #541
+NULL,                                                  // #542
+NULL,                                                  // #543
+NULL,                                                  // #544
+NULL,                                                  // #545
+NULL,                                                  // #546
+NULL,                                                  // #547
+NULL,                                                  // #548
+NULL,                                                  // #549
+NULL,                                                  // #550
+NULL,                                                  // #551
+NULL,                                                  // #552
+NULL,                                                  // #553
+NULL,                                                  // #554
+NULL,                                                  // #555
+NULL,                                                  // #556
+NULL,                                                  // #557
+NULL,                                                  // #558
+NULL,                                                  // #559
+NULL,                                                  // #560
+NULL,                                                  // #561
+NULL,                                                  // #562
+NULL,                                                  // #563
+NULL,                                                  // #564
+NULL,                                                  // #565
+NULL,                                                  // #566
+NULL,                                                  // #567
+NULL,                                                  // #568
+NULL,                                                  // #569
+NULL,                                                  // #570
+NULL,                                                  // #571
+NULL,                                                  // #572
+NULL,                                                  // #573
+NULL,                                                  // #574
+NULL,                                                  // #575
+NULL,                                                  // #576
+NULL,                                                  // #577
+NULL,                                                  // #578
+NULL,                                                  // #579
+NULL,                                                  // #580
+NULL,                                                  // #581
+NULL,                                                  // #582
+NULL,                                                  // #583
+NULL,                                                  // #584
+NULL,                                                  // #585
+NULL,                                                  // #586
+NULL,                                                  // #587
+NULL,                                                  // #588
+NULL,                                                  // #589
+NULL,                                                  // #590
+NULL,                                                  // #591
+NULL,                                                  // #592
+NULL,                                                  // #593
+NULL,                                                  // #594
+NULL,                                                  // #595
+NULL,                                                  // #596
+NULL,                                                  // #597
+NULL,                                                  // #598
+NULL,                                                  // #599
+NULL,                                                  // #600
+NULL,                                                  // #601
+NULL,                                                  // #602
+NULL,                                                  // #603
+NULL,                                                  // #604
+VM_callfunction,                               // #605
+VM_writetofile,                                        // #606
+VM_isfunction,                                 // #607
+NULL,                                                  // #608
+NULL,                                                  // #609
+NULL,                                                  // #610
+NULL,                                                  // #611
+NULL,                                                  // #612
+VM_parseentitydata,                            // #613
+NULL,                                                  // #614
+NULL,                                                  // #615
+NULL,                                                  // #616
+NULL,                                                  // #617
+NULL,                                                  // #618
+NULL,                                                  // #619
+NULL,                                                  // #620
+NULL,                                                  // #621
+NULL,                                                  // #622
+NULL,                                                  // #623
+VM_getextresponse,                             // #624 string getextresponse(void)
+NULL,                                                  // #625
 };
 
 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
@@ -3433,6 +3714,7 @@ void VM_SV_Cmd_Init(void)
 
 void VM_SV_Cmd_Reset(void)
 {
+       World_End(&sv.world);
        if(prog->funcoffsets.SV_Shutdown)
        {
                func_t s = prog->funcoffsets.SV_Shutdown;