X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=svvm_cmds.c;h=8a6a81ecb2aac735b999906c3df3f39fce02f1f7;hb=HEAD;hp=f899b295890a60091c7fd3f567d524a03e29fe00;hpb=da028866966d99b93c3a0f8049655ade5c5361a3;p=xonotic%2Fdarkplaces.git diff --git a/svvm_cmds.c b/svvm_cmds.c index f899b295..770f1abe 100644 --- a/svvm_cmds.c +++ b/svvm_cmds.c @@ -8,222 +8,232 @@ -const char *vm_sv_extensions = -"BX_WAL_SUPPORT " -"DP_BUTTONCHAT " -"DP_BUTTONUSE " -"DP_CL_LOADSKY " -"DP_CON_ALIASPARAMETERS " -"DP_CON_BESTWEAPON " -"DP_CON_EXPANDCVAR " -"DP_CON_SET " -"DP_CON_SETA " -"DP_CON_STARTMAP " -"DP_CRYPTO " -"DP_CSQC_BINDMAPS " -"DP_CSQC_ENTITYWORLDOBJECT " -"DP_CSQC_ENTITYMODELLIGHT " -"DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET " -"DP_CSQC_MAINVIEW " -"DP_CSQC_MINFPS_QUALITY " -"DP_CSQC_MULTIFRAME_INTERPOLATION " -"DP_CSQC_BOXPARTICLES " -"DP_CSQC_SPAWNPARTICLE " -"DP_CSQC_QUERYRENDERENTITY " -"DP_CSQC_ROTATEMOVES " -"DP_CSQC_SETPAUSE " -"DP_CSQC_V_CALCREFDEF_WIP1 " -"DP_EF_ADDITIVE " -"DP_EF_BLUE " -"DP_EF_DOUBLESIDED " -"DP_EF_DYNAMICMODELLIGHT " -"DP_EF_FLAME " -"DP_EF_FULLBRIGHT " -"DP_EF_NODEPTHTEST " -"DP_EF_NODRAW " -"DP_EF_NOGUNBOB " -"DP_EF_NOSELFSHADOW " -"DP_EF_NOSHADOW " -"DP_EF_RED " -"DP_EF_RESTARTANIM_BIT " -"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_TRAILEFFECTNUM " -"DP_ENT_VIEWMODEL " -"DP_GFX_EXTERNALTEXTURES " -"DP_GFX_EXTERNALTEXTURES_PERMAP " -"DP_GFX_FOG " -"DP_GFX_MODEL_INTERPOLATION " -"DP_GFX_QUAKE3MODELTAGS " -"DP_GFX_SKINFILES " -"DP_GFX_SKYBOX " -"DP_GFX_FONTS " -"DP_GFX_FONTS_FREETYPE " -"DP_UTF8 " -"DP_FONT_VARIABLEWIDTH " -"DP_HALFLIFE_MAP " -"DP_HALFLIFE_MAP_CVAR " -"DP_HALFLIFE_SPRITE " -"DP_INPUTBUTTONS " -"DP_LIGHTSTYLE_STATICVALUE " -"DP_LITSPRITES " -"DP_LITSUPPORT " -"DP_MONSTERWALK " -"DP_MOVETYPEBOUNCEMISSILE " -"DP_MOVETYPEFLYWORLDONLY " -"DP_MOVETYPEFOLLOW " -"DP_NULL_MODEL " -"DP_QC_ASINACOSATANATAN2TAN " -"DP_QC_AUTOCVARS " -"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_DIGEST " -"DP_QC_DIGEST_SHA256 " -"DP_QC_EDICT_NUM " -"DP_QC_ENTITYDATA " -"DP_QC_ENTITYSTRING " -"DP_QC_ETOS " -"DP_QC_EXTRESPONSEPACKET " -"DP_QC_FINDCHAIN " -"DP_QC_FINDCHAINFLAGS " -"DP_QC_FINDCHAINFLOAT " -"DP_QC_FINDCHAIN_TOFIELD " -"DP_QC_FINDFLAGS " -"DP_QC_FINDFLOAT " -"DP_QC_FS_SEARCH " -"DP_QC_GETLIGHT " -"DP_QC_GETSURFACE " -"DP_QC_GETSURFACETRIANGLE " -"DP_QC_GETSURFACEPOINTATTRIBUTE " -"DP_QC_GETTAGINFO " -"DP_QC_GETTAGINFO_BONEPROPERTIES " -"DP_QC_GETTIME " -"DP_QC_GETTIME_CDTRACK " -"DP_QC_I18N " -"DP_QC_LOG " -"DP_QC_MINMAXBOUND " -"DP_QC_MULTIPLETEMPSTRINGS " -"DP_QC_NUM_FOR_EDICT " -"DP_QC_RANDOMVEC " -"DP_QC_SINCOSSQRTPOW " -"DP_QC_SPRINTF " -"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_URI_POST " -"DP_QC_VECTOANGLES_WITH_ROLL " -"DP_QC_VECTORVECTORS " -"DP_QC_WHICHPACK " -"DP_QUAKE2_MODEL " -"DP_QUAKE2_SPRITE " -"DP_QUAKE3_MAP " -"DP_QUAKE3_MODEL " -"DP_REGISTERCVAR " -"DP_SKELETONOBJECTS " -"DP_SND_DIRECTIONLESSATTNNONE " -"DP_SND_FAKETRACKS " -"DP_SND_SOUND7_WIP1 " -"DP_SND_SOUND7_WIP2 " -"DP_SND_OGGVORBIS " -"DP_SND_SETPARAMS " -"DP_SND_STEREOWAV " -"DP_SND_GETSOUNDTIME " -"DP_VIDEO_DPV " -"DP_VIDEO_SUBTITLES " -"DP_SOLIDCORPSE " -"DP_SPRITE32 " -"DP_SV_BOTCLIENT " -"DP_SV_BOUNCEFACTOR " -"DP_SV_CLIENTCAMERA " -"DP_SV_CLIENTCOLORS " -"DP_SV_CLIENTNAME " -"DP_SV_CMD " -"DP_SV_CUSTOMIZEENTITYFORCLIENT " -"DP_SV_DISCARDABLEDEMO " -"DP_SV_DRAWONLYTOCLIENT " -"DP_SV_DROPCLIENT " -"DP_SV_EFFECT " -"DP_SV_ENTITYCONTENTSTRANSITION " -"DP_SV_MODELFLAGS_AS_EFFECTS " -"DP_SV_MOVETYPESTEP_LANDEVENT " -"DP_SV_NETADDRESS " -"DP_SV_NODRAWTOCLIENT " -"DP_SV_ONENTITYNOSPAWNFUNCTION " -"DP_SV_ONENTITYPREPOSTSPAWNFUNCTION " -"DP_SV_PING " -"DP_SV_PING_PACKETLOSS " -"DP_SV_PLAYERPHYSICS " -"DP_PHYSICS_ODE " -"DP_SV_POINTPARTICLES " -"DP_SV_POINTSOUND " -"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_TE_CUSTOMFLASH " -"DP_TE_EXPLOSIONRGB " -"DP_TE_FLAMEJET " -"DP_TE_PARTICLECUBE " -"DP_TE_PARTICLERAIN " -"DP_TE_PARTICLESNOW " -"DP_TE_PLASMABURN " -"DP_TE_QUADEFFECTS1 " -"DP_TE_SMALLFLASH " -"DP_TE_SPARK " -"DP_TE_STANDARDEFFECTBUILTINS " -"DP_TRACE_HITCONTENTSMASK_SURFACEINFO " -"DP_VIEWZOOM " -"EXT_BITSHIFT " -"FRIK_FILE " -"FTE_CSQC_SKELETONOBJECTS " -"FTE_QC_CHECKPVS " -"FTE_STRINGS " -"KRIMZON_SV_PARSECLIENTCOMMAND " -"NEH_CMD_PLAY2 " -"NEH_RESTOREGAME " -"NEXUIZ_PLAYERMODEL " -"NXQ_GFX_LETTERBOX " -"PRYDON_CLIENTCURSOR " -"TENEBRAE_GFX_DLIGHTS " -"TW_SV_STEPCONTROL " -"ZQ_PAUSE " -//"EXT_CSQC " // not ready yet -; +const char *vm_sv_extensions[] = { +"BX_WAL_SUPPORT", +"DP_BUTTONCHAT", +"DP_BUTTONUSE", +"DP_CL_LOADSKY", +"DP_CON_ALIASPARAMETERS", +"DP_CON_BESTWEAPON", +"DP_CON_EXPANDCVAR", +"DP_CON_SET", +"DP_CON_SETA", +"DP_CON_STARTMAP", +"DP_COVERAGE", +"DP_CRYPTO", +"DP_CSQC_BINDMAPS", +"DP_CSQC_ENTITYWORLDOBJECT", +"DP_CSQC_ENTITYMODELLIGHT", +"DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET", +"DP_CSQC_MAINVIEW", +"DP_CSQC_MINFPS_QUALITY", +"DP_CSQC_MULTIFRAME_INTERPOLATION", +"DP_CSQC_BOXPARTICLES", +"DP_CSQC_SPAWNPARTICLE", +"DP_CSQC_QUERYRENDERENTITY", +"DP_CSQC_ROTATEMOVES", +"DP_CSQC_SETPAUSE", +"DP_CSQC_V_CALCREFDEF_WIP1", +"DP_CSQC_V_CALCREFDEF_WIP2", +"DP_EF_ADDITIVE", +"DP_EF_BLUE", +"DP_EF_DOUBLESIDED", +"DP_EF_DYNAMICMODELLIGHT", +"DP_EF_FLAME", +"DP_EF_FULLBRIGHT", +"DP_EF_NODEPTHTEST", +"DP_EF_NODRAW", +"DP_EF_NOGUNBOB", +"DP_EF_NOSELFSHADOW", +"DP_EF_NOSHADOW", +"DP_EF_RED", +"DP_EF_RESTARTANIM_BIT", +"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_TRAILEFFECTNUM", +"DP_ENT_VIEWMODEL", +"DP_GFX_EXTERNALTEXTURES", +"DP_GFX_EXTERNALTEXTURES_PERMAP", +"DP_GFX_FOG", +"DP_GFX_MODEL_INTERPOLATION", +"DP_GFX_QUAKE3MODELTAGS", +"DP_GFX_SKINFILES", +"DP_GFX_SKYBOX", +"DP_GFX_FONTS", +"DP_GFX_FONTS_FREETYPE", +"DP_UTF8", +"DP_FONT_VARIABLEWIDTH", +"DP_HALFLIFE_MAP", +"DP_HALFLIFE_MAP_CVAR", +"DP_HALFLIFE_SPRITE", +"DP_INPUTBUTTONS", +"DP_LIGHTSTYLE_STATICVALUE", +"DP_LITSPRITES", +"DP_LITSUPPORT", +"DP_MONSTERWALK", +"DP_MOVETYPEBOUNCEMISSILE", +"DP_MOVETYPEFLYWORLDONLY", +"DP_MOVETYPEFOLLOW", +"DP_NULL_MODEL", +"DP_QC_ASINACOSATANATAN2TAN", +"DP_QC_AUTOCVARS", +"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_DIGEST", +"DP_QC_DIGEST_SHA256", +"DP_QC_EDICT_NUM", +"DP_QC_ENTITYDATA", +"DP_QC_ENTITYSTRING", +"DP_QC_ETOS", +"DP_QC_EXTRESPONSEPACKET", +"DP_QC_FINDBOX", +"DP_QC_FINDCHAIN", +"DP_QC_FINDCHAINFLAGS", +"DP_QC_FINDCHAINFLOAT", +"DP_QC_FINDCHAIN_TOFIELD", +"DP_QC_FINDFLAGS", +"DP_QC_FINDFLOAT", +"DP_QC_FS_SEARCH", +"DP_QC_FS_SEARCH_PACKFILE", +"DP_QC_GETLIGHT", +"DP_QC_GETSURFACE", +"DP_QC_GETSURFACETRIANGLE", +"DP_QC_GETSURFACEPOINTATTRIBUTE", +"DP_QC_GETTAGINFO", +"DP_QC_GETTAGINFO_BONEPROPERTIES", +"DP_QC_GETTIME", +"DP_QC_GETTIME_CDTRACK", +"DP_QC_I18N", +"DP_QC_LOG", +"DP_QC_MINMAXBOUND", +"DP_QC_MULTIPLETEMPSTRINGS", +"DP_QC_NUDGEOUTOFSOLID", +"DP_QC_NUM_FOR_EDICT", +"DP_QC_RANDOMVEC", +"DP_QC_SINCOSSQRTPOW", +"DP_QC_SPRINTF", +"DP_QC_STRFTIME", +"DP_QC_STRINGBUFFERS", +"DP_QC_STRINGBUFFERS_CVARLIST", +"DP_QC_STRINGBUFFERS_EXT_WIP", +"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_URI_POST", +"DP_QC_VECTOANGLES_WITH_ROLL", +"DP_QC_VECTORVECTORS", +"DP_QC_WHICHPACK", +"DP_QUAKE2_MODEL", +"DP_QUAKE2_SPRITE", +"DP_QUAKE3_MAP", +"DP_QUAKE3_MODEL", +"DP_REGISTERCVAR", +"DP_SKELETONOBJECTS", +"DP_SND_DIRECTIONLESSATTNNONE", +"DP_SND_FAKETRACKS", +"DP_SND_SOUND7_WIP1", +"DP_SND_SOUND7_WIP2", +"DP_SND_OGGVORBIS", +"DP_SND_SETPARAMS", +"DP_SND_STEREOWAV", +"DP_SND_GETSOUNDTIME", +"DP_VIDEO_DPV", +"DP_VIDEO_SUBTITLES", +"DP_SOLIDCORPSE", +"DP_SPRITE32", +"DP_SV_BOTCLIENT", +"DP_SV_BOUNCEFACTOR", +"DP_SV_CLIENTCAMERA", +"DP_SV_CLIENTCOLORS", +"DP_SV_CLIENTNAME", +"DP_SV_CMD", +"DP_SV_CUSTOMIZEENTITYFORCLIENT", +"DP_SV_DISABLECLIENTPREDICTION", +"DP_SV_DISCARDABLEDEMO", +"DP_SV_DRAWONLYTOCLIENT", +"DP_SV_DROPCLIENT", +"DP_SV_EFFECT", +"DP_SV_ENTITYCONTENTSTRANSITION", +"DP_SV_MODELFLAGS_AS_EFFECTS", +"DP_SV_MOVETYPESTEP_LANDEVENT", +"DP_SV_NETADDRESS", +"DP_SV_NODRAWTOCLIENT", +"DP_SV_ONENTITYNOSPAWNFUNCTION", +"DP_SV_ONENTITYPREPOSTSPAWNFUNCTION", +"DP_SV_PING", +"DP_SV_PING_PACKETLOSS", +"DP_SV_PLAYERPHYSICS", +"DP_PHYSICS_ODE", +"DP_SV_POINTPARTICLES", +"DP_SV_POINTSOUND", +"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_TE_CUSTOMFLASH", +"DP_TE_EXPLOSIONRGB", +"DP_TE_FLAMEJET", +"DP_TE_PARTICLECUBE", +"DP_TE_PARTICLERAIN", +"DP_TE_PARTICLESNOW", +"DP_TE_PLASMABURN", +"DP_TE_QUADEFFECTS1", +"DP_TE_SMALLFLASH", +"DP_TE_SPARK", +"DP_TE_STANDARDEFFECTBUILTINS", +"DP_TRACE_HITCONTENTSMASK_SURFACEINFO" +"DP_USERMOVETYPES", +"DP_VIEWZOOM", +"EXT_BITSHIFT", +"FRIK_FILE", +"FTE_CSQC_SKELETONOBJECTS", +"FTE_QC_CHECKPVS", +"FTE_STRINGS", +"KRIMZON_SV_PARSECLIENTCOMMAND", +"NEH_CMD_PLAY2", +"NEH_RESTOREGAME", +"NEXUIZ_PLAYERMODEL", +"NXQ_GFX_LETTERBOX", +"PRYDON_CLIENTCURSOR", +"TENEBRAE_GFX_DLIGHTS", +"TW_SV_STEPCONTROL", +"ZQ_PAUSE", +"DP_RM_CLIPGROUP", +NULL +//"EXT_CSQC" // not ready yet +}; /* ================= @@ -237,9 +247,8 @@ setorigin (entity, origin) static void VM_SV_setorigin(prvm_prog_t *prog) { prvm_edict_t *e; - float *org; - VM_SAFEPARMCOUNT(2, VM_setorigin); + VM_SAFEPARMCOUNT(2, VM_SV_setorigin); e = PRVM_G_EDICT(OFS_PARM0); if (e == prog->edicts) @@ -247,20 +256,19 @@ static void VM_SV_setorigin(prvm_prog_t *prog) VM_Warning(prog, "setorigin: can not modify world entity\n"); return; } - if (e->priv.server->free) + if (e->free) { VM_Warning(prog, "setorigin: can not modify free entity\n"); return; } - org = PRVM_G_VECTOR(OFS_PARM1); - VectorCopy (org, PRVM_serveredictvector(e, origin)); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), PRVM_serveredictvector(e, origin)); if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN) e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT; SV_LinkEdict(e); } // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black] -static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max, qboolean rotate) +static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max, qbool rotate) { int i; @@ -281,7 +289,7 @@ static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float VM_SV_setsize the size box is rotated by the current angle -LordHavoc: no it isn't... +LadyHavoc: no it isn't... setsize (entity, minvector, maxvector) ================= @@ -289,9 +297,9 @@ setsize (entity, minvector, maxvector) static void VM_SV_setsize(prvm_prog_t *prog) { prvm_edict_t *e; - float *min, *max; + vec3_t mins, maxs; - VM_SAFEPARMCOUNT(3, VM_setsize); + VM_SAFEPARMCOUNT(3, VM_SV_setsize); e = PRVM_G_EDICT(OFS_PARM0); if (e == prog->edicts) @@ -299,14 +307,14 @@ static void VM_SV_setsize(prvm_prog_t *prog) VM_Warning(prog, "setsize: can not modify world entity\n"); return; } - if (e->priv.server->free) + if (e->free) { VM_Warning(prog, "setsize: can not modify free entity\n"); return; } - min = PRVM_G_VECTOR(OFS_PARM1); - max = PRVM_G_VECTOR(OFS_PARM2); - SetMinMaxSize(prog, e, min, max, false); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), mins); + VectorCopy(PRVM_G_VECTOR(OFS_PARM2), maxs); + SetMinMaxSize(prog, e, mins, maxs, false); } @@ -321,10 +329,10 @@ static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16}; static void VM_SV_setmodel(prvm_prog_t *prog) { prvm_edict_t *e; - dp_model_t *mod; + model_t *mod; int i; - VM_SAFEPARMCOUNT(2, VM_setmodel); + VM_SAFEPARMCOUNT(2, VM_SV_setmodel); e = PRVM_G_EDICT(OFS_PARM0); if (e == prog->edicts) @@ -332,7 +340,7 @@ static void VM_SV_setmodel(prvm_prog_t *prog) VM_Warning(prog, "setmodel: can not modify world entity\n"); return; } - if (e->priv.server->free) + if (e->free) { VM_Warning(prog, "setmodel: can not modify free entity\n"); return; @@ -367,14 +375,14 @@ static void VM_SV_sprint(prvm_prog_t *prog) { client_t *client; int entnum; - char string[VM_STRINGTEMP_LENGTH]; + char string[VM_TEMPSTRING_MAXSIZE]; VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint); VM_VarString(prog, 1, string, sizeof(string)); entnum = PRVM_G_EDICTNUM(OFS_PARM0); - // LordHavoc: div0 requested that sprintto world operate like print + // LadyHavoc: div0 requested that sprintto world operate like print if (entnum == 0) { Con_Print(string); @@ -409,7 +417,7 @@ static void VM_SV_centerprint(prvm_prog_t *prog) { client_t *client; int entnum; - char string[VM_STRINGTEMP_LENGTH]; + char string[VM_TEMPSTRING_MAXSIZE]; VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint); @@ -439,17 +447,17 @@ particle(origin, color, count) */ static void VM_SV_particle(prvm_prog_t *prog) { - float *org, *dir; - float color; - float count; + vec3_t org, dir; + int color; + int count; VM_SAFEPARMCOUNT(4, VM_SV_particle); - org = PRVM_G_VECTOR(OFS_PARM0); - dir = PRVM_G_VECTOR(OFS_PARM1); - color = PRVM_G_FLOAT(OFS_PARM2); - count = PRVM_G_FLOAT(OFS_PARM3); - SV_StartParticle (org, dir, (int)color, (int)count); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), dir); + color = (int)PRVM_G_FLOAT(OFS_PARM2); + count = (int)PRVM_G_FLOAT(OFS_PARM3); + SV_StartParticle (org, dir, color, count); } @@ -462,13 +470,13 @@ VM_SV_ambientsound static void VM_SV_ambientsound(prvm_prog_t *prog) { const char *samp; - float *pos; - float vol, attenuation; + vec3_t pos; + prvm_vec_t vol, attenuation; int soundnum, large; VM_SAFEPARMCOUNT(4, VM_SV_ambientsound); - pos = PRVM_G_VECTOR (OFS_PARM0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos); samp = PRVM_G_STRING(OFS_PARM1); vol = PRVM_G_FLOAT(OFS_PARM2); attenuation = PRVM_G_FLOAT(OFS_PARM3); @@ -482,6 +490,9 @@ static void VM_SV_ambientsound(prvm_prog_t *prog) if (soundnum >= 256) large = true; + if(sv.protocol == PROTOCOL_NEHAHRABJP) + large = false; + // add an svc_spawnambient command to the level signon packet if (large) @@ -491,7 +502,7 @@ static void VM_SV_ambientsound(prvm_prog_t *prog) MSG_WriteVector(&sv.signon, pos, sv.protocol); - if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) + if (large || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) MSG_WriteShort (&sv.signon, soundnum); else MSG_WriteByte (&sv.signon, soundnum); @@ -514,6 +525,7 @@ already running on that entity/channel pair. An attenuation of 0 will play full volume everywhere in the level. Larger attenuations will drop off. +void(entity e, float chan, string samp, float volume[, float atten[, float pitchchange[, float flags]]]) sound (QUAKE) ================= */ static void VM_SV_sound(prvm_prog_t *prog) @@ -521,7 +533,7 @@ static void VM_SV_sound(prvm_prog_t *prog) const char *sample; int channel; prvm_edict_t *entity; - int volume; + int nvolume; int flags; float attenuation; float pitchchange; @@ -531,7 +543,7 @@ static void VM_SV_sound(prvm_prog_t *prog) entity = PRVM_G_EDICT(OFS_PARM0); channel = (int)PRVM_G_FLOAT(OFS_PARM1); sample = PRVM_G_STRING(OFS_PARM2); - volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255); + nvolume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255); if (prog->argc < 5) { Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n"); @@ -549,14 +561,17 @@ static void VM_SV_sound(prvm_prog_t *prog) flags = 0; if(channel >= 8 && channel <= 15) // weird QW feature { - flags |= CHANFLAG_RELIABLE; + flags |= CHANNELFLAG_RELIABLE; channel -= 8; } } else - flags = PRVM_G_FLOAT(OFS_PARM6); + { + // LadyHavoc: we only let the qc set certain flags, others are off-limits + flags = (int)PRVM_G_FLOAT(OFS_PARM6) & (CHANNELFLAG_RELIABLE | CHANNELFLAG_FORCELOOP | CHANNELFLAG_PAUSED | CHANNELFLAG_FULLVOLUME); + } - if (volume < 0 || volume > 255) + if (nvolume < 0 || nvolume > 255) { VM_Warning(prog, "SV_StartSound: volume must be in range 0-1\n"); return; @@ -576,7 +591,7 @@ static void VM_SV_sound(prvm_prog_t *prog) return; } - SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANFLAG_RELIABLE, pitchchange); + SV_StartSound (entity, channel, sample, nvolume, attenuation, flags & CHANNELFLAG_RELIABLE, pitchchange); } /* @@ -592,7 +607,7 @@ is omitted (since no entity is being tracked). static void VM_SV_pointsound(prvm_prog_t *prog) { const char *sample; - int volume; + int nvolume; float attenuation; float pitchchange; vec3_t org; @@ -601,11 +616,11 @@ static void VM_SV_pointsound(prvm_prog_t *prog) VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org); sample = PRVM_G_STRING(OFS_PARM1); - volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255); + nvolume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255); attenuation = PRVM_G_FLOAT(OFS_PARM3); pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f; - if (volume < 0 || volume > 255) + if (nvolume < 0 || nvolume > 255) { VM_Warning(prog, "SV_StartPointSound: volume must be in range 0-1\n"); return; @@ -617,7 +632,7 @@ static void VM_SV_pointsound(prvm_prog_t *prog) return; } - SV_StartPointSound (org, sample, volume, attenuation, pitchchange); + SV_StartPointSound (org, sample, nvolume, attenuation, pitchchange); } /* @@ -633,7 +648,7 @@ traceline (vector1, vector2, movetype, ignore) */ static void VM_SV_traceline(prvm_prog_t *prog) { - float *v1, *v2; + vec3_t v1, v2; trace_t trace; int move; prvm_edict_t *ent; @@ -642,15 +657,15 @@ static void VM_SV_traceline(prvm_prog_t *prog) prog->xfunction->builtinsprofile += 30; - v1 = PRVM_G_VECTOR(OFS_PARM0); - v2 = PRVM_G_VECTOR(OFS_PARM1); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), v2); 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(v2[1]) || IS_NAN(v2[2])) + if (isnan(v1[0]) || isnan(v1[1]) || isnan(v1[2]) || isnan(v2[0]) || isnan(v2[1]) || isnan(v2[2])) prog->error_cmd("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", prog->name, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent)); - trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent)); + trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendtracelinelength.value); VM_SetTraceGlobals(prog, &trace); } @@ -667,10 +682,10 @@ if the tryents flag is set. tracebox (vector1, vector mins, vector maxs, vector2, tryents) ================= */ -// LordHavoc: added this for my own use, VERY useful, similar to traceline +// LadyHavoc: added this for my own use, VERY useful, similar to traceline static void VM_SV_tracebox(prvm_prog_t *prog) { - float *v1, *v2, *m1, *m2; + vec3_t v1, v2, m1, m2; trace_t trace; int move; prvm_edict_t *ent; @@ -679,17 +694,17 @@ static void VM_SV_tracebox(prvm_prog_t *prog) prog->xfunction->builtinsprofile += 30; - v1 = PRVM_G_VECTOR(OFS_PARM0); - m1 = PRVM_G_VECTOR(OFS_PARM1); - m2 = PRVM_G_VECTOR(OFS_PARM2); - v2 = PRVM_G_VECTOR(OFS_PARM3); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), m1); + VectorCopy(PRVM_G_VECTOR(OFS_PARM2), m2); + VectorCopy(PRVM_G_VECTOR(OFS_PARM3), v2); 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(v2[1]) || IS_NAN(v2[2])) + if (isnan(v1[0]) || isnan(v1[1]) || isnan(v1[2]) || isnan(v2[0]) || isnan(v2[1]) || isnan(v2[2])) prog->error_cmd("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", prog->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_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent)); + trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendtraceboxlength.value); VM_SetTraceGlobals(prog, &trace); } @@ -698,7 +713,7 @@ static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edic { int i; float gravity; - vec3_t move, end; + vec3_t move, end, tossentorigin, tossentmins, tossentmaxs; vec3_t original_origin; vec3_t original_velocity; vec3_t original_angles; @@ -715,14 +730,17 @@ static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edic gravity = 1.0f; gravity *= sv_gravity.value * 0.025; - for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds + for (i = 0;i < 200;i++) // LadyHavoc: sanity check; never trace more than 10 seconds { SV_CheckVelocity (tossent); PRVM_serveredictvector(tossent, velocity)[2] -= gravity; VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles)); VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move); VectorAdd (PRVM_serveredictvector(tossent, origin), move, end); - trace = SV_TraceBox(PRVM_serveredictvector(tossent, origin), PRVM_serveredictvector(tossent, mins), PRVM_serveredictvector(tossent, maxs), end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent)); + VectorCopy(PRVM_serveredictvector(tossent, origin), tossentorigin); + VectorCopy(PRVM_serveredictvector(tossent, mins), tossentmins); + VectorCopy(PRVM_serveredictvector(tossent, maxs), tossentmaxs); + trace = SV_TraceBox(tossentorigin, tossentmins, tossentmaxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent), 0, 0, collision_extendmovelength.value); VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin)); PRVM_serveredictvector(tossent, velocity)[2] -= gravity; @@ -763,8 +781,7 @@ static void VM_SV_tracetoss(prvm_prog_t *prog) //============================================================================ -static int checkpvsbytes; -static unsigned char checkpvs[MAX_MAP_LEAFS/8]; +static unsigned char *checkpvs; static int VM_SV_newcheckclient(prvm_prog_t *prog, int check) { @@ -790,7 +807,7 @@ static int VM_SV_newcheckclient(prvm_prog_t *prog, int check) // look up the client's edict ent = PRVM_EDICT_NUM(i); // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop) - if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET))) + if (i != check && (ent->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET))) continue; // found a valid client (possibly the same one again) break; @@ -798,9 +815,10 @@ static int VM_SV_newcheckclient(prvm_prog_t *prog, int check) // get the PVS for the entity VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org); - checkpvsbytes = 0; if (sv.worldmodel && sv.worldmodel->brush.FatPVS) - checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false); + sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, &checkpvs, sv_mempool, false); + else + checkpvs = NULL; return i; } @@ -837,7 +855,7 @@ static void VM_SV_checkclient(prvm_prog_t *prog) // return check if it might be visible ent = PRVM_EDICT_NUM(sv.lastcheck); - if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0) + if (ent->free || PRVM_serveredictfloat(ent, health) <= 0) { VM_RETURN_EDICT(prog->edicts); return; @@ -846,7 +864,7 @@ static void VM_SV_checkclient(prvm_prog_t *prog) // if current entity can't possibly see the check entity, return 0 self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self)); VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view); - if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view)) + if (sv.worldmodel && checkpvs && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view)) { c_notvis++; VM_RETURN_EDICT(prog->edicts); @@ -872,20 +890,19 @@ float checkpvs(vector viewpos, entity viewee) = #240; */ static void VM_SV_checkpvs(prvm_prog_t *prog) { - vec3_t viewpos; + vec3_t viewpos, absmin, absmax; prvm_edict_t *viewee; #if 1 unsigned char *pvs; #else - int fatpvsbytes; - unsigned char fatpvs[MAX_MAP_LEAFS/8]; + unsigned char *fatpvs = NULL; #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) + if(viewee->free) { VM_Warning(prog, "checkpvs: can not check free entity\n"); PRVM_G_FLOAT(OFS_RETURN) = 4; @@ -893,7 +910,7 @@ static void VM_SV_checkpvs(prvm_prog_t *prog) } #if 1 - if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS) + if(!sv.worldmodel || !sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS) { // no PVS support on this worldmodel... darn PRVM_G_FLOAT(OFS_RETURN) = 3; @@ -906,23 +923,27 @@ static void VM_SV_checkpvs(prvm_prog_t *prog) PRVM_G_FLOAT(OFS_RETURN) = 2; return; } - PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax)); + VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin); + VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax); + PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, absmin, absmax); #else // using fat PVS like FTEQW does (slow) - if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS) + if(!sv.worldmodel || !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) + sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, &fatpvs, sv_mempool, false); + if(!fatpvs) { // 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, PRVM_serveredictvector(viewee, absmin), PRVM_serveredictvector(viewee, absmax)); + VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin); + VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax); + PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, absmin, absmax); #endif } @@ -940,7 +961,7 @@ static void VM_SV_stuffcmd(prvm_prog_t *prog) { int entnum; client_t *old; - char string[VM_STRINGTEMP_LENGTH]; + char string[VM_TEMPSTRING_MAXSIZE]; VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd); @@ -955,7 +976,7 @@ static void VM_SV_stuffcmd(prvm_prog_t *prog) old = host_client; host_client = svs.clients + entnum-1; - Host_ClientCommands ("%s", string); + SV_ClientCommands ("%s", string); host_client = old; } @@ -985,7 +1006,7 @@ static void VM_SV_findradius(prvm_prog_t *prog) else chainfield = prog->fieldoffsets.chain; if (chainfield < 0) - prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name); + prog->error_cmd("VM_SV_findradius: %s doesnt have the specified chain field !", prog->name); chain = (prvm_edict_t *)prog->edicts; @@ -1014,7 +1035,7 @@ static void VM_SV_findradius(prvm_prog_t *prog) // (note: this is the reason you can't blow up fallen zombies) if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer) continue; - // LordHavoc: compare against bounding box rather than center so it + // LadyHavoc: compare against bounding box rather than center so it // doesn't miss large objects, and use DotProduct instead of Length // for a major speedup VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg); @@ -1036,6 +1057,50 @@ static void VM_SV_findradius(prvm_prog_t *prog) VM_RETURN_EDICT(chain); } +/* +================= +VM_SV_findbox + +Returns a chain of entities that are touching a box (a simpler findradius); supports DP_QC_FINDCHAIN_TOFIELD + +findbox (mins, maxs) +================= +*/ +static void VM_SV_findbox(prvm_prog_t *prog) +{ + prvm_edict_t *chain; + int i, numtouchedicts; + static prvm_edict_t *touchedicts[MAX_EDICTS]; + int chainfield; + + VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findbox); + + if(prog->argc == 3) + chainfield = PRVM_G_INT(OFS_PARM2); + else + chainfield = prog->fieldoffsets.chain; + if (chainfield < 0) + prog->error_cmd("VM_SV_findbox: %s doesnt have the specified chain field !", prog->name); + + chain = (prvm_edict_t *)prog->edicts; + + numtouchedicts = SV_EntitiesInBox(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), MAX_EDICTS, touchedicts); + if (numtouchedicts > MAX_EDICTS) + { + // this never happens + Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS); + numtouchedicts = MAX_EDICTS; + } + for (i = 0; i < numtouchedicts; ++i) + { + prog->xfunction->builtinsprofile++; + PRVM_EDICTFIELDEDICT(touchedicts[i], chainfield) = PRVM_EDICT_TO_PROG(chain); + chain = touchedicts[i]; + } + + VM_RETURN_EDICT(chain); +} + static void VM_SV_precache_sound(prvm_prog_t *prog) { VM_SAFEPARMCOUNT(1, VM_SV_precache_sound); @@ -1063,7 +1128,7 @@ static void VM_SV_walkmove(prvm_prog_t *prog) vec3_t move; mfunction_t *oldf; int oldself; - qboolean settrace; + qbool settrace; VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove); @@ -1076,7 +1141,7 @@ static void VM_SV_walkmove(prvm_prog_t *prog) VM_Warning(prog, "walkmove: can not modify world entity\n"); return; } - if (ent->priv.server->free) + if (ent->free) { VM_Warning(prog, "walkmove: can not modify free entity\n"); return; @@ -1113,12 +1178,18 @@ VM_SV_droptofloor void() droptofloor =============== */ - +inline static qbool droptofloor_bsp_failcond(trace_t *trace) +{ + if (sv.worldmodel->brush.isq3bsp || sv.worldmodel->brush.isq2bsp) + return trace->startsolid; + else + return trace->allsolid || trace->fraction == 1; +} static void VM_SV_droptofloor(prvm_prog_t *prog) { - prvm_edict_t *ent; - vec3_t end; - trace_t trace; + prvm_edict_t *ent; + vec3_t end; + trace_t trace; VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype @@ -1131,65 +1202,77 @@ static void VM_SV_droptofloor(prvm_prog_t *prog) VM_Warning(prog, "droptofloor: can not modify world entity\n"); return; } - if (ent->priv.server->free) + if (ent->free) { VM_Warning(prog, "droptofloor: can not modify free entity\n"); return; } - VectorCopy (PRVM_serveredictvector(ent, origin), end); - end[2] -= 256; - if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer) - if (sv_gameplayfix_unstickentities.integer) - SV_UnstickEntity(ent); - - trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent)); - if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer) - { - vec3_t offset, org; - VectorSet(offset, 0.5f * (PRVM_serveredictvector(ent, mins)[0] + PRVM_serveredictvector(ent, maxs)[0]), 0.5f * (PRVM_serveredictvector(ent, mins)[1] + PRVM_serveredictvector(ent, maxs)[1]), PRVM_serveredictvector(ent, mins)[2]); - VectorAdd(PRVM_serveredictvector(ent, origin), offset, org); - trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent)); - VectorSubtract(trace.endpos, offset, trace.endpos); - if (trace.startsolid) + { + int n = PHYS_NudgeOutOfSolid(prog, ent); + if (!n) + VM_Warning(prog, "droptofloor at \"%f %f %f\": sv_gameplayfix_droptofloorstartsolid_nudgetocorrect COULD NOT FIX badly placed entity \"%s\" before drop\n", PRVM_gameedictvector(ent, origin)[0], PRVM_gameedictvector(ent, origin)[1], PRVM_gameedictvector(ent, origin)[2], PRVM_GetString(prog, PRVM_gameedictstring(ent, classname))); + else if (n > 0) + VM_Warning(prog, "droptofloor at \"%f %f %f\": sv_gameplayfix_droptofloorstartsolid_nudgetocorrect FIXED badly placed entity \"%s\" before drop\n", PRVM_gameedictvector(ent, origin)[0], PRVM_gameedictvector(ent, origin)[1], PRVM_gameedictvector(ent, origin)[2], PRVM_GetString(prog, PRVM_gameedictstring(ent, classname))); + } + + VectorCopy (PRVM_serveredictvector(ent, origin), end); + if (sv.worldmodel->brush.isq3bsp) + end[2] -= 4096; + else if (sv.worldmodel->brush.isq2bsp) + end[2] -= 128; + else + end[2] -= 256; // Quake, QuakeWorld + + /* bones_was_here: not using SV_GenericHitSuperContentsMask(ent) anymore because it was setting: + * items: SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY + * monsters: SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP + * explobox: SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_CORPSE + * which caused (startsolid == true) when, for example, a health was touching a monster. + * Changing MOVE_NORMAL also fixes that, but other engines are using MOVE_NORMAL here. + */ + trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID, 0, 0, collision_extendmovelength.value); + if (droptofloor_bsp_failcond(&trace)) + { + if (sv_gameplayfix_droptofloorstartsolid.integer) { - Con_DPrintf("droptofloor at %f %f %f - COULD NOT FIX BADLY PLACED ENTITY\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]); - if (sv_gameplayfix_unstickentities.integer) - SV_UnstickEntity(ent); - SV_LinkEdict(ent); - PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND; - PRVM_serveredictedict(ent, groundentity) = 0; - PRVM_G_FLOAT(OFS_RETURN) = 1; + vec3_t offset, org; + + offset[0] = 0.5f * (PRVM_serveredictvector(ent, mins)[0] + PRVM_serveredictvector(ent, maxs)[0]); + offset[1] = 0.5f * (PRVM_serveredictvector(ent, mins)[1] + PRVM_serveredictvector(ent, maxs)[1]); + offset[2] = PRVM_serveredictvector(ent, mins)[2]; + VectorAdd(PRVM_serveredictvector(ent, origin), offset, org); + VectorAdd(end, offset, end); + + trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID, 0, 0, collision_extendmovelength.value); + if (droptofloor_bsp_failcond(&trace)) + { + VM_Warning(prog, "droptofloor at \"%f %f %f\": sv_gameplayfix_droptofloorstartsolid COULD NOT FIX badly placed entity \"%s\"\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2], PRVM_GetString(prog, PRVM_gameedictstring(ent, classname))); + return; + } + VM_Warning(prog, "droptofloor at \"%f %f %f\": sv_gameplayfix_droptofloorstartsolid FIXED badly placed entity \"%s\"\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2], PRVM_GetString(prog, PRVM_gameedictstring(ent, classname))); + VectorSubtract(trace.endpos, offset, PRVM_serveredictvector(ent, origin)); + + // only because we dropped it without considering its bbox + if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer) + PHYS_NudgeOutOfSolid(prog, ent); } - else if (trace.fraction < 1) + else { - Con_DPrintf("droptofloor at %f %f %f - FIXED BADLY PLACED ENTITY\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]); - VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin)); - if (sv_gameplayfix_unstickentities.integer) - SV_UnstickEntity(ent); - SV_LinkEdict(ent); - PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND; - PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent); - PRVM_G_FLOAT(OFS_RETURN) = 1; - // if support is destroyed, keep suspended (gross hack for floating items in various maps) - ent->priv.server->suspendedinairflag = true; + VM_Warning(prog, "droptofloor at \"%f %f %f\": badly placed entity \"%s\", startsolid: %d allsolid: %d\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2], PRVM_GetString(prog, PRVM_gameedictstring(ent, classname)), trace.startsolid, trace.allsolid); + return; } } else - { - if (trace.fraction != 1) - { - if (trace.fraction < 1) - VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin)); - SV_LinkEdict(ent); - PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND; - PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent); - PRVM_G_FLOAT(OFS_RETURN) = 1; - // if support is destroyed, keep suspended (gross hack for floating items in various maps) - ent->priv.server->suspendedinairflag = true; - } - } + VectorCopy(trace.endpos, PRVM_serveredictvector(ent, origin)); + + SV_LinkEdict(ent); + PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND; + PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent); + PRVM_G_FLOAT(OFS_RETURN) = 1; + // if support is destroyed, keep suspended (gross hack for floating items in various maps) + ent->priv.server->suspendedinairflag = true; } /* @@ -1216,7 +1299,7 @@ static void VM_SV_lightstyle(prvm_prog_t *prog) } // change the string in sv - strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style])); + dp_strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style])); // send message to all clients on this server if (sv.state != ss_active) @@ -1251,8 +1334,10 @@ VM_SV_pointcontents */ static void VM_SV_pointcontents(prvm_prog_t *prog) { + vec3_t point; VM_SAFEPARMCOUNT(1, VM_SV_pointcontents); - PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0))); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), point); + PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(SV_PointSuperContents(point)); } /* @@ -1286,7 +1371,7 @@ static void VM_SV_aim(prvm_prog_t *prog) VM_Warning(prog, "aim: can not use world entity\n"); return; } - if (ent->priv.server->free) + if (ent->free) { VM_Warning(prog, "aim: can not use free entity\n"); return; @@ -1299,7 +1384,7 @@ static void VM_SV_aim(prvm_prog_t *prog) // try sending a trace straight VectorCopy (PRVM_serverglobalvector(v_forward), dir); VectorMA (start, 2048, dir, end); - tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY); + tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, 0, 0, collision_extendmovelength.value); if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) ) { @@ -1331,7 +1416,7 @@ static void VM_SV_aim(prvm_prog_t *prog) dist = DotProduct (dir, PRVM_serverglobalvector(v_forward)); if (dist < bestdist) continue; // to far to turn - tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY); + tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, 0, 0, collision_extendmovelength.value); if (tr.ent == check) { // can shoot at this one bestdist = dist; @@ -1383,11 +1468,21 @@ static sizebuf_t *WriteDest(prvm_prog_t *prog) case MSG_ONE: ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity)); entnum = PRVM_NUM_FOR_EDICT(ent); - if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection) + if (entnum < 1 || entnum > svs.maxclients) { VM_Warning(prog, "WriteDest: tried to write to non-client\n"); return &sv.reliable_datagram; } + else if (!svs.clients[entnum-1].active) + { + VM_Warning(prog, "WriteDest: tried to write to a disconnected client\n"); + return &sv.reliable_datagram; + } + else if (!svs.clients[entnum-1].netconnection) + { + VM_Warning(prog, "WriteDest: tried to write to a bot client\n"); + return &sv.reliable_datagram; + } else return &svs.clients[entnum-1].netconnection->message; @@ -1476,7 +1571,7 @@ static void VM_SV_WritePicture(prvm_prog_t *prog) VM_SAFEPARMCOUNT(3, VM_SV_WritePicture); imgname = PRVM_G_STRING(OFS_PARM1); - size = (int) PRVM_G_FLOAT(OFS_PARM2); + size = (size_t) PRVM_G_FLOAT(OFS_PARM2); if(size > 65535) size = 65535; @@ -1484,8 +1579,8 @@ static void VM_SV_WritePicture(prvm_prog_t *prog) if(Image_Compress(imgname, size, &buf, &size)) { // actual picture - MSG_WriteShort(WriteDest(prog), size); - SZ_Write(WriteDest(prog), (unsigned char *) buf, size); + MSG_WriteShort(WriteDest(prog), (int)size); + SZ_Write(WriteDest(prog), (unsigned char *) buf, (int)size); } else { @@ -1514,7 +1609,7 @@ static void VM_SV_makestatic(prvm_prog_t *prog) VM_Warning(prog, "makestatic: can not modify world entity\n"); return; } - if (ent->priv.server->free) + if (ent->free) { VM_Warning(prog, "makestatic: can not modify free entity\n"); return; @@ -1524,17 +1619,17 @@ static void VM_SV_makestatic(prvm_prog_t *prog) if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256) large = true; - if (large) + if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) { - MSG_WriteByte (&sv.signon,svc_spawnstatic2); + MSG_WriteByte (&sv.signon,svc_spawnstatic); MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex)); - MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame)); + MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame)); } - else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) + else if (large) { - MSG_WriteByte (&sv.signon,svc_spawnstatic); + MSG_WriteByte (&sv.signon,svc_spawnstatic2); MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex)); - MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame)); + MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame)); } else { @@ -1599,9 +1694,9 @@ getlight(vector) static void VM_SV_getlight(prvm_prog_t *prog) { vec3_t ambientcolor, diffusecolor, diffusenormal; - vec_t *p; + vec3_t p; VM_SAFEPARMCOUNT(1, VM_SV_getlight); - p = PRVM_G_VECTOR(OFS_PARM0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), p); VectorClear(ambientcolor); VectorClear(diffusecolor); VectorClear(diffusenormal); @@ -1612,21 +1707,17 @@ static void VM_SV_getlight(prvm_prog_t *prog) typedef struct { - unsigned char type; // 1/2/8 or other value if isn't used + unsigned char type; // 1/2/8 or 0 to indicate unused int fieldoffset; }customstat_t; -static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32 +static customstat_t vm_customstats[MAX_CL_STATS]; // matches the regular stat numbers, but only MIN_VM_STAT to MAX_VM_STAT range is used if things are working properly (can register stats from MAX_VM_STAT to MAX_CL_STATS but will warn) static int vm_customstats_last; void VM_CustomStats_Clear (void) { - if(vm_customstats) - { - Z_Free(vm_customstats); - vm_customstats = NULL; - vm_customstats_last = -1; - } + memset(vm_customstats, 0, sizeof(vm_customstats)); + vm_customstats_last = -1; } void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats) @@ -1634,11 +1725,12 @@ void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *ms prvm_prog_t *prog = SVVM_prog; int i; char s[17]; + union { + int i; + float f; + } u; - if(!vm_customstats) - return; - - for(i=0; i= (MAX_CL_STATS-32)) + + if (i >= MAX_CL_STATS) { - VM_Warning(prog, "PF_SV_AddStat: index >= MAX_CL_STATS\n"); + VM_Warning(prog, "PF_SV_AddStat: index (%i) >= MAX_CL_STATS (%i), not supported by protocol, and AddStat beyond MAX_VM_STAT (%i) conflicts with engine MOVEVARS\n", i, MAX_CL_STATS, MAX_VM_STAT); return; } - if(i > (MAX_CL_STATS-32-4) && type == 1) + + if (i > (MAX_CL_STATS - 4) && type == 1) { - VM_Warning(prog, "PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n"); + VM_Warning(prog, "PF_SV_AddStat: index (%i) > (MAX_CL_STATS (%i) - 4) with string type won't fit in the protocol, and AddStat beyond MAX_VM_STAT conflicts with engine MOVEVARS\n", i, MAX_CL_STATS); return; } + + // these are hazardous to override but sort of allowed if one wants to be adventurous... and enjoys warnings. + if (i < MIN_VM_STAT) + VM_Warning(prog, "PF_SV_AddStat: index (%i) < MIN_VM_STAT (%i) may conflict with engine stats - allowed, but this may break things\n", i, MIN_VM_STAT); + else if (i >= MAX_VM_STAT && !sv_qcstats.integer) + VM_Warning(prog, "PF_SV_AddStat: index (%i) >= MAX_VM_STAT (%i) conflicts with engine stats - allowed, but this may break slowmo and stuff\n", i, MAX_VM_STAT); + else if (i > (MAX_VM_STAT - 4) && type == 1 && !sv_qcstats.integer) + VM_Warning(prog, "PF_SV_AddStat: index (%i) >= MAX_VM_STAT (%i) - 4 with string type won't fit within MAX_VM_STAT, thus conflicting with engine stats - allowed, but this may break slowmo and stuff\n", i, MAX_VM_STAT); + vm_customstats[i].type = type; vm_customstats[i].fieldoffset = off; if(vm_customstats_last < i) @@ -1735,7 +1842,7 @@ static void VM_SV_copyentity(prvm_prog_t *prog) VM_Warning(prog, "copyentity: can not read world entity\n"); return; } - if (in->priv.server->free) + if (in->free) { VM_Warning(prog, "copyentity: can not read free entity\n"); return; @@ -1746,12 +1853,13 @@ static void VM_SV_copyentity(prvm_prog_t *prog) VM_Warning(prog, "copyentity: can not modify world entity\n"); return; } - if (out->priv.server->free) + if (out->free) { VM_Warning(prog, "copyentity: can not modify free entity\n"); return; } - memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4); + memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t)); + SV_LinkEdict(out); } @@ -1808,6 +1916,7 @@ static void VM_SV_effect(prvm_prog_t *prog) { int i; const char *s; + vec3_t org; VM_SAFEPARMCOUNT(5, VM_SV_effect); s = PRVM_G_STRING(OFS_PARM1); if (!s[0]) @@ -1835,7 +1944,8 @@ static void VM_SV_effect(prvm_prog_t *prog) return; } - SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4)); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org); + SV_StartEffect(org, i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4)); } static void VM_SV_te_blood(prvm_prog_t *prog) @@ -2305,7 +2415,7 @@ static void VM_SV_te_flamejet(prvm_prog_t *prog) } //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client -//this function originally written by KrimZon, made shorter by LordHavoc +//this function originally written by KrimZon, made shorter by LadyHavoc static void VM_SV_clientcommand(prvm_prog_t *prog) { client_t *temp_client; @@ -2322,7 +2432,7 @@ static void VM_SV_clientcommand(prvm_prog_t *prog) temp_client = host_client; host_client = svs.clients + i; - Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client, true); + Cmd_ExecuteString(cmd_serverfromclient, PRVM_G_STRING(OFS_PARM1), strlen(PRVM_G_STRING(OFS_PARM1)), src_client, true); host_client = temp_client; } @@ -2332,7 +2442,7 @@ static void VM_SV_setattachment(prvm_prog_t *prog) prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0); prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1); const char *tagname = PRVM_G_STRING(OFS_PARM2); - dp_model_t *model; + model_t *model; int tagindex; VM_SAFEPARMCOUNT(3, VM_SV_setattachment); @@ -2341,7 +2451,7 @@ static void VM_SV_setattachment(prvm_prog_t *prog) VM_Warning(prog, "setattachment: can not modify world entity\n"); return; } - if (e->priv.server->free) + if (e->free) { VM_Warning(prog, "setattachment: can not modify free entity\n"); return; @@ -2386,7 +2496,7 @@ static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagna static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix) { int r; - dp_model_t *model; + model_t *model; *tagname = NULL; *parentindex = 0; @@ -2405,7 +2515,7 @@ static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagind return 1; } -void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix) +void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qbool viewmatrix) { float scale; float pitchsign = 1; @@ -2425,11 +2535,11 @@ void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out) { - dp_model_t *model; + model_t *model; if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes) { VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent); - VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model); + VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time); VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend); return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out); } @@ -2444,21 +2554,18 @@ static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int // 3 - null or non-precached model // 4 - no tags with requested index // 5 - runaway loop at attachment chain -extern cvar_t cl_bob; -extern cvar_t cl_bobcycle; -extern cvar_t cl_bobup; static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex) { int ret; int modelindex, attachloop; matrix4x4_t entitymatrix, tagmatrix, attachmatrix; - dp_model_t *model; + model_t *model; *out = identitymatrix; // warnings and errors return identical matrix if (ent == prog->edicts) return 1; - if (ent->priv.server->free) + if (ent->free) return 2; modelindex = (int)PRVM_serveredictfloat(ent, modelindex); @@ -2468,7 +2575,7 @@ static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *e model = SV_GetModelByIndex(modelindex); VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent); - VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model); + VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time); VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend); tagmatrix = identitymatrix; @@ -2505,29 +2612,6 @@ static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *e SV_GetEntityMatrix(prog, ent, &entitymatrix, true); Matrix4x4_Concat(out, &entitymatrix, &tagmatrix); - - /* - // Cl_bob, ported from rendering code - if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value) - { - double bob, cycle; - // LordHavoc: this code is *weird*, but not replacable (I think it - // should be done in QC on the server, but oh well, quake is quake) - // LordHavoc: figured out bobup: the time at which the sin is at 180 - // degrees (which allows lengthening or squishing the peak or valley) - cycle = sv.time/cl_bobcycle.value; - cycle -= (int)cycle; - if (cycle < cl_bobup.value) - cycle = sin(M_PI * cycle / cl_bobup.value); - else - cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value)); - // bob is proportional to velocity in the xy plane - // (don't count Z, or jumping messes it up) - bob = sqrt(PRVM_serveredictvector(ent, velocity)[0]*PRVM_serveredictvector(ent, velocity)[0] + PRVM_serveredictvector(ent, velocity)[1]*PRVM_serveredictvector(ent, velocity)[1])*cl_bob.value; - bob = bob*0.3 + bob*0.7*cycle; - Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4)); - } - */ } return 0; } @@ -2550,7 +2634,7 @@ static void VM_SV_gettagindex(prvm_prog_t *prog) VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent)); return; } - if (ent->priv.server->free) + if (ent->free) { VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent)); return; @@ -2579,8 +2663,8 @@ static void VM_SV_gettaginfo(prvm_prog_t *prog) int parentindex; const char *tagname; int returncode; - vec3_t fo, le, up, trans; - const dp_model_t *model; + vec3_t forward, left, up, origin; + const model_t *model; VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo); @@ -2588,21 +2672,24 @@ static void VM_SV_gettaginfo(prvm_prog_t *prog) tagindex = (int)PRVM_G_FLOAT(OFS_PARM1); returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex); - Matrix4x4_ToVectors(&tag_matrix, PRVM_serverglobalvector(v_forward), le, PRVM_serverglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN)); - VectorScale(le, -1, PRVM_serverglobalvector(v_right)); + Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin); + VectorCopy(forward, PRVM_serverglobalvector(v_forward)); + VectorNegate(left, PRVM_serverglobalvector(v_right)); + VectorCopy(up, PRVM_serverglobalvector(v_up)); + VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN)); model = SV_GetModelFromEdict(e); VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e); - VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model); + VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, sv.time); VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend); SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix); - Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans); + Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin); PRVM_serverglobalfloat(gettaginfo_parent) = parentindex; - PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0; - VectorCopy(trans, PRVM_serverglobalvector(gettaginfo_offset)); - VectorCopy(fo, PRVM_serverglobalvector(gettaginfo_forward)); - VectorScale(le, -1, PRVM_serverglobalvector(gettaginfo_right)); + PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname, strlen(tagname)) : 0; + VectorCopy(forward, PRVM_serverglobalvector(gettaginfo_forward)); + VectorNegate(left, PRVM_serverglobalvector(gettaginfo_right)); VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up)); + VectorCopy(origin, PRVM_serverglobalvector(gettaginfo_offset)); switch(returncode) { @@ -2643,7 +2730,7 @@ static void VM_SV_dropclient(prvm_prog_t *prog) } oldhostclient = host_client; host_client = svs.clients + clientnum; - SV_DropClient(false); + SV_DropClient(false, "Client dropped"); host_client = oldhostclient; } @@ -2678,13 +2765,13 @@ static void VM_SV_clienttype(prvm_prog_t *prog) VM_SAFEPARMCOUNT(1, VM_SV_clienttype); clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1; if (clientnum < 0 || clientnum >= svs.maxclients) - PRVM_G_FLOAT(OFS_RETURN) = 3; + PRVM_G_FLOAT(OFS_RETURN) = 3; // CLIENTTYPE_NOTACLIENT else if (!svs.clients[clientnum].active) - PRVM_G_FLOAT(OFS_RETURN) = 0; + PRVM_G_FLOAT(OFS_RETURN) = 0; // CLIENTTYPE_DISCONNECTED else if (svs.clients[clientnum].netconnection) - PRVM_G_FLOAT(OFS_RETURN) = 1; + PRVM_G_FLOAT(OFS_RETURN) = 1; // CLIENTTYPE_REAL else - PRVM_G_FLOAT(OFS_RETURN) = 2; + PRVM_G_FLOAT(OFS_RETURN) = 2; // CLIENTTYPE_BOT } /* @@ -2696,17 +2783,18 @@ string(string key) serverkey */ static void VM_SV_serverkey(prvm_prog_t *prog) { - char string[VM_STRINGTEMP_LENGTH]; + char string[VM_TEMPSTRING_MAXSIZE]; + VM_SAFEPARMCOUNT(1, VM_SV_serverkey); InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string)); - PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string); + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string, strlen(string)); } //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC) static void VM_SV_setmodelindex(prvm_prog_t *prog) { prvm_edict_t *e; - dp_model_t *mod; + model_t *mod; int i; VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex); @@ -2716,7 +2804,7 @@ static void VM_SV_setmodelindex(prvm_prog_t *prog) VM_Warning(prog, "setmodelindex: can not modify world entity\n"); return; } - if (e->priv.server->free) + if (e->free) { VM_Warning(prog, "setmodelindex: can not modify free entity\n"); return; @@ -2786,6 +2874,7 @@ static void VM_SV_particleeffectnum(prvm_prog_t *prog) // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC) static void VM_SV_trailparticles(prvm_prog_t *prog) { + vec3_t start, end; VM_SAFEPARMCOUNT(4, VM_SV_trailparticles); if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0) @@ -2794,8 +2883,10 @@ static void VM_SV_trailparticles(prvm_prog_t *prog) 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)); - MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol); - MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol); + VectorCopy(PRVM_G_VECTOR(OFS_PARM2), start); + VectorCopy(PRVM_G_VECTOR(OFS_PARM3), end); + MSG_WriteVector(&sv.datagram, start, sv.protocol); + MSG_WriteVector(&sv.datagram, end, sv.protocol); SV_FlushBroadcastMessages(); } @@ -2833,13 +2924,26 @@ static void VM_SV_pointparticles(prvm_prog_t *prog) SV_FlushBroadcastMessages(); } +qbool SV_VM_ConsoleCommand(const char *text, size_t textlen) +{ + prvm_prog_t *prog = SVVM_prog; + return PRVM_ConsoleCommand(prog, text, textlen, &prog->funcoffsets.ConsoleCmd, true, PRVM_EDICT_TO_PROG(sv.world.prog->edicts), sv.time, "QC function ConsoleCmd is missing"); +} + +// #352 void(string cmdname) registercommand (EXT_CSQC) +static void VM_SV_registercommand (prvm_prog_t *prog) +{ + VM_SAFEPARMCOUNT(1, VM_SV_registercmd); + Cmd_AddCommand(CF_SERVER, PRVM_G_STRING(OFS_PARM0), NULL, "console command created by QuakeC"); +} + //PF_setpause, // void(float pause) setpause = #531; static void VM_SV_setpause(prvm_prog_t *prog) { int pauseValue; pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0); if (pauseValue != 0) { //pause the game sv.paused = 1; - sv.pausedstart = realtime; + sv.pausedstart = host.realtime; } else { //disable pause, in case it was enabled if (sv.paused != 0) { sv.paused = 0; @@ -2855,7 +2959,7 @@ static void VM_SV_setpause(prvm_prog_t *prog) { static void VM_SV_skel_create(prvm_prog_t *prog) { int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0); - dp_model_t *model = SV_GetModelByIndex(modelindex); + model_t *model = SV_GetModelByIndex(modelindex); skeleton_t *skeleton; int i; PRVM_G_FLOAT(OFS_RETURN) = 0; @@ -2866,7 +2970,7 @@ static void VM_SV_skel_create(prvm_prog_t *prog) break; if (i == MAX_EDICTS) return; - prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(cls.levelmempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t)); + prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(prog->progs_mempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t)); PRVM_G_FLOAT(OFS_RETURN) = i + 1; skeleton->model = model; skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1); @@ -2885,14 +2989,13 @@ static void VM_SV_skel_build(prvm_prog_t *prog) float retainfrac = PRVM_G_FLOAT(OFS_PARM3); int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1; int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1; - dp_model_t *model = SV_GetModelByIndex(modelindex); - float blendfrac; + model_t *model = SV_GetModelByIndex(modelindex); int numblends; int bonenum; int blendindex; framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS]; frameblend_t frameblend[MAX_FRAMEBLENDS]; - matrix4x4_t blendedmatrix; + matrix4x4_t bonematrix; matrix4x4_t matrix; PRVM_G_FLOAT(OFS_RETURN) = 0; if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex])) @@ -2901,20 +3004,19 @@ static void VM_SV_skel_build(prvm_prog_t *prog) lastbone = min(lastbone, model->num_bones - 1); lastbone = min(lastbone, skeleton->model->num_bones - 1); VM_GenerateFrameGroupBlend(prog, framegroupblend, ed); - VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model); - blendfrac = 1.0f - retainfrac; + VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model, sv.time); for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++) - frameblend[numblends].lerp *= blendfrac; + ; for (bonenum = firstbone;bonenum <= lastbone;bonenum++) { - memset(&blendedmatrix, 0, sizeof(blendedmatrix)); - Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac); + memset(&bonematrix, 0, sizeof(bonematrix)); for (blendindex = 0;blendindex < numblends;blendindex++) { - Matrix4x4_FromBonePose6s(&matrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + bonenum)); - Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp); + Matrix4x4_FromBonePose7s(&matrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + bonenum)); + Matrix4x4_Accumulate(&bonematrix, &matrix, frameblend[blendindex].lerp); } - skeleton->relativetransforms[bonenum] = blendedmatrix; + Matrix4x4_Normalize3(&bonematrix, &bonematrix); + Matrix4x4_Interpolate(&skeleton->relativetransforms[bonenum], &bonematrix, &skeleton->relativetransforms[bonenum], retainfrac); } PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1; } @@ -2941,7 +3043,7 @@ static void VM_SV_skel_get_bonename(prvm_prog_t *prog) return; if (bonenum < 0 || bonenum >= skeleton->model->num_bones) return; - PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name); + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name, strlen(skeleton->model->data_bones[bonenum].name)); } // #267 float(float skel, float bonenum) skel_get_boneparent = #267; // (FTE_CSQC_SKELETONOBJECTS) returns parent num for supplied bonenum, 0 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this) @@ -3130,7 +3232,7 @@ static void VM_SV_skel_delete(prvm_prog_t *prog) static void VM_SV_frameforname(prvm_prog_t *prog) { int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0); - dp_model_t *model = SV_GetModelByIndex(modelindex); + model_t *model = SV_GetModelByIndex(modelindex); const char *name = PRVM_G_STRING(OFS_PARM1); int i; PRVM_G_FLOAT(OFS_RETURN) = -1; @@ -3150,7 +3252,7 @@ static void VM_SV_frameforname(prvm_prog_t *prog) static void VM_SV_frameduration(prvm_prog_t *prog) { int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0); - dp_model_t *model = SV_GetModelByIndex(modelindex); + model_t *model = SV_GetModelByIndex(modelindex); int framenum = (int)PRVM_G_FLOAT(OFS_PARM1); PRVM_G_FLOAT(OFS_RETURN) = 0; if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes) @@ -3169,7 +3271,7 @@ VM_SV_setsize, // #4 void(entity e, vector min, vector max) setsize (QUAKE) NULL, // #5 void(entity e, vector min, vector max) setabssize (QUAKE) VM_break, // #6 void() break (QUAKE) VM_random, // #7 float() random (QUAKE) -VM_SV_sound, // #8 void(entity e, float chan, string samp) sound (QUAKE) +VM_SV_sound, // #8 void(entity e, float chan, string samp, float volume[, float atten[, float pitchchange[, float flags]]]) sound (QUAKE) VM_normalize, // #9 vector(vector v) normalize (QUAKE) VM_error, // #10 void(string e) error (QUAKE) VM_objerror, // #11 void(string e) objerror (QUAKE) @@ -3277,7 +3379,7 @@ VM_fclose, // #111 void(float fhandle) fclose (FRIK_FILE) VM_fgets, // #112 string(float fhandle) fgets (FRIK_FILE) VM_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE) VM_strlen, // #114 float(string s) strlen (FRIK_FILE) -VM_strcat, // #115 string(string s1, string s2, ...) strcat (FRIK_FILE) +VM_strcat, // #115 string(string s, string...) strcat (FRIK_FILE) VM_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE) VM_stov, // #117 vector(string) stov (FRIK_FILE) VM_strzone, // #118 string(string s) strzone (FRIK_FILE) @@ -3408,7 +3510,7 @@ NULL, // #241 NULL, // #242 NULL, // #243 NULL, // #244 -NULL, // #245 +VM_modulo, // #245 NULL, // #246 NULL, // #247 NULL, // #248 @@ -3516,7 +3618,7 @@ NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (E NULL, // #349 float() isdemo (EXT_CSQC) VM_isserver, // #350 float() isserver (EXT_CSQC) NULL, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC) -NULL, // #352 void(string cmdname) registercommand (EXT_CSQC) +VM_SV_registercommand, // #352 void(string cmdname) registercommand (EXT_CSQC) VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too) VM_SV_serverkey, // #354 string(string key) serverkey (EXT_CSQC) NULL, // #355 @@ -3564,7 +3666,7 @@ NULL, // #396 NULL, // #397 NULL, // #398 NULL, // #399 -// LordHavoc's range #400-#499 +// LadyHavoc's range #400-#499 VM_SV_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY) VM_SV_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR) VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN) @@ -3700,10 +3802,10 @@ VM_SV_setpause, // #531 void(float pause) setpause = #531; VM_log, // #532 VM_getsoundtime, // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME) VM_soundlength, // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME) -NULL, // #535 -NULL, // #536 -NULL, // #537 -NULL, // #538 +VM_buf_loadfile, // #535 float(string filename, float bufhandle) buf_loadfile (DP_QC_STRINGBUFFERS_EXT_WIP) +VM_buf_writefile, // #536 float(float filehandle, float bufhandle, float startpos, float numstrings) buf_writefile (DP_QC_STRINGBUFFERS_EXT_WIP) +VM_bufstr_find, // #537 float(float bufhandle, string match, float matchrule, float startpos) bufstr_find (DP_QC_STRINGBUFFERS_EXT_WIP) +VM_matchpattern, // #538 float(string s, string pattern, float matchrule) matchpattern (DP_QC_STRINGBUFFERS_EXT_WIP) NULL, // #539 VM_physics_enable, // #540 void(entity e, float physics_enabled) physics_enable = #540; (DP_PHYSICS_ODE) VM_physics_addforce, // #541 void(entity e, vector force, vector relative_ofs) physics_addforce = #541; (DP_PHYSICS_ODE) @@ -3731,8 +3833,8 @@ NULL, // #562 NULL, // #563 NULL, // #564 NULL, // #565 -NULL, // #566 -NULL, // #567 +VM_SV_findbox, // #566 entity(vector mins, vector maxs) findbox = #566; (DP_QC_FINDBOX) +VM_nudgeoutofsolid, // #567 float(entity ent) nudgeoutofsolid = #567; (DP_QC_NUDGEOUTOFSOLID) NULL, // #568 NULL, // #569 NULL, // #570 @@ -3806,6 +3908,9 @@ NULL, // #637 NULL, // #638 VM_digest_hex, // #639 NULL, // #640 +NULL, // #641 +VM_coverage, // #642 +NULL, // #643 }; const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t); @@ -3818,13 +3923,5 @@ void SVVM_init_cmd(prvm_prog_t *prog) void SVVM_reset_cmd(prvm_prog_t *prog) { World_End(&sv.world); - if(PRVM_serverfunction(SV_Shutdown)) - { - func_t s = PRVM_serverfunction(SV_Shutdown); - PRVM_serverglobalfloat(time) = sv.time; - PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again - prog->ExecuteProgram(prog, s,"SV_Shutdown() required"); - } - VM_Cmd_Reset(prog); }