"TENEBRAE_GFX_DLIGHTS "
"TW_SV_STEPCONTROL "
"ZQ_PAUSE "
+"DP_RM_CLIPGROUP "
//"EXT_CSQC " // not ready yet
;
{
prvm_edict_t *e;
- VM_SAFEPARMCOUNT(2, VM_setorigin);
+ VM_SAFEPARMCOUNT(2, VM_SV_setorigin);
e = PRVM_G_EDICT(OFS_PARM0);
if (e == prog->edicts)
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)
=================
prvm_edict_t *e;
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)
dp_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)
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);
}
else
{
- // LordHavoc: we only let the qc set certain flags, others are off-limits
+ // 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);
}
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)
{
vec3_t v1, v2, m1, m2;
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;
old = host_client;
host_client = svs.clients + entnum-1;
- Host_ClientCommands ("%s", string);
+ SV_ClientCommands ("%s", string);
host_client = old;
}
// (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);
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)
float f;
} u;
- if(!vm_customstats)
- return;
-
- for(i=0; i<vm_customstats_last+1 ;i++)
+ for(i=MIN_VM_STAT; i<=vm_customstats_last ;i++)
{
if(!vm_customstats[i].type)
continue;
case 1:
memset(s, 0, 17);
strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
- stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
- stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
- stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
- stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
+ stats[i] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
+ stats[i+1] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
+ stats[i+2] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
+ stats[i+3] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
break;
//float field sent as-is
case 8:
// can't directly use PRVM_E_INT on the field because it may be PRVM_64 and a double is not the representation we want to send
u.f = PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
- stats[i+32] = u.i;
+ stats[i] = u.i;
break;
//integer value of float field
case 2:
- stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
+ stats[i] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
break;
default:
break;
}
}
+extern cvar_t sv_gameplayfix_customstats;
+
// void(float index, float type, .void field) SV_AddStat = #232;
// Set up an auto-sent player stat.
// Client's get thier own fields sent to them. Index may not be less than 32.
// 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
static void VM_SV_AddStat(prvm_prog_t *prog)
{
- int off, i;
- unsigned char type;
+ int off, i, type;
VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
- if(!vm_customstats)
- {
- vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
- if(!vm_customstats)
- {
- VM_Warning(prog, "PF_SV_AddStat: not enough memory\n");
- return;
- }
- }
i = (int)PRVM_G_FLOAT(OFS_PARM0);
type = (int)PRVM_G_FLOAT(OFS_PARM1);
off = PRVM_G_INT (OFS_PARM2);
- i -= 32;
- if(i < 0)
+ switch (type)
+ {
+ case 1:
+ case 2:
+ case 8:
+ break;
+ default:
+ VM_Warning(prog, "PF_SV_AddStat: unrecognized type %i - supported types are 1 (string up to 16 bytes, takes 4 stat slots), 2 (truncate to int32), 8 (send as float)", type);
+ return;
+ }
+
+ if (i < 0)
{
- VM_Warning(prog, "PF_SV_AddStat: index may not be less than 32\n");
+ VM_Warning(prog, "PF_SV_AddStat: index (%i) may not be less than %i\n", i, MIN_VM_STAT);
return;
}
- if(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_gameplayfix_customstats.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_gameplayfix_customstats.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)
return;
}
memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t));
+ if (VectorCompare(PRVM_serveredictvector(out, absmin), PRVM_serveredictvector(out, absmax)))
+ return;
SV_LinkEdict(out);
}
}
//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;
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), src_client, true);
host_client = temp_client;
}
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
+ // LadyHavoc: 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
+ // LadyHavoc: 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;
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;
VM_fabs, // #43 float(float f) fabs (QUAKE)
VM_SV_aim, // #44 vector(entity e, float speed) aim (QUAKE)
VM_cvar, // #45 float(string s) cvar (QUAKE)
-VM_localcmd, // #46 void(string s) localcmd (QUAKE)
+VM_localcmd_server, // #46 void(string s) localcmd (QUAKE)
VM_nextent, // #47 entity(entity e) nextent (QUAKE)
VM_SV_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
VM_changeyaw, // #49 void() ChangeYaw (QUAKE)
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)