X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=svvm_cmds.c;h=030bb92bf3bdc6ff478ea24f78de3cce97de2dd7;hp=6bbd066da6d2a451cccca4e6213fe9d205111ff3;hb=c0b8da8b7012a02ffd416d83840ad2bae7056191;hpb=29cbb66a5e4ab2d5a9bbc370f8c54d9e5a2600bf diff --git a/svvm_cmds.c b/svvm_cmds.c index 6bbd066d..030bb92b 100644 --- a/svvm_cmds.c +++ b/svvm_cmds.c @@ -1,6 +1,7 @@ #include "quakedef.h" #include "prvm_cmds.h" +#include "jpeg.h" //============================================================================ // Server @@ -18,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 " @@ -26,14 +28,17 @@ char *vm_sv_extensions = "DP_EF_NODEPTHTEST " "DP_EF_NODRAW " "DP_EF_NOGUNBOB " +"DP_EF_NOSELFSHADOW " "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 " @@ -44,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 " @@ -53,17 +59,23 @@ char *vm_sv_extensions = "DP_MONSTERWALK " "DP_MOVETYPEBOUNCEMISSILE " "DP_MOVETYPEFOLLOW " +"DP_NULL_MODEL " "DP_QC_ASINACOSATANATAN2TAN " "DP_QC_CHANGEPITCH " "DP_QC_CMD " "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 " @@ -73,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 " @@ -80,18 +96,22 @@ 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 " "DP_QC_TOKENIZEBYSEPARATOR " +"DP_QC_TOKENIZE_CONSOLE " "DP_QC_TRACEBOX " "DP_QC_TRACETOSS " "DP_QC_TRACE_MOVETYPE_HITMODEL " "DP_QC_TRACE_MOVETYPE_WORLDONLY " "DP_QC_UNLIMITEDTEMPSTRINGS " "DP_QC_URI_ESCAPE " +"DP_QC_URI_GET " "DP_QC_VECTOANGLES_WITH_ROLL " "DP_QC_VECTORVECTORS " +"DP_QC_WHICHPACK " "DP_QUAKE2_MODEL " "DP_QUAKE2_SPRITE " "DP_QUAKE3_MAP " @@ -104,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 " @@ -117,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 " @@ -124,10 +146,13 @@ char *vm_sv_extensions = "DP_SV_PRECACHEANYTIME " "DP_SV_PRINT " "DP_SV_PUNCHVECTOR " +"DP_SV_QCSTATUS " "DP_SV_ROTATINGBMODEL " "DP_SV_SETCOLOR " "DP_SV_SHUTDOWN " "DP_SV_SLOWMO " +"DP_SV_SPAWNFUNC_PREFIX " +"DP_SV_WRITEPICTURE " "DP_SV_WRITEUNTERMINATEDSTRING " "DP_TE_BLOOD " "DP_TE_BLOODSHOWER " @@ -144,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 " @@ -155,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 ; @@ -187,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] @@ -204,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); } /* @@ -555,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); } @@ -594,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); } @@ -624,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 { @@ -633,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; @@ -770,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 +} + /* ================= @@ -820,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; @@ -864,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; } } @@ -978,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; @@ -1000,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; @@ -1014,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; @@ -1131,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) ) { @@ -1163,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; @@ -1293,6 +1399,39 @@ static void VM_SV_WriteEntity (void) MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1)); } +// writes a picture as at most size bytes of data +// message: +// IMGNAME \0 SIZE(short) IMGDATA +// if failed to read/compress: +// IMGNAME \0 \0 \0 +//#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE)) +static void VM_SV_WritePicture (void) +{ + const char *imgname; + void *buf; + size_t size; + + VM_SAFEPARMCOUNT(3, VM_SV_WritePicture); + + imgname = PRVM_G_STRING(OFS_PARM1); + size = (int) PRVM_G_FLOAT(OFS_PARM2); + if(size > 65535) + size = 65535; + + MSG_WriteString(WriteDest(), imgname); + if(Image_Compress(imgname, size, &buf, &size)) + { + // actual picture + MSG_WriteShort(WriteDest(), size); + SZ_Write(WriteDest(), (unsigned char *) buf, size); + } + else + { + // placeholder + MSG_WriteShort(WriteDest(), 0); + } +} + ////////////////////////////////////////////////////////// static void VM_SV_makestatic (void) @@ -1550,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); } @@ -1650,9 +1789,9 @@ static void VM_SV_te_blood (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); // velocity - MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127)); - MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127)); - MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127)); + MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127)); + MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127)); + MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127)); // count MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255)); SV_FlushBroadcastMessages(); @@ -1790,9 +1929,9 @@ static void VM_SV_te_spark (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); // velocity - MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127)); - MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127)); - MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127)); + MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127)); + MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127)); + MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127)); // count MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255)); SV_FlushBroadcastMessages(); @@ -2446,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) @@ -2505,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]; @@ -2522,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) { @@ -2597,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 { @@ -2607,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) @@ -2615,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); @@ -2623,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) { @@ -2743,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; @@ -2779,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; @@ -2854,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) @@ -2871,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) @@ -3097,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 @@ -3355,14 +3573,14 @@ NULL, // #492 NULL, // #493 VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16) VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE) -NULL, // #496 -NULL, // #497 -NULL, // #498 -NULL, // #499 -NULL, // #500 -NULL, // #501 +VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA) +VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA) +VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA) +VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA) +VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA) +VM_SV_WritePicture, // #501 NULL, // #502 -NULL, // #503 +VM_whichpack, // #503 string(string) whichpack = #503; NULL, // #504 NULL, // #505 NULL, // #506 @@ -3372,13 +3590,119 @@ NULL, // #509 VM_uri_escape, // #510 string(string in) uri_escape = #510; VM_uri_unescape, // #511 string(string in) uri_unescape = #511; VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT) -NULL, // #513 -NULL, // #514 -NULL, // #515 -NULL, // #516 -NULL, // #517 -NULL, // #518 -NULL, // #519 +VM_uri_get, // #513 float(string uril, float id) uri_get = #513; (DP_QC_URI_GET) +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) +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); @@ -3390,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;