#include "quakedef.h"
#include "prvm_cmds.h"
+#include "jpeg.h"
//============================================================================
// Server
"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_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_ETOS "
"DP_QC_FINDCHAIN "
+"DP_QC_FINDCHAIN_TOFIELD "
"DP_QC_FINDCHAINFLAGS "
"DP_QC_FINDCHAINFLOAT "
"DP_QC_FINDFLAGS "
"DP_QC_GETSURFACE "
"DP_QC_GETSURFACEPOINTATTRIBUTE "
"DP_QC_GETTAGINFO "
+"DP_QC_GETTAGINFO_BONEPROPERTIES "
"DP_QC_MINMAXBOUND "
"DP_QC_MULTIPLETEMPSTRINGS "
"DP_QC_NUM_FOR_EDICT "
"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 "
"DP_SV_NETADDRESS "
"DP_SV_NODRAWTOCLIENT "
"DP_SV_ONENTITYNOSPAWNFUNCTION "
+"DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
"DP_SV_PING "
"DP_SV_PLAYERPHYSICS "
"DP_SV_POINTPARTICLES "
"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 "
"DP_VIEWZOOM "
"EXT_BITSHIFT "
"FRIK_FILE "
+"FTE_QC_CHECKPVS "
"FTE_STRINGS "
"KRIMZON_SV_PARSECLIENTCOMMAND "
"NEH_CMD_PLAY2 "
"PRYDON_CLIENTCURSOR "
"TENEBRAE_GFX_DLIGHTS "
"TW_SV_STEPCONTROL "
+"ZQ_PAUSE "
//"EXT_CSQC " // not ready yet
;
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
{
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));
VectorCopy (trace.endpos, tossent->fields.server->origin);
+ tossent->fields.server->velocity[2] -= gravity;
if (trace.fraction < 1)
break;
//============================================================================
+/*
+=================
+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
+}
+
/*
=================
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;
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;
}
}
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)
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();
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();
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)
{
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, ri, up, trans;
VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
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));
+ SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
+ Matrix4x4_ToVectors(&tag_localmatrix, fo, ri, 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)))
+ VectorCopy(ri, val->vector);
+ if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_up)))
+ VectorCopy(up, val->vector);
switch(returncode)
{
{
VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
+ if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
+ return;
+
MSG_WriteByte(&sv.datagram, svc_trailparticles);
MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
int effectnum, count;
vec3_t org, vel;
VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
+
+ if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
+ return;
+
effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
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)
NULL, // #237
NULL, // #238
NULL, // #239
-NULL, // #240
+VM_SV_checkpvs, // #240 float(vector viewpos, entity viewee) checkpvs;
NULL, // #241
NULL, // #242
NULL, // #243
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
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
+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)
NULL, // #519
+NULL, // #520
+NULL, // #521
+NULL, // #522
+NULL, // #523
+NULL, // #524
+NULL, // #525
+NULL, // #526
+NULL, // #527
+NULL, // #528
+NULL, // #529
+NULL, // #530
+VM_SV_setpause, // #531 void(float pause) setpause = #531;
+NULL, // #532
};
const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);