X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=svvm_cmds.c;h=90ee0787b6073eb44cc91ae6a3f17132b7a81263;hb=906474fc025ff5b0b8799d9045a581bceafd2e7d;hp=a884d0f1b42c47393300edc8e88d21df774becb6;hpb=eb4b5704b95c3c5184afead9925be8c1602f870b;p=xonotic%2Fdarkplaces.git diff --git a/svvm_cmds.c b/svvm_cmds.c index a884d0f1..90ee0787 100644 --- a/svvm_cmds.c +++ b/svvm_cmds.c @@ -100,6 +100,7 @@ const char *vm_sv_extensions[] = { "DP_QC_ENTITYSTRING", "DP_QC_ETOS", "DP_QC_EXTRESPONSEPACKET", +"DP_QC_FINDBOX", "DP_QC_FINDCHAIN", "DP_QC_FINDCHAINFLAGS", "DP_QC_FINDCHAINFLOAT", @@ -107,6 +108,7 @@ const char *vm_sv_extensions[] = { "DP_QC_FINDFLAGS", "DP_QC_FINDFLOAT", "DP_QC_FS_SEARCH", +"DP_QC_FS_SEARCH_PACKFILE", "DP_QC_GETLIGHT", "DP_QC_GETSURFACE", "DP_QC_GETSURFACETRIANGLE", @@ -119,6 +121,7 @@ const char *vm_sv_extensions[] = { "DP_QC_LOG", "DP_QC_MINMAXBOUND", "DP_QC_MULTIPLETEMPSTRINGS", +"DP_QC_NUDGEOUTOFSOLID", "DP_QC_NUM_FOR_EDICT", "DP_QC_RANDOMVEC", "DP_QC_SINCOSSQRTPOW", @@ -228,7 +231,6 @@ const char *vm_sv_extensions[] = { "TW_SV_STEPCONTROL", "ZQ_PAUSE", "DP_RM_CLIPGROUP", -"DP_QC_FS_SEARCH_PACKFILE", NULL //"EXT_CSQC" // not ready yet }; @@ -660,7 +662,7 @@ static void VM_SV_traceline(prvm_prog_t *prog) move = (int)PRVM_G_FLOAT(OFS_PARM2); ent = PRVM_G_EDICT(OFS_PARM3); - if (VEC_IS_NAN(v1[0]) || VEC_IS_NAN(v1[1]) || VEC_IS_NAN(v1[2]) || VEC_IS_NAN(v2[0]) || VEC_IS_NAN(v2[1]) || VEC_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), 0, 0, collision_extendtracelinelength.value); @@ -699,7 +701,7 @@ static void VM_SV_tracebox(prvm_prog_t *prog) move = (int)PRVM_G_FLOAT(OFS_PARM4); ent = PRVM_G_EDICT(OFS_PARM5); - if (VEC_IS_NAN(v1[0]) || VEC_IS_NAN(v1[1]) || VEC_IS_NAN(v1[2]) || VEC_IS_NAN(v2[0]) || VEC_IS_NAN(v2[1]) || VEC_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), 0, 0, collision_extendtraceboxlength.value); @@ -1005,7 +1007,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; @@ -1056,6 +1058,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); @@ -1133,12 +1179,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, entorigin, entmins, entmaxs; - 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 @@ -1157,6 +1209,15 @@ static void VM_SV_droptofloor(prvm_prog_t *prog) return; } + if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer) + { + 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; @@ -1165,55 +1226,54 @@ static void VM_SV_droptofloor(prvm_prog_t *prog) else end[2] -= 256; // Quake, QuakeWorld - if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer) - SV_NudgeOutOfSolid(ent); - - VectorCopy(PRVM_serveredictvector(ent, origin), entorigin); - VectorCopy(PRVM_serveredictvector(ent, mins), entmins); - VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs); - trace = SV_TraceBox(entorigin, entmins, entmaxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value); - 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), 0, 0, collision_extendmovelength.value); - VectorSubtract(trace.endpos, offset, trace.endpos); - if (trace.startsolid) - { - 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]); - 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; - } - else if (trace.fraction < 1) + /* 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 - 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)); + 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) - SV_NudgeOutOfSolid(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; + PHYS_NudgeOutOfSolid(prog, ent); } - } - else - { - if (!trace.allsolid && trace.fraction < 1) + else { - 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; + 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 + 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; } /* @@ -1240,7 +1300,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) @@ -1409,11 +1469,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; @@ -1670,7 +1740,7 @@ void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *ms //string as 16 bytes case 1: memset(s, 0, 17); - strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16); + dp_strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16); 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; @@ -1692,7 +1762,7 @@ void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *ms } } -extern cvar_t sv_gameplayfix_customstats; +extern cvar_t sv_qcstats; // void(float index, float type, .void field) SV_AddStat = #232; // Set up an auto-sent player stat. @@ -1743,9 +1813,9 @@ static void VM_SV_AddStat(prvm_prog_t *prog) // 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) + 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_gameplayfix_customstats.integer) + 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; @@ -1790,8 +1860,7 @@ static void VM_SV_copyentity(prvm_prog_t *prog) 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); } @@ -2697,13 +2766,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 } /* @@ -2865,8 +2934,7 @@ qbool SV_VM_ConsoleCommand (const char *text) static void VM_SV_registercommand (prvm_prog_t *prog) { VM_SAFEPARMCOUNT(1, VM_SV_registercmd); - if(!Cmd_Exists(cmd_local, PRVM_G_STRING(OFS_PARM0))) - Cmd_AddCommand(CF_SERVER, PRVM_G_STRING(OFS_PARM0), NULL, "console command created by QuakeC"); + Cmd_AddCommand(CF_SERVER, PRVM_G_STRING(OFS_PARM0), NULL, "console command created by QuakeC"); } //PF_setpause, // void(float pause) setpause = #531; @@ -3311,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) @@ -3765,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