From: havoc Date: Mon, 19 Feb 2007 01:33:38 +0000 (+0000) Subject: this patch may break things and needs testing X-Git-Tag: xonotic-v0.1.0preview~3554 X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=commitdiff_plain;h=16742571f9a7d696a654668febdc10b4f4affd57;hp=ded16fd66f1a999d35ee57f989f881f205a428c7 this patch may break things and needs testing major cleanup of csqc and ssqc builtin tables minimized differences between csqc and ssqc builtin tables (everything that can be implemented in both is implemented in both) added VM_SAFEPARMCOUNTRANGE to allow a function to have, for example, 2-4 parameters (where as VM_SAFEPARMCOUNT requires it to be an exact match) added VM_SAFEPARMCOUNT or VM_SAFEPARMCOUNTRANGE to ALL builtins, this may break buggy qc (and it's possible that one or more of these checks are wrong) replaced CL_TraceBox with CL_Move, this is a proper csqc-entity aware version akin to SV_Move, it has a ton of parameters due to support for network entity collisions as well (ideally this needs cleanup somehow but I have no idea how, as non-csqc network entities do not share the prvm_edict_t system and do not have entity numbers in the csqc world) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@6862 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/cl_collision.c b/cl_collision.c index 92d5b8de..82aa3cec 100644 --- a/cl_collision.c +++ b/cl_collision.c @@ -2,182 +2,6 @@ #include "quakedef.h" #include "cl_collision.h" -/* -// not yet used -typedef struct physentity_s -{ - // this may be a entity_t, or a prvm_edict_t, or whatever - void *realentity; - - // can be NULL if it is a bbox object - model_t *bmodel; - - // node this entity crosses - // for avoiding unnecessary collisions - physnode_t *node; - - // matrix for converting from model to world coordinates - double modeltoworldmatrix[3][4]; - - // matrix for converting from world to model coordinates - double worldtomodelmatrix[3][4]; - - // if this is a bmodel, this is used for culling it quickly - // if this is not a bmodel, this is used for actual collisions - double mins[3], maxs[3]; -} -physentity_t; -*/ - -trace_t CL_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitbmodels, int *hitent, int hitsupercontentsmask, qboolean hitplayers) -{ - int n; - entity_render_t *ent; - vec3_t tracemins, tracemaxs; - trace_t cliptrace, trace; - vec3_t origin; - vec3_t starttransformed, endtransformed; - vec3_t entmins, entmaxs; - vec_t *playermins, *playermaxs; - - memset (&cliptrace, 0 , sizeof(trace_t)); - cliptrace.fraction = 1; - cliptrace.realfraction = 1; - - if (cl.worldmodel && cl.worldmodel->TraceBox) - cl.worldmodel->TraceBox(cl.worldmodel, 0, &cliptrace, start, mins, maxs, end, hitsupercontentsmask); - - if (hitent) - *hitent = 0; - - if (hitbmodels && cl.num_brushmodel_entities) - { - tracemins[0] = min(start[0], end[0]) + mins[0]; - tracemaxs[0] = max(start[0], end[0]) + maxs[0]; - tracemins[1] = min(start[1], end[1]) + mins[1]; - tracemaxs[1] = max(start[1], end[1]) + maxs[1]; - tracemins[2] = min(start[2], end[2]) + mins[2]; - tracemaxs[2] = max(start[2], end[2]) + maxs[2]; - - // look for embedded bmodels - for (n = 0;n < cl.num_brushmodel_entities;n++) - { - ent = &cl.entities[cl.brushmodel_entities[n]].render; - if (!BoxesOverlap(tracemins, tracemaxs, ent->mins, ent->maxs)) - continue; - - Matrix4x4_Transform(&ent->inversematrix, start, starttransformed); - Matrix4x4_Transform(&ent->inversematrix, end, endtransformed); - - memset (&trace, 0 , sizeof(trace_t)); - trace.fraction = 1; - trace.realfraction = 1; - - if (ent->model && ent->model->TraceBox) - ent->model->TraceBox(ent->model, 0, &trace, starttransformed, mins, maxs, endtransformed, hitsupercontentsmask); - - // LordHavoc: take the 'best' answers from the new trace and combine with existing data - if (trace.allsolid) - cliptrace.allsolid = true; - if (trace.startsolid) - { - cliptrace.startsolid = true; - if (cliptrace.realfraction == 1) - if (hitent) - *hitent = cl.brushmodel_entities[n]; - } - // don't set this except on the world, because it can easily confuse - // monsters underwater if there's a bmodel involved in the trace - // (inopen && inwater is how they check water visibility) - //if (trace.inopen) - // cliptrace.inopen = true; - if (trace.inwater) - cliptrace.inwater = true; - if (trace.realfraction < cliptrace.realfraction) - { - cliptrace.fraction = trace.fraction; - cliptrace.realfraction = trace.realfraction; - cliptrace.plane = trace.plane; - if (hitent) - *hitent = cl.brushmodel_entities[n]; - Matrix4x4_Transform3x3(&ent->matrix, trace.plane.normal, cliptrace.plane.normal); - cliptrace.hitsupercontents = trace.hitsupercontents; - cliptrace.hitq3surfaceflags = trace.hitq3surfaceflags; - cliptrace.hittexture = trace.hittexture; - } - cliptrace.startsupercontents |= trace.startsupercontents; - } - } - if (hitplayers) - { - tracemins[0] = min(start[0], end[0]) + mins[0]; - tracemaxs[0] = max(start[0], end[0]) + maxs[0]; - tracemins[1] = min(start[1], end[1]) + mins[1]; - tracemaxs[1] = max(start[1], end[1]) + maxs[1]; - tracemins[2] = min(start[2], end[2]) + mins[2]; - tracemaxs[2] = max(start[2], end[2]) + maxs[2]; - - for (n = 1;n < cl.maxclients+1;n++) - { - if (n != cl.playerentity) - { - ent = &cl.entities[n].render; - // FIXME: crouch - playermins = cl.playerstandmins; - playermaxs = cl.playerstandmaxs; - Matrix4x4_OriginFromMatrix(&ent->matrix, origin); - VectorAdd(origin, playermins, entmins); - VectorAdd(origin, playermaxs, entmaxs); - if (!BoxesOverlap(tracemins, tracemaxs, entmins, entmaxs)) - continue; - - memset (&trace, 0 , sizeof(trace_t)); - trace.fraction = 1; - trace.realfraction = 1; - - Matrix4x4_Transform(&ent->inversematrix, start, starttransformed); - Matrix4x4_Transform(&ent->inversematrix, end, endtransformed); - Collision_ClipTrace_Box(&trace, playermins, playermaxs, starttransformed, mins, maxs, endtransformed, hitsupercontentsmask, SUPERCONTENTS_BODY, 0, NULL); - - // LordHavoc: take the 'best' answers from the new trace and combine with existing data - if (trace.allsolid) - cliptrace.allsolid = true; - if (trace.startsolid) - { - cliptrace.startsolid = true; - if (cliptrace.realfraction == 1) - if (hitent) - *hitent = n; - } - // don't set this except on the world, because it can easily confuse - // monsters underwater if there's a bmodel involved in the trace - // (inopen && inwater is how they check water visibility) - //if (trace.inopen) - // cliptrace.inopen = true; - if (trace.inwater) - cliptrace.inwater = true; - if (trace.realfraction < cliptrace.realfraction) - { - cliptrace.fraction = trace.fraction; - cliptrace.realfraction = trace.realfraction; - cliptrace.plane = trace.plane; - if (hitent) - *hitent = n; - Matrix4x4_Transform3x3(&ent->matrix, trace.plane.normal, cliptrace.plane.normal); - cliptrace.hitsupercontents = trace.hitsupercontents; - cliptrace.hitq3surfaceflags = trace.hitq3surfaceflags; - cliptrace.hittexture = trace.hittexture; - } - cliptrace.startsupercontents |= trace.startsupercontents; - } - } - } - cliptrace.fraction = bound(0, cliptrace.fraction, 1); - cliptrace.realfraction = bound(0, cliptrace.realfraction, 1); - VectorLerp(start, cliptrace.fraction, end, cliptrace.endpos); - return cliptrace; -} - float CL_SelectTraceLine(const vec3_t start, const vec3_t end, vec3_t impact, vec3_t normal, int *hitent, entity_render_t *ignoreent) { float maxfrac, maxrealfrac; @@ -260,8 +84,268 @@ void CL_FindNonSolidLocation(const vec3_t in, vec3_t out, vec_t radius) cl.worldmodel->brush.FindNonSolidLocation(cl.worldmodel, in, out, radius); } -int CL_PointSuperContents(const vec3_t p) +model_t *CL_GetModelByIndex(int modelindex) { - return CL_TraceBox(p, vec3_origin, vec3_origin, p, true, NULL, 0, false).startsupercontents; + if(!modelindex) + return NULL; + if (modelindex < 0) + { + modelindex = -(modelindex+1); + if (modelindex < MAX_MODELS) + return cl.csqc_model_precache[modelindex]; + } + else + { + if(modelindex < MAX_MODELS) + return cl.model_precache[modelindex]; + } + return NULL; +} + +model_t *CL_GetModelFromEdict(prvm_edict_t *ed) +{ + if (!ed || ed->priv.server->free) + return NULL; + return CL_GetModelByIndex((int)ed->fields.client->modelindex); +} + +void CL_LinkEdict(prvm_edict_t *ent) +{ + if (ent == prog->edicts) + return; // don't add the world + + if (ent->priv.server->free) + return; + + VectorAdd(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->absmin); + VectorAdd(ent->fields.client->origin, ent->fields.client->maxs, ent->fields.client->absmax); + + World_LinkEdict(&cl.world, ent, ent->fields.client->absmin, ent->fields.client->absmax); } +int CL_GenericHitSuperContentsMask(const prvm_edict_t *passedict) +{ + prvm_eval_t *val; + if (passedict) + { + val = PRVM_EDICTFIELDVALUE(passedict, prog->fieldoffsets.dphitcontentsmask); + if (val && val->_float) + return (int)val->_float; + else if (passedict->fields.client->solid == SOLID_SLIDEBOX) + { + if ((int)passedict->fields.client->flags & FL_MONSTER) + return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_MONSTERCLIP; + else + return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP; + } + else if (passedict->fields.client->solid == SOLID_CORPSE) + return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY; + else + return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_CORPSE; + } + else + return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_CORPSE; +} + +/* +================== +CL_Move +================== +*/ +extern cvar_t sv_debugmove; +trace_t CL_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask, qboolean hitnetworkbrushmodels, qboolean hitnetworkplayers, int *hitnetworkentity, qboolean hitcsqcentities) +{ + vec3_t hullmins, hullmaxs; + int i; + int passedictprog; + qboolean pointtrace; + prvm_edict_t *traceowner, *touch; + trace_t trace; + // bounding box of entire move area + vec3_t clipboxmins, clipboxmaxs; + // size of the moving object + vec3_t clipmins, clipmaxs; + // size when clipping against monsters + vec3_t clipmins2, clipmaxs2; + // start and end origin of move + vec3_t clipstart, clipend; + // trace results + trace_t cliptrace; + // matrices to transform into/out of other entity's space + matrix4x4_t matrix, imatrix; + // model of other entity + model_t *model; + // list of entities to test for collisions + int numtouchedicts; + prvm_edict_t *touchedicts[MAX_EDICTS]; + + if (hitnetworkentity) + *hitnetworkentity = 0; + + VectorCopy(start, clipstart); + VectorCopy(end, clipend); + VectorCopy(mins, clipmins); + VectorCopy(maxs, clipmaxs); + VectorCopy(mins, clipmins2); + VectorCopy(maxs, clipmaxs2); +#if COLLISIONPARANOID >= 3 + Con_Printf("move(%f %f %f,%f %f %f)", clipstart[0], clipstart[1], clipstart[2], clipend[0], clipend[1], clipend[2]); +#endif + + // clip to world + Collision_ClipToWorld(&cliptrace, cl.worldmodel, clipstart, clipmins, clipmaxs, clipend, hitsupercontentsmask); + cliptrace.bmodelstartsolid = cliptrace.startsolid; + if (cliptrace.startsolid || cliptrace.fraction < 1) + cliptrace.ent = prog ? prog->edicts : NULL; + if (type == MOVE_WORLDONLY) + return cliptrace; + + if (type == MOVE_MISSILE) + { + // LordHavoc: modified this, was = -15, now -= 15 + for (i = 0;i < 3;i++) + { + clipmins2[i] -= 15; + clipmaxs2[i] += 15; + } + } + + // get adjusted box for bmodel collisions if the world is q1bsp or hlbsp + if (cl.worldmodel && cl.worldmodel->brush.RoundUpToHullSize) + cl.worldmodel->brush.RoundUpToHullSize(cl.worldmodel, clipmins, clipmaxs, hullmins, hullmaxs); + else + { + VectorCopy(clipmins, hullmins); + VectorCopy(clipmaxs, hullmaxs); + } + + // create the bounding box of the entire move + for (i = 0;i < 3;i++) + { + clipboxmins[i] = min(clipstart[i], cliptrace.endpos[i]) + min(hullmins[i], clipmins2[i]) - 1; + clipboxmaxs[i] = max(clipstart[i], cliptrace.endpos[i]) + max(hullmaxs[i], clipmaxs2[i]) + 1; + } + + // debug override to test against everything + if (sv_debugmove.integer) + { + clipboxmins[0] = clipboxmins[1] = clipboxmins[2] = -999999999; + clipboxmaxs[0] = clipboxmaxs[1] = clipboxmaxs[2] = 999999999; + } + + // if the passedict is world, make it NULL (to avoid two checks each time) + // this checks prog because this function is often called without a CSQC + // VM context + if (prog == NULL || passedict == prog->edicts) + passedict = NULL; + // precalculate prog value for passedict for comparisons + passedictprog = prog != NULL ? PRVM_EDICT_TO_PROG(passedict) : 0; + // figure out whether this is a point trace for comparisons + pointtrace = VectorCompare(clipmins, clipmaxs); + // precalculate passedict's owner edict pointer for comparisons + traceowner = passedict ? PRVM_PROG_TO_EDICT(passedict->fields.client->owner) : 0; + + // collide against network entities + if (hitnetworkbrushmodels) + { + for (i = 0;i < cl.num_brushmodel_entities;i++) + { + entity_render_t *ent = &cl.entities[cl.brushmodel_entities[i]].render; + if (!BoxesOverlap(clipboxmins, clipboxmaxs, ent->mins, ent->maxs)) + continue; + Collision_ClipToGenericEntity(&trace, ent->model, ent->frame, vec3_origin, vec3_origin, 0, &ent->matrix, &ent->inversematrix, start, mins, maxs, end, hitsupercontentsmask); + if (cliptrace.realfraction > trace.realfraction && hitnetworkentity) + *hitnetworkentity = cl.brushmodel_entities[i]; + Collision_CombineTraces(&cliptrace, &trace, NULL, true); + } + } + + // collide against player entities + if (hitnetworkplayers) + { + vec3_t origin, entmins, entmaxs; + matrix4x4_t entmatrix, entinversematrix; + for (i = 1;i < cl.maxclients+1;i++) + { + entity_render_t *ent = &cl.entities[i].render; + // don't hit ourselves + if (i == cl.playerentity) + continue; + Matrix4x4_OriginFromMatrix(&ent->matrix, origin); + VectorAdd(origin, cl.playerstandmins, entmins); + VectorAdd(origin, cl.playerstandmaxs, entmaxs); + if (!BoxesOverlap(clipboxmins, clipboxmaxs, entmins, entmaxs)) + continue; + Matrix4x4_CreateTranslate(&entmatrix, origin[0], origin[1], origin[2]); + Matrix4x4_CreateTranslate(&entinversematrix, -origin[0], -origin[1], -origin[2]); + Collision_ClipToGenericEntity(&trace, NULL, 0, cl.playerstandmins, cl.playerstandmaxs, SUPERCONTENTS_BODY, &entmatrix, &entinversematrix, start, mins, maxs, end, hitsupercontentsmask); + if (cliptrace.realfraction > trace.realfraction && hitnetworkentity) + *hitnetworkentity = i; + Collision_CombineTraces(&cliptrace, &trace, NULL, false); + } + } + + // clip to entities + // because this uses World_EntitiestoBox, we know all entity boxes overlap + // the clip region, so we can skip culling checks in the loop below + // note: if prog is NULL then there won't be any linked entities + numtouchedicts = 0; + if (hitcsqcentities && prog != NULL) + { + numtouchedicts = World_EntitiesInBox(&cl.world, clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts); + if (numtouchedicts > MAX_EDICTS) + { + // this never happens + Con_Printf("CL_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS); + numtouchedicts = MAX_EDICTS; + } + } + for (i = 0;i < numtouchedicts;i++) + { + touch = touchedicts[i]; + + if (touch->fields.client->solid < SOLID_BBOX) + continue; + if (type == MOVE_NOMONSTERS && touch->fields.client->solid != SOLID_BSP) + continue; + + if (passedict) + { + // don't clip against self + if (passedict == touch) + continue; + // don't clip owned entities against owner + if (traceowner == touch) + continue; + // don't clip owner against owned entities + if (passedictprog == touch->fields.client->owner) + continue; + // don't clip points against points (they can't collide) + if (pointtrace && VectorCompare(touch->fields.client->mins, touch->fields.client->maxs) && (type != MOVE_MISSILE || !((int)touch->fields.client->flags & FL_MONSTER))) + continue; + } + + // might interact, so do an exact clip + model = NULL; + if ((int) touch->fields.client->solid == SOLID_BSP || type == MOVE_HITMODEL) + { + unsigned int modelindex = (unsigned int)touch->fields.client->modelindex; + // if the modelindex is 0, it shouldn't be SOLID_BSP! + if (modelindex > 0 && modelindex < MAX_MODELS) + model = CL_GetModelByIndex((int)touch->fields.client->modelindex); + Matrix4x4_CreateFromQuakeEntity(&matrix, touch->fields.client->origin[0], touch->fields.client->origin[1], touch->fields.client->origin[2], touch->fields.client->angles[0], touch->fields.client->angles[1], touch->fields.client->angles[2], 1); + } + else + Matrix4x4_CreateTranslate(&matrix, touch->fields.client->origin[0], touch->fields.client->origin[1], touch->fields.client->origin[2]); + Matrix4x4_Invert_Simple(&imatrix, &matrix); + if ((int)touch->fields.client->flags & FL_MONSTER) + Collision_ClipToGenericEntity(&trace, model, touch->fields.client->frame, touch->fields.client->mins, touch->fields.client->maxs, SUPERCONTENTS_BODY, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask); + else + Collision_ClipToGenericEntity(&trace, model, touch->fields.client->frame, touch->fields.client->mins, touch->fields.client->maxs, SUPERCONTENTS_BODY, &matrix, &imatrix, clipstart, clipmins, clipmaxs, clipend, hitsupercontentsmask); + if (cliptrace.realfraction > trace.realfraction && hitnetworkentity) + *hitnetworkentity = 0; + Collision_CombineTraces(&cliptrace, &trace, (void *)touch, touch->fields.client->solid == SOLID_BSP); + } + + return cliptrace; +} diff --git a/cl_collision.h b/cl_collision.h index 740ec2af..f6837b7b 100644 --- a/cl_collision.h +++ b/cl_collision.h @@ -2,9 +2,15 @@ #ifndef CL_COLLISION_H #define CL_COLLISION_H -trace_t CL_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitbmodels, int *hitent, int hitsupercontentsmask, qboolean hitplayers); float CL_SelectTraceLine(const vec3_t start, const vec3_t end, vec3_t impact, vec3_t normal, int *hitent, entity_render_t *ignoreent); void CL_FindNonSolidLocation(const vec3_t in, vec3_t out, vec_t radius); -int CL_PointSuperContents(const vec3_t p); + +model_t *CL_GetModelByIndex(int modelindex); +model_t *CL_GetModelFromEdict(prvm_edict_t *ed); + +void CL_LinkEdict(prvm_edict_t *ent); +int CL_GenericHitSuperContentsMask(const prvm_edict_t *edict); +trace_t CL_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask, qboolean hitnetworkbrushmodels, qboolean hitnetworkplayers, int *hitnetworkentity, qboolean hitcsqcentities); +#define CL_PointSuperContents(point) (CL_Move((point), vec3_origin, vec3_origin, (point), sv_gameplayfix_swiminbmodels.integer ? MOVE_NOMONSTERS : MOVE_WORLDONLY, NULL, 0, true, false, NULL, true).startsupercontents) #endif diff --git a/cl_input.c b/cl_input.c index 8bdec9a8..59eef71c 100644 --- a/cl_input.c +++ b/cl_input.c @@ -730,7 +730,7 @@ qboolean CL_ClientMovement_Unstick(cl_clientmovement_state_t *s) for (i = 0;i < NUMOFFSETS;i++) { VectorAdd(offsets[i], s->origin, neworigin); - if (!CL_TraceBox(neworigin, cl.playercrouchmins, cl.playercrouchmaxs, neworigin, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, true).startsolid) + if (!CL_Move(neworigin, cl.playercrouchmins, cl.playercrouchmaxs, neworigin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false).startsolid) { VectorCopy(neworigin, s->origin); return true; @@ -761,7 +761,7 @@ void CL_ClientMovement_UpdateStatus(cl_clientmovement_state_t *s) // low ceiling first if (s->crouched) { - trace = CL_TraceBox(s->origin, cl.playerstandmins, cl.playerstandmaxs, s->origin, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true); + trace = CL_Move(s->origin, cl.playerstandmins, cl.playerstandmaxs, s->origin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false); if (!trace.startsolid) s->crouched = false; } @@ -780,22 +780,22 @@ void CL_ClientMovement_UpdateStatus(cl_clientmovement_state_t *s) // set onground VectorSet(origin1, s->origin[0], s->origin[1], s->origin[2] + 1); VectorSet(origin2, s->origin[0], s->origin[1], s->origin[2] - 2); - trace = CL_TraceBox(origin1, s->mins, s->maxs, origin2, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true); + trace = CL_Move(origin1, s->mins, s->maxs, origin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false); s->onground = trace.fraction < 1 && trace.plane.normal[2] > 0.7 && s->velocity[2] < cl_gravity.value * s->q.frametime; // set watertype/waterlevel VectorSet(origin1, s->origin[0], s->origin[1], s->origin[2] + s->mins[2] + 1); s->waterlevel = WATERLEVEL_NONE; - s->watertype = CL_TraceBox(origin1, vec3_origin, vec3_origin, origin1, true, NULL, 0, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK; + s->watertype = CL_Move(origin1, vec3_origin, vec3_origin, origin1, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK; if (s->watertype) { s->waterlevel = WATERLEVEL_WETFEET; origin1[2] = s->origin[2] + (s->mins[2] + s->maxs[2]) * 0.5f; - if (CL_TraceBox(origin1, vec3_origin, vec3_origin, origin1, true, NULL, 0, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK) + if (CL_Move(origin1, vec3_origin, vec3_origin, origin1, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK) { s->waterlevel = WATERLEVEL_SWIMMING; origin1[2] = s->origin[2] + 22; - if (CL_TraceBox(origin1, vec3_origin, vec3_origin, origin1, true, NULL, 0, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK) + if (CL_Move(origin1, vec3_origin, vec3_origin, origin1, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK) s->waterlevel = WATERLEVEL_SUBMERGED; } } @@ -822,20 +822,20 @@ void CL_ClientMovement_Move(cl_clientmovement_state_t *s) for (bump = 0, t = s->q.frametime;bump < 8 && VectorLength2(s->velocity) > 0;bump++) { VectorMA(s->origin, t, s->velocity, neworigin); - trace = CL_TraceBox(s->origin, s->mins, s->maxs, neworigin, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true); + trace = CL_Move(s->origin, s->mins, s->maxs, neworigin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false); if (trace.fraction < 1 && trace.plane.normal[2] == 0) { // may be a step or wall, try stepping up // first move forward at a higher level VectorSet(currentorigin2, s->origin[0], s->origin[1], s->origin[2] + s->movevars_stepheight); VectorSet(neworigin2, neworigin[0], neworigin[1], s->origin[2] + s->movevars_stepheight); - trace2 = CL_TraceBox(currentorigin2, s->mins, s->maxs, neworigin2, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true); + trace2 = CL_Move(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false); if (!trace2.startsolid) { // then move down from there VectorCopy(trace2.endpos, currentorigin2); VectorSet(neworigin2, trace2.endpos[0], trace2.endpos[1], s->origin[2]); - trace3 = CL_TraceBox(currentorigin2, s->mins, s->maxs, neworigin2, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true); + trace3 = CL_Move(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false); //Con_Printf("%f %f %f %f : %f %f %f %f : %f %f %f %f\n", trace.fraction, trace.endpos[0], trace.endpos[1], trace.endpos[2], trace2.fraction, trace2.endpos[0], trace2.endpos[1], trace2.endpos[2], trace3.fraction, trace3.endpos[0], trace3.endpos[1], trace3.endpos[2]); // accept the new trace if it made some progress if (fabs(trace3.endpos[0] - trace.endpos[0]) >= 0.03125 || fabs(trace3.endpos[1] - trace.endpos[1]) >= 0.03125) @@ -885,10 +885,10 @@ void CL_ClientMovement_Physics_Swim(cl_clientmovement_state_t *s) AngleVectors(yawangles, forward, NULL, NULL); VectorMA(s->origin, 24, forward, spot); spot[2] += 8; - if (CL_TraceBox(spot, vec3_origin, vec3_origin, spot, true, NULL, 0, false).startsolid) + if (CL_Move(spot, vec3_origin, vec3_origin, spot, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsolid) { spot[2] += 24; - if (!CL_TraceBox(spot, vec3_origin, vec3_origin, spot, true, NULL, 0, false).startsolid) + if (!CL_Move(spot, vec3_origin, vec3_origin, spot, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsolid) { VectorScale(forward, 50, s->velocity); s->velocity[2] = 310; @@ -1017,9 +1017,9 @@ void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s) VectorSet(neworigin2, s->origin[0] + s->velocity[0]*(16/f), s->origin[1] + s->velocity[1]*(16/f), s->origin[2] + s->mins[2]); VectorSet(neworigin3, neworigin2[0], neworigin2[1], neworigin2[2] - 34); if (cls.protocol == PROTOCOL_QUAKEWORLD) - trace = CL_TraceBox(neworigin2, s->mins, s->maxs, neworigin3, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true); + trace = CL_Move(neworigin2, s->mins, s->maxs, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false); else - trace = CL_TraceBox(neworigin2, vec3_origin, vec3_origin, neworigin3, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true); + trace = CL_Move(neworigin2, vec3_origin, vec3_origin, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false); if (trace.fraction == 1 && !trace.startsolid) friction *= s->movevars_edgefriction; } diff --git a/cl_main.c b/cl_main.c index 05a36f55..f3620532 100644 --- a/cl_main.c +++ b/cl_main.c @@ -1230,7 +1230,7 @@ void CL_LinkNetworkEntity(entity_t *e) trace_t trace; matrix4x4_t tempmatrix; Matrix4x4_Transform(&e->render.matrix, muzzleflashorigin, v2); - trace = CL_TraceBox(origin, vec3_origin, vec3_origin, v2, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_SKY, false); + trace = CL_Move(origin, vec3_origin, vec3_origin, v2, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_SKY, true, false, NULL, false); Matrix4x4_Normalize(&tempmatrix, &e->render.matrix); Matrix4x4_SetOrigin(&tempmatrix, trace.endpos[0], trace.endpos[1], trace.endpos[2]); Matrix4x4_Scale(&tempmatrix, 150, 1); diff --git a/cl_particles.c b/cl_particles.c index 8b80cadd..d658b7b6 100644 --- a/cl_particles.c +++ b/cl_particles.c @@ -521,7 +521,7 @@ void CL_SpawnDecalParticleForPoint(const vec3_t org, float maxdist, float size, { VectorRandom(org2); VectorMA(org, maxdist, org2, org2); - trace = CL_TraceBox(org, vec3_origin, vec3_origin, org2, true, &hitent, SUPERCONTENTS_SOLID | SUPERCONTENTS_SKY, false); + trace = CL_Move(org, vec3_origin, vec3_origin, org2, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_SKY, true, false, &hitent, false); // take the closest trace result that doesn't end up hitting a NOMARKS // surface (sky for example) if (bestfrac > trace.fraction && !(trace.hitq3surfaceflags & Q3SURFACEFLAG_NOMARKS)) @@ -1324,7 +1324,7 @@ void CL_ParticleExplosion (const vec3_t org) v[0] = org[0] + lhrandom(-48, 48); v[1] = org[1] + lhrandom(-48, 48); v[2] = org[2] + lhrandom(-48, 48); - trace = CL_TraceBox(org, vec3_origin, vec3_origin, v, true, NULL, SUPERCONTENTS_SOLID, false); + trace = CL_Move(org, vec3_origin, vec3_origin, v, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false); if (trace.fraction >= 0.1) break; } @@ -1534,7 +1534,7 @@ void CL_MoveParticles (void) VectorCopy(p->org, org); if (p->bounce) { - trace = CL_TraceBox(oldorg, vec3_origin, vec3_origin, p->org, true, &hitent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | (p->type == particletype + pt_rain ? SUPERCONTENTS_LIQUIDSMASK : 0), false); + trace = CL_Move(oldorg, vec3_origin, vec3_origin, p->org, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | (p->type == particletype + pt_rain ? SUPERCONTENTS_LIQUIDSMASK : 0), true, false, &hitent, false); // if the trace started in or hit something of SUPERCONTENTS_NODROP // or if the trace hit something flagged as NOIMPACT // then remove the particle diff --git a/clvm_cmds.c b/clvm_cmds.c index 21626ad4..43ca54ad 100644 --- a/clvm_cmds.c +++ b/clvm_cmds.c @@ -17,16 +17,12 @@ //4 feature darkplaces csqc: add builtins to clientside qc for gl calls sfx_t *S_FindName(const char *name); -void PF_registercvar (void); int Sbar_GetPlayer (int index); void Sbar_SortFrags (void); void CL_FindNonSolidLocation(const vec3_t in, vec3_t out, vec_t radius); void CSQC_RelinkAllEntities (int drawmask); void CSQC_RelinkCSQCEntities (void); char *Key_GetBind (int key); -model_t *CSQC_GetModelByIndex(int modelindex); -model_t *CSQC_GetModelFromEntity(prvm_edict_t *ed); -void CL_LinkEdict(prvm_edict_t *ed); @@ -34,17 +30,18 @@ void CL_LinkEdict(prvm_edict_t *ed); // #1 void(vector ang) makevectors -void VM_CL_makevectors (void) +static void VM_CL_makevectors (void) { VM_SAFEPARMCOUNT(1, VM_CL_makevectors); AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.client->v_forward, prog->globals.client->v_right, prog->globals.client->v_up); } // #2 void(entity e, vector o) setorigin -void VM_CL_setorigin (void) +static void VM_CL_setorigin (void) { prvm_edict_t *e; float *org; + VM_SAFEPARMCOUNT(2, VM_CL_setorigin); e = PRVM_G_EDICT(OFS_PARM0); if (e == prog->edicts) @@ -63,7 +60,7 @@ void VM_CL_setorigin (void) } // #3 void(entity e, string m) setmodel -void VM_CL_setmodel (void) +static void VM_CL_setmodel (void) { prvm_edict_t *e; const char *m; @@ -100,7 +97,7 @@ void VM_CL_setmodel (void) } // #4 void(entity e, vector min, vector max) setsize -void VM_CL_setsize (void) +static void VM_CL_setsize (void) { prvm_edict_t *e; float *min, *max; @@ -127,8 +124,8 @@ void VM_CL_setsize (void) CL_LinkEdict(e); } -// #8 void(entity e, float chan, string samp) sound -void VM_CL_sound (void) +// #8 void(entity e, float chan, string samp, float volume, float atten) sound +static void VM_CL_sound (void) { const char *sample; int channel; @@ -166,7 +163,7 @@ void VM_CL_sound (void) } // #14 entity() spawn -void VM_CL_spawn (void) +static void VM_CL_spawn (void) { prvm_edict_t *ed; ed = PRVM_ED_Alloc(); @@ -174,41 +171,141 @@ void VM_CL_spawn (void) VM_RETURN_EDICT(ed); } -// #16 float(vector v1, vector v2, float tryents) traceline -void VM_CL_traceline (void) +// #16 float(vector v1, vector v2, float movetype, entity ignore) traceline +static void VM_CL_traceline (void) { float *v1, *v2; trace_t trace; - int ent; + int move; + prvm_edict_t *ent; + + VM_SAFEPARMCOUNTRANGE(4, 8, VM_CL_traceline); // allow more parameters for future expansion + + prog->xfunction->builtinsprofile += 30; v1 = PRVM_G_VECTOR(OFS_PARM0); v2 = PRVM_G_VECTOR(OFS_PARM1); + move = (int)PRVM_G_FLOAT(OFS_PARM2); + ent = PRVM_G_EDICT(OFS_PARM3); + + if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v1[2]) || IS_NAN(v2[2])) + PRVM_ERROR("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent)); + + trace = CL_Move(v1, vec3_origin, vec3_origin, v2, move, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true); + + VM_SetTraceGlobals(&trace); +} + +/* +================= +VM_CL_tracebox + +Used for use tracing and shot targeting +Traces are blocked by bbox and exact bsp entityes, and also slide box entities +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 +static void VM_CL_tracebox (void) +{ + float *v1, *v2, *m1, *m2; + trace_t trace; + int move; + prvm_edict_t *ent; + + VM_SAFEPARMCOUNTRANGE(6, 8, VM_CL_tracebox); // allow more parameters for future expansion + + 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); + move = (int)PRVM_G_FLOAT(OFS_PARM4); + ent = PRVM_G_EDICT(OFS_PARM5); + + if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v1[2]) || IS_NAN(v2[2])) + PRVM_ERROR("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent)); - trace = CL_TraceBox(v1, vec3_origin, vec3_origin, v2, 1, &ent, 1, false); - - prog->globals.client->trace_allsolid = trace.allsolid; - prog->globals.client->trace_startsolid = trace.startsolid; - prog->globals.client->trace_fraction = trace.fraction; - prog->globals.client->trace_inwater = trace.inwater; - prog->globals.client->trace_inopen = trace.inopen; - VectorCopy (trace.endpos, prog->globals.client->trace_endpos); - VectorCopy (trace.plane.normal, prog->globals.client->trace_plane_normal); - prog->globals.client->trace_plane_dist = trace.plane.dist; - if (ent) - prog->globals.client->trace_ent = ent; + trace = CL_Move(v1, m1, m2, v2, move, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true); + + VM_SetTraceGlobals(&trace); +} + +extern cvar_t cl_gravity; +trace_t CL_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore) +{ + int i; + float gravity; + vec3_t move, end; + vec3_t original_origin; + vec3_t original_velocity; + vec3_t original_angles; + vec3_t original_avelocity; + prvm_eval_t *val; + trace_t trace; + + VectorCopy(tossent->fields.client->origin , original_origin ); + VectorCopy(tossent->fields.client->velocity , original_velocity ); + VectorCopy(tossent->fields.client->angles , original_angles ); + VectorCopy(tossent->fields.client->avelocity, original_avelocity); + + val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity); + if (val != NULL && val->_float != 0) + gravity = val->_float; else - prog->globals.client->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts); + gravity = 1.0; + gravity *= cl_gravity.value * 0.05; + + for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds + { + tossent->fields.client->velocity[2] -= gravity; + VectorMA (tossent->fields.client->angles, 0.05, tossent->fields.client->avelocity, tossent->fields.client->angles); + VectorScale (tossent->fields.client->velocity, 0.05, move); + VectorAdd (tossent->fields.client->origin, move, end); + trace = CL_Move (tossent->fields.client->origin, tossent->fields.client->mins, tossent->fields.client->maxs, end, MOVE_NORMAL, tossent, CL_GenericHitSuperContentsMask(tossent), true, true, NULL, true); + VectorCopy (trace.endpos, tossent->fields.client->origin); + + if (trace.fraction < 1) + break; + } + + VectorCopy(original_origin , tossent->fields.client->origin ); + VectorCopy(original_velocity , tossent->fields.client->velocity ); + VectorCopy(original_angles , tossent->fields.client->angles ); + VectorCopy(original_avelocity, tossent->fields.client->avelocity); + + return trace; } -// #19 void(string s) precache_sound -void VM_CL_precache_sound (void) +static void VM_CL_tracetoss (void) { - VM_SAFEPARMCOUNT(1, VM_CL_precache_sound); - S_PrecacheSound(PRVM_G_STRING(OFS_PARM0), true, false); + trace_t trace; + prvm_edict_t *ent; + prvm_edict_t *ignore; + + prog->xfunction->builtinsprofile += 600; + + VM_SAFEPARMCOUNT(2, VM_CL_tracetoss); + + ent = PRVM_G_EDICT(OFS_PARM0); + if (ent == prog->edicts) + { + VM_Warning("tracetoss: can not use world entity\n"); + return; + } + ignore = PRVM_G_EDICT(OFS_PARM1); + + trace = CL_Trace_Toss (ent, ignore); + + VM_SetTraceGlobals(&trace); } + // #20 void(string s) precache_model -void VM_CL_precache_model (void) +static void VM_CL_precache_model (void) { const char *name; int i; @@ -263,7 +360,7 @@ int CSQC_EntitiesInBox (vec3_t mins, vec3_t maxs, int maxlist, prvm_edict_t **li } // #22 entity(vector org, float rad) findradius -void VM_CL_findradius (void) +static void VM_CL_findradius (void) { prvm_edict_t *ent, *chain; vec_t radius, radius2; @@ -271,6 +368,8 @@ void VM_CL_findradius (void) int i, numtouchedicts; prvm_edict_t *touchedicts[MAX_EDICTS]; + VM_SAFEPARMCOUNT(2, VM_CL_findradius); + chain = (prvm_edict_t *)prog->edicts; VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org); @@ -320,12 +419,14 @@ void VM_CL_findradius (void) } // #34 float() droptofloor -void VM_CL_droptofloor (void) +static void VM_CL_droptofloor (void) { prvm_edict_t *ent; + prvm_eval_t *val; vec3_t end; trace_t trace; - int i; + + VM_SAFEPARMCOUNTRANGE(0, 2, VM_CL_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype // assume failure if it returns early PRVM_G_FLOAT(OFS_RETURN) = 0; @@ -345,13 +446,14 @@ void VM_CL_droptofloor (void) VectorCopy (ent->fields.client->origin, end); end[2] -= 256; - trace = CL_TraceBox(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, end, 1, &i, 1, false); + trace = CL_Move(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true); if (trace.fraction != 1) { VectorCopy (trace.endpos, ent->fields.client->origin); ent->fields.client->flags = (int)ent->fields.client->flags | FL_ONGROUND; -// ent->fields.client->groundentity = PRVM_EDICT_TO_PROG(trace.ent); + if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.groundentity))) + val->edict = 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; @@ -359,7 +461,7 @@ void VM_CL_droptofloor (void) } // #35 void(float style, string value) lightstyle -void VM_CL_lightstyle (void) +static void VM_CL_lightstyle (void) { int i; const char *c; @@ -379,13 +481,13 @@ void VM_CL_lightstyle (void) } // #40 float(entity e) checkbottom -void VM_CL_checkbottom (void) +static void VM_CL_checkbottom (void) { static int cs_yes, cs_no; prvm_edict_t *ent; vec3_t mins, maxs, start, stop; trace_t trace; - int x, y, hit; + int x, y; float mid, bottom; VM_SAFEPARMCOUNT(1, VM_CL_checkbottom); @@ -423,7 +525,7 @@ realcheck: start[0] = stop[0] = (mins[0] + maxs[0])*0.5; start[1] = stop[1] = (mins[1] + maxs[1])*0.5; stop[2] = start[2] - 2*sv_stepheight.value; - trace = CL_TraceBox (start, vec3_origin, vec3_origin, stop, 1, &hit, 1, true); + trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true); if (trace.fraction == 1.0) return; @@ -437,7 +539,7 @@ realcheck: start[0] = stop[0] = x ? maxs[0] : mins[0]; start[1] = stop[1] = y ? maxs[1] : mins[1]; - trace = CL_TraceBox (start, vec3_origin, vec3_origin, stop, 1, &hit, 1, true); + trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true); if (trace.fraction != 1.0 && trace.endpos[2] > bottom) bottom = trace.endpos[2]; @@ -450,14 +552,14 @@ realcheck: } // #41 float(vector v) pointcontents -void VM_CL_pointcontents (void) +static void VM_CL_pointcontents (void) { VM_SAFEPARMCOUNT(1, VM_CL_pointcontents); PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, CL_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0))); } // #48 void(vector o, vector d, float color, float count) particle -void VM_CL_particle (void) +static void VM_CL_particle (void) { float *org, *dir; int count; @@ -471,41 +573,8 @@ void VM_CL_particle (void) CL_ParticleEffect(EFFECT_SVC_PARTICLE, count, org, org, dir, dir, NULL, color); } -// #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) -void VM_CL_tracetoss (void) -{ -/* trace_t trace; - prvm_edict_t *ent; - prvm_edict_t *ignore; - - ent = PRVM_G_EDICT(OFS_PARM0); - if (ent == prog->edicts) - { - VM_Warning("tracetoss: can not use world entity\n"); - return; - } - ignore = PRVM_G_EDICT(OFS_PARM1); - -//FIXME - trace = SV_Trace_Toss (ent, ignore); - - prog->globals.server->trace_allsolid = trace.allsolid; - prog->globals.server->trace_startsolid = trace.startsolid; - prog->globals.server->trace_fraction = trace.fraction; - prog->globals.server->trace_inwater = trace.inwater; - prog->globals.server->trace_inopen = trace.inopen; - VectorCopy (trace.endpos, prog->globals.server->trace_endpos); - VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal); - prog->globals.server->trace_plane_dist = trace.plane.dist; - if (trace.ent) - prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent); - else - prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts); -*/ -} - // #74 void(vector pos, string samp, float vol, float atten) ambientsound -void VM_CL_ambientsound (void) +static void VM_CL_ambientsound (void) { float *f; sfx_t *s; @@ -515,36 +584,8 @@ void VM_CL_ambientsound (void) S_StaticSound (s, f, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3)*64); } -// #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX) -void VM_CL_tracebox (void) -{ - float *v1, *v2, *m1, *m2; - trace_t trace; - int ent; - - v1 = PRVM_G_VECTOR(OFS_PARM0); - m1 = PRVM_G_VECTOR(OFS_PARM1); - m2 = PRVM_G_VECTOR(OFS_PARM2); - v2 = PRVM_G_VECTOR(OFS_PARM3); - - trace = CL_TraceBox(v1, m1, m2, v2, 1, &ent, 1, false); - - prog->globals.client->trace_allsolid = trace.allsolid; - prog->globals.client->trace_startsolid = trace.startsolid; - prog->globals.client->trace_fraction = trace.fraction; - prog->globals.client->trace_inwater = trace.inwater; - prog->globals.client->trace_inopen = trace.inopen; - VectorCopy (trace.endpos, prog->globals.client->trace_endpos); - VectorCopy (trace.plane.normal, prog->globals.client->trace_plane_normal); - prog->globals.client->trace_plane_dist = trace.plane.dist; - if (ent) - prog->globals.client->trace_ent = ent; - else - prog->globals.client->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts); -} - // #92 vector(vector org) getlight (DP_QC_GETLIGHT) -void VM_CL_getlight (void) +static void VM_CL_getlight (void) { vec3_t ambientcolor, diffusecolor, diffusenormal; vec_t *p; @@ -577,9 +618,9 @@ static void CSQC_R_RecalcView (void) void CL_RelinkLightFlashes(void); //#300 void() clearscene (EXT_CSQC) -void VM_R_ClearScene (void) +static void VM_CL_R_ClearScene (void) { - VM_SAFEPARMCOUNT(0, VM_R_ClearScene); + VM_SAFEPARMCOUNT(0, VM_CL_R_ClearScene); // clear renderable entity and light lists r_refdef.numentities = 0; r_refdef.numlights = 0; @@ -588,11 +629,11 @@ void VM_R_ClearScene (void) //#301 void(float mask) addentities (EXT_CSQC) extern void CSQC_Predraw (prvm_edict_t *ed);//csprogs.c extern void CSQC_Think (prvm_edict_t *ed);//csprogs.c -void VM_R_AddEntities (void) +static void VM_CL_R_AddEntities (void) { int i, drawmask; prvm_edict_t *ed; - VM_SAFEPARMCOUNT(1, VM_R_AddEntities); + VM_SAFEPARMCOUNT(1, VM_CL_R_AddEntities); drawmask = (int)PRVM_G_FLOAT(OFS_PARM0); CSQC_RelinkAllEntities(drawmask); CL_RelinkLightFlashes(); @@ -619,21 +660,20 @@ void VM_R_AddEntities (void) } //#302 void(entity ent) addentity (EXT_CSQC) -void VM_R_AddEntity (void) +static void VM_CL_R_AddEntity (void) { - VM_SAFEPARMCOUNT(1, VM_R_AddEntity); + VM_SAFEPARMCOUNT(1, VM_CL_R_AddEntity); CSQC_AddRenderEdict(PRVM_G_EDICT(OFS_PARM0)); } //#303 float(float property, ...) setproperty (EXT_CSQC) -void VM_R_SetView (void) +static void VM_CL_R_SetView (void) { int c; float *f; float k; - if(prog->argc < 2) - VM_SAFEPARMCOUNT(2, VM_R_SetView); + VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_R_SetView); c = (int)PRVM_G_FLOAT(OFS_PARM0); f = PRVM_G_VECTOR(OFS_PARM1); @@ -712,7 +752,7 @@ void VM_R_SetView (void) break; default: PRVM_G_FLOAT(OFS_RETURN) = 0; - VM_Warning("VM_R_SetView : unknown parm %i\n", c); + VM_Warning("VM_CL_R_SetView : unknown parm %i\n", c); return; } PRVM_G_FLOAT(OFS_RETURN) = 1; @@ -720,10 +760,10 @@ void VM_R_SetView (void) extern void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit); //#304 void() renderscene (EXT_CSQC) -void VM_R_RenderScene (void) //#134 +static void VM_CL_R_RenderScene (void) { int i; - VM_SAFEPARMCOUNT(0, VM_R_RenderScene); + VM_SAFEPARMCOUNT(0, VM_CL_R_RenderScene); // we need to update any RENDER_VIEWMODEL entities at this point because // csqc supplies its own view matrix for (i = 1;i < cl.num_entities;i++) @@ -742,11 +782,11 @@ void VM_R_RenderScene (void) //#134 } //#305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC) -void VM_R_AddDynamicLight (void) +static void VM_CL_R_AddDynamicLight (void) { float *pos, *col; matrix4x4_t matrix; - VM_SAFEPARMCOUNT(3, VM_R_AddDynamicLight); + VM_SAFEPARMCOUNTRANGE(3, 8, VM_CL_R_AddDynamicLight); // allow more than 3 because we may extend this in the future // if we've run out of dlights, just return if (r_refdef.numlights >= MAX_DLIGHTS) @@ -761,7 +801,7 @@ void VM_R_AddDynamicLight (void) //============================================================================ //#310 vector (vector v) cs_unproject (EXT_CSQC) -void VM_CL_unproject (void) +static void VM_CL_unproject (void) { float *f; vec3_t temp; @@ -773,7 +813,7 @@ void VM_CL_unproject (void) } //#311 vector (vector v) cs_project (EXT_CSQC) -void VM_CL_project (void) +static void VM_CL_project (void) { float *f; vec3_t v; @@ -787,7 +827,7 @@ void VM_CL_project (void) } //#330 float(float stnum) getstatf (EXT_CSQC) -void VM_CL_getstatf (void) +static void VM_CL_getstatf (void) { int i; union @@ -807,7 +847,7 @@ void VM_CL_getstatf (void) } //#331 float(float stnum) getstati (EXT_CSQC) -void VM_CL_getstati (void) +static void VM_CL_getstati (void) { int i, index; VM_SAFEPARMCOUNT(1, VM_CL_getstati); @@ -823,7 +863,7 @@ void VM_CL_getstati (void) } //#332 string(float firststnum) getstats (EXT_CSQC) -void VM_CL_getstats (void) +static void VM_CL_getstats (void) { int i; char t[17]; @@ -840,7 +880,7 @@ void VM_CL_getstats (void) } //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC) -void VM_CL_setmodelindex (void) +static void VM_CL_setmodelindex (void) { int i; prvm_edict_t *t; @@ -858,7 +898,7 @@ void VM_CL_setmodelindex (void) if (!i) return; - model = CSQC_GetModelByIndex(i); + model = CL_GetModelByIndex(i); if (!model) { VM_Warning("VM_CL_setmodelindex: null model\n"); @@ -869,19 +909,19 @@ void VM_CL_setmodelindex (void) } //#334 string(float mdlindex) modelnameforindex (EXT_CSQC) -void VM_CL_modelnameforindex (void) +static void VM_CL_modelnameforindex (void) { model_t *model; VM_SAFEPARMCOUNT(1, VM_CL_modelnameforindex); PRVM_G_INT(OFS_RETURN) = OFS_NULL; - model = CSQC_GetModelByIndex((int)PRVM_G_FLOAT(OFS_PARM0)); + model = CL_GetModelByIndex((int)PRVM_G_FLOAT(OFS_PARM0)); PRVM_G_INT(OFS_RETURN) = model ? PRVM_SetEngineString(model->name) : 0; } //#335 float(string effectname) particleeffectnum (EXT_CSQC) -void VM_CL_particleeffectnum (void) +static void VM_CL_particleeffectnum (void) { int i; VM_SAFEPARMCOUNT(1, VM_CL_particleeffectnum); @@ -892,53 +932,43 @@ void VM_CL_particleeffectnum (void) } // #336 void(entity ent, float effectnum, vector start, vector end[, float color]) trailparticles (EXT_CSQC) -void VM_CL_trailparticles (void) +static void VM_CL_trailparticles (void) { int i; float *start, *end; prvm_edict_t *t; - VM_SAFEPARMCOUNT(4, VM_CL_trailparticles); + VM_SAFEPARMCOUNTRANGE(4, 5, VM_CL_trailparticles); t = PRVM_G_EDICT(OFS_PARM0); i = (int)PRVM_G_FLOAT(OFS_PARM1); start = PRVM_G_VECTOR(OFS_PARM2); end = PRVM_G_VECTOR(OFS_PARM3); - CL_ParticleEffect(i, VectorDistance(start, end), start, end, t->fields.client->velocity, t->fields.client->velocity, NULL, (int)PRVM_G_FLOAT(OFS_PARM4)); + CL_ParticleEffect(i, VectorDistance(start, end), start, end, t->fields.client->velocity, t->fields.client->velocity, NULL, prog->argc >= 5 ? (int)PRVM_G_FLOAT(OFS_PARM4) : 0); } -//#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC) -void VM_CL_pointparticles (void) +//#337 void(float effectnum, vector origin, vector dir, float count[, float color]) pointparticles (EXT_CSQC) +static void VM_CL_pointparticles (void) { int i, n; float *f, *v; - VM_SAFEPARMCOUNT(4, VM_CL_pointparticles); + VM_SAFEPARMCOUNTRANGE(4, 5, VM_CL_pointparticles); i = (int)PRVM_G_FLOAT(OFS_PARM0); f = PRVM_G_VECTOR(OFS_PARM1); v = PRVM_G_VECTOR(OFS_PARM2); n = (int)PRVM_G_FLOAT(OFS_PARM3); - CL_ParticleEffect(i, n, f, f, v, v, NULL, 0); -} - -//#338 void(string s) cprint (EXT_CSQC) -void VM_CL_centerprint (void) -{ - char s[VM_STRINGTEMP_LENGTH]; - if(prog->argc < 1) - VM_SAFEPARMCOUNT(1, VM_CL_centerprint); - VM_VarString(0, s, sizeof(s)); - SCR_CenterPrint(s); + CL_ParticleEffect(i, n, f, f, v, v, NULL, prog->argc >= 5 ? (int)PRVM_G_FLOAT(OFS_PARM4) : 0); } //#342 string(float keynum) getkeybind (EXT_CSQC) -void VM_CL_getkeybind (void) +static void VM_CL_getkeybind (void) { VM_SAFEPARMCOUNT(1, VM_CL_getkeybind); PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(Key_GetBind((int)PRVM_G_FLOAT(OFS_PARM0))); } //#343 void(float usecursor) setcursormode (EXT_CSQC) -void VM_CL_setcursormode (void) +static void VM_CL_setcursormode (void) { VM_SAFEPARMCOUNT(1, VM_CL_setcursormode); cl.csqc_wantsmousemove = PRVM_G_FLOAT(OFS_PARM0); @@ -946,7 +976,7 @@ void VM_CL_setcursormode (void) } //#345 float(float framenum) getinputstate (EXT_CSQC) -void VM_CL_getinputstate (void) +static void VM_CL_getinputstate (void) { int i, frame; VM_SAFEPARMCOUNT(1, VM_CL_getinputstate); @@ -972,19 +1002,19 @@ void VM_CL_getinputstate (void) } //#346 void(float sens) setsensitivityscaler (EXT_CSQC) -void VM_CL_setsensitivityscale (void) +static void VM_CL_setsensitivityscale (void) { VM_SAFEPARMCOUNT(1, VM_CL_setsensitivityscale); cl.sensitivityscale = PRVM_G_FLOAT(OFS_PARM0); } //#347 void() runstandardplayerphysics (EXT_CSQC) -void VM_CL_runplayerphysics (void) +static void VM_CL_runplayerphysics (void) { } //#348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC) -void VM_CL_getplayerkey (void) +static void VM_CL_getplayerkey (void) { int i; char t[128]; @@ -1032,13 +1062,14 @@ void VM_CL_getplayerkey (void) } //#349 float() isdemo (EXT_CSQC) -void VM_CL_isdemo (void) +static void VM_CL_isdemo (void) { + VM_SAFEPARMCOUNT(0, VM_CL_isdemo); PRVM_G_FLOAT(OFS_RETURN) = cls.demoplayback; } //#351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC) -void VM_CL_setlistener (void) +static void VM_CL_setlistener (void) { VM_SAFEPARMCOUNT(4, VM_CL_setlistener); Matrix4x4_FromVectors(&csqc_listenermatrix, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), PRVM_G_VECTOR(OFS_PARM3), PRVM_G_VECTOR(OFS_PARM0)); @@ -1046,7 +1077,7 @@ void VM_CL_setlistener (void) } //#352 void(string cmdname) registercommand (EXT_CSQC) -void VM_CL_registercmd (void) +static void VM_CL_registercmd (void) { char *t; VM_SAFEPARMCOUNT(1, VM_CL_registercmd); @@ -1064,84 +1095,190 @@ void VM_CL_registercmd (void) } -//#354 float() playernum (EXT_CSQC) -void VM_CL_playernum (void) -{ - int i, k; - - VM_SAFEPARMCOUNT(0, VM_CL_playernum); - - for(i=k=0 ; iedicts) + { + VM_Warning("makestatic: can not modify world entity\n"); + return; + } + if (ent->priv.server->free) + { + VM_Warning("makestatic: can not modify free entity\n"); + return; + } + + if (cl.num_static_entities < cl.max_static_entities) + { + int renderflags; + prvm_eval_t *val; + entity_t *staticent = &cl.static_entities[cl.num_static_entities++]; + + // copy it to the current state + staticent->render.model = CL_GetModelByIndex((int)ent->fields.client->modelindex); + staticent->render.frame = staticent->render.frame1 = staticent->render.frame2 = (int)ent->fields.client->frame; + staticent->render.framelerp = 0; + // make torchs play out of sync + staticent->render.frame1time = staticent->render.frame2time = lhrandom(-10, -1); + staticent->render.colormap = (int)ent->fields.client->colormap; // no special coloring + staticent->render.skinnum = (int)ent->fields.client->skin; + staticent->render.effects = (int)ent->fields.client->effects; + staticent->render.alpha = 1; + if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.alpha)) && val->_float) staticent->render.alpha = val->_float; + staticent->render.scale = 1; + if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale)) && val->_float) staticent->render.scale = val->_float; + if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.colormod)) && VectorLength2(val->vector)) VectorCopy(val->vector, staticent->render.colormod); + + renderflags = 0; + if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.renderflags)) && val->_float) renderflags = (int)val->_float; + if (renderflags & RF_USEAXIS) + { + vec3_t left; + VectorNegate(prog->globals.client->v_right, left); + Matrix4x4_FromVectors(&staticent->render.matrix, prog->globals.client->v_forward, left, prog->globals.client->v_up, ent->fields.client->origin); + Matrix4x4_Scale(&staticent->render.matrix, staticent->render.scale, 1); + } + else + Matrix4x4_CreateFromQuakeEntity(&staticent->render.matrix, ent->fields.client->origin[0], ent->fields.client->origin[1], ent->fields.client->origin[2], ent->fields.client->angles[0], ent->fields.client->angles[1], ent->fields.client->angles[2], staticent->render.scale); + CL_UpdateRenderEntity(&staticent->render); + + // transparent stuff can't be lit during the opaque stage + if (staticent->render.effects & (EF_ADDITIVE | EF_NODEPTHTEST) || staticent->render.alpha < 1) + staticent->render.flags |= RENDER_TRANSPARENT; + // double sided rendering mode causes backfaces to be visible + // (mostly useful on transparent stuff) + if (staticent->render.effects & EF_DOUBLESIDED) + staticent->render.flags |= RENDER_NOCULLFACE; + // either fullbright or lit + if (!(staticent->render.effects & EF_FULLBRIGHT) && !r_fullbright.integer) + staticent->render.flags |= RENDER_LIGHT; + // turn off shadows from transparent objects + if (!(staticent->render.effects & EF_NOSHADOW) + && !(staticent->render.flags & RENDER_TRANSPARENT)) + staticent->render.flags |= RENDER_SHADOW; + } + else + Con_Printf("Too many static entities"); + +// throw the entity away now + PRVM_ED_Free (ent); +} + +//=================================================================// + +/* +================= +VM_CL_copyentity + +copies data from one entity to another + +copyentity(src, dst) +================= +*/ +static void VM_CL_copyentity (void) +{ + prvm_edict_t *in, *out; + VM_SAFEPARMCOUNT(2, VM_CL_copyentity); + in = PRVM_G_EDICT(OFS_PARM0); + if (in == prog->edicts) + { + VM_Warning("copyentity: can not read world entity\n"); + return; + } + if (in->priv.server->free) + { + VM_Warning("copyentity: can not read free entity\n"); + return; + } + out = PRVM_G_EDICT(OFS_PARM1); + if (out == prog->edicts) + { + VM_Warning("copyentity: can not modify world entity\n"); + return; + } + if (out->priv.server->free) + { + VM_Warning("copyentity: can not modify free entity\n"); + return; + } + memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4); + CL_LinkEdict(out); +} + //=================================================================// // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT) -void VM_CL_effect (void) +static void VM_CL_effect (void) { VM_SAFEPARMCOUNT(5, VM_CL_effect); CL_Effect(PRVM_G_VECTOR(OFS_PARM0), (int)PRVM_G_FLOAT(OFS_PARM1), (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4)); } // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD) -void VM_CL_te_blood (void) +static void VM_CL_te_blood (void) { float *pos; vec3_t pos2; @@ -1154,7 +1291,7 @@ void VM_CL_te_blood (void) } // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER) -void VM_CL_te_bloodshower (void) +static void VM_CL_te_bloodshower (void) { vec_t speed; vec3_t vel1, vel2; @@ -1172,7 +1309,7 @@ void VM_CL_te_bloodshower (void) } // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB) -void VM_CL_te_explosionrgb (void) +static void VM_CL_te_explosionrgb (void) { float *pos; vec3_t pos2; @@ -1186,28 +1323,28 @@ void VM_CL_te_explosionrgb (void) } // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE) -void VM_CL_te_particlecube (void) +static void VM_CL_te_particlecube (void) { VM_SAFEPARMCOUNT(7, VM_CL_te_particlecube); CL_ParticleCube(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), PRVM_G_FLOAT(OFS_PARM5), PRVM_G_FLOAT(OFS_PARM6)); } // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN) -void VM_CL_te_particlerain (void) +static void VM_CL_te_particlerain (void) { VM_SAFEPARMCOUNT(5, VM_CL_te_particlerain); CL_ParticleRain(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), 0); } // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW) -void VM_CL_te_particlesnow (void) +static void VM_CL_te_particlesnow (void) { VM_SAFEPARMCOUNT(5, VM_CL_te_particlesnow); CL_ParticleRain(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), 1); } // #411 void(vector org, vector vel, float howmany) te_spark -void VM_CL_te_spark (void) +static void VM_CL_te_spark (void) { float *pos; vec3_t pos2; @@ -1219,7 +1356,7 @@ void VM_CL_te_spark (void) } // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1) -void VM_CL_te_gunshotquad (void) +static void VM_CL_te_gunshotquad (void) { float *pos; vec3_t pos2; @@ -1231,7 +1368,7 @@ void VM_CL_te_gunshotquad (void) } // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1) -void VM_CL_te_spikequad (void) +static void VM_CL_te_spikequad (void) { float *pos; vec3_t pos2; @@ -1252,7 +1389,7 @@ void VM_CL_te_spikequad (void) } // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1) -void VM_CL_te_superspikequad (void) +static void VM_CL_te_superspikequad (void) { float *pos; vec3_t pos2; @@ -1273,7 +1410,7 @@ void VM_CL_te_superspikequad (void) } // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1) -void VM_CL_te_explosionquad (void) +static void VM_CL_te_explosionquad (void) { float *pos; vec3_t pos2; @@ -1286,7 +1423,7 @@ void VM_CL_te_explosionquad (void) } // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH) -void VM_CL_te_smallflash (void) +static void VM_CL_te_smallflash (void) { float *pos; vec3_t pos2; @@ -1298,7 +1435,7 @@ void VM_CL_te_smallflash (void) } // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH) -void VM_CL_te_customflash (void) +static void VM_CL_te_customflash (void) { float *pos; vec3_t pos2; @@ -1312,7 +1449,7 @@ void VM_CL_te_customflash (void) } // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS) -void VM_CL_te_gunshot (void) +static void VM_CL_te_gunshot (void) { float *pos; vec3_t pos2; @@ -1324,7 +1461,7 @@ void VM_CL_te_gunshot (void) } // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS) -void VM_CL_te_spike (void) +static void VM_CL_te_spike (void) { float *pos; vec3_t pos2; @@ -1345,7 +1482,7 @@ void VM_CL_te_spike (void) } // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS) -void VM_CL_te_superspike (void) +static void VM_CL_te_superspike (void) { float *pos; vec3_t pos2; @@ -1366,7 +1503,7 @@ void VM_CL_te_superspike (void) } // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS) -void VM_CL_te_explosion (void) +static void VM_CL_te_explosion (void) { float *pos; vec3_t pos2; @@ -1379,7 +1516,7 @@ void VM_CL_te_explosion (void) } // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS) -void VM_CL_te_tarexplosion (void) +static void VM_CL_te_tarexplosion (void) { float *pos; vec3_t pos2; @@ -1392,7 +1529,7 @@ void VM_CL_te_tarexplosion (void) } // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS) -void VM_CL_te_wizspike (void) +static void VM_CL_te_wizspike (void) { float *pos; vec3_t pos2; @@ -1405,7 +1542,7 @@ void VM_CL_te_wizspike (void) } // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS) -void VM_CL_te_knightspike (void) +static void VM_CL_te_knightspike (void) { float *pos; vec3_t pos2; @@ -1418,21 +1555,21 @@ void VM_CL_te_knightspike (void) } // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS) -void VM_CL_te_lavasplash (void) +static void VM_CL_te_lavasplash (void) { VM_SAFEPARMCOUNT(1, VM_CL_te_lavasplash); CL_ParticleEffect(EFFECT_TE_LAVASPLASH, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0); } // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS) -void VM_CL_te_teleport (void) +static void VM_CL_te_teleport (void) { VM_SAFEPARMCOUNT(1, VM_CL_te_teleport); CL_ParticleEffect(EFFECT_TE_TELEPORT, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0); } // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS) -void VM_CL_te_explosion2 (void) +static void VM_CL_te_explosion2 (void) { float *pos; vec3_t pos2, color; @@ -1457,35 +1594,35 @@ void VM_CL_te_explosion2 (void) // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS) -void VM_CL_te_lightning1 (void) +static void VM_CL_te_lightning1 (void) { VM_SAFEPARMCOUNT(3, VM_CL_te_lightning1); CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt, true); } // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS) -void VM_CL_te_lightning2 (void) +static void VM_CL_te_lightning2 (void) { VM_SAFEPARMCOUNT(3, VM_CL_te_lightning2); CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt2, true); } // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS) -void VM_CL_te_lightning3 (void) +static void VM_CL_te_lightning3 (void) { VM_SAFEPARMCOUNT(3, VM_CL_te_lightning3); CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt3, false); } // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS) -void VM_CL_te_beam (void) +static void VM_CL_te_beam (void) { VM_SAFEPARMCOUNT(3, VM_CL_te_beam); CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_beam, false); } // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN) -void VM_CL_te_plasmaburn (void) +static void VM_CL_te_plasmaburn (void) { float *pos; vec3_t pos2; @@ -1496,6 +1633,19 @@ void VM_CL_te_plasmaburn (void) CL_ParticleEffect(EFFECT_TE_PLASMABURN, 1, pos2, pos2, vec3_origin, vec3_origin, NULL, 0); } +// #457 void(vector org, vector velocity, float howmany) te_flamejet (DP_TE_FLAMEJET) +static void VM_CL_te_flamejet (void) +{ + float *pos; + vec3_t pos2; + VM_SAFEPARMCOUNT(3, VM_CL_te_flamejet); + if (PRVM_G_FLOAT(OFS_PARM2) < 1) + return; + pos = PRVM_G_VECTOR(OFS_PARM0); + CL_FindNonSolidLocation(pos, pos2, 4); + CL_ParticleEffect(EFFECT_TE_FLAMEJET, PRVM_G_FLOAT(OFS_PARM2), pos2, pos2, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM1), NULL, 0); +} + //==================================================================== //DP_QC_GETSURFACE @@ -1510,12 +1660,13 @@ static msurface_t *cl_getsurface(model_t *model, int surfacenum) } // #434 float(entity e, float s) getsurfacenumpoints -void VM_CL_getsurfacenumpoints(void) +static void VM_CL_getsurfacenumpoints(void) { - model_t *model = CSQC_GetModelFromEntity(PRVM_G_EDICT(OFS_PARM0)); + model_t *model; msurface_t *surface; + VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenumpoints); // return 0 if no such surface - if (!model || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) + if (!(model = CL_GetModelFromEdict(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) { PRVM_G_FLOAT(OFS_RETURN) = 0; return; @@ -1526,15 +1677,16 @@ void VM_CL_getsurfacenumpoints(void) } // #435 vector(entity e, float s, float n) getsurfacepoint -void VM_CL_getsurfacepoint(void) +static void VM_CL_getsurfacepoint(void) { prvm_edict_t *ed; model_t *model; msurface_t *surface; int pointnum; + VM_SAFEPARMCOUNT(3, VM_CL_getsurfacenumpoints); VectorClear(PRVM_G_VECTOR(OFS_RETURN)); ed = PRVM_G_EDICT(OFS_PARM0); - if (!(model = CSQC_GetModelFromEntity(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) + if (!(model = CL_GetModelFromEdict(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) return; // note: this (incorrectly) assumes it is a simple polygon pointnum = (int)PRVM_G_FLOAT(OFS_PARM2); @@ -1545,13 +1697,14 @@ void VM_CL_getsurfacepoint(void) } // #436 vector(entity e, float s) getsurfacenormal -void VM_CL_getsurfacenormal(void) +static void VM_CL_getsurfacenormal(void) { model_t *model; msurface_t *surface; vec3_t normal; + VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenormal); VectorClear(PRVM_G_VECTOR(OFS_RETURN)); - if (!(model = CSQC_GetModelFromEntity(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) + if (!(model = CL_GetModelFromEdict(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) return; // FIXME: implement rotation/scaling // note: this (incorrectly) assumes it is a simple polygon @@ -1563,18 +1716,19 @@ void VM_CL_getsurfacenormal(void) } // #437 string(entity e, float s) getsurfacetexture -void VM_CL_getsurfacetexture(void) +static void VM_CL_getsurfacetexture(void) { model_t *model; msurface_t *surface; + VM_SAFEPARMCOUNT(2, VM_CL_getsurfacetexture); PRVM_G_INT(OFS_RETURN) = OFS_NULL; - if (!(model = CSQC_GetModelFromEntity(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) + if (!(model = CL_GetModelFromEdict(PRVM_G_EDICT(OFS_PARM0))) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) return; PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name); } // #438 float(entity e, vector p) getsurfacenearpoint -void VM_CL_getsurfacenearpoint(void) +static void VM_CL_getsurfacenearpoint(void) { int surfacenum, best; vec3_t clipped, p; @@ -1583,9 +1737,10 @@ void VM_CL_getsurfacenearpoint(void) model_t *model = NULL; msurface_t *surface; vec_t *point; + VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenearpoint); PRVM_G_FLOAT(OFS_RETURN) = -1; ed = PRVM_G_EDICT(OFS_PARM0); - if(!(model = CSQC_GetModelFromEntity(ed)) || !model->num_surfaces) + if(!(model = CL_GetModelFromEdict(ed)) || !model->num_surfaces) return; // FIXME: implement rotation/scaling @@ -1619,15 +1774,16 @@ void VM_CL_getsurfacenearpoint(void) } // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint -void VM_CL_getsurfaceclippedpoint(void) +static void VM_CL_getsurfaceclippedpoint(void) { prvm_edict_t *ed; model_t *model; msurface_t *surface; vec3_t p, out; + VM_SAFEPARMCOUNT(3, VM_CL_getsurfaceclippedpoint); VectorClear(PRVM_G_VECTOR(OFS_RETURN)); ed = PRVM_G_EDICT(OFS_PARM0); - if (!(model = CSQC_GetModelFromEntity(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) + if (!(model = CL_GetModelFromEdict(ed)) || !(surface = cl_getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) return; // FIXME: implement rotation/scaling VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.client->origin, p); @@ -1637,14 +1793,19 @@ void VM_CL_getsurfaceclippedpoint(void) } // #443 void(entity e, entity tagentity, string tagname) setattachment -void VM_CL_setattachment (void) +static void VM_CL_setattachment (void) { - 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); + prvm_edict_t *e; + prvm_edict_t *tagentity; + const char *tagname; prvm_eval_t *v; int modelindex; model_t *model; + VM_SAFEPARMCOUNT(3, VM_CL_setattachment); + + e = PRVM_G_EDICT(OFS_PARM0); + tagentity = PRVM_G_EDICT(OFS_PARM1); + tagname = PRVM_G_STRING(OFS_PARM2); if (e == prog->edicts) { @@ -1670,7 +1831,7 @@ void VM_CL_setattachment (void) if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0]) { modelindex = (int)tagentity->fields.client->modelindex; - model = CSQC_GetModelByIndex(modelindex); + model = CL_GetModelByIndex(modelindex); if (model) { v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.client->skin, tagname); @@ -1687,7 +1848,7 @@ void VM_CL_setattachment (void) int CL_GetTagIndex (prvm_edict_t *e, const char *tagname) { - model_t *model = CSQC_GetModelFromEntity(e); + model_t *model = CL_GetModelFromEdict(e); if (model) return Mod_Alias_GetTagIndexForName(model, (int)e->fields.client->skin, tagname); else @@ -1719,7 +1880,7 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex) if (ent->priv.server->free) return 2; - model = CSQC_GetModelFromEntity(ent); + model = CL_GetModelFromEdict(ent); if(!model) return 3; @@ -1747,7 +1908,7 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex) attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index); - model = CSQC_GetModelFromEntity(attachent); + model = CL_GetModelFromEdict(attachent); if (model && val->_float >= 1 && model->animscenes && attachent->fields.client->frame >= 0 && attachent->fields.client->frame < model->numframes) Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.client->frame].firstframe, (int)val->_float - 1, &attachmatrix); @@ -1820,12 +1981,16 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex) } // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO) -void VM_CL_gettagindex (void) +static void VM_CL_gettagindex (void) { - prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0); - const char *tag_name = PRVM_G_STRING(OFS_PARM1); + prvm_edict_t *ent; + const char *tag_name; int modelindex, tag_index; + VM_SAFEPARMCOUNT(2, VM_CL_gettagindex); + + ent = PRVM_G_EDICT(OFS_PARM0); + tag_name = PRVM_G_STRING(OFS_PARM1); if (ent == prog->edicts) { VM_Warning("gettagindex: can't affect world entity\n"); @@ -1853,13 +2018,17 @@ void VM_CL_gettagindex (void) } // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO) -void VM_CL_gettaginfo (void) +static void VM_CL_gettaginfo (void) { - prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0); - int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1); + prvm_edict_t *e; + int tagindex; matrix4x4_t tag_matrix; int returncode; + VM_SAFEPARMCOUNT(2, VM_CL_gettaginfo); + + e = PRVM_G_EDICT(OFS_PARM0); + tagindex = (int)PRVM_G_FLOAT(OFS_PARM1); returncode = CL_GetTagMatrix(&tag_matrix, e, tagindex); Matrix4x4_ToVectors(&tag_matrix, prog->globals.client->v_forward, prog->globals.client->v_right, prog->globals.client->v_up, PRVM_G_VECTOR(OFS_RETURN)); @@ -1883,451 +2052,1037 @@ void VM_CL_gettaginfo (void) } } -//================================================= -//[515]: here goes test/unfinished/etc. +//============================================================================ + +//==================== +//QC POLYGON functions +//==================== -//[515]: check if it is what it should be -void VM_WasFreed (void) +typedef struct { - prvm_edict_t *e; - VM_SAFEPARMCOUNT(1, VM_WasFreed); + rtexture_t *tex; + float data[36]; //[515]: enough for polygons + unsigned char flags; //[515]: + VM_POLYGON_2D and VM_POLYGON_FL4V flags +}vm_polygon_t; - e = PRVM_G_EDICT(OFS_PARM0); - if (!e->priv.required->free || (e->priv.required->free && (e->priv.required->freetime < 2 || (prog->globals.client->time - e->priv.required->freetime) > 0.5 ))) - PRVM_G_FLOAT(OFS_RETURN) = false; +//static float vm_polygon_linewidth = 1; +static mempool_t *vm_polygons_pool = NULL; +static unsigned char vm_current_vertices = 0; +static qboolean vm_polygons_initialized = false; +static vm_polygon_t *vm_polygons = NULL; +static unsigned long vm_polygons_num = 0, vm_drawpolygons_num = 0; //[515]: ok long on 64bit ? +static qboolean vm_polygonbegin = false; //[515]: for "no-crap-on-the-screen" check +#define VM_DEFPOLYNUM 64 //[515]: enough for default ? + +#define VM_POLYGON_FL3V 16 //more than 2 vertices (used only for lines) +#define VM_POLYGON_FLLINES 32 +#define VM_POLYGON_FL2D 64 +#define VM_POLYGON_FL4V 128 //4 vertices + +static void VM_InitPolygons (void) +{ + vm_polygons_pool = Mem_AllocPool("VMPOLY", 0, NULL); + vm_polygons = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, VM_DEFPOLYNUM*sizeof(vm_polygon_t)); + memset(vm_polygons, 0, VM_DEFPOLYNUM*sizeof(vm_polygon_t)); + vm_polygons_num = VM_DEFPOLYNUM; + vm_drawpolygons_num = 0; + vm_polygonbegin = false; + vm_polygons_initialized = true; +} + +static void VM_DrawPolygonCallback (const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) +{ + int surfacelistindex; + // LordHavoc: FIXME: this is stupid code + for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++) + { + const vm_polygon_t *p = &vm_polygons[surfacelist[surfacelistindex]]; + int flags = p->flags & 0x0f; + + if(flags == DRAWFLAG_ADDITIVE) + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + else if(flags == DRAWFLAG_MODULATE) + GL_BlendFunc(GL_DST_COLOR, GL_ZERO); + else if(flags == DRAWFLAG_2XMODULATE) + GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR); + else + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + R_Mesh_TexBind(0, R_GetTexture(p->tex)); + + CHECKGLERROR + //[515]: is speed is max ? + if(p->flags & VM_POLYGON_FLLINES) //[515]: lines + { + qglLineWidth(p->data[13]);CHECKGLERROR + qglBegin(GL_LINE_LOOP); + qglTexCoord1f (p->data[12]); + qglColor4f (p->data[20], p->data[21], p->data[22], p->data[23]); + qglVertex3f (p->data[0] , p->data[1], p->data[2]); + + qglTexCoord1f (p->data[14]); + qglColor4f (p->data[24], p->data[25], p->data[26], p->data[27]); + qglVertex3f (p->data[3] , p->data[4], p->data[5]); + + if(p->flags & VM_POLYGON_FL3V) + { + qglTexCoord1f (p->data[16]); + qglColor4f (p->data[28], p->data[29], p->data[30], p->data[31]); + qglVertex3f (p->data[6] , p->data[7], p->data[8]); + + if(p->flags & VM_POLYGON_FL4V) + { + qglTexCoord1f (p->data[18]); + qglColor4f (p->data[32], p->data[33], p->data[34], p->data[35]); + qglVertex3f (p->data[9] , p->data[10], p->data[11]); + } + } + qglEnd(); + CHECKGLERROR + } + else + { + qglBegin(GL_POLYGON); + qglTexCoord2f (p->data[12], p->data[13]); + qglColor4f (p->data[20], p->data[21], p->data[22], p->data[23]); + qglVertex3f (p->data[0] , p->data[1], p->data[2]); + + qglTexCoord2f (p->data[14], p->data[15]); + qglColor4f (p->data[24], p->data[25], p->data[26], p->data[27]); + qglVertex3f (p->data[3] , p->data[4], p->data[5]); + + qglTexCoord2f (p->data[16], p->data[17]); + qglColor4f (p->data[28], p->data[29], p->data[30], p->data[31]); + qglVertex3f (p->data[6] , p->data[7], p->data[8]); + + if(p->flags & VM_POLYGON_FL4V) + { + qglTexCoord2f (p->data[18], p->data[19]); + qglColor4f (p->data[32], p->data[33], p->data[34], p->data[35]); + qglVertex3f (p->data[9] , p->data[10], p->data[11]); + } + qglEnd(); + CHECKGLERROR + } + } +} + +static void VM_CL_AddPolygonTo2DScene (vm_polygon_t *p) +{ + drawqueuemesh_t mesh; + static int picelements[6] = {0, 1, 2, 0, 2, 3}; + + mesh.texture = p->tex; + mesh.data_element3i = picelements; + mesh.data_vertex3f = p->data; + mesh.data_texcoord2f = p->data + 12; + mesh.data_color4f = p->data + 20; + if(p->flags & VM_POLYGON_FL4V) + { + mesh.num_vertices = 4; + mesh.num_triangles = 2; + } else - PRVM_G_FLOAT(OFS_RETURN) = true; + { + mesh.num_vertices = 3; + mesh.num_triangles = 1; + } + if(p->flags & VM_POLYGON_FLLINES) //[515]: lines + DrawQ_LineLoop (&mesh, (p->flags&0x0f)); + else + DrawQ_Mesh (&mesh, (p->flags&0x0f)); } -void VM_CL_select_cube (void) +void VM_CL_AddPolygonsToMeshQueue (void) { - int i; - float *mins2, *maxs2; - prvm_edict_t *ent, *chain; - vec3_t mins1, maxs1; + int i; + if(!vm_drawpolygons_num) + return; + R_Mesh_Matrix(&identitymatrix); + GL_CullFace(GL_NONE); + for(i = 0;i < (int)vm_drawpolygons_num;i++) + VM_DrawPolygonCallback(NULL, NULL, 1, &i); + vm_drawpolygons_num = 0; +} - VM_SAFEPARMCOUNT(2, VM_CL_select_cube); +//void(string texturename, float flag[, float 2d[, float lines]]) R_BeginPolygon +static void VM_CL_R_PolygonBegin (void) +{ + vm_polygon_t *p; + const char *picname; + VM_SAFEPARMCOUNTRANGE(2, 4, VM_CL_R_PolygonBegin); - if (prog->fieldoffsets.chain < 0) - PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME); + if(!vm_polygons_initialized) + VM_InitPolygons(); + if(vm_polygonbegin) + { + VM_Warning("VM_CL_R_PolygonBegin: called twice without VM_CL_R_PolygonEnd after first\n"); + return; + } + if(vm_drawpolygons_num >= vm_polygons_num) + { + p = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, 2 * vm_polygons_num * sizeof(vm_polygon_t)); + memset(p, 0, 2 * vm_polygons_num * sizeof(vm_polygon_t)); + memcpy(p, vm_polygons, vm_polygons_num * sizeof(vm_polygon_t)); + Mem_Free(vm_polygons); + vm_polygons = p; + vm_polygons_num *= 2; + } + p = &vm_polygons[vm_drawpolygons_num]; + picname = PRVM_G_STRING(OFS_PARM0); + if(picname[0]) + p->tex = Draw_CachePic(picname, true)->tex; + else + p->tex = r_texture_white; + p->flags = (unsigned char)PRVM_G_FLOAT(OFS_PARM1); + vm_current_vertices = 0; + vm_polygonbegin = true; + if(prog->argc >= 3) + { + if(PRVM_G_FLOAT(OFS_PARM2)) + p->flags |= VM_POLYGON_FL2D; + if(prog->argc >= 4 && PRVM_G_FLOAT(OFS_PARM3)) + { + p->data[13] = PRVM_G_FLOAT(OFS_PARM3); //[515]: linewidth + p->flags |= VM_POLYGON_FLLINES; + } + } +} - chain = prog->edicts; +//void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex +static void VM_CL_R_PolygonVertex (void) +{ + float *coords, *tx, *rgb, alpha; + vm_polygon_t *p; + VM_SAFEPARMCOUNT(4, VM_CL_R_PolygonVertex); - mins2 = PRVM_G_VECTOR(OFS_PARM0); - maxs2 = PRVM_G_VECTOR(OFS_PARM1); + if(!vm_polygonbegin) + { + VM_Warning("VM_CL_R_PolygonVertex: VM_CL_R_PolygonBegin wasn't called\n"); + return; + } + coords = PRVM_G_VECTOR(OFS_PARM0); + tx = PRVM_G_VECTOR(OFS_PARM1); + rgb = PRVM_G_VECTOR(OFS_PARM2); + alpha = PRVM_G_FLOAT(OFS_PARM3); - ent = PRVM_NEXT_EDICT(prog->edicts); - for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent)) + p = &vm_polygons[vm_drawpolygons_num]; + if(vm_current_vertices > 4) { - if (ent->priv.required->free) - continue; - VectorCopy(ent->fields.client->origin, mins1); - VectorAdd(mins1, ent->fields.client->maxs, maxs1); - VectorAdd(mins1, ent->fields.client->mins, mins1); - if (mins1[0] > maxs2[0] || mins1[1] > maxs2[1] || mins1[2] > maxs2[2]) - continue; - if (maxs1[0] < mins2[0] || maxs1[1] < mins2[1] || maxs1[2] < mins2[2]) - continue; - PRVM_EDICTFIELDVALUE(ent,prog->fieldoffsets.chain)->edict = PRVM_NUM_FOR_EDICT(chain); - chain = ent; + VM_Warning("VM_CL_R_PolygonVertex: may have 4 vertices max\n"); + return; } - VM_RETURN_EDICT(chain); + p->data[vm_current_vertices*3] = coords[0]; + p->data[1+vm_current_vertices*3] = coords[1]; + p->data[2+vm_current_vertices*3] = coords[2]; + + p->data[12+vm_current_vertices*2] = tx[0]; + if(!(p->flags & VM_POLYGON_FLLINES)) + p->data[13+vm_current_vertices*2] = tx[1]; + + p->data[20+vm_current_vertices*4] = rgb[0]; + p->data[21+vm_current_vertices*4] = rgb[1]; + p->data[22+vm_current_vertices*4] = rgb[2]; + p->data[23+vm_current_vertices*4] = alpha; + + vm_current_vertices++; + if(vm_current_vertices == 4) + p->flags |= VM_POLYGON_FL4V; + else + if(vm_current_vertices == 3) + p->flags |= VM_POLYGON_FL3V; } -void VM_CL_select_super (void) +//void() R_EndPolygon +static void VM_CL_R_PolygonEnd (void) { -/* int i; - float *v[8]; - prvm_edict_t *ent, *chain; - vec3_t mins1, maxs1; + VM_SAFEPARMCOUNT(0, VM_CL_R_PolygonEnd); + if(!vm_polygonbegin) + { + VM_Warning("VM_CL_R_PolygonEnd: VM_CL_R_PolygonBegin wasn't called\n"); + return; + } + vm_polygonbegin = false; + if(vm_current_vertices > 2 || (vm_current_vertices >= 2 && vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FLLINES)) + { + if(vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FL2D) //[515]: don't use qcpolygons memory if 2D + VM_CL_AddPolygonTo2DScene(&vm_polygons[vm_drawpolygons_num]); + else + vm_drawpolygons_num++; + } + else + VM_Warning("VM_CL_R_PolygonEnd: %i vertices isn't a good choice\n", vm_current_vertices); +} - VM_SAFEPARMCOUNT(8, VM_findchain); - for(i=0;i<8;i++) - v[i] = PRVM_G_VECTOR(OFS_PARM0+i*3); +void Debug_PolygonBegin(const char *picname, int flags, qboolean draw2d, float linewidth) +{ + vm_polygon_t *p; - if (prog->fieldoffsets.chain < 0) - PRVM_ERROR("VM_findchain: %s doesnt have a chain field !\n", PRVM_NAME); + if(!vm_polygons_initialized) + VM_InitPolygons(); + if(vm_polygonbegin) + { + Con_Printf("Debug_PolygonBegin: called twice without Debug_PolygonEnd after first\n"); + return; + } + // limit polygons to a vaguely sane amount, beyond this each one just + // replaces the last one + vm_drawpolygons_num = min(vm_drawpolygons_num, (1<<20)-1); + if(vm_drawpolygons_num >= vm_polygons_num) + { + p = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, 2 * vm_polygons_num * sizeof(vm_polygon_t)); + memset(p, 0, 2 * vm_polygons_num * sizeof(vm_polygon_t)); + memcpy(p, vm_polygons, vm_polygons_num * sizeof(vm_polygon_t)); + Mem_Free(vm_polygons); + vm_polygons = p; + vm_polygons_num *= 2; + } + p = &vm_polygons[vm_drawpolygons_num]; + if(picname && picname[0]) + p->tex = Draw_CachePic(picname, true)->tex; + else + p->tex = r_texture_white; + p->flags = flags; + vm_current_vertices = 0; + vm_polygonbegin = true; + if(draw2d) + p->flags |= VM_POLYGON_FL2D; + if(linewidth) + { + p->data[13] = linewidth; //[515]: linewidth + p->flags |= VM_POLYGON_FLLINES; + } +} - chain = prog->edicts; +void Debug_PolygonVertex(float x, float y, float z, float s, float t, float r, float g, float b, float a) +{ + vm_polygon_t *p; - mins2 = PRVM_G_VECTOR(OFS_PARM0); - maxs2 = PRVM_G_VECTOR(OFS_PARM1); + if(!vm_polygonbegin) + { + Con_Printf("Debug_PolygonVertex: Debug_PolygonBegin wasn't called\n"); + return; + } - ent = PRVM_NEXT_EDICT(prog->edicts); - for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent)) + p = &vm_polygons[vm_drawpolygons_num]; + if(vm_current_vertices > 4) { - if (ent->priv.required->free) - continue; - VectorCopy(ent->fields.client->origin, mins1); - VectorAdd(mins1, ent->fields.client->maxs, maxs1); - VectorAdd(mins1, ent->fields.client->mins, mins1); - if (mins1[0] > maxs2[0] || mins1[1] > maxs2[1] || mins1[2] > maxs2[2]) - continue; - if (maxs1[0] < mins2[0] || maxs1[1] < mins2[1] || maxs1[2] < mins2[2]) - continue; - PRVM_EDICTFIELDVALUE(ent,prog->fieldoffsets.chain)->edict = PRVM_NUM_FOR_EDICT(chain); - chain = ent; + Con_Printf("Debug_PolygonVertex: may have 4 vertices max\n"); + return; } - VM_RETURN_EDICT(chain);*/ + p->data[vm_current_vertices*3] = x; + p->data[1+vm_current_vertices*3] = y; + p->data[2+vm_current_vertices*3] = z; + + p->data[12+vm_current_vertices*2] = s; + if(!(p->flags & VM_POLYGON_FLLINES)) + p->data[13+vm_current_vertices*2] = t; + + p->data[20+vm_current_vertices*4] = r; + p->data[21+vm_current_vertices*4] = g; + p->data[22+vm_current_vertices*4] = b; + p->data[23+vm_current_vertices*4] = a; + + vm_current_vertices++; + if(vm_current_vertices == 4) + p->flags |= VM_POLYGON_FL4V; + else + if(vm_current_vertices == 3) + p->flags |= VM_POLYGON_FL3V; } -static int Is_Text_Color (char c, char t) +void Debug_PolygonEnd(void) { - int a = 0; - char c2 = c - (c & 128); - char t2 = t - (t & 128); + if(!vm_polygonbegin) + { + Con_Printf("Debug_PolygonEnd: Debug_PolygonBegin wasn't called\n"); + return; + } + vm_polygonbegin = false; + if(vm_current_vertices > 2 || (vm_current_vertices >= 2 && vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FLLINES)) + { + if(vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FL2D) //[515]: don't use qcpolygons memory if 2D + VM_CL_AddPolygonTo2DScene(&vm_polygons[vm_drawpolygons_num]); + else + vm_drawpolygons_num++; + } + else + Con_Printf("Debug_PolygonEnd: %i vertices isn't a good choice\n", vm_current_vertices); +} - if(c != STRING_COLOR_TAG && c2 != STRING_COLOR_TAG) return 0; - if(t >= '0' && t <= '9') a = 1; - if(t2 >= '0' && t2 <= '9') a = 1; -/* if(t >= 'A' && t <= 'Z') a = 2; - if(t2 >= 'A' && t2 <= 'Z') a = 2; +/* +============= +CL_CheckBottom - if(a == 1 && scr_colortext.integer > 0) - return 1; - if(a == 2 && scr_multifonts.integer > 0) - return 2; +Returns false if any part of the bottom of the entity is off an edge that +is not a staircase. + +============= */ - return a; +qboolean CL_CheckBottom (prvm_edict_t *ent) +{ + vec3_t mins, maxs, start, stop; + trace_t trace; + int x, y; + float mid, bottom; + + VectorAdd (ent->fields.client->origin, ent->fields.client->mins, mins); + VectorAdd (ent->fields.client->origin, ent->fields.client->maxs, maxs); + +// if all of the points under the corners are solid world, don't bother +// with the tougher checks +// the corners must be within 16 of the midpoint + start[2] = mins[2] - 1; + for (x=0 ; x<=1 ; x++) + for (y=0 ; y<=1 ; y++) + { + start[0] = x ? maxs[0] : mins[0]; + start[1] = y ? maxs[1] : mins[1]; + if (!(CL_PointSuperContents(start) & (SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY))) + goto realcheck; + } + + return true; // we got out easy + +realcheck: +// +// check it for real... +// + start[2] = mins[2]; + +// the midpoint must be within 16 of the bottom + start[0] = stop[0] = (mins[0] + maxs[0])*0.5; + start[1] = stop[1] = (mins[1] + maxs[1])*0.5; + stop[2] = start[2] - 2*sv_stepheight.value; + trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true); + + if (trace.fraction == 1.0) + return false; + mid = bottom = trace.endpos[2]; + +// the corners must be within 16 of the midpoint + for (x=0 ; x<=1 ; x++) + for (y=0 ; y<=1 ; y++) + { + start[0] = stop[0] = x ? maxs[0] : mins[0]; + start[1] = stop[1] = y ? maxs[1] : mins[1]; + + trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true); + + if (trace.fraction != 1.0 && trace.endpos[2] > bottom) + bottom = trace.endpos[2]; + if (trace.fraction == 1.0 || mid - trace.endpos[2] > sv_stepheight.value) + return false; + } + + return true; } -void VM_uncolorstring (void) //#170 +/* +============= +CL_movestep + +Called by monster program code. +The move will be adjusted for slopes and stairs, but if the move isn't +possible, no move is done and false is returned +============= +*/ +qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean noenemy, qboolean settrace) { - const char *in; - char out[VM_STRINGTEMP_LENGTH]; - int k = 0, i = 0; + float dz; + vec3_t oldorg, neworg, end, traceendpos; + trace_t trace; + int i; + prvm_edict_t *enemy; + prvm_eval_t *val; - VM_SAFEPARMCOUNT(1, VM_uncolorstring); - in = PRVM_G_STRING(OFS_PARM0); - VM_CheckEmptyString (in); +// try the move + VectorCopy (ent->fields.client->origin, oldorg); + VectorAdd (ent->fields.client->origin, move, neworg); - while (in[k]) +// flying monsters don't step up + if ( (int)ent->fields.client->flags & (FL_SWIM | FL_FLY) ) { - if(in[k+1]) - if(Is_Text_Color(in[k], in[k+1]) == 1/* || (in[k] == '&' && in[k+1] == 'r')*/) + // try one move with vertical motion, then one without + for (i=0 ; i<2 ; i++) { - k += 2; - continue; + VectorAdd (ent->fields.client->origin, move, neworg); + enemy = PRVM_PROG_TO_EDICT(ent->fields.client->enemy); + if (i == 0 && enemy != prog->edicts) + { + dz = ent->fields.client->origin[2] - PRVM_PROG_TO_EDICT(ent->fields.client->enemy)->fields.client->origin[2]; + if (dz > 40) + neworg[2] -= 8; + if (dz < 30) + neworg[2] += 8; + } + trace = CL_Move (ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, neworg, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true); + if (settrace) + VM_SetTraceGlobals(&trace); + + if (trace.fraction == 1) + { + VectorCopy(trace.endpos, traceendpos); + if (((int)ent->fields.client->flags & FL_SWIM) && !(CL_PointSuperContents(traceendpos) & SUPERCONTENTS_LIQUIDSMASK)) + return false; // swim monster left water + + VectorCopy (traceendpos, ent->fields.client->origin); + if (relink) + CL_LinkEdict(ent); + return true; + } + + if (enemy == prog->edicts) + break; + } + + return false; + } + +// push down from a step height above the wished position + neworg[2] += sv_stepheight.value; + VectorCopy (neworg, end); + end[2] -= sv_stepheight.value*2; + + trace = CL_Move (neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true); + if (settrace) + VM_SetTraceGlobals(&trace); + + if (trace.startsolid) + { + neworg[2] -= sv_stepheight.value; + trace = CL_Move (neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true); + if (settrace) + VM_SetTraceGlobals(&trace); + if (trace.startsolid) + return false; + } + if (trace.fraction == 1) + { + // if monster had the ground pulled out, go ahead and fall + if ( (int)ent->fields.client->flags & FL_PARTIALGROUND ) + { + VectorAdd (ent->fields.client->origin, move, ent->fields.client->origin); + if (relink) + CL_LinkEdict(ent); + ent->fields.client->flags = (int)ent->fields.client->flags & ~FL_ONGROUND; + return true; + } + + return false; // walked off an edge + } + +// check point traces down for dangling corners + VectorCopy (trace.endpos, ent->fields.client->origin); + + if (!CL_CheckBottom (ent)) + { + if ( (int)ent->fields.client->flags & FL_PARTIALGROUND ) + { // entity had floor mostly pulled out from underneath it + // and is trying to correct + if (relink) + CL_LinkEdict(ent); + return true; } - out[i] = in[k]; - ++k; - ++i; + VectorCopy (oldorg, ent->fields.client->origin); + return false; } - PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(out); + + if ( (int)ent->fields.client->flags & FL_PARTIALGROUND ) + ent->fields.client->flags = (int)ent->fields.client->flags & ~FL_PARTIALGROUND; + + if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.groundentity))) + val->edict = PRVM_EDICT_TO_PROG(trace.ent); + +// the move is ok + if (relink) + CL_LinkEdict(ent); + return true; } -void VM_CL_selecttraceline (void) +/* +=============== +VM_CL_walkmove + +float(float yaw, float dist[, settrace]) walkmove +=============== +*/ +static void VM_CL_walkmove (void) { - float *v1, *v2; - int ent, ignore, csqcents; + prvm_edict_t *ent; + float yaw, dist; + vec3_t move; + mfunction_t *oldf; + int oldself; + qboolean settrace; - v1 = PRVM_G_VECTOR(OFS_PARM0); - v2 = PRVM_G_VECTOR(OFS_PARM1); - ignore = (int)PRVM_G_FLOAT(OFS_PARM2); - csqcents = (int)PRVM_G_FLOAT(OFS_PARM3); - ent = 0; + VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_walkmove); - if (csqcents) + // assume failure if it returns early + PRVM_G_FLOAT(OFS_RETURN) = 0; + + ent = PRVM_PROG_TO_EDICT(prog->globals.client->self); + if (ent == prog->edicts) { - VM_Warning("VM_CL_selecttraceline: csqcents flag not supported anymore, and this function is deprecated\n"); + VM_Warning("walkmove: can not modify world entity\n"); return; } - prog->globals.client->trace_fraction = CL_SelectTraceLine(v1, v2, prog->globals.client->trace_endpos, prog->globals.client->trace_plane_normal, &ent, &cl.entities[ignore].render); - PRVM_G_FLOAT(OFS_RETURN) = ent; -} + if (ent->priv.server->free) + { + VM_Warning("walkmove: can not modify free entity\n"); + return; + } + yaw = PRVM_G_FLOAT(OFS_PARM0); + dist = PRVM_G_FLOAT(OFS_PARM1); + settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2); -void VM_charindex (void) -{ - const char *s; - s = PRVM_G_STRING(OFS_PARM0); - if((unsigned)PRVM_G_FLOAT(OFS_PARM1) > strlen(s)) + if ( !( (int)ent->fields.client->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) ) return; - PRVM_G_FLOAT(OFS_RETURN) = (unsigned char)s[(int)PRVM_G_FLOAT(OFS_PARM1)]; -} -//#223 string(float c, ...) chr2str (FTE_STRINGS) -void VM_chr2str (void) -{ - char t[128]; - int i; - for(i = 0;i < prog->argc && i < (int)sizeof(t) - 1;i++) - t[i] = (unsigned char)PRVM_G_FLOAT(OFS_PARM0+i*3); - t[i] = 0; - PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t); + yaw = yaw*M_PI*2 / 360; + + move[0] = cos(yaw)*dist; + move[1] = sin(yaw)*dist; + move[2] = 0; + +// save program state, because CL_movestep may call other progs + oldf = prog->xfunction; + oldself = prog->globals.client->self; + + PRVM_G_FLOAT(OFS_RETURN) = CL_movestep(ent, move, true, false, settrace); + + +// restore program state + prog->xfunction = oldf; + prog->globals.client->self = oldself; } -//#228 float(string s1, string s2, float len) strncmp (FTE_STRINGS) -void VM_strncmp (void) +/* +=============== +VM_CL_serverkey + +string(string key) serverkey +=============== +*/ +void VM_CL_serverkey(void) { - const char *s1, *s2; - VM_SAFEPARMCOUNT(1, VM_strncmp); - s1 = PRVM_G_STRING(OFS_PARM0); - s2 = PRVM_G_STRING(OFS_PARM1); - PRVM_G_FLOAT(OFS_RETURN) = strncmp(s1, s2, (size_t)PRVM_G_FLOAT(OFS_PARM2)); + char string[VM_STRINGTEMP_LENGTH]; + VM_SAFEPARMCOUNT(1, VM_CL_serverkey); + InfoString_GetValue(cl.qw_serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string)); + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string); } -//============================================================================ //============================================================================ prvm_builtin_t vm_cl_builtins[] = { -0, // to be consistent with the old vm -VM_CL_makevectors, // #1 void(vector ang) makevectors -VM_CL_setorigin, // #2 void(entity e, vector o) setorigin -VM_CL_setmodel, // #3 void(entity e, string m) setmodel -VM_CL_setsize, // #4 void(entity e, vector min, vector max) setsize -0, -VM_break, // #6 void() break -VM_random, // #7 float() random -VM_CL_sound, // #8 void(entity e, float chan, string samp) sound -VM_normalize, // #9 vector(vector v) normalize -VM_error, // #10 void(string e) error -VM_objerror, // #11 void(string e) objerror -VM_vlen, // #12 float(vector v) vlen -VM_vectoyaw, // #13 float(vector v) vectoyaw -VM_CL_spawn, // #14 entity() spawn -VM_remove, // #15 void(entity e) remove -VM_CL_traceline, // #16 float(vector v1, vector v2, float tryents) traceline -0, -VM_find, // #18 entity(entity start, .string fld, string match) find -VM_CL_precache_sound, // #19 void(string s) precache_sound -VM_CL_precache_model, // #20 void(string s) precache_model -0, -VM_CL_findradius, // #22 entity(vector org, float rad) findradius -0, -0, -VM_dprint, // #25 void(string s) dprint -VM_ftos, // #26 void(string s) ftos -VM_vtos, // #27 void(string s) vtos -VM_coredump, // #28 void() coredump -VM_traceon, // #29 void() traceon -VM_traceoff, // #30 void() traceoff -VM_eprint, // #31 void(entity e) eprint -0, -NULL, // #33 -VM_CL_droptofloor, // #34 float() droptofloor -VM_CL_lightstyle, // #35 void(float style, string value) lightstyle -VM_rint, // #36 float(float v) rint -VM_floor, // #37 float(float v) floor -VM_ceil, // #38 float(float v) ceil -NULL, // #39 -VM_CL_checkbottom, // #40 float(entity e) checkbottom -VM_CL_pointcontents, // #41 float(vector v) pointcontents -NULL, // #42 -VM_fabs, // #43 float(float f) fabs -0, -VM_cvar, // #45 float(string s) cvar -VM_localcmd, // #46 void(string s) localcmd -VM_nextent, // #47 entity(entity e) nextent -VM_CL_particle, // #48 void(vector o, vector d, float color, float count) particle -VM_changeyaw, // #49 void(entity ent) ChangeYaw -NULL, // #50 -VM_vectoangles, // #51 vector(vector v) vectoangles -0, // #52 void(float to, float f) WriteByte -0, // #53 void(float to, float f) WriteChar -0, // #54 void(float to, float f) WriteShort -0, // #55 void(float to, float f) WriteLong -0, // #56 void(float to, float f) WriteCoord -0, // #57 void(float to, float f) WriteAngle -0, // #58 void(float to, string s) WriteString -0, -VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) -VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) -VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) -VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) -VM_CL_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) -VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) -NULL, // #66 -0, // #67 -0, // #68 -0, // #69 -0, // #70 -NULL, // #71 -VM_cvar_set, // #72 void(string var, string val) cvar_set -0, // #73 -VM_CL_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound -VM_CL_precache_model, // #75 string(string s) precache_model2 -VM_CL_precache_sound, // #76 string(string s) precache_sound2 -0, // #77 -VM_chr, // #78 -NULL, // #79 -NULL, // #80 -VM_stof, // #81 float(string s) stof (FRIK_FILE) -NULL, // #82 -NULL, // #83 -NULL, // #84 -NULL, // #85 -NULL, // #86 -NULL, // #87 -NULL, // #88 -NULL, // #89 -VM_CL_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX) -VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC) -VM_CL_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT) -PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR) -VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND) -VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND) -VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND) -VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW) -VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT) -VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system) -NULL, // #100 -NULL, // #101 -NULL, // #102 -NULL, // #103 -NULL, // #104 -NULL, // #105 -NULL, // #106 -NULL, // #107 -NULL, // #108 -NULL, // #109 -VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE) -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_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) -VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE) - -e10, e10, e10, e10, e10, e10, e10, e10, // #120-199 -e10, //#200-209 -0, //#210 -0, //#211 -0, //#212 -0, //#213 -0, //#214 -0, //#215 -0, //#216 -0, //#217 -VM_bitshift, //#218 float(float number, float quantity) bitshift (EXT_BITSHIFT) -0, //#219 -0, //#220 -0, //#221 -VM_charindex, //#222 float(string str, float ofs) str2chr (FTE_STRINGS) -VM_chr2str, //#223 string(float c, ...) chr2str (FTE_STRINGS) -0, //#224 -0, //#225 -0, //#226 -0, //#227 -VM_strncmp, //#228 float(string s1, string s2, float len) strncmp (FTE_STRINGS) -0, -e10, e10, e10, e10, e10, e10, e10, // #230-299 - -//======CSQC start=======// -//3d world (buffer/buffering) operations -VM_R_ClearScene, //#300 void() clearscene (EXT_CSQC) -VM_R_AddEntities, //#301 void(float mask) addentities (EXT_CSQC) -VM_R_AddEntity, //#302 void(entity ent) addentity (EXT_CSQC) -VM_R_SetView, //#303 float(float property, ...) setproperty (EXT_CSQC) -VM_R_RenderScene, //#304 void() renderscene (EXT_CSQC) -VM_R_AddDynamicLight, //#305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC) -VM_R_PolygonBegin, //#306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon -VM_R_PolygonVertex, //#307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex -VM_R_PolygonEnd, //#308 void() R_EndPolygon -0, //#309 - -//maths stuff that uses the current view settings -VM_CL_unproject, //#310 vector (vector v) cs_unproject (EXT_CSQC) -VM_CL_project, //#311 vector (vector v) cs_project (EXT_CSQC) -0, //#312 -0, //#313 -0, //#314 - -//2d (immediate) operations -VM_drawline, //#315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC) -VM_iscachedpic, //#316 float(string name) iscachedpic (EXT_CSQC) -VM_precache_pic, //#317 string(string name, float trywad) precache_pic (EXT_CSQC) -VM_getimagesize, //#318 vector(string picname) draw_getimagesize (EXT_CSQC) -VM_freepic, //#319 void(string name) freepic (EXT_CSQC) -VM_drawcharacter, //#320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC) -VM_drawstring, //#321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC) -VM_drawpic, //#322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC) -VM_drawfill, //#323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC) -VM_drawsetcliparea, //#324 void(float x, float y, float width, float height) drawsetcliparea -VM_drawresetcliparea, //#325 void(void) drawresetcliparea -0, //#326 -0, //#327 -0, //#328 -0, //#329 - -VM_CL_getstatf, //#330 float(float stnum) getstatf (EXT_CSQC) -VM_CL_getstati, //#331 float(float stnum) getstati (EXT_CSQC) -VM_CL_getstats, //#332 string(float firststnum) getstats (EXT_CSQC) -VM_CL_setmodelindex, //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC) -VM_CL_modelnameforindex, //#334 string(float mdlindex) modelnameforindex (EXT_CSQC) -VM_CL_particleeffectnum, //#335 float(string effectname) particleeffectnum (EXT_CSQC) -VM_CL_trailparticles, //#336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC) -VM_CL_pointparticles, //#337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC) -VM_CL_centerprint, //#338 void(string s) cprint (EXT_CSQC) -VM_print, //#339 void(string s) print (EXT_CSQC) -VM_keynumtostring, //#340 string(float keynum) keynumtostring (EXT_CSQC) -VM_stringtokeynum, //#341 float(string keyname) stringtokeynum (EXT_CSQC) -VM_CL_getkeybind, //#342 string(float keynum) getkeybind (EXT_CSQC) -VM_CL_setcursormode, //#343 void(float usecursor) setcursormode (EXT_CSQC) -VM_getmousepos, //#344 vector() getmousepos (EXT_CSQC) -VM_CL_getinputstate, //#345 float(float framenum) getinputstate (EXT_CSQC) -VM_CL_setsensitivityscale, //#346 void(float sens) setsensitivityscaler (EXT_CSQC) -VM_CL_runplayerphysics, //#347 void() runstandardplayerphysics (EXT_CSQC) -VM_CL_getplayerkey, //#348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC) -VM_CL_isdemo, //#349 float() isdemo (EXT_CSQC) -VM_isserver, //#350 float() isserver (EXT_CSQC) -VM_CL_setlistener, //#351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC) -VM_CL_registercmd, //#352 void(string cmdname) registercommand (EXT_CSQC) -VM_WasFreed, //#353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too) -VM_CL_playernum, //#354 float() playernum -VM_CL_onground, //#355 float() cl_onground (EXT_CSQC) -VM_charindex, //#356 float(string s, float num) charindex -VM_CL_selecttraceline, //#357 float(vector start, vector end, float ignore, float csqcents) selecttraceline -0, //#358 -0, //#359 -VM_CL_ReadByte, //#360 float() readbyte (EXT_CSQC) -VM_CL_ReadChar, //#361 float() readchar (EXT_CSQC) -VM_CL_ReadShort, //#362 float() readshort (EXT_CSQC) -VM_CL_ReadLong, //#363 float() readlong (EXT_CSQC) -VM_CL_ReadCoord, //#364 float() readcoord (EXT_CSQC) -VM_CL_ReadAngle, //#365 float() readangle (EXT_CSQC) -VM_CL_ReadString, //#366 string() readstring (EXT_CSQC) -VM_CL_ReadFloat, //#367 float() readfloat (EXT_CSQC) -0, //#368 -0, //#369 -0, //#370 -0, //#371 -0, //#372 -0, //#373 -0, //#374 -0, //#375 -0, //#376 -0, //#377 -0, //#378 -0, //#379 -0, //#380 -0, //#381 -0, //#382 -0, //#383 -0, //#384 -0, //#385 -0, //#386 -0, //#387 -0, //#388 -0, //#389 -0, //#390 -0, //#391 -0, //#392 -0, //#393 -0, //#394 -0, //#395 -0, //#396 -0, //#397 -0, //#398 -0, //#399 -//=========CSQC end========// - -VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY) -0, +NULL, // #0 NULL function (not callable) (QUAKE) +VM_CL_makevectors, // #1 void(vector ang) makevectors (QUAKE) +VM_CL_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE) +VM_CL_setmodel, // #3 void(entity e, string m) setmodel (QUAKE) +VM_CL_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_CL_sound, // #8 void(entity e, float chan, string samp) 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) +VM_vlen, // #12 float(vector v) vlen (QUAKE) +VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE) +VM_CL_spawn, // #14 entity() spawn (QUAKE) +VM_remove, // #15 void(entity e) remove (QUAKE) +VM_CL_traceline, // #16 float(vector v1, vector v2, float tryents) traceline (QUAKE) +NULL, // #17 entity() checkclient (QUAKE) +VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE) +VM_precache_sound, // #19 void(string s) precache_sound (QUAKE) +VM_CL_precache_model, // #20 void(string s) precache_model (QUAKE) +NULL, // #21 void(entity client, string s, ...) stuffcmd (QUAKE) +VM_CL_findradius, // #22 entity(vector org, float rad) findradius (QUAKE) +NULL, // #23 void(string s, ...) bprint (QUAKE) +NULL, // #24 void(entity client, string s, ...) sprint (QUAKE) +VM_dprint, // #25 void(string s, ...) dprint (QUAKE) +VM_ftos, // #26 string(float f) ftos (QUAKE) +VM_vtos, // #27 string(vector v) vtos (QUAKE) +VM_coredump, // #28 void() coredump (QUAKE) +VM_traceon, // #29 void() traceon (QUAKE) +VM_traceoff, // #30 void() traceoff (QUAKE) +VM_eprint, // #31 void(entity e) eprint (QUAKE) +VM_CL_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE) +NULL, // #33 (QUAKE) +VM_CL_droptofloor, // #34 float() droptofloor (QUAKE) +VM_CL_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE) +VM_rint, // #36 float(float v) rint (QUAKE) +VM_floor, // #37 float(float v) floor (QUAKE) +VM_ceil, // #38 float(float v) ceil (QUAKE) +NULL, // #39 (QUAKE) +VM_CL_checkbottom, // #40 float(entity e) checkbottom (QUAKE) +VM_CL_pointcontents, // #41 float(vector v) pointcontents (QUAKE) +NULL, // #42 (QUAKE) +VM_fabs, // #43 float(float f) fabs (QUAKE) +NULL, // #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_nextent, // #47 entity(entity e) nextent (QUAKE) +VM_CL_particle, // #48 void(vector o, vector d, float color, float count) particle (QUAKE) +VM_changeyaw, // #49 void() ChangeYaw (QUAKE) +NULL, // #50 (QUAKE) +VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE) +NULL, // #52 void(float to, float f) WriteByte (QUAKE) +NULL, // #53 void(float to, float f) WriteChar (QUAKE) +NULL, // #54 void(float to, float f) WriteShort (QUAKE) +NULL, // #55 void(float to, float f) WriteLong (QUAKE) +NULL, // #56 void(float to, float f) WriteCoord (QUAKE) +NULL, // #57 void(float to, float f) WriteAngle (QUAKE) +NULL, // #58 void(float to, string s) WriteString (QUAKE) +NULL, // #59 (QUAKE) +VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) +VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) +VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) +VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) +VM_CL_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) +VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) +NULL, // #66 (QUAKE) +NULL, // #67 void(float step) movetogoal (QUAKE) +VM_precache_file, // #68 string(string s) precache_file (QUAKE) +VM_CL_makestatic, // #69 void(entity e) makestatic (QUAKE) +NULL, // #70 void(string s) changelevel (QUAKE) +NULL, // #71 (QUAKE) +VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE) +NULL, // #73 void(entity client, strings) centerprint (QUAKE) +VM_CL_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE) +VM_CL_precache_model, // #75 string(string s) precache_model2 (QUAKE) +VM_precache_sound, // #76 string(string s) precache_sound2 (QUAKE) +VM_precache_file, // #77 string(string s) precache_file2 (QUAKE) +NULL, // #78 void(entity e) setspawnparms (QUAKE) +NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD) +NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD) +VM_stof, // #81 float(string s) stof (FRIK_FILE) +NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD) +NULL, // #83 (QUAKE) +NULL, // #84 (QUAKE) +NULL, // #85 (QUAKE) +NULL, // #86 (QUAKE) +NULL, // #87 (QUAKE) +NULL, // #88 (QUAKE) +NULL, // #89 (QUAKE) +VM_CL_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX) +VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC) +VM_CL_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT) +VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR) +VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND) +VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND) +VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND) +VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW) +VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT) +VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system) +// FrikaC and Telejano range #100-#199 +NULL, // #100 +NULL, // #101 +NULL, // #102 +NULL, // #103 +NULL, // #104 +NULL, // #105 +NULL, // #106 +NULL, // #107 +NULL, // #108 +NULL, // #109 +VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE) +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_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) +VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE) +NULL, // #120 +NULL, // #121 +NULL, // #122 +NULL, // #123 +NULL, // #124 +NULL, // #125 +NULL, // #126 +NULL, // #127 +NULL, // #128 +NULL, // #129 +NULL, // #130 +NULL, // #131 +NULL, // #132 +NULL, // #133 +NULL, // #134 +NULL, // #135 +NULL, // #136 +NULL, // #137 +NULL, // #138 +NULL, // #139 +NULL, // #140 +NULL, // #141 +NULL, // #142 +NULL, // #143 +NULL, // #144 +NULL, // #145 +NULL, // #146 +NULL, // #147 +NULL, // #148 +NULL, // #149 +NULL, // #150 +NULL, // #151 +NULL, // #152 +NULL, // #153 +NULL, // #154 +NULL, // #155 +NULL, // #156 +NULL, // #157 +NULL, // #158 +NULL, // #159 +NULL, // #160 +NULL, // #161 +NULL, // #162 +NULL, // #163 +NULL, // #164 +NULL, // #165 +NULL, // #166 +NULL, // #167 +NULL, // #168 +NULL, // #169 +NULL, // #170 +NULL, // #171 +NULL, // #172 +NULL, // #173 +NULL, // #174 +NULL, // #175 +NULL, // #176 +NULL, // #177 +NULL, // #178 +NULL, // #179 +NULL, // #180 +NULL, // #181 +NULL, // #182 +NULL, // #183 +NULL, // #184 +NULL, // #185 +NULL, // #186 +NULL, // #187 +NULL, // #188 +NULL, // #189 +NULL, // #190 +NULL, // #191 +NULL, // #192 +NULL, // #193 +NULL, // #194 +NULL, // #195 +NULL, // #196 +NULL, // #197 +NULL, // #198 +NULL, // #199 +// FTEQW range #200-#299 +NULL, // #200 +NULL, // #201 +NULL, // #202 +NULL, // #203 +NULL, // #204 +NULL, // #205 +NULL, // #206 +NULL, // #207 +NULL, // #208 +NULL, // #209 +NULL, // #210 +NULL, // #211 +NULL, // #212 +NULL, // #213 +NULL, // #214 +NULL, // #215 +NULL, // #216 +NULL, // #217 +VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT) +NULL, // #219 +NULL, // #220 +NULL, // #221 +VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS) +VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS) +NULL, // #224 +NULL, // #225 +NULL, // #226 +NULL, // #227 +VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS) +NULL, // #229 +NULL, // #230 +NULL, // #231 +NULL, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC) +NULL, // #233 +NULL, // #234 +NULL, // #235 +NULL, // #236 +NULL, // #237 +NULL, // #238 +NULL, // #239 +NULL, // #240 +NULL, // #241 +NULL, // #242 +NULL, // #243 +NULL, // #244 +NULL, // #245 +NULL, // #246 +NULL, // #247 +NULL, // #248 +NULL, // #249 +NULL, // #250 +NULL, // #251 +NULL, // #252 +NULL, // #253 +NULL, // #254 +NULL, // #255 +NULL, // #256 +NULL, // #257 +NULL, // #258 +NULL, // #259 +NULL, // #260 +NULL, // #261 +NULL, // #262 +NULL, // #263 +NULL, // #264 +NULL, // #265 +NULL, // #266 +NULL, // #267 +NULL, // #268 +NULL, // #269 +NULL, // #270 +NULL, // #271 +NULL, // #272 +NULL, // #273 +NULL, // #274 +NULL, // #275 +NULL, // #276 +NULL, // #277 +NULL, // #278 +NULL, // #279 +NULL, // #280 +NULL, // #281 +NULL, // #282 +NULL, // #283 +NULL, // #284 +NULL, // #285 +NULL, // #286 +NULL, // #287 +NULL, // #288 +NULL, // #289 +NULL, // #290 +NULL, // #291 +NULL, // #292 +NULL, // #293 +NULL, // #294 +NULL, // #295 +NULL, // #296 +NULL, // #297 +NULL, // #298 +NULL, // #299 +// CSQC range #300-#399 +VM_CL_R_ClearScene, // #300 void() clearscene (EXT_CSQC) +VM_CL_R_AddEntities, // #301 void(float mask) addentities (EXT_CSQC) +VM_CL_R_AddEntity, // #302 void(entity ent) addentity (EXT_CSQC) +VM_CL_R_SetView, // #303 float(float property, ...) setproperty (EXT_CSQC) +VM_CL_R_RenderScene, // #304 void() renderscene (EXT_CSQC) +VM_CL_R_AddDynamicLight, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC) +VM_CL_R_PolygonBegin, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon +VM_CL_R_PolygonVertex, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex +VM_CL_R_PolygonEnd, // #308 void() R_EndPolygon +NULL, // #309 +VM_CL_unproject, // #310 vector (vector v) cs_unproject (EXT_CSQC) +VM_CL_project, // #311 vector (vector v) cs_project (EXT_CSQC) +NULL, // #312 +NULL, // #313 +NULL, // #314 +VM_drawline, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC) +VM_iscachedpic, // #316 float(string name) iscachedpic (EXT_CSQC) +VM_precache_pic, // #317 string(string name, float trywad) precache_pic (EXT_CSQC) +VM_getimagesize, // #318 vector(string picname) draw_getimagesize (EXT_CSQC) +VM_freepic, // #319 void(string name) freepic (EXT_CSQC) +VM_drawcharacter, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC) +VM_drawstring, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC) +VM_drawpic, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC) +VM_drawfill, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC) +VM_drawsetcliparea, // #324 void(float x, float y, float width, float height) drawsetcliparea +VM_drawresetcliparea, // #325 void(void) drawresetcliparea +NULL, // #326 +NULL, // #327 +NULL, // #328 +NULL, // #329 +VM_CL_getstatf, // #330 float(float stnum) getstatf (EXT_CSQC) +VM_CL_getstati, // #331 float(float stnum) getstati (EXT_CSQC) +VM_CL_getstats, // #332 string(float firststnum) getstats (EXT_CSQC) +VM_CL_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC) +VM_CL_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC) +VM_CL_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC) +VM_CL_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC) +VM_CL_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC) +VM_centerprint, // #338 void(string s, ...) centerprint (EXT_CSQC) +VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT) +VM_keynumtostring, // #340 string(float keynum) keynumtostring (EXT_CSQC) +VM_stringtokeynum, // #341 float(string keyname) stringtokeynum (EXT_CSQC) +VM_CL_getkeybind, // #342 string(float keynum) getkeybind (EXT_CSQC) +VM_CL_setcursormode, // #343 void(float usecursor) setcursormode (EXT_CSQC) +VM_getmousepos, // #344 vector() getmousepos (EXT_CSQC) +VM_CL_getinputstate, // #345 float(float framenum) getinputstate (EXT_CSQC) +VM_CL_setsensitivityscale, // #346 void(float sens) setsensitivityscaler (EXT_CSQC) +VM_CL_runplayerphysics, // #347 void() runstandardplayerphysics (EXT_CSQC) +VM_CL_getplayerkey, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC) +VM_CL_isdemo, // #349 float() isdemo (EXT_CSQC) +VM_isserver, // #350 float() isserver (EXT_CSQC) +VM_CL_setlistener, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC) +VM_CL_registercmd, // #352 void(string cmdname) registercommand (EXT_CSQC) +VM_wasfreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too) +VM_CL_serverkey, // #354 string(string key) serverkey (EXT_CSQC) +NULL, // #355 +NULL, // #356 +NULL, // #357 +NULL, // #358 +NULL, // #359 +VM_CL_ReadByte, // #360 float() readbyte (EXT_CSQC) +VM_CL_ReadChar, // #361 float() readchar (EXT_CSQC) +VM_CL_ReadShort, // #362 float() readshort (EXT_CSQC) +VM_CL_ReadLong, // #363 float() readlong (EXT_CSQC) +VM_CL_ReadCoord, // #364 float() readcoord (EXT_CSQC) +VM_CL_ReadAngle, // #365 float() readangle (EXT_CSQC) +VM_CL_ReadString, // #366 string() readstring (EXT_CSQC) +VM_CL_ReadFloat, // #367 float() readfloat (EXT_CSQC) +NULL, // #368 +NULL, // #369 +NULL, // #370 +NULL, // #371 +NULL, // #372 +NULL, // #373 +NULL, // #374 +NULL, // #375 +NULL, // #376 +NULL, // #377 +NULL, // #378 +NULL, // #379 +NULL, // #380 +NULL, // #381 +NULL, // #382 +NULL, // #383 +NULL, // #384 +NULL, // #385 +NULL, // #386 +NULL, // #387 +NULL, // #388 +NULL, // #389 +NULL, // #390 +NULL, // #391 +NULL, // #392 +NULL, // #393 +NULL, // #394 +NULL, // #395 +NULL, // #396 +NULL, // #397 +NULL, // #398 +NULL, // #399 +// LordHavoc's range #400-#499 +VM_CL_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY) +NULL, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR) VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN) VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT) VM_CL_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT) @@ -2366,56 +3121,86 @@ VM_CL_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP VM_CL_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE) VM_CL_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE) VM_CL_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE) -0, // #440 -VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND) -VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND) -VM_CL_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS) -VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH) -VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH) -VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH) -VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH) -VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING) -VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS) -VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS) -VM_CL_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO) -VM_CL_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO) -0, // #453 -0, // #454 -0, // #455 -NULL, // #456 -NULL, // #457 -NULL, // #458 -NULL, // #459 -VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS) -VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS) -VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS) -VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS) -VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS) -VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS) -VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS) -VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS) -VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS) -VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS) -NULL, // #470 -VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN) -VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN) -VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN) -VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN) -VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN) -VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS) -VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_QC_STRINGCOLORFUNCTIONS) -VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME) -NULL, // #479 -e10, e10 // #480-499 (LordHavoc) +NULL, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND) +VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND) +VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND) +VM_CL_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS) +VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH) +VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH) +VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH) +VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH) +VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING) +VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS) +VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS) +VM_CL_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO) +VM_CL_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO) +NULL, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT) +NULL, // #454 entity() spawnclient (DP_SV_BOTCLIENT) +NULL, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT) +NULL, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING) +VM_CL_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET) +NULL, // #458 +VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM) +VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS) +VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS) +VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS) +VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS) +VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS) +VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS) +VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS) +VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS) +VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS) +VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS) +NULL, // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC) +VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN) +VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN) +VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN) +VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN) +VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN) +VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS) +VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_QC_STRINGCOLORFUNCTIONS) +VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME) +NULL, // #479 +NULL, // #480 +NULL, // #481 +NULL, // #482 +NULL, // #483 +NULL, // #484 +NULL, // #485 +NULL, // #486 +NULL, // #487 +NULL, // #488 +NULL, // #489 +NULL, // #490 +NULL, // #491 +NULL, // #492 +NULL, // #493 +NULL, // #494 +NULL, // #495 +NULL, // #496 +NULL, // #497 +NULL, // #498 +NULL, // #499 }; const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t); void VM_CL_Cmd_Init(void) { + // TODO: replace vm_polygons stuff with a more general debugging polygon system, and make vm_polygons functions use that system + if(vm_polygons_initialized) + { + Mem_FreePool(&vm_polygons_pool); + vm_polygons_initialized = false; + } } void VM_CL_Cmd_Reset(void) { + if(vm_polygons_initialized) + { + Mem_FreePool(&vm_polygons_pool); + vm_polygons_initialized = false; + } } diff --git a/csprogs.c b/csprogs.c index 343f8a1f..1268888d 100644 --- a/csprogs.c +++ b/csprogs.c @@ -2,6 +2,7 @@ #include "progsvm.h" #include "clprogdefs.h" #include "csprogs.h" +#include "cl_collision.h" //============================================================================ // Client prog handling @@ -56,31 +57,6 @@ void CL_VM_Error (const char *format, ...) //[515]: hope it will be never execut Host_Error(va("CL_VM_Error: %s", errorstring)); } -model_t *CSQC_GetModelByIndex(int modelindex) -{ - if(!modelindex) - return NULL; - if (modelindex < 0) - { - modelindex = -(modelindex+1); - if (modelindex < MAX_MODELS) - return cl.csqc_model_precache[modelindex]; - } - else - { - if(modelindex < MAX_MODELS) - return cl.model_precache[modelindex]; - } - return NULL; -} - -model_t *CSQC_GetModelFromEntity(prvm_edict_t *ed) -{ - if (!ed || ed->priv.server->free) - return NULL; - return CSQC_GetModelByIndex((int)ed->fields.client->modelindex); -} - //[515]: set globals before calling R_UpdateView, WEIRD CRAP static void CSQC_SetGlobals (void) { @@ -140,7 +116,7 @@ qboolean CSQC_AddRenderEdict(prvm_edict_t *ed) model_t *model; matrix4x4_t tagmatrix, matrix2; - model = CSQC_GetModelFromEntity(ed); + model = CL_GetModelFromEdict(ed); if (!model) return false; @@ -154,14 +130,8 @@ qboolean CSQC_AddRenderEdict(prvm_edict_t *ed) e->render.skinnum = (int)ed->fields.client->skin; e->render.effects |= e->render.model->flags2 & (EF_FULLBRIGHT | EF_ADDITIVE); scale = 1; - // FIXME: renderflags should be in the cl_entvars_t -#if 1 renderflags = 0; if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.renderflags)) && val->_float) renderflags = (int)val->_float; -#else - renderflags = (int)ed->fields.client->renderflags; -#endif - if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.alpha)) && val->_float) e->render.alpha = val->_float; if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.scale)) && val->_float) e->render.scale = scale = val->_float; if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.colormod)) && VectorLength2(val->vector)) VectorCopy(val->vector, e->render.colormod); @@ -184,6 +154,7 @@ qboolean CSQC_AddRenderEdict(prvm_edict_t *ed) vec3_t left; VectorNegate(prog->globals.client->v_right, left); Matrix4x4_FromVectors(&matrix2, prog->globals.client->v_forward, left, prog->globals.client->v_up, ed->fields.client->origin); + Matrix4x4_Scale(&matrix2, scale, 1); } else { @@ -474,20 +445,6 @@ void CSQC_ReadEntities (void) CSQC_END } -void CL_LinkEdict(prvm_edict_t *ent) -{ - if (ent == prog->edicts) - return; // don't add the world - - if (ent->priv.server->free) - return; - - VectorAdd(ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->absmin); - VectorAdd(ent->fields.client->origin, ent->fields.client->maxs, ent->fields.client->absmax); - - World_LinkEdict(&cl.world, ent, ent->fields.client->absmin, ent->fields.client->absmax); -} - void CL_VM_CB_BeginIncreaseEdicts(void) { int i; diff --git a/gl_rmain.c b/gl_rmain.c index dd4cfb31..f6475aa4 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -1212,7 +1212,7 @@ void GL_Init (void) VID_CheckExtensions(); // LordHavoc: report supported extensions - Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions ); + Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions ); // clear to black (loading plaque will be seen over this) CHECKGLERROR @@ -2107,7 +2107,7 @@ void R_RenderView(void) } extern void R_DrawLightningBeams (void); -extern void VM_AddPolygonsToMeshQueue (void); +extern void VM_CL_AddPolygonsToMeshQueue (void); extern void R_DrawPortals (void); void R_RenderScene(void) { @@ -2197,7 +2197,7 @@ void R_RenderScene(void) { qglUseProgramObjectARB(0);CHECKGLERROR } - VM_AddPolygonsToMeshQueue(); + VM_CL_AddPolygonsToMeshQueue(); if (r_drawportals.integer) { diff --git a/mvm_cmds.c b/mvm_cmds.c index b53f5282..abd29d4b 100644 --- a/mvm_cmds.c +++ b/mvm_cmds.c @@ -12,57 +12,6 @@ char *vm_m_extensions = "DP_QC_STRINGCOLORFUNCTIONS " "DP_QC_UNLIMITEDTEMPSTRINGS"; -/* -========= -VM_M_precache_file - -string precache_file(string) -========= -*/ -void VM_M_precache_file (void) -{ // precache_file is only used to copy files with qcc, it does nothing - VM_SAFEPARMCOUNT(1,VM_precache_file); - - PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0); -} - -/* -========= -VM_M_preache_error - -used instead of the other VM_precache_* functions in the builtin list -========= -*/ - -void VM_M_precache_error (void) -{ - PRVM_ERROR ("PF_Precache_*: Precache can only be done in spawn functions"); -} - -/* -========= -VM_M_precache_sound - -string precache_sound (string sample) -========= -*/ -void VM_M_precache_sound (void) -{ - const char *s; - - VM_SAFEPARMCOUNT(1, VM_precache_sound); - - s = PRVM_G_STRING(OFS_PARM0); - PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0); - VM_CheckEmptyString (s); - - if(snd_initialized.integer && !S_PrecacheSound (s,true, true)) - { - VM_Warning("VM_precache_sound: Failed to load %s for %s\n", s, PRVM_NAME); - return; - } -} - /* ========= VM_M_setmousetarget @@ -179,8 +128,7 @@ void VM_M_callfunction(void) mfunction_t *func; const char *s; - if(prog->argc == 0) - PRVM_ERROR("VM_M_callfunction: 1 parameter is required !"); + VM_SAFEPARMCOUNTRANGE(1, 8, VM_M_callfunction); s = PRVM_G_STRING(OFS_PARM0 + (prog->argc - 1)); @@ -235,37 +183,6 @@ void VM_M_isfunction(void) PRVM_G_FLOAT(OFS_RETURN) = true; } -/* -========= -VM_M_writetofile - - writetofile(float fhandle, entity ent) -========= -*/ -void VM_M_writetofile(void) -{ - prvm_edict_t * ent; - qfile_t *file; - - VM_SAFEPARMCOUNT(2, VM_M_writetofile); - - file = VM_GetFileHandle( (int)PRVM_G_FLOAT(OFS_PARM0) ); - if( !file ) - { - VM_Warning("VM_M_writetofile: invalid or closed file handle\n"); - return; - } - - ent = PRVM_G_EDICT(OFS_PARM1); - if(ent->priv.required->free) - { - VM_Warning("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent)); - return; - } - - PRVM_ED_Write (file, ent); -} - /* ========= VM_M_getresolution @@ -386,6 +303,7 @@ resetserverlistmasks() */ void VM_M_resetserverlistmasks( void ) { + VM_SAFEPARMCOUNT(0, VM_M_resetserverlistmasks); ServerList_ResetMasks(); } @@ -511,6 +429,7 @@ resortserverlist */ void VM_M_resortserverlist( void ) { + VM_SAFEPARMCOUNT(0, VM_M_resortserverlist); ServerList_RebuildViewList(); } @@ -690,7 +609,7 @@ void VM_M_addwantedserverlistkey( void ) MESSAGE WRITING used only for client and menu -severs uses VM_SV_... +server uses VM_SV_... Write*(* data, float type, float to) @@ -702,13 +621,13 @@ Write*(* data, float type, float to) #define MSG_ALL 2 // reliable to all #define MSG_INIT 3 // write to the init string -sizebuf_t *VM_WriteDest (void) +sizebuf_t *VM_M_WriteDest (void) { int dest; int destclient; if(!sv.active) - PRVM_ERROR("VM_WriteDest: game is not server (%s)", PRVM_NAME); + PRVM_ERROR("VM_M_WriteDest: game is not server (%s)", PRVM_NAME); dest = (int)PRVM_G_FLOAT(OFS_PARM1); switch (dest) @@ -739,42 +658,50 @@ sizebuf_t *VM_WriteDest (void) void VM_M_WriteByte (void) { - MSG_WriteByte (VM_WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM0)); + VM_SAFEPARMCOUNT(1, VM_M_WriteByte); + MSG_WriteByte (VM_M_WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM0)); } void VM_M_WriteChar (void) { - MSG_WriteChar (VM_WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM0)); + VM_SAFEPARMCOUNT(1, VM_M_WriteChar); + MSG_WriteChar (VM_M_WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM0)); } void VM_M_WriteShort (void) { - MSG_WriteShort (VM_WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM0)); + VM_SAFEPARMCOUNT(1, VM_M_WriteShort); + MSG_WriteShort (VM_M_WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM0)); } void VM_M_WriteLong (void) { - MSG_WriteLong (VM_WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM0)); + VM_SAFEPARMCOUNT(1, VM_M_WriteLong); + MSG_WriteLong (VM_M_WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM0)); } void VM_M_WriteAngle (void) { - MSG_WriteAngle (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol); + VM_SAFEPARMCOUNT(1, VM_M_WriteAngle); + MSG_WriteAngle (VM_M_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol); } void VM_M_WriteCoord (void) { - MSG_WriteCoord (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol); + VM_SAFEPARMCOUNT(1, VM_M_WriteCoord); + MSG_WriteCoord (VM_M_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol); } void VM_M_WriteString (void) { - MSG_WriteString (VM_WriteDest(), PRVM_G_STRING(OFS_PARM0)); + VM_SAFEPARMCOUNT(1, VM_M_WriteString); + MSG_WriteString (VM_M_WriteDest(), PRVM_G_STRING(OFS_PARM0)); } void VM_M_WriteEntity (void) { - MSG_WriteShort (VM_WriteDest(), PRVM_G_EDICTNUM(OFS_PARM0)); + VM_SAFEPARMCOUNT(1, VM_M_WriteEntity); + MSG_WriteShort (VM_M_WriteDest(), PRVM_G_EDICTNUM(OFS_PARM0)); } //string(void) getextresponse = #624; // returns the next extResponse packet that was sent to this client @@ -793,174 +720,650 @@ void VM_M_getextresponse (void) } } +/* +================= +VM_M_copyentity + +copies data from one entity to another + +copyentity(entity src, entity dst) +================= +*/ +static void VM_M_copyentity (void) +{ + prvm_edict_t *in, *out; + VM_SAFEPARMCOUNT(2,VM_M_copyentity); + in = PRVM_G_EDICT(OFS_PARM0); + out = PRVM_G_EDICT(OFS_PARM1); + memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4); +} + prvm_builtin_t vm_m_builtins[] = { - 0, // to be consistent with the old vm - // common builtings (mostly) - VM_checkextension, - VM_error, - VM_objerror, - VM_print, - VM_bprint, - VM_sprint, - VM_centerprint, - VM_normalize, - VM_vlen, - VM_vectoyaw, // #10 - VM_vectoangles, - VM_random, - VM_localcmd, - VM_cvar, - VM_cvar_set, - VM_dprint, - VM_ftos, - VM_fabs, - VM_vtos, - VM_etos, // 20 - VM_stof, - VM_spawn, - VM_remove, - VM_find, - VM_findfloat, - VM_findchain, - VM_findchainfloat, - VM_M_precache_file, - VM_M_precache_sound, - VM_coredump, // 30 - VM_traceon, - VM_traceoff, - VM_eprint, - VM_rint, - VM_floor, - VM_ceil, - VM_nextent, - VM_sin, - VM_cos, - VM_sqrt, // 40 - VM_randomvec, - VM_registercvar, - VM_min, - VM_max, - VM_bound, - VM_pow, - VM_copyentity, - VM_fopen, - VM_fclose, - VM_fgets, // 50 - VM_fputs, - VM_strlen, - VM_strcat, - VM_substring, - VM_stov, - VM_strzone, - VM_strunzone, - VM_tokenize, - VM_argv, - VM_isserver, // 60 - VM_clientcount, - VM_clientstate, - VM_clcommand, - VM_changelevel, - VM_localsound, - VM_getmousepos, - VM_gettime, - VM_loadfromdata, - VM_loadfromfile, - VM_modulo, // 70 - VM_cvar_string, - VM_crash, - VM_stackdump, // 73 - VM_search_begin, - VM_search_end, - VM_search_getsize, - VM_search_getfilename, // 77 - VM_chr, - VM_itof, - VM_ftoe, // 80 - VM_itof, // isString - VM_altstr_count, - VM_altstr_prepare, - VM_altstr_get, - VM_altstr_set, - VM_altstr_ins, - VM_findflags, - VM_findchainflags, - VM_cvar_defstring, // 89 - 0, // 90 - e10, // 100 - e100, // 200 - e100, // 300 - e100, // 400 - // msg functions - VM_M_WriteByte, - VM_M_WriteChar, - VM_M_WriteShort, - VM_M_WriteLong, - VM_M_WriteAngle, - VM_M_WriteCoord, - VM_M_WriteString, - VM_M_WriteEntity, // 408 - 0, - 0, // 410 - e10, // 420 - e10, // 430 - e10, // 440 - e10, // 450 - // draw functions - VM_iscachedpic, - VM_precache_pic, - VM_freepic, - VM_drawcharacter, - VM_drawstring, - VM_drawpic, - VM_drawfill, - VM_drawsetcliparea, - VM_drawresetcliparea, - VM_getimagesize,// 460 - VM_cin_open, - VM_cin_close, - VM_cin_setstate, - VM_cin_getstate, - VM_cin_restart, // 465 - VM_drawline, // 466 - 0,0,0,0, // 470 - VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN) - VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN) - VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN) - VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN) - VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN) - VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS) - VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_QC_STRINGCOLORFUNCTIONS) - VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME) - 0, // 479 - 0, // 480 - e10, // 490 - e10, // 500 - e100, // 600 - // menu functions - VM_M_setkeydest, - VM_M_getkeydest, - VM_M_setmousetarget, - VM_M_getmousetarget, - VM_M_callfunction, - VM_M_writetofile, - VM_M_isfunction, - VM_M_getresolution, - VM_keynumtostring, - VM_M_findkeysforcommand,// 610 - VM_M_getserverliststat, - VM_M_getserverliststring, - VM_parseentitydata, - VM_stringtokeynum, - VM_M_resetserverlistmasks, - VM_M_setserverlistmaskstring, - VM_M_setserverlistmasknumber, - VM_M_resortserverlist, - VM_M_setserverlistsort, - VM_M_refreshserverlist, - VM_M_getserverlistnumber, - VM_M_getserverlistindexforkey, - VM_M_addwantedserverlistkey, // 623 - VM_M_getextresponse +NULL, // #0 NULL function (not callable) +VM_checkextension, // #1 +VM_error, // #2 +VM_objerror, // #3 +VM_print, // #4 +VM_bprint, // #5 +VM_sprint, // #6 +VM_centerprint, // #7 +VM_normalize, // #8 +VM_vlen, // #9 +VM_vectoyaw, // #10 +VM_vectoangles, // #11 +VM_random, // #12 +VM_localcmd, // #13 +VM_cvar, // #14 +VM_cvar_set, // #15 +VM_dprint, // #16 +VM_ftos, // #17 +VM_fabs, // #18 +VM_vtos, // #19 +VM_etos, // #20 +VM_stof, // #21 +VM_spawn, // #22 +VM_remove, // #23 +VM_find, // #24 +VM_findfloat, // #25 +VM_findchain, // #26 +VM_findchainfloat, // #27 +VM_precache_file, // #28 +VM_precache_sound, // #29 +VM_coredump, // #30 +VM_traceon, // #31 +VM_traceoff, // #32 +VM_eprint, // #33 +VM_rint, // #34 +VM_floor, // #35 +VM_ceil, // #36 +VM_nextent, // #37 +VM_sin, // #38 +VM_cos, // #39 +VM_sqrt, // #40 +VM_randomvec, // #41 +VM_registercvar, // #42 +VM_min, // #43 +VM_max, // #44 +VM_bound, // #45 +VM_pow, // #46 +VM_M_copyentity, // #47 +VM_fopen, // #48 +VM_fclose, // #49 +VM_fgets, // #50 +VM_fputs, // #51 +VM_strlen, // #52 +VM_strcat, // #53 +VM_substring, // #54 +VM_stov, // #55 +VM_strzone, // #56 +VM_strunzone, // #57 +VM_tokenize, // #58 +VM_argv, // #59 +VM_isserver, // #60 +VM_clientcount, // #61 +VM_clientstate, // #62 +VM_clcommand, // #63 +VM_changelevel, // #64 +VM_localsound, // #65 +VM_getmousepos, // #66 +VM_gettime, // #67 +VM_loadfromdata, // #68 +VM_loadfromfile, // #69 +VM_modulo, // #70 +VM_cvar_string, // #71 +VM_crash, // #72 +VM_stackdump, // #73 +VM_search_begin, // #74 +VM_search_end, // #75 +VM_search_getsize, // #76 +VM_search_getfilename, // #77 +VM_chr, // #78 +VM_itof, // #79 +VM_ftoe, // #80 +VM_itof, // #81 isString +VM_altstr_count, // #82 +VM_altstr_prepare, // #83 +VM_altstr_get, // #84 +VM_altstr_set, // #85 +VM_altstr_ins, // #86 +VM_findflags, // #87 +VM_findchainflags, // #88 +VM_cvar_defstring, // #89 +NULL, // #90 +NULL, // #91 +NULL, // #92 +NULL, // #93 +NULL, // #94 +NULL, // #95 +NULL, // #96 +NULL, // #97 +NULL, // #98 +NULL, // #99 +NULL, // #100 +NULL, // #101 +NULL, // #102 +NULL, // #103 +NULL, // #104 +NULL, // #105 +NULL, // #106 +NULL, // #107 +NULL, // #108 +NULL, // #109 +NULL, // #110 +NULL, // #111 +NULL, // #112 +NULL, // #113 +NULL, // #114 +NULL, // #115 +NULL, // #116 +NULL, // #117 +NULL, // #118 +NULL, // #119 +NULL, // #120 +NULL, // #121 +NULL, // #122 +NULL, // #123 +NULL, // #124 +NULL, // #125 +NULL, // #126 +NULL, // #127 +NULL, // #128 +NULL, // #129 +NULL, // #130 +NULL, // #131 +NULL, // #132 +NULL, // #133 +NULL, // #134 +NULL, // #135 +NULL, // #136 +NULL, // #137 +NULL, // #138 +NULL, // #139 +NULL, // #140 +NULL, // #141 +NULL, // #142 +NULL, // #143 +NULL, // #144 +NULL, // #145 +NULL, // #146 +NULL, // #147 +NULL, // #148 +NULL, // #149 +NULL, // #150 +NULL, // #151 +NULL, // #152 +NULL, // #153 +NULL, // #154 +NULL, // #155 +NULL, // #156 +NULL, // #157 +NULL, // #158 +NULL, // #159 +NULL, // #160 +NULL, // #161 +NULL, // #162 +NULL, // #163 +NULL, // #164 +NULL, // #165 +NULL, // #166 +NULL, // #167 +NULL, // #168 +NULL, // #169 +NULL, // #170 +NULL, // #171 +NULL, // #172 +NULL, // #173 +NULL, // #174 +NULL, // #175 +NULL, // #176 +NULL, // #177 +NULL, // #178 +NULL, // #179 +NULL, // #180 +NULL, // #181 +NULL, // #182 +NULL, // #183 +NULL, // #184 +NULL, // #185 +NULL, // #186 +NULL, // #187 +NULL, // #188 +NULL, // #189 +NULL, // #190 +NULL, // #191 +NULL, // #192 +NULL, // #193 +NULL, // #194 +NULL, // #195 +NULL, // #196 +NULL, // #197 +NULL, // #198 +NULL, // #199 +NULL, // #200 +NULL, // #201 +NULL, // #202 +NULL, // #203 +NULL, // #204 +NULL, // #205 +NULL, // #206 +NULL, // #207 +NULL, // #208 +NULL, // #209 +NULL, // #210 +NULL, // #211 +NULL, // #212 +NULL, // #213 +NULL, // #214 +NULL, // #215 +NULL, // #216 +NULL, // #217 +NULL, // #218 +NULL, // #219 +NULL, // #220 +NULL, // #221 +NULL, // #222 +NULL, // #223 +NULL, // #224 +NULL, // #225 +NULL, // #226 +NULL, // #227 +NULL, // #228 +NULL, // #229 +NULL, // #230 +NULL, // #231 +NULL, // #232 +NULL, // #233 +NULL, // #234 +NULL, // #235 +NULL, // #236 +NULL, // #237 +NULL, // #238 +NULL, // #239 +NULL, // #240 +NULL, // #241 +NULL, // #242 +NULL, // #243 +NULL, // #244 +NULL, // #245 +NULL, // #246 +NULL, // #247 +NULL, // #248 +NULL, // #249 +NULL, // #250 +NULL, // #251 +NULL, // #252 +NULL, // #253 +NULL, // #254 +NULL, // #255 +NULL, // #256 +NULL, // #257 +NULL, // #258 +NULL, // #259 +NULL, // #260 +NULL, // #261 +NULL, // #262 +NULL, // #263 +NULL, // #264 +NULL, // #265 +NULL, // #266 +NULL, // #267 +NULL, // #268 +NULL, // #269 +NULL, // #270 +NULL, // #271 +NULL, // #272 +NULL, // #273 +NULL, // #274 +NULL, // #275 +NULL, // #276 +NULL, // #277 +NULL, // #278 +NULL, // #279 +NULL, // #280 +NULL, // #281 +NULL, // #282 +NULL, // #283 +NULL, // #284 +NULL, // #285 +NULL, // #286 +NULL, // #287 +NULL, // #288 +NULL, // #289 +NULL, // #290 +NULL, // #291 +NULL, // #292 +NULL, // #293 +NULL, // #294 +NULL, // #295 +NULL, // #296 +NULL, // #297 +NULL, // #298 +NULL, // #299 +NULL, // #300 +NULL, // #301 +NULL, // #302 +NULL, // #303 +NULL, // #304 +NULL, // #305 +NULL, // #306 +NULL, // #307 +NULL, // #308 +NULL, // #309 +NULL, // #310 +NULL, // #311 +NULL, // #312 +NULL, // #313 +NULL, // #314 +NULL, // #315 +NULL, // #316 +NULL, // #317 +NULL, // #318 +NULL, // #319 +NULL, // #320 +NULL, // #321 +NULL, // #322 +NULL, // #323 +NULL, // #324 +NULL, // #325 +NULL, // #326 +NULL, // #327 +NULL, // #328 +NULL, // #329 +NULL, // #330 +NULL, // #331 +NULL, // #332 +NULL, // #333 +NULL, // #334 +NULL, // #335 +NULL, // #336 +NULL, // #337 +NULL, // #338 +NULL, // #339 +NULL, // #340 +NULL, // #341 +NULL, // #342 +NULL, // #343 +NULL, // #344 +NULL, // #345 +NULL, // #346 +NULL, // #347 +NULL, // #348 +NULL, // #349 +NULL, // #350 +NULL, // #351 +NULL, // #352 +NULL, // #353 +NULL, // #354 +NULL, // #355 +NULL, // #356 +NULL, // #357 +NULL, // #358 +NULL, // #359 +NULL, // #360 +NULL, // #361 +NULL, // #362 +NULL, // #363 +NULL, // #364 +NULL, // #365 +NULL, // #366 +NULL, // #367 +NULL, // #368 +NULL, // #369 +NULL, // #370 +NULL, // #371 +NULL, // #372 +NULL, // #373 +NULL, // #374 +NULL, // #375 +NULL, // #376 +NULL, // #377 +NULL, // #378 +NULL, // #379 +NULL, // #380 +NULL, // #381 +NULL, // #382 +NULL, // #383 +NULL, // #384 +NULL, // #385 +NULL, // #386 +NULL, // #387 +NULL, // #388 +NULL, // #389 +NULL, // #390 +NULL, // #391 +NULL, // #392 +NULL, // #393 +NULL, // #394 +NULL, // #395 +NULL, // #396 +NULL, // #397 +NULL, // #398 +NULL, // #399 +NULL, // #400 +VM_M_WriteByte, // #401 +VM_M_WriteChar, // #402 +VM_M_WriteShort, // #403 +VM_M_WriteLong, // #404 +VM_M_WriteAngle, // #405 +VM_M_WriteCoord, // #406 +VM_M_WriteString, // #407 +VM_M_WriteEntity, // #408 +NULL, // #409 +NULL, // #410 +NULL, // #411 +NULL, // #412 +NULL, // #413 +NULL, // #414 +NULL, // #415 +NULL, // #416 +NULL, // #417 +NULL, // #418 +NULL, // #419 +NULL, // #420 +NULL, // #421 +NULL, // #422 +NULL, // #423 +NULL, // #424 +NULL, // #425 +NULL, // #426 +NULL, // #427 +NULL, // #428 +NULL, // #429 +NULL, // #430 +NULL, // #431 +NULL, // #432 +NULL, // #433 +NULL, // #434 +NULL, // #435 +NULL, // #436 +NULL, // #437 +NULL, // #438 +NULL, // #439 +NULL, // #440 +NULL, // #441 +NULL, // #442 +NULL, // #443 +NULL, // #444 +NULL, // #445 +NULL, // #446 +NULL, // #447 +NULL, // #448 +NULL, // #449 +NULL, // #450 +VM_iscachedpic, // #451 draw functions... +VM_precache_pic, // #452 +VM_freepic, // #453 +VM_drawcharacter, // #454 +VM_drawstring, // #455 +VM_drawpic, // #456 +VM_drawfill, // #457 +VM_drawsetcliparea, // #458 +VM_drawresetcliparea, // #459 +VM_getimagesize, // #460 +VM_cin_open, // #461 +VM_cin_close, // #462 +VM_cin_setstate, // #463 +VM_cin_getstate, // #464 +VM_cin_restart, // #465 +VM_drawline, // #466 +NULL, // #467 +NULL, // #468 +NULL, // #469 +NULL, // #470 +VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN) +VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN) +VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN) +VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN) +VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN) +VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS) +VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_QC_STRINGCOLORFUNCTIONS) +VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME) +NULL, // #479 +NULL, // #480 +NULL, // #481 +NULL, // #482 +NULL, // #483 +NULL, // #484 +NULL, // #485 +NULL, // #486 +NULL, // #487 +NULL, // #488 +NULL, // #489 +NULL, // #490 +NULL, // #491 +NULL, // #492 +NULL, // #493 +NULL, // #494 +NULL, // #495 +NULL, // #496 +NULL, // #497 +NULL, // #498 +NULL, // #499 +NULL, // #500 +NULL, // #501 +NULL, // #502 +NULL, // #503 +NULL, // #504 +NULL, // #505 +NULL, // #506 +NULL, // #507 +NULL, // #508 +NULL, // #509 +NULL, // #510 +NULL, // #511 +NULL, // #512 +NULL, // #513 +NULL, // #514 +NULL, // #515 +NULL, // #516 +NULL, // #517 +NULL, // #518 +NULL, // #519 +NULL, // #520 +NULL, // #521 +NULL, // #522 +NULL, // #523 +NULL, // #524 +NULL, // #525 +NULL, // #526 +NULL, // #527 +NULL, // #528 +NULL, // #529 +NULL, // #530 +NULL, // #531 +NULL, // #532 +NULL, // #533 +NULL, // #534 +NULL, // #535 +NULL, // #536 +NULL, // #537 +NULL, // #538 +NULL, // #539 +NULL, // #540 +NULL, // #541 +NULL, // #542 +NULL, // #543 +NULL, // #544 +NULL, // #545 +NULL, // #546 +NULL, // #547 +NULL, // #548 +NULL, // #549 +NULL, // #550 +NULL, // #551 +NULL, // #552 +NULL, // #553 +NULL, // #554 +NULL, // #555 +NULL, // #556 +NULL, // #557 +NULL, // #558 +NULL, // #559 +NULL, // #560 +NULL, // #561 +NULL, // #562 +NULL, // #563 +NULL, // #564 +NULL, // #565 +NULL, // #566 +NULL, // #567 +NULL, // #568 +NULL, // #569 +NULL, // #570 +NULL, // #571 +NULL, // #572 +NULL, // #573 +NULL, // #574 +NULL, // #575 +NULL, // #576 +NULL, // #577 +NULL, // #578 +NULL, // #579 +NULL, // #580 +NULL, // #581 +NULL, // #582 +NULL, // #583 +NULL, // #584 +NULL, // #585 +NULL, // #586 +NULL, // #587 +NULL, // #588 +NULL, // #589 +NULL, // #590 +NULL, // #591 +NULL, // #592 +NULL, // #593 +NULL, // #594 +NULL, // #595 +NULL, // #596 +NULL, // #597 +NULL, // #598 +NULL, // #599 +NULL, // #600 +VM_M_setkeydest, // #601 menu functions... +VM_M_getkeydest, // #602 +VM_M_setmousetarget, // #603 +VM_M_getmousetarget, // #604 +VM_M_callfunction, // #605 +VM_writetofile, // #606 +VM_M_isfunction, // #607 +VM_M_getresolution, // #608 +VM_keynumtostring, // #609 +VM_M_findkeysforcommand, // #610 +VM_M_getserverliststat, // #611 +VM_M_getserverliststring, // #612 +VM_parseentitydata, // #613 +VM_stringtokeynum, // #614 +VM_M_resetserverlistmasks, // #615 +VM_M_setserverlistmaskstring,// #616 +VM_M_setserverlistmasknumber,// #617 +VM_M_resortserverlist, // #618 +VM_M_setserverlistsort, // #619 +VM_M_refreshserverlist, // #620 +VM_M_getserverlistnumber, // #621 +VM_M_getserverlistindexforkey,// #622 +VM_M_addwantedserverlistkey,// #623 +VM_M_getextresponse // #624 }; const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t); diff --git a/prvm_cmds.c b/prvm_cmds.c index 47e94fe6..887192dd 100644 --- a/prvm_cmds.c +++ b/prvm_cmds.c @@ -206,6 +206,8 @@ void VM_sprint (void) int clientnum; char string[VM_STRINGTEMP_LENGTH]; + VM_SAFEPARMCOUNTRANGE(1, 8, VM_sprint); + //find client for this entity clientnum = (int)PRVM_G_FLOAT(OFS_PARM0); if (!sv.active || clientnum < 0 || clientnum >= svs.maxclients || !svs.clients[clientnum].active) @@ -229,13 +231,14 @@ VM_centerprint single print to the screen -centerprint(clientent, value) +centerprint(value) ================= */ void VM_centerprint (void) { char string[VM_STRINGTEMP_LENGTH]; + VM_SAFEPARMCOUNTRANGE(1, 8, VM_centerprint); VM_VarString(0, string, sizeof(string)); SCR_CenterPrint(string); } @@ -377,49 +380,6 @@ void VM_random (void) PRVM_G_FLOAT(OFS_RETURN) = lhrandom(0, 1); } -/* -================= -PF_sound - -Each entity can have eight independant sound sources, like voice, -weapon, feet, etc. - -Channel 0 is an auto-allocate channel, the others override anything -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 PF_sound (void) -{ - char *sample; - int channel; - prvm_edict_t *entity; - int volume; - float attenuation; - - entity = PRVM_G_EDICT(OFS_PARM0); - channel = PRVM_G_FLOAT(OFS_PARM1); - sample = PRVM_G_STRING(OFS_PARM2); - volume = PRVM_G_FLOAT(OFS_PARM3) * 255; - attenuation = PRVM_G_FLOAT(OFS_PARM4); - - if (volume < 0 || volume > 255) - Host_Error ("SV_StartSound: volume = %i", volume); - - if (attenuation < 0 || attenuation > 4) - Host_Error ("SV_StartSound: attenuation = %f", attenuation); - - if (channel < 0 || channel > 7) - Host_Error ("SV_StartSound: channel = %i", channel); - - SV_StartSound (entity, channel, sample, volume, attenuation); -} -*/ - /* ========= VM_localsound @@ -472,6 +432,7 @@ cmd (string, ...) void VM_localcmd (void) { char string[VM_STRINGTEMP_LENGTH]; + VM_SAFEPARMCOUNTRANGE(1, 8, VM_localcmd); VM_VarString(0, string, sizeof(string)); Cbuf_AddText(string); } @@ -552,6 +513,7 @@ dprint(...[string]) void VM_dprint (void) { char string[VM_STRINGTEMP_LENGTH]; + VM_SAFEPARMCOUNTRANGE(1, 8, VM_dprint); if (developer.integer) { VM_VarString(0, string, sizeof(string)); @@ -651,6 +613,7 @@ float stof(...[string]) void VM_stof(void) { char string[VM_STRINGTEMP_LENGTH]; + VM_SAFEPARMCOUNTRANGE(1, 8, VM_stof); VM_VarString(0, string, sizeof(string)); PRVM_G_FLOAT(OFS_RETURN) = atof(string); } @@ -700,7 +663,8 @@ void VM_strftime(void) struct tm *tm; char fmt[VM_STRINGTEMP_LENGTH]; char result[VM_STRINGTEMP_LENGTH]; - VM_VarString(0, fmt, sizeof(fmt)); + VM_SAFEPARMCOUNTRANGE(2, 8, VM_strftime); + VM_VarString(1, fmt, sizeof(fmt)); t = time(NULL); if (PRVM_G_FLOAT(OFS_PARM0)) tm = localtime(&t); @@ -726,6 +690,7 @@ entity spawn() void VM_spawn (void) { prvm_edict_t *ed; + VM_SAFEPARMCOUNT(0, VM_spawn); prog->xfunction->builtinsprofile += 20; ed = PRVM_ED_Alloc(); VM_RETURN_EDICT(ed); @@ -1022,6 +987,46 @@ void VM_findchainflags (void) VM_RETURN_EDICT(chain); } +/* +========= +VM_precache_sound + +string precache_sound (string sample) +========= +*/ +void VM_precache_sound (void) +{ + const char *s; + + VM_SAFEPARMCOUNT(1, VM_precache_sound); + + s = PRVM_G_STRING(OFS_PARM0); + PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0); + VM_CheckEmptyString(s); + + if(snd_initialized.integer && !S_PrecacheSound(s, true, false)) + { + VM_Warning("VM_precache_sound: Failed to load %s for %s\n", s, PRVM_NAME); + return; + } +} + +/* +================= +VM_precache_file + +returns the same string as output + +does nothing, only used by qcc to build .pak archives +================= +*/ +void VM_precache_file (void) +{ + VM_SAFEPARMCOUNT(1,VM_precache_file); + // precache_file is only used to copy files with qcc, it does nothing + PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0); +} + /* ========= VM_coredump @@ -1170,6 +1175,8 @@ void VM_nextent (void) int i; prvm_edict_t *ent; + VM_SAFEPARMCOUNT(1, VM_nextent); + i = PRVM_G_EDICTNUM(OFS_PARM0); while (1) { @@ -1358,7 +1365,7 @@ void VM_randomvec (void) ========= VM_registercvar -float registercvar (string name, string value, float flags) +float registercvar (string name, string value[, float flags]) ========= */ void VM_registercvar (void) @@ -1366,11 +1373,11 @@ void VM_registercvar (void) const char *name, *value; int flags; - VM_SAFEPARMCOUNT(3,VM_registercvar); + VM_SAFEPARMCOUNTRANGE(2, 3, VM_registercvar); name = PRVM_G_STRING(OFS_PARM0); value = PRVM_G_STRING(OFS_PARM1); - flags = (int)PRVM_G_FLOAT(OFS_PARM2); + flags = prog->argc >= 3 ? (int)PRVM_G_FLOAT(OFS_PARM2) : 0; PRVM_G_FLOAT(OFS_RETURN) = 0; if(flags > CVAR_MAXFLAGSVAL) @@ -1392,6 +1399,7 @@ void VM_registercvar (void) PRVM_G_FLOAT(OFS_RETURN) = 1; // success } + /* ================= VM_min @@ -1403,20 +1411,19 @@ float min(float a, float b, ...[float]) */ void VM_min (void) { + VM_SAFEPARMCOUNTRANGE(2, 8, VM_min); // LordHavoc: 3+ argument enhancement suggested by FrikaC - if (prog->argc == 2) - PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1)); - else if (prog->argc >= 3) + if (prog->argc >= 3) { int i; float f = PRVM_G_FLOAT(OFS_PARM0); for (i = 1;i < prog->argc;i++) - if (PRVM_G_FLOAT((OFS_PARM0+i*3)) < f) + if (f > PRVM_G_FLOAT((OFS_PARM0+i*3))) f = PRVM_G_FLOAT((OFS_PARM0+i*3)); PRVM_G_FLOAT(OFS_RETURN) = f; } else - PRVM_ERROR("VM_min: %s must supply at least 2 floats", PRVM_NAME); + PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1)); } /* @@ -1430,20 +1437,19 @@ float max(float a, float b, ...[float]) */ void VM_max (void) { + VM_SAFEPARMCOUNTRANGE(2, 8, VM_max); // LordHavoc: 3+ argument enhancement suggested by FrikaC - if (prog->argc == 2) - PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1)); - else if (prog->argc >= 3) + if (prog->argc >= 3) { int i; float f = PRVM_G_FLOAT(OFS_PARM0); for (i = 1;i < prog->argc;i++) - if (PRVM_G_FLOAT((OFS_PARM0+i*3)) > f) + if (f < PRVM_G_FLOAT((OFS_PARM0+i*3))) f = PRVM_G_FLOAT((OFS_PARM0+i*3)); PRVM_G_FLOAT(OFS_RETURN) = f; } else - PRVM_ERROR("VM_max: %s must supply at least 2 floats", PRVM_NAME); + PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1)); } /* @@ -1476,24 +1482,6 @@ void VM_pow (void) PRVM_G_FLOAT(OFS_RETURN) = pow(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1)); } -/* -================= -VM_copyentity - -copies data from one entity to another - -copyentity(entity src, entity dst) -================= -*/ -void VM_copyentity (void) -{ - prvm_edict_t *in, *out; - VM_SAFEPARMCOUNT(2,VM_copyentity); - in = PRVM_G_EDICT(OFS_PARM0); - out = PRVM_G_EDICT(OFS_PARM1); - memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4); -} - void VM_Files_Init(void) { int i; @@ -1512,7 +1500,7 @@ void VM_Files_CloseAll(void) } } -qfile_t *VM_GetFileHandle( int index ) +static qfile_t *VM_GetFileHandle( int index ) { if (index < 0 || index >= PRVM_MAX_OPENFILES) { @@ -1707,6 +1695,37 @@ void VM_fputs(void) Con_Printf("fputs: %s: %s\n", PRVM_NAME, string); } +/* +========= +VM_writetofile + + writetofile(float fhandle, entity ent) +========= +*/ +void VM_writetofile(void) +{ + prvm_edict_t * ent; + qfile_t *file; + + VM_SAFEPARMCOUNT(2, VM_writetofile); + + file = VM_GetFileHandle( (int)PRVM_G_FLOAT(OFS_PARM0) ); + if( !file ) + { + VM_Warning("VM_writetofile: invalid or closed file handle\n"); + return; + } + + ent = PRVM_G_EDICT(OFS_PARM1); + if(ent->priv.required->free) + { + VM_Warning("VM_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent)); + return; + } + + PRVM_ED_Write (file, ent); +} + /* ========= VM_strlen @@ -1862,9 +1881,7 @@ string strcat(string,string,...[string]) void VM_strcat(void) { char s[VM_STRINGTEMP_LENGTH]; - - if(prog->argc < 1) - PRVM_ERROR("VM_strcat wrong parameter count (min. 1 expected ) !"); + VM_SAFEPARMCOUNTRANGE(1, 8, VM_strcat); VM_VarString(0, s, sizeof(s)); PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(s); @@ -2053,7 +2070,7 @@ void VM_isserver(void) { VM_SAFEPARMCOUNT(0,VM_serverstate); - PRVM_G_FLOAT(OFS_RETURN) = sv.active; + PRVM_G_FLOAT(OFS_RETURN) = sv.active && (svs.maxclients > 1 || cls.state == ca_dedicated); } /* @@ -2831,18 +2848,51 @@ void VM_cin_restart( void ) CL_RestartVideo( video ); } +/* +============== +VM_makevectors + +Writes new values for v_forward, v_up, and v_right based on angles +void makevectors(vector angle) +============== +*/ +void VM_makevectors (void) +{ + prvm_eval_t *valforward, *valright, *valup; + valforward = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.v_forward); + valright = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.v_right); + valup = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.v_up); + if (!valforward || !valright || !valup) + { + VM_Warning("makevectors: could not find v_forward, v_right, or v_up global variables\n"); + return; + } + VM_SAFEPARMCOUNT(1, VM_makevectors); + AngleVectors (PRVM_G_VECTOR(OFS_PARM0), valforward->vector, valright->vector, valup->vector); +} + /* ============== VM_vectorvectors Writes new values for v_forward, v_up, and v_right based on the given forward vector -vectorvectors(vector, vector) +vectorvectors(vector) ============== */ void VM_vectorvectors (void) { - VectorNormalize2(PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward); - VectorVectors(prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up); + prvm_eval_t *valforward, *valright, *valup; + valforward = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.v_forward); + valright = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.v_right); + valup = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.v_up); + if (!valforward || !valright || !valup) + { + VM_Warning("vectorvectors: could not find v_forward, v_right, or v_up global variables\n"); + return; + } + VM_SAFEPARMCOUNT(1, VM_vectorvectors); + VectorNormalize2(PRVM_G_VECTOR(OFS_PARM0), valforward->vector); + VectorVectors(valforward->vector, valright->vector, valup->vector); } /* @@ -2868,364 +2918,6 @@ void VM_drawline (void) DrawQ_Line(width, c1[0], c1[1], c2[0], c2[1], rgb[0], rgb[1], rgb[2], alpha, flags); } -//==================== -//QC POLYGON functions -//==================== - -typedef struct -{ - rtexture_t *tex; - float data[36]; //[515]: enough for polygons - unsigned char flags; //[515]: + VM_POLYGON_2D and VM_POLYGON_FL4V flags -}vm_polygon_t; - -//static float vm_polygon_linewidth = 1; -static mempool_t *vm_polygons_pool = NULL; -static unsigned char vm_current_vertices = 0; -static qboolean vm_polygons_initialized = false; -static vm_polygon_t *vm_polygons = NULL; -static unsigned long vm_polygons_num = 0, vm_drawpolygons_num = 0; //[515]: ok long on 64bit ? -static qboolean vm_polygonbegin = false; //[515]: for "no-crap-on-the-screen" check -#define VM_DEFPOLYNUM 64 //[515]: enough for default ? - -#define VM_POLYGON_FL3V 16 //more than 2 vertices (used only for lines) -#define VM_POLYGON_FLLINES 32 -#define VM_POLYGON_FL2D 64 -#define VM_POLYGON_FL4V 128 //4 vertices - -void VM_InitPolygons (void) -{ - vm_polygons_pool = Mem_AllocPool("VMPOLY", 0, NULL); - vm_polygons = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, VM_DEFPOLYNUM*sizeof(vm_polygon_t)); - memset(vm_polygons, 0, VM_DEFPOLYNUM*sizeof(vm_polygon_t)); - vm_polygons_num = VM_DEFPOLYNUM; - vm_drawpolygons_num = 0; - vm_polygonbegin = false; - vm_polygons_initialized = true; -} - -void VM_DrawPolygonCallback (const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) -{ - int surfacelistindex; - // LordHavoc: FIXME: this is stupid code - for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++) - { - const vm_polygon_t *p = &vm_polygons[surfacelist[surfacelistindex]]; - int flags = p->flags & 0x0f; - - if(flags == DRAWFLAG_ADDITIVE) - GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); - else if(flags == DRAWFLAG_MODULATE) - GL_BlendFunc(GL_DST_COLOR, GL_ZERO); - else if(flags == DRAWFLAG_2XMODULATE) - GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR); - else - GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - R_Mesh_TexBind(0, R_GetTexture(p->tex)); - - CHECKGLERROR - //[515]: is speed is max ? - if(p->flags & VM_POLYGON_FLLINES) //[515]: lines - { - qglLineWidth(p->data[13]);CHECKGLERROR - qglBegin(GL_LINE_LOOP); - qglTexCoord1f (p->data[12]); - qglColor4f (p->data[20], p->data[21], p->data[22], p->data[23]); - qglVertex3f (p->data[0] , p->data[1], p->data[2]); - - qglTexCoord1f (p->data[14]); - qglColor4f (p->data[24], p->data[25], p->data[26], p->data[27]); - qglVertex3f (p->data[3] , p->data[4], p->data[5]); - - if(p->flags & VM_POLYGON_FL3V) - { - qglTexCoord1f (p->data[16]); - qglColor4f (p->data[28], p->data[29], p->data[30], p->data[31]); - qglVertex3f (p->data[6] , p->data[7], p->data[8]); - - if(p->flags & VM_POLYGON_FL4V) - { - qglTexCoord1f (p->data[18]); - qglColor4f (p->data[32], p->data[33], p->data[34], p->data[35]); - qglVertex3f (p->data[9] , p->data[10], p->data[11]); - } - } - qglEnd(); - CHECKGLERROR - } - else - { - qglBegin(GL_POLYGON); - qglTexCoord2f (p->data[12], p->data[13]); - qglColor4f (p->data[20], p->data[21], p->data[22], p->data[23]); - qglVertex3f (p->data[0] , p->data[1], p->data[2]); - - qglTexCoord2f (p->data[14], p->data[15]); - qglColor4f (p->data[24], p->data[25], p->data[26], p->data[27]); - qglVertex3f (p->data[3] , p->data[4], p->data[5]); - - qglTexCoord2f (p->data[16], p->data[17]); - qglColor4f (p->data[28], p->data[29], p->data[30], p->data[31]); - qglVertex3f (p->data[6] , p->data[7], p->data[8]); - - if(p->flags & VM_POLYGON_FL4V) - { - qglTexCoord2f (p->data[18], p->data[19]); - qglColor4f (p->data[32], p->data[33], p->data[34], p->data[35]); - qglVertex3f (p->data[9] , p->data[10], p->data[11]); - } - qglEnd(); - CHECKGLERROR - } - } -} - -void VM_AddPolygonTo2DScene (vm_polygon_t *p) -{ - drawqueuemesh_t mesh; - static int picelements[6] = {0, 1, 2, 0, 2, 3}; - - mesh.texture = p->tex; - mesh.data_element3i = picelements; - mesh.data_vertex3f = p->data; - mesh.data_texcoord2f = p->data + 12; - mesh.data_color4f = p->data + 20; - if(p->flags & VM_POLYGON_FL4V) - { - mesh.num_vertices = 4; - mesh.num_triangles = 2; - } - else - { - mesh.num_vertices = 3; - mesh.num_triangles = 1; - } - if(p->flags & VM_POLYGON_FLLINES) //[515]: lines - DrawQ_LineLoop (&mesh, (p->flags&0x0f)); - else - DrawQ_Mesh (&mesh, (p->flags&0x0f)); -} - -//void(string texturename, float flag, float 2d, float lines) R_BeginPolygon -void VM_R_PolygonBegin (void) -{ - vm_polygon_t *p; - const char *picname; - if(prog->argc < 2) - VM_SAFEPARMCOUNT(2, VM_R_PolygonBegin); - - if(!vm_polygons_initialized) - VM_InitPolygons(); - if(vm_polygonbegin) - { - VM_Warning("VM_R_PolygonBegin: called twice without VM_R_PolygonEnd after first\n"); - return; - } - if(vm_drawpolygons_num >= vm_polygons_num) - { - p = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, 2 * vm_polygons_num * sizeof(vm_polygon_t)); - memset(p, 0, 2 * vm_polygons_num * sizeof(vm_polygon_t)); - memcpy(p, vm_polygons, vm_polygons_num * sizeof(vm_polygon_t)); - Mem_Free(vm_polygons); - vm_polygons = p; - vm_polygons_num *= 2; - } - p = &vm_polygons[vm_drawpolygons_num]; - picname = PRVM_G_STRING(OFS_PARM0); - if(picname[0]) - p->tex = Draw_CachePic(picname, true)->tex; - else - p->tex = r_texture_white; - p->flags = (unsigned char)PRVM_G_FLOAT(OFS_PARM1); - vm_current_vertices = 0; - vm_polygonbegin = true; - if(prog->argc >= 3) - { - if(PRVM_G_FLOAT(OFS_PARM2)) - p->flags |= VM_POLYGON_FL2D; - if(prog->argc >= 4 && PRVM_G_FLOAT(OFS_PARM3)) - { - p->data[13] = PRVM_G_FLOAT(OFS_PARM3); //[515]: linewidth - p->flags |= VM_POLYGON_FLLINES; - } - } -} - -//void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex -void VM_R_PolygonVertex (void) -{ - float *coords, *tx, *rgb, alpha; - vm_polygon_t *p; - VM_SAFEPARMCOUNT(4, VM_R_PolygonVertex); - - if(!vm_polygonbegin) - { - VM_Warning("VM_R_PolygonVertex: VM_R_PolygonBegin wasn't called\n"); - return; - } - coords = PRVM_G_VECTOR(OFS_PARM0); - tx = PRVM_G_VECTOR(OFS_PARM1); - rgb = PRVM_G_VECTOR(OFS_PARM2); - alpha = PRVM_G_FLOAT(OFS_PARM3); - - p = &vm_polygons[vm_drawpolygons_num]; - if(vm_current_vertices > 4) - { - VM_Warning("VM_R_PolygonVertex: may have 4 vertices max\n"); - return; - } - - p->data[vm_current_vertices*3] = coords[0]; - p->data[1+vm_current_vertices*3] = coords[1]; - p->data[2+vm_current_vertices*3] = coords[2]; - - p->data[12+vm_current_vertices*2] = tx[0]; - if(!(p->flags & VM_POLYGON_FLLINES)) - p->data[13+vm_current_vertices*2] = tx[1]; - - p->data[20+vm_current_vertices*4] = rgb[0]; - p->data[21+vm_current_vertices*4] = rgb[1]; - p->data[22+vm_current_vertices*4] = rgb[2]; - p->data[23+vm_current_vertices*4] = alpha; - - vm_current_vertices++; - if(vm_current_vertices == 4) - p->flags |= VM_POLYGON_FL4V; - else - if(vm_current_vertices == 3) - p->flags |= VM_POLYGON_FL3V; -} - -//void() R_EndPolygon -void VM_R_PolygonEnd (void) -{ - if(!vm_polygonbegin) - { - VM_Warning("VM_R_PolygonEnd: VM_R_PolygonBegin wasn't called\n"); - return; - } - vm_polygonbegin = false; - if(vm_current_vertices > 2 || (vm_current_vertices >= 2 && vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FLLINES)) - { - if(vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FL2D) //[515]: don't use qcpolygons memory if 2D - VM_AddPolygonTo2DScene(&vm_polygons[vm_drawpolygons_num]); - else - vm_drawpolygons_num++; - } - else - VM_Warning("VM_R_PolygonEnd: %i vertices isn't a good choice\n", vm_current_vertices); -} - -void VM_AddPolygonsToMeshQueue (void) -{ - int i; - if(!vm_drawpolygons_num) - return; - R_Mesh_Matrix(&identitymatrix); - GL_CullFace(GL_NONE); - for(i = 0;i < (int)vm_drawpolygons_num;i++) - VM_DrawPolygonCallback(NULL, NULL, 1, &i); - vm_drawpolygons_num = 0; -} - -void Debug_PolygonBegin(const char *picname, int flags, qboolean draw2d, float linewidth) -{ - vm_polygon_t *p; - - if(!vm_polygons_initialized) - VM_InitPolygons(); - if(vm_polygonbegin) - { - Con_Printf("Debug_PolygonBegin: called twice without Debug_PolygonEnd after first\n"); - return; - } - // limit polygons to a vaguely sane amount, beyond this each one just - // replaces the last one - vm_drawpolygons_num = min(vm_drawpolygons_num, (1<<20)-1); - if(vm_drawpolygons_num >= vm_polygons_num) - { - p = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, 2 * vm_polygons_num * sizeof(vm_polygon_t)); - memset(p, 0, 2 * vm_polygons_num * sizeof(vm_polygon_t)); - memcpy(p, vm_polygons, vm_polygons_num * sizeof(vm_polygon_t)); - Mem_Free(vm_polygons); - vm_polygons = p; - vm_polygons_num *= 2; - } - p = &vm_polygons[vm_drawpolygons_num]; - if(picname && picname[0]) - p->tex = Draw_CachePic(picname, true)->tex; - else - p->tex = r_texture_white; - p->flags = flags; - vm_current_vertices = 0; - vm_polygonbegin = true; - if(draw2d) - p->flags |= VM_POLYGON_FL2D; - if(linewidth) - { - p->data[13] = linewidth; //[515]: linewidth - p->flags |= VM_POLYGON_FLLINES; - } -} - -void Debug_PolygonVertex(float x, float y, float z, float s, float t, float r, float g, float b, float a) -{ - vm_polygon_t *p; - - if(!vm_polygonbegin) - { - Con_Printf("Debug_PolygonVertex: Debug_PolygonBegin wasn't called\n"); - return; - } - - p = &vm_polygons[vm_drawpolygons_num]; - if(vm_current_vertices > 4) - { - Con_Printf("Debug_PolygonVertex: may have 4 vertices max\n"); - return; - } - - p->data[vm_current_vertices*3] = x; - p->data[1+vm_current_vertices*3] = y; - p->data[2+vm_current_vertices*3] = z; - - p->data[12+vm_current_vertices*2] = s; - if(!(p->flags & VM_POLYGON_FLLINES)) - p->data[13+vm_current_vertices*2] = t; - - p->data[20+vm_current_vertices*4] = r; - p->data[21+vm_current_vertices*4] = g; - p->data[22+vm_current_vertices*4] = b; - p->data[23+vm_current_vertices*4] = a; - - vm_current_vertices++; - if(vm_current_vertices == 4) - p->flags |= VM_POLYGON_FL4V; - else - if(vm_current_vertices == 3) - p->flags |= VM_POLYGON_FL3V; -} - -void Debug_PolygonEnd(void) -{ - if(!vm_polygonbegin) - { - Con_Printf("Debug_PolygonEnd: Debug_PolygonBegin wasn't called\n"); - return; - } - vm_polygonbegin = false; - if(vm_current_vertices > 2 || (vm_current_vertices >= 2 && vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FLLINES)) - { - if(vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FL2D) //[515]: don't use qcpolygons memory if 2D - VM_AddPolygonTo2DScene(&vm_polygons[vm_drawpolygons_num]); - else - vm_drawpolygons_num++; - } - else - Con_Printf("Debug_PolygonEnd: %i vertices isn't a good choice\n", vm_current_vertices); -} - @@ -3420,6 +3112,8 @@ void VM_altstr_ins(void) char *out; char outstr[VM_STRINGTEMP_LENGTH]; + VM_SAFEPARMCOUNT(3, VM_altstr_ins); + in = instr = PRVM_G_STRING( OFS_PARM0 ); num = (int)PRVM_G_FLOAT( OFS_PARM1 ); set = setstr = PRVM_G_STRING( OFS_PARM2 ); @@ -3456,6 +3150,7 @@ typedef struct char *strings[MAX_QCSTR_STRINGS]; }qcstrbuffer_t; +// FIXME: move stringbuffers to prog_t to allow multiple progs! static qcstrbuffer_t *qcstringbuffers[MAX_QCSTR_BUFFERS]; static int num_qcstringbuffers; static int buf_sortpower; @@ -3527,21 +3222,6 @@ static int BufStr_SortStringsDOWN (const void *in1, const void *in2) return strncmp(b, a, buf_sortpower); } -#ifdef REMOVETHIS -static void VM_BufStr_Init (void) -{ - memset(qcstringbuffers, 0, sizeof(qcstringbuffers)); - num_qcstringbuffers = 0; -} - -static void VM_BufStr_ShutDown (void) -{ - int i; - for(i=0;iglobaloffsets.self)->edict); if (ent == prog->edicts) { @@ -3973,6 +3655,8 @@ void VM_changepitch (void) prvm_edict_t *ent; float ideal, current, move, speed; + VM_SAFEPARMCOUNT(1, VM_changepitch); + ent = PRVM_G_EDICT(OFS_PARM0); if (ent == prog->edicts) { @@ -4020,6 +3704,122 @@ void VM_changepitch (void) PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.angles)->vector[0] = ANGLEMOD (current + move); } + +static int Is_Text_Color (char c, char t) +{ + int a = 0; + char c2 = c - (c & 128); + char t2 = t - (t & 128); + + if(c != STRING_COLOR_TAG && c2 != STRING_COLOR_TAG) return 0; + if(t >= '0' && t <= '9') a = 1; + if(t2 >= '0' && t2 <= '9') a = 1; +/* if(t >= 'A' && t <= 'Z') a = 2; + if(t2 >= 'A' && t2 <= 'Z') a = 2; + + if(a == 1 && scr_colortext.integer > 0) + return 1; + if(a == 2 && scr_multifonts.integer > 0) + return 2; +*/ + return a; +} + +void VM_uncolorstring (void) +{ + const char *in; + char out[VM_STRINGTEMP_LENGTH]; + int k = 0, i = 0; + + VM_SAFEPARMCOUNT(1, VM_uncolorstring); + in = PRVM_G_STRING(OFS_PARM0); + VM_CheckEmptyString (in); + + while (in[k]) + { + if(in[k+1]) + if(Is_Text_Color(in[k], in[k+1]) == 1/* || (in[k] == '&' && in[k+1] == 'r')*/) + { + k += 2; + continue; + } + out[i] = in[k]; + ++k; + ++i; + } + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(out); +} + +//#222 string(string s, float index) str2chr (FTE_STRINGS) +void VM_str2chr (void) +{ + const char *s; + VM_SAFEPARMCOUNT(2, VM_str2chr); + s = PRVM_G_STRING(OFS_PARM0); + if((unsigned)PRVM_G_FLOAT(OFS_PARM1) > strlen(s)) + return; + PRVM_G_FLOAT(OFS_RETURN) = (unsigned char)s[(int)PRVM_G_FLOAT(OFS_PARM1)]; +} + +//#223 string(float c, ...) chr2str (FTE_STRINGS) +void VM_chr2str (void) +{ + char t[9]; + int i; + VM_SAFEPARMCOUNTRANGE(0, 8, VM_chr2str); + for(i = 0;i < prog->argc && i < (int)sizeof(t) - 1;i++) + t[i] = (unsigned char)PRVM_G_FLOAT(OFS_PARM0+i*3); + t[i] = 0; + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t); +} + +//#228 float(string s1, string s2, float len) strncmp (FTE_STRINGS) +void VM_strncmp (void) +{ + const char *s1, *s2; + VM_SAFEPARMCOUNT(1, VM_strncmp); + s1 = PRVM_G_STRING(OFS_PARM0); + s2 = PRVM_G_STRING(OFS_PARM1); + PRVM_G_FLOAT(OFS_RETURN) = strncmp(s1, s2, (size_t)PRVM_G_FLOAT(OFS_PARM2)); +} + +void VM_wasfreed (void) +{ + VM_SAFEPARMCOUNT(1, VM_wasfreed); + PRVM_G_FLOAT(OFS_RETURN) = PRVM_G_EDICT(OFS_PARM0)->priv.required->free; +} + +void VM_SetTraceGlobals(const trace_t *trace) +{ + prvm_eval_t *val; + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_allsolid))) + val->_float = trace->allsolid; + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_startsolid))) + val->_float = trace->startsolid; + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_fraction))) + val->_float = trace->fraction; + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_inwater))) + val->_float = trace->inwater; + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_inopen))) + val->_float = trace->inopen; + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_endpos))) + VectorCopy(trace->endpos, val->vector); + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_plane_normal))) + VectorCopy(trace->plane.normal, val->vector); + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_plane_dist))) + val->_float = trace->plane.dist; + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_ent))) + val->edict = PRVM_EDICT_TO_PROG(trace->ent ? trace->ent : prog->edicts); + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dpstartcontents))) + val->_float = trace->startsupercontents; + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitcontents))) + val->_float = trace->hitsupercontents; + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitq3surfaceflags))) + val->_float = trace->hitq3surfaceflags; + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphittexturename))) + val->string = trace->hittexture ? PRVM_SetTempString(trace->hittexture->name) : 0; +} + //============= void VM_Cmd_Init(void) @@ -4028,11 +3828,6 @@ void VM_Cmd_Init(void) VM_Files_Init(); VM_Search_Init(); // VM_BufStr_Init(); - if(vm_polygons_initialized) - { - Mem_FreePool(&vm_polygons_pool); - vm_polygons_initialized = false; - } } void VM_Cmd_Reset(void) @@ -4041,10 +3836,5 @@ void VM_Cmd_Reset(void) VM_Search_Reset(); VM_Files_CloseAll(); // VM_BufStr_ShutDown(); - if(vm_polygons_initialized) - { - Mem_FreePool(&vm_polygons_pool); - vm_polygons_initialized = false; - } } diff --git a/prvm_cmds.h b/prvm_cmds.h index 98645894..5856e569 100644 --- a/prvm_cmds.h +++ b/prvm_cmds.h @@ -189,18 +189,15 @@ float getserverlistindexforkey(string key) // nice helper macros #ifndef VM_NOPARMCHECK -#define VM_SAFEPARMCOUNT(p,f) if(prog->argc != p) PRVM_ERROR(#f " wrong parameter count (" #p " expected ) !") +#define VM_SAFEPARMCOUNTRANGE(p1,p2,f) if(prog->argc < p1 || prog->argc > p2) PRVM_ERROR(#f " wrong parameter count %i (" #p1 " to " #p2 " expected ) !", prog->argc) +#define VM_SAFEPARMCOUNT(p,f) if(prog->argc != p) PRVM_ERROR(#f " wrong parameter count %i (" #p " expected ) !", prog->argc) #else +#define VM_SAFEPARMCOUNTRANGE(p1,p2,f) #define VM_SAFEPARMCOUNT(p,f) #endif #define VM_RETURN_EDICT(e) (((int *)prog->globals.generic)[OFS_RETURN] = PRVM_EDICT_TO_PROG(e)) -#define e10 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL -#define e100 e10,e10,e10,e10,e10,e10,e10,e10,e10,e10 -#define e1000 e100,e100,e100,e100,e100,e100,e100,e100,e100,e100 - -#define VM_STRINGTEMP_BUFFERS 16 #define VM_STRINGTEMP_LENGTH MAX_INPUTLINE // builtins and other general functions @@ -245,7 +242,6 @@ void VM_findchainfloat (void); void VM_findflags (void); void VM_findchainflags (void); void VM_precache_file (void); -void VM_precache_error (void); void VM_precache_sound (void); void VM_coredump (void); @@ -269,7 +265,6 @@ void VM_min (void); void VM_max (void); void VM_bound (void); void VM_pow (void); -void VM_copyentity (void); void VM_asin (void); void VM_acos (void); void VM_atan (void); @@ -283,9 +278,7 @@ void VM_fopen(void); void VM_fclose(void); void VM_fgets(void); void VM_fputs(void); -// used by M_WriteToFile -// should be only called from a builtin -qfile_t *VM_GetFileHandle( int index ); +void VM_writetofile(void); // only used by menu void VM_strlen(void); void VM_strcat(void); @@ -332,6 +325,7 @@ void VM_drawsetcliparea(void); void VM_drawresetcliparea(void); void VM_getimagesize(void); +void VM_makevectors (void); void VM_vectorvectors (void); void VM_keynumtostring (void); @@ -344,9 +338,6 @@ void VM_cin_getstate( void ); void VM_cin_restart( void ); void VM_drawline (void); -void VM_R_PolygonBegin (void); -void VM_R_PolygonVertex (void); -void VM_R_PolygonEnd (void); void VM_bitshift (void); @@ -370,5 +361,14 @@ void VM_bufstr_free (void); void VM_changeyaw (void); void VM_changepitch (void); +void VM_uncolorstring (void); +void VM_str2chr (void); +void VM_chr2str (void); +void VM_strncmp (void); +void VM_registercvar (void); +void VM_wasfreed (void); + +void VM_SetTraceGlobals(const trace_t *trace); + void VM_Cmd_Init(void); void VM_Cmd_Reset(void); diff --git a/r_explosion.c b/r_explosion.c index a504dd30..0c343154 100644 --- a/r_explosion.c +++ b/r_explosion.c @@ -171,7 +171,7 @@ void R_NewExplosion(const vec3_t org) // clip start origin if (e->clipping) { - trace = CL_TraceBox(e->origin, vec3_origin, vec3_origin, e->vert[j], true, NULL, SUPERCONTENTS_SOLID, false); + trace = CL_Move(e->origin, vec3_origin, vec3_origin, e->vert[j], MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false); VectorCopy(trace.endpos, e->vert[i]); } } @@ -229,7 +229,7 @@ static void R_MoveExplosion(explosion_t *e) VectorMA(e->vert[i], frametime, e->vertvel[i], end); if (e->clipping) { - trace = CL_TraceBox(e->vert[i], vec3_origin, vec3_origin, end, true, NULL, SUPERCONTENTS_SOLID, false); + trace = CL_Move(e->vert[i], vec3_origin, vec3_origin, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false); if (trace.fraction < 1) { // clip velocity against the wall diff --git a/r_light.c b/r_light.c index 4ba71dc8..b61ec11f 100644 --- a/r_light.c +++ b/r_light.c @@ -83,9 +83,10 @@ void R_DrawCoronas(void) R_Mesh_Matrix(&identitymatrix); viewdist = DotProduct(r_view.origin, r_view.forward); flag = r_refdef.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE; + // FIXME: these traces should scan all render entities instead of cl.world for (lnum = 0, light = r_shadow_worldlightchain;light;light = light->next, lnum++) { - if ((light->flags & flag) && light->corona * r_coronas.value > 0 && (r_shadow_debuglight.integer < 0 || r_shadow_debuglight.integer == lnum) && (dist = (DotProduct(light->rtlight.shadoworigin, r_view.forward) - viewdist)) >= 24.0f && CL_TraceBox(light->rtlight.shadoworigin, vec3_origin, vec3_origin, r_view.origin, true, NULL, SUPERCONTENTS_SOLID, false).fraction == 1) + if ((light->flags & flag) && light->corona * r_coronas.value > 0 && (r_shadow_debuglight.integer < 0 || r_shadow_debuglight.integer == lnum) && (dist = (DotProduct(light->rtlight.shadoworigin, r_view.forward) - viewdist)) >= 24.0f && CL_Move(light->rtlight.shadoworigin, vec3_origin, vec3_origin, r_view.origin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction == 1) { cscale = light->rtlight.corona * r_coronas.value * 0.25f; scale = light->rtlight.radius * light->rtlight.coronasizescale; @@ -95,7 +96,7 @@ void R_DrawCoronas(void) for (i = 0;i < r_refdef.numlights;i++) { rtlight = &r_refdef.lights[i]; - if ((rtlight->flags & flag) && rtlight->corona * r_coronas.value > 0 && (dist = (DotProduct(rtlight->shadoworigin, r_view.forward) - viewdist)) >= 24.0f && CL_TraceBox(rtlight->shadoworigin, vec3_origin, vec3_origin, r_view.origin, true, NULL, SUPERCONTENTS_SOLID, false).fraction == 1) + if ((rtlight->flags & flag) && rtlight->corona * r_coronas.value > 0 && (dist = (DotProduct(rtlight->shadoworigin, r_view.forward) - viewdist)) >= 24.0f && CL_Move(rtlight->shadoworigin, vec3_origin, vec3_origin, r_view.origin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction == 1) { cscale = rtlight->corona * r_coronas.value * 0.25f; scale = rtlight->radius * rtlight->coronasizescale; @@ -140,7 +141,7 @@ void R_CompleteLightPoint(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffu light = &r_refdef.lights[i]; Matrix4x4_Transform(&light->matrix_worldtolight, p, v); f = 1 - VectorLength2(v); - if (f > 0 && CL_TraceBox(p, vec3_origin, vec3_origin, light->shadoworigin, false, NULL, SUPERCONTENTS_SOLID, false).fraction == 1) + if (f > 0 && CL_Move(p, vec3_origin, vec3_origin, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction == 1) VectorMA(ambientcolor, f, light->currentcolor, ambientcolor); } } diff --git a/r_shadow.c b/r_shadow.c index 25aa8f81..1ed8fe70 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -2883,7 +2883,7 @@ void R_Shadow_SelectLightInView(void) if (rating >= 0.95) { rating /= (1 + 0.0625f * sqrt(DotProduct(temp, temp))); - if (bestrating < rating && CL_TraceBox(light->origin, vec3_origin, vec3_origin, r_view.origin, true, NULL, SUPERCONTENTS_SOLID, false).fraction == 1.0f) + if (bestrating < rating && CL_Move(light->origin, vec3_origin, vec3_origin, r_view.origin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction == 1.0f) { bestrating = rating; best = light; @@ -3312,7 +3312,7 @@ void R_Shadow_SetCursorLocationForView(void) vec3_t dest, endpos; trace_t trace; VectorMA(r_view.origin, r_editlights_cursordistance.value, r_view.forward, dest); - trace = CL_TraceBox(r_view.origin, vec3_origin, vec3_origin, dest, true, NULL, SUPERCONTENTS_SOLID, false); + trace = CL_Move(r_view.origin, vec3_origin, vec3_origin, dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false); if (trace.fraction < 1) { dist = trace.fraction * r_editlights_cursordistance.value; diff --git a/server.h b/server.h index ba73d8f2..dff58cac 100644 --- a/server.h +++ b/server.h @@ -112,6 +112,10 @@ typedef struct server_s // note this is in server_t rather than server_static_t so that it is // reset on each map command (such as New Game in singleplayer) server_connectfloodaddress_t connectfloodaddresses[MAX_CONNECTFLOODADDRESSES]; + +#define SV_MAX_PARTICLEEFFECTNAME 256 + qboolean particleeffectnamesloaded; + char particleeffectname[SV_MAX_PARTICLEEFFECTNAME][MAX_QPATH]; } server_t; // if defined this does ping smoothing, otherwise it does not @@ -340,6 +344,8 @@ void SV_ReadClientMessage(void); int SV_ModelIndex(const char *s, int precachemode); int SV_SoundIndex(const char *s, int precachemode); +int SV_ParticleEffectIndex(const char *name); + void SV_SetIdealPitch (void); void SV_AddUpdates (void); @@ -356,31 +362,19 @@ void SV_Physics_ClientEntity (prvm_edict_t *ent); qboolean SV_PlayerCheckGround (prvm_edict_t *ent); qboolean SV_CheckBottom (prvm_edict_t *ent); -qboolean SV_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink); +qboolean SV_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean noenemy, qboolean settrace); // Needs to be called any time an entity changes origin, mins, maxs, or solid // sets ent->v.absmin and ent->v.absmax // if touchtriggers, calls prog functions for the intersected triggers void SV_LinkEdict (prvm_edict_t *ent, qboolean touch_triggers); -// traces a box move against a single entity -// mins and maxs are relative -// -// if the entire move stays in a single solid brush, trace.allsolid will be set -// -// if the starting point is in a solid, it will be allowed to move out to an -// open area, and trace.startsolid will be set -// -// type is one of the MOVE_ values such as MOVE_NOMONSTERS which skips box -// entities, only colliding with SOLID_BSP entities (doors, lifts) -// -// passedict is excluded from clipping checks -struct trace_s SV_Move_ClipToEntity(prvm_edict_t *ent, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int movetype, int hitsupercontents); - +// calculates hitsupercontentsmask for a generic qc entity +int SV_GenericHitSuperContentsMask(const prvm_edict_t *edict); // traces a box move against worldmodel and all entities in the specified area -trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict); +trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask); -#define SV_PointSuperContents(point) (SV_Move((point), vec3_origin, vec3_origin, (point), sv_gameplayfix_swiminbmodels.integer ? MOVE_NOMONSTERS : MOVE_WORLDONLY, NULL).startsupercontents) +#define SV_PointSuperContents(point) (SV_Move((point), vec3_origin, vec3_origin, (point), sv_gameplayfix_swiminbmodels.integer ? MOVE_NOMONSTERS : MOVE_WORLDONLY, NULL, 0).startsupercontents) void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats); diff --git a/sv_main.c b/sv_main.c index 0f3eb574..27f84b26 100644 --- a/sv_main.c +++ b/sv_main.c @@ -1722,6 +1722,126 @@ int SV_SoundIndex(const char *s, int precachemode) return 0; } +// MUST match effectnameindex_t in client.h +static const char *standardeffectnames[EFFECT_TOTAL] = +{ + "", + "TE_GUNSHOT", + "TE_GUNSHOTQUAD", + "TE_SPIKE", + "TE_SPIKEQUAD", + "TE_SUPERSPIKE", + "TE_SUPERSPIKEQUAD", + "TE_WIZSPIKE", + "TE_KNIGHTSPIKE", + "TE_EXPLOSION", + "TE_EXPLOSIONQUAD", + "TE_TAREXPLOSION", + "TE_TELEPORT", + "TE_LAVASPLASH", + "TE_SMALLFLASH", + "TE_FLAMEJET", + "EF_FLAME", + "TE_BLOOD", + "TE_SPARK", + "TE_PLASMABURN", + "TE_TEI_G3", + "TE_TEI_SMOKE", + "TE_TEI_BIGEXPLOSION", + "TE_TEI_PLASMAHIT", + "EF_STARDUST", + "TR_ROCKET", + "TR_GRENADE", + "TR_BLOOD", + "TR_WIZSPIKE", + "TR_SLIGHTBLOOD", + "TR_KNIGHTSPIKE", + "TR_VORESPIKE", + "TR_NEHAHRASMOKE", + "TR_NEXUIZPLASMA", + "TR_GLOWTRAIL", + "SVC_PARTICLE" +}; + +/* +================ +SV_ParticleEffectIndex + +================ +*/ +int SV_ParticleEffectIndex(const char *name) +{ + int i, argc, linenumber, effectnameindex; + fs_offset_t filesize; + unsigned char *filedata; + const char *text, *textstart, *textend; + char argv[16][1024]; + if (!sv.particleeffectnamesloaded) + { + sv.particleeffectnamesloaded = true; + memset(sv.particleeffectname, 0, sizeof(sv.particleeffectname)); + for (i = 0;i < EFFECT_TOTAL;i++) + strlcpy(sv.particleeffectname[i], standardeffectnames[i], sizeof(sv.particleeffectname[i])); + filedata = FS_LoadFile("effectinfo.txt", tempmempool, true, &filesize); + if (filedata) + { + textstart = (const char *)filedata; + textend = (const char *)filedata + filesize; + text = textstart; + for (linenumber = 1;;linenumber++) + { + argc = 0; + for (;;) + { + if (!COM_ParseToken(&text, true) || !strcmp(com_token, "\n")) + break; + if (argc < 16) + { + strlcpy(argv[argc], com_token, sizeof(argv[argc])); + argc++; + } + } + if (com_token[0] == 0) + break; // if the loop exited and it's not a \n, it's EOF + if (argc < 1) + continue; + if (!strcmp(argv[0], "effect")) + { + if (argc == 2) + { + for (effectnameindex = 1;effectnameindex < SV_MAX_PARTICLEEFFECTNAME;effectnameindex++) + { + if (sv.particleeffectname[effectnameindex][0]) + { + if (!strcmp(sv.particleeffectname[effectnameindex], argv[1])) + break; + } + else + { + strlcpy(sv.particleeffectname[effectnameindex], argv[1], sizeof(sv.particleeffectname[effectnameindex])); + break; + } + } + // if we run out of names, abort + if (effectnameindex == SV_MAX_PARTICLEEFFECTNAME) + { + Con_Printf("effectinfo.txt:%i: too many effects!\n", linenumber); + break; + } + } + } + } + Mem_Free(filedata); + } + } + // search for the name + for (effectnameindex = 1;effectnameindex < SV_MAX_PARTICLEEFFECTNAME && sv.particleeffectname[effectnameindex][0];effectnameindex++) + if (!strcmp(sv.particleeffectname[effectnameindex], name)) + return effectnameindex; + // return 0 if we couldn't find it + return 0; +} + /* ================ SV_CreateBaseline diff --git a/sv_move.c b/sv_move.c index bd7404c1..2c1eb00e 100644 --- a/sv_move.c +++ b/sv_move.c @@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // sv_move.c -- monster movement #include "quakedef.h" +#include "prvm_cmds.h" /* ============= @@ -69,7 +70,7 @@ realcheck: start[0] = stop[0] = (mins[0] + maxs[0])*0.5; start[1] = stop[1] = (mins[1] + maxs[1])*0.5; stop[2] = start[2] - 2*sv_stepheight.value; - trace = SV_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent); + trace = SV_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, SV_GenericHitSuperContentsMask(ent)); if (trace.fraction == 1.0) return false; @@ -82,7 +83,7 @@ realcheck: start[0] = stop[0] = x ? maxs[0] : mins[0]; start[1] = stop[1] = y ? maxs[1] : mins[1]; - trace = SV_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent); + trace = SV_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, SV_GenericHitSuperContentsMask(ent)); if (trace.fraction != 1.0 && trace.endpos[2] > bottom) bottom = trace.endpos[2]; @@ -101,11 +102,10 @@ SV_movestep Called by monster program code. The move will be adjusted for slopes and stairs, but if the move isn't -possible, no move is done, false is returned, and -prog->globals.server->trace_normal is set to the normal of the blocking wall +possible, no move is done and false is returned ============= */ -qboolean SV_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink) +qboolean SV_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean noenemy, qboolean settrace) { float dz; vec3_t oldorg, neworg, end, traceendpos; @@ -124,16 +124,19 @@ qboolean SV_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink) for (i=0 ; i<2 ; i++) { VectorAdd (ent->fields.server->origin, move, neworg); - enemy = PRVM_PROG_TO_EDICT(ent->fields.server->enemy); - if (i == 0 && enemy != prog->edicts) + if (!noenemy) { - dz = ent->fields.server->origin[2] - PRVM_PROG_TO_EDICT(ent->fields.server->enemy)->fields.server->origin[2]; - if (dz > 40) - neworg[2] -= 8; - if (dz < 30) - neworg[2] += 8; + enemy = PRVM_PROG_TO_EDICT(ent->fields.server->enemy); + if (i == 0 && enemy != prog->edicts) + { + dz = ent->fields.server->origin[2] - PRVM_PROG_TO_EDICT(ent->fields.server->enemy)->fields.server->origin[2]; + if (dz > 40) + neworg[2] -= 8; + if (dz < 30) + neworg[2] += 8; + } } - trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, neworg, MOVE_NORMAL, ent); + trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, neworg, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent)); if (trace.fraction == 1) { @@ -159,12 +162,12 @@ qboolean SV_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink) VectorCopy (neworg, end); end[2] -= sv_stepheight.value*2; - trace = SV_Move (neworg, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent); + trace = SV_Move (neworg, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent)); if (trace.startsolid) { neworg[2] -= sv_stepheight.value; - trace = SV_Move (neworg, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent); + trace = SV_Move (neworg, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent)); if (trace.startsolid) return false; } @@ -237,7 +240,7 @@ qboolean SV_StepDirection (prvm_edict_t *ent, float yaw, float dist) move[2] = 0; VectorCopy (ent->fields.server->origin, oldorigin); - if (SV_movestep (ent, move, false)) + if (SV_movestep (ent, move, false, false, false)) { delta = ent->fields.server->angles[YAW] - ent->fields.server->ideal_yaw; if (delta > 45 && delta < 315) @@ -386,6 +389,8 @@ void SV_MoveToGoal (void) prvm_edict_t *ent, *goal; float dist; + VM_SAFEPARMCOUNT(1, SV_MoveToGoal); + ent = PRVM_PROG_TO_EDICT(prog->globals.server->self); goal = PRVM_PROG_TO_EDICT(ent->fields.server->goalentity); dist = PRVM_G_FLOAT(OFS_PARM0); diff --git a/sv_phys.c b/sv_phys.c index 6b2d0207..f85429b4 100644 --- a/sv_phys.c +++ b/sv_phys.c @@ -85,111 +85,28 @@ LINE TESTING IN HULLS =============================================================================== */ -/* -================== -SV_Move_ClipToEntity - -Handles selection or creation of a clipping hull, and offseting (and -eventually rotation) of the end points -================== -*/ -trace_t SV_Move_ClipToEntity(prvm_edict_t *ent, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int movetype, int hitsupercontents) +int SV_GenericHitSuperContentsMask(const prvm_edict_t *passedict) { - trace_t trace; - model_t *model = NULL; - matrix4x4_t matrix, imatrix; - float tempnormal[3], starttransformed[3], endtransformed[3]; - - memset(&trace, 0, sizeof(trace)); - trace.fraction = trace.realfraction = 1; - VectorCopy(end, trace.endpos); - - if ((int) ent->fields.server->solid == SOLID_BSP || movetype == MOVE_HITMODEL) + prvm_eval_t *val; + if (passedict) { - unsigned int modelindex = (unsigned int)ent->fields.server->modelindex; - // if the modelindex is 0, it shouldn't be SOLID_BSP! - if (modelindex == 0) - { - Con_Printf("SV_Move_ClipToEntity: edict %i: SOLID_BSP with no model\n", PRVM_NUM_FOR_EDICT(ent)); - return trace; - } - if (modelindex >= MAX_MODELS) - { - Con_Printf("SV_Move_ClipToEntity: edict %i: SOLID_BSP with invalid modelindex\n", PRVM_NUM_FOR_EDICT(ent)); - return trace; - } - model = sv.models[modelindex]; - if (modelindex != 0 && model == NULL) - { - Con_Printf("SV_Move_ClipToEntity: edict %i: SOLID_BSP with invalid modelindex\n", PRVM_NUM_FOR_EDICT(ent)); - return trace; - } - - if ((int) ent->fields.server->solid == SOLID_BSP) + val = PRVM_EDICTFIELDVALUE(passedict, prog->fieldoffsets.dphitcontentsmask); + if (val && val->_float) + return (int)val->_float; + else if (passedict->fields.server->solid == SOLID_SLIDEBOX) { - if (!model->TraceBox) - { - Con_Printf("SV_Move_ClipToEntity: edict %i: SOLID_BSP with a non-collidable model\n", PRVM_NUM_FOR_EDICT(ent)); - return trace; - } - //if ((int) ent->fields.server->movetype != MOVETYPE_PUSH) - //{ - // Con_Printf("SV_Move_ClipToEntity: edict %i: SOLID_BSP without MOVETYPE_PUSH\n", PRVM_NUM_FOR_EDICT(ent)); - // return trace; - //} + if ((int)passedict->fields.server->flags & FL_MONSTER) + return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_MONSTERCLIP; + else + return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP; } - Matrix4x4_CreateFromQuakeEntity(&matrix, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2], ent->fields.server->angles[0], ent->fields.server->angles[1], ent->fields.server->angles[2], 1); - } - else - Matrix4x4_CreateTranslate(&matrix, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2]); - - Matrix4x4_Invert_Simple(&imatrix, &matrix); - Matrix4x4_Transform(&imatrix, start, starttransformed); - Matrix4x4_Transform(&imatrix, end, endtransformed); -#if COLLISIONPARANOID >= 3 - Con_Printf("trans(%f %f %f -> %f %f %f, %f %f %f -> %f %f %f)", start[0], start[1], start[2], starttransformed[0], starttransformed[1], starttransformed[2], end[0], end[1], end[2], endtransformed[0], endtransformed[1], endtransformed[2]); -#endif - - if (model && model->TraceBox) - { - int frame; - frame = (int)ent->fields.server->frame; - frame = bound(0, frame, (model->numframes - 1)); - model->TraceBox(model, frame, &trace, starttransformed, mins, maxs, endtransformed, hitsupercontents); - } - else - Collision_ClipTrace_Box(&trace, ent->fields.server->mins, ent->fields.server->maxs, starttransformed, mins, maxs, endtransformed, hitsupercontents, ent->fields.server->solid == SOLID_CORPSE ? SUPERCONTENTS_CORPSE : SUPERCONTENTS_BODY, 0, NULL); - trace.fraction = bound(0, trace.fraction, 1); - trace.realfraction = bound(0, trace.realfraction, 1); - - if (trace.fraction < 1) - { - VectorLerp(start, trace.fraction, end, trace.endpos); - VectorCopy(trace.plane.normal, tempnormal); - Matrix4x4_Transform3x3(&matrix, tempnormal, trace.plane.normal); - // FIXME: should recalc trace.plane.dist + else if (passedict->fields.server->solid == SOLID_CORPSE) + return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY; + else + return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_CORPSE; } else - VectorCopy(end, trace.endpos); - - return trace; -} - -/* -================== -SV_Move_ClipToWorld -================== -*/ -trace_t SV_Move_ClipToWorld(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int movetype, int hitsupercontents) -{ - trace_t trace; - memset(&trace, 0, sizeof(trace)); - trace.fraction = trace.realfraction = 1; - sv.worldmodel->TraceBox(sv.worldmodel, 0, &trace, start, mins, maxs, end, hitsupercontents); - trace.fraction = bound(0, trace.fraction, 1); - trace.realfraction = bound(0, trace.realfraction, 1); - VectorLerp(start, trace.fraction, end, trace.endpos); - return trace; + return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_CORPSE; } /* @@ -198,18 +115,16 @@ SV_Move ================== */ #if COLLISIONPARANOID >= 1 -trace_t SV_Move_(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict) +trace_t SV_Move_(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask) #else -trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict) +trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask) #endif { vec3_t hullmins, hullmaxs; int i; - int hitsupercontentsmask; int passedictprog; qboolean pointtrace; prvm_edict_t *traceowner, *touch; - prvm_eval_t *val; trace_t trace; // bounding box of entire move area vec3_t clipboxmins, clipboxmaxs; @@ -221,6 +136,11 @@ trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t clipstart, clipend; // trace results trace_t cliptrace; + // matrices to transform into/out of other entity's space + matrix4x4_t matrix, imatrix; + // model of other entity + model_t *model; + // list of entities to test for collisions int numtouchedicts; prvm_edict_t *touchedicts[MAX_EDICTS]; @@ -234,28 +154,8 @@ trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const Con_Printf("move(%f %f %f,%f %f %f)", clipstart[0], clipstart[1], clipstart[2], clipend[0], clipend[1], clipend[2]); #endif - if (passedict) - { - val = PRVM_EDICTFIELDVALUE(passedict, prog->fieldoffsets.dphitcontentsmask); - if (val && val->_float) - hitsupercontentsmask = (int)val->_float; - else if (passedict->fields.server->solid == SOLID_SLIDEBOX) - { - if ((int)passedict->fields.server->flags & FL_MONSTER) - hitsupercontentsmask = SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_MONSTERCLIP; - else - hitsupercontentsmask = SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP; - } - else if (passedict->fields.server->solid == SOLID_CORPSE) - hitsupercontentsmask = SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY; - else - hitsupercontentsmask = SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_CORPSE; - } - else - hitsupercontentsmask = SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_CORPSE; - // clip to world - cliptrace = SV_Move_ClipToWorld(clipstart, clipmins, clipmaxs, clipend, type, hitsupercontentsmask); + Collision_ClipToWorld(&cliptrace, sv.worldmodel, clipstart, clipmins, clipmaxs, clipend, hitsupercontentsmask); cliptrace.bmodelstartsolid = cliptrace.startsolid; if (cliptrace.startsolid || cliptrace.fraction < 1) cliptrace.ent = prog->edicts; @@ -306,6 +206,8 @@ trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const traceowner = passedict ? PRVM_PROG_TO_EDICT(passedict->fields.server->owner) : 0; // clip to entities + // because this uses World_EntitiestoBox, we know all entity boxes overlap + // the clip region, so we can skip culling checks in the loop below numtouchedicts = World_EntitiesInBox(&sv.world, clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts); if (numtouchedicts > MAX_EDICTS) { @@ -339,56 +241,39 @@ trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const } // might interact, so do an exact clip - if ((int)touch->fields.server->flags & FL_MONSTER) - trace = SV_Move_ClipToEntity(touch, clipstart, clipmins2, clipmaxs2, clipend, type, hitsupercontentsmask); - else - trace = SV_Move_ClipToEntity(touch, clipstart, clipmins, clipmaxs, clipend, type, hitsupercontentsmask); - // LordHavoc: take the 'best' answers from the new trace and combine with existing data - if (trace.allsolid) - cliptrace.allsolid = true; - if (trace.startsolid) + model = NULL; + if ((int) touch->fields.server->solid == SOLID_BSP || type == MOVE_HITMODEL) { - if (touch->fields.server->solid == SOLID_BSP) - cliptrace.bmodelstartsolid = true; - cliptrace.startsolid = true; - if (cliptrace.realfraction == 1) - cliptrace.ent = touch; + unsigned int modelindex = (unsigned int)touch->fields.server->modelindex; + // if the modelindex is 0, it shouldn't be SOLID_BSP! + if (modelindex > 0 && modelindex < MAX_MODELS) + model = sv.models[(int)touch->fields.server->modelindex]; + Matrix4x4_CreateFromQuakeEntity(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2], touch->fields.server->angles[0], touch->fields.server->angles[1], touch->fields.server->angles[2], 1); } - // don't set this except on the world, because it can easily confuse - // monsters underwater if there's a bmodel involved in the trace - // (inopen && inwater is how they check water visibility) - //if (trace.inopen) - // cliptrace.inopen = true; - if (trace.inwater) - cliptrace.inwater = true; - if (trace.realfraction < cliptrace.realfraction) - { - cliptrace.fraction = trace.fraction; - cliptrace.realfraction = trace.realfraction; - VectorCopy(trace.endpos, cliptrace.endpos); - cliptrace.plane = trace.plane; - cliptrace.ent = touch; - cliptrace.hitsupercontents = trace.hitsupercontents; - cliptrace.hitq3surfaceflags = trace.hitq3surfaceflags; - cliptrace.hittexture = trace.hittexture; - } - cliptrace.startsupercontents |= trace.startsupercontents; + else + Matrix4x4_CreateTranslate(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2]); + Matrix4x4_Invert_Simple(&imatrix, &matrix); + if ((int)touch->fields.server->flags & FL_MONSTER) + Collision_ClipToGenericEntity(&trace, model, touch->fields.server->frame, touch->fields.server->mins, touch->fields.server->maxs, SUPERCONTENTS_BODY, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask); + else + Collision_ClipToGenericEntity(&trace, model, touch->fields.server->frame, touch->fields.server->mins, touch->fields.server->maxs, SUPERCONTENTS_BODY, &matrix, &imatrix, clipstart, clipmins, clipmaxs, clipend, hitsupercontentsmask); + Collision_CombineTraces(&cliptrace, &trace, (void *)touch, touch->fields.server->solid == SOLID_BSP); } return cliptrace; } #if COLLISIONPARANOID >= 1 -trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict) +trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask) { int endstuck; trace_t trace; vec3_t temp; - trace = SV_Move_(start, mins, maxs, end, type, passedict); + trace = SV_Move_(start, mins, maxs, end, type, passedict, hitsupercontentsmask); if (passedict) { VectorCopy(trace.endpos, temp); - endstuck = SV_Move_(temp, mins, maxs, temp, type, passedict).startsolid; + endstuck = SV_Move_(temp, mins, maxs, temp, type, passedict, hitsupercontentsmask).startsolid; #if COLLISIONPARANOID < 3 if (trace.startsolid || endstuck) #endif @@ -570,7 +455,7 @@ returns true if the entity is in solid currently */ static int SV_TestEntityPosition (prvm_edict_t *ent) { - trace_t trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, ent->fields.server->origin, MOVE_NOMONSTERS, ent); + trace_t trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, ent->fields.server->origin, MOVE_NOMONSTERS, ent, SUPERCONTENTS_SOLID); if (trace.startsupercontents & SUPERCONTENTS_SOLID) return true; else @@ -745,6 +630,7 @@ SV_Impact Two entities have touched, so run their touch functions ================== */ +extern void VM_SetTraceGlobals(const trace_t *trace); void SV_Impact (prvm_edict_t *e1, trace_t *trace) { int old_self, old_other; @@ -754,36 +640,13 @@ void SV_Impact (prvm_edict_t *e1, trace_t *trace) old_self = prog->globals.server->self; old_other = prog->globals.server->other; + VM_SetTraceGlobals(trace); + prog->globals.server->time = sv.time; if (!e1->priv.server->free && !e2->priv.server->free && e1->fields.server->touch && e1->fields.server->solid != SOLID_NOT) { prog->globals.server->self = PRVM_EDICT_TO_PROG(e1); prog->globals.server->other = PRVM_EDICT_TO_PROG(e2); - prog->globals.server->trace_allsolid = trace->allsolid; - prog->globals.server->trace_startsolid = trace->startsolid; - prog->globals.server->trace_fraction = trace->fraction; - prog->globals.server->trace_inwater = trace->inwater; - prog->globals.server->trace_inopen = trace->inopen; - VectorCopy (trace->endpos, prog->globals.server->trace_endpos); - VectorCopy (trace->plane.normal, prog->globals.server->trace_plane_normal); - prog->globals.server->trace_plane_dist = trace->plane.dist; - if (trace->ent) - prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace->ent); - else - prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts); - if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dpstartcontents))) - val->_float = trace->startsupercontents; - if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitcontents))) - val->_float = trace->hitsupercontents; - if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitq3surfaceflags))) - val->_float = trace->hitq3surfaceflags; - if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphittexturename))) - { - if (trace->hittexture) - val->string = PRVM_SetTempString(trace->hittexture->name); - else - val->string = 0; - } PRVM_ExecuteProgram (e1->fields.server->touch, "QC function self.touch is missing"); } @@ -791,14 +654,9 @@ void SV_Impact (prvm_edict_t *e1, trace_t *trace) { prog->globals.server->self = PRVM_EDICT_TO_PROG(e2); prog->globals.server->other = PRVM_EDICT_TO_PROG(e1); - prog->globals.server->trace_allsolid = false; - prog->globals.server->trace_startsolid = false; - prog->globals.server->trace_fraction = 1; - prog->globals.server->trace_inwater = false; - prog->globals.server->trace_inopen = true; - VectorCopy (e2->fields.server->origin, prog->globals.server->trace_endpos); - VectorSet (prog->globals.server->trace_plane_normal, 0, 0, 1); - prog->globals.server->trace_plane_dist = 0; + VectorCopy(e2->fields.server->origin, prog->globals.server->trace_endpos); + VectorNegate(trace->plane.normal, prog->globals.server->trace_plane_normal); + prog->globals.server->trace_plane_dist = -trace->plane.dist; prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(e1); if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dpstartcontents))) val->_float = 0; @@ -853,7 +711,7 @@ If stepnormal is not NULL, the plane normal of any vertical wall hit will be sto */ // LordHavoc: increased from 5 to 32 #define MAX_CLIP_PLANES 32 -int SV_FlyMove (prvm_edict_t *ent, float time, float *stepnormal) +int SV_FlyMove (prvm_edict_t *ent, float time, float *stepnormal, int hitsupercontentsmask) { int blocked, bumpcount; int i, j, impact, numplanes; @@ -873,7 +731,7 @@ int SV_FlyMove (prvm_edict_t *ent, float time, float *stepnormal) break; VectorMA(ent->fields.server->origin, time_left, ent->fields.server->velocity, end); - trace = SV_Move(ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent); + trace = SV_Move(ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, hitsupercontentsmask); #if 0 //if (trace.fraction < 0.002) { @@ -884,7 +742,7 @@ int SV_FlyMove (prvm_edict_t *ent, float time, float *stepnormal) start[2] += 3;//0.03125; VectorMA(ent->fields.server->origin, time_left, ent->fields.server->velocity, end); end[2] += 3;//0.03125; - testtrace = SV_Move(start, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent); + testtrace = SV_Move(start, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, hitsupercontentsmask); if (trace.fraction < testtrace.fraction && !testtrace.startsolid && (testtrace.fraction == 1 || DotProduct(trace.plane.normal, ent->fields.server->velocity) < DotProduct(testtrace.plane.normal, ent->fields.server->velocity))) { Con_Printf("got further (new %f > old %f)\n", testtrace.fraction, trace.fraction); @@ -899,7 +757,7 @@ int SV_FlyMove (prvm_edict_t *ent, float time, float *stepnormal) VectorMA(ent->fields.server->origin, time_left, ent->fields.server->velocity, end); VectorMA(start, 3, planes[i], start); VectorMA(end, 3, planes[i], end); - testtrace = SV_Move(start, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent); + testtrace = SV_Move(start, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, hitsupercontentsmask); if (trace.fraction < testtrace.fraction) { trace = testtrace; @@ -1074,7 +932,7 @@ int SV_FlyMove (prvm_edict_t *ent, float time, float *stepnormal) { // LordHavoc: fix the 'fall to your death in a wedge corner' glitch // flag ONGROUND if there's ground under it - trace = SV_Move(ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent); + trace = SV_Move(ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, hitsupercontentsmask); } */ @@ -1134,7 +992,7 @@ static trace_t SV_PushEntity (prvm_edict_t *ent, vec3_t push, qboolean failonbmo else type = MOVE_NORMAL; - trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, type, ent); + trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, type, ent, SV_GenericHitSuperContentsMask(ent)); if (trace.bmodelstartsolid && failonbmodelstartsolid) return trace; @@ -1163,6 +1021,7 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) static prvm_edict_t *checkentities[MAX_EDICTS]; model_t *pushermodel; trace_t trace; + matrix4x4_t pusherfinalmatrix, pusherfinalimatrix; if (!pusher->fields.server->velocity[0] && !pusher->fields.server->velocity[1] && !pusher->fields.server->velocity[2] && !pusher->fields.server->avelocity[0] && !pusher->fields.server->avelocity[1] && !pusher->fields.server->avelocity[2]) { @@ -1267,6 +1126,12 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) pusher->fields.server->ltime += movetime; SV_LinkEdict (pusher, false); + pushermodel = NULL; + if (pusher->fields.server->modelindex >= 1 && pusher->fields.server->modelindex < MAX_MODELS) + pushermodel = sv.models[(int)pusher->fields.server->modelindex]; + Matrix4x4_CreateFromQuakeEntity(&pusherfinalmatrix, pusher->fields.server->origin[0], pusher->fields.server->origin[1], pusher->fields.server->origin[2], pusher->fields.server->angles[0], pusher->fields.server->angles[1], pusher->fields.server->angles[2], 1); + Matrix4x4_Invert_Simple(&pusherfinalimatrix, &pusherfinalmatrix); + savesolid = pusher->fields.server->solid; // see if any solid entities are inside the final position @@ -1293,7 +1158,8 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) else { // if the entity is not inside the pusher's final position, leave it alone - if (!SV_Move_ClipToEntity(pusher, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, 0, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY).startsolid) + Collision_ClipToGenericEntity(&trace, pushermodel, pusher->fields.server->frame, pusher->fields.server->mins, pusher->fields.server->maxs, SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY); + if (!trace.startsolid) continue; } @@ -1324,7 +1190,8 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) //Con_Printf("%s:%d frac %f startsolid %d bmodelstartsolid %d allsolid %d\n", __FILE__, __LINE__, trace.fraction, trace.startsolid, trace.bmodelstartsolid, trace.allsolid); // if it is still inside the pusher, block - if (SV_Move_ClipToEntity(pusher, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, 0, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY).startsolid) + Collision_ClipToGenericEntity(&trace, pushermodel, pusher->fields.server->frame, pusher->fields.server->mins, pusher->fields.server->maxs, SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY); + if (trace.startsolid) { // try moving the contacted entity a tiny bit further to account for precision errors vec3_t move2; @@ -1334,7 +1201,8 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) VectorCopy (check->priv.server->moved_fromangles, check->fields.server->angles); SV_PushEntity (check, move2, true); pusher->fields.server->solid = savesolid; - if (SV_Move_ClipToEntity(pusher, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, 0, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY).startsolid) + Collision_ClipToGenericEntity(&trace, pushermodel, pusher->fields.server->frame, pusher->fields.server->mins, pusher->fields.server->maxs, SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY); + if (trace.startsolid) { // try moving the contacted entity a tiny bit less to account for precision errors pusher->fields.server->solid = SOLID_NOT; @@ -1343,7 +1211,8 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) VectorCopy (check->priv.server->moved_fromangles, check->fields.server->angles); SV_PushEntity (check, move2, true); pusher->fields.server->solid = savesolid; - if (SV_Move_ClipToEntity(pusher, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, 0, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY).startsolid) + Collision_ClipToGenericEntity(&trace, pushermodel, pusher->fields.server->frame, pusher->fields.server->mins, pusher->fields.server->maxs, SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY); + if (trace.startsolid) { // still inside pusher, so it's really blocked @@ -1629,7 +1498,7 @@ int SV_TryUnstick (prvm_edict_t *ent, vec3_t oldvel) ent->fields.server->velocity[0] = oldvel[0]; ent->fields.server->velocity[1] = oldvel[1]; ent->fields.server->velocity[2] = 0; - clip = SV_FlyMove (ent, 0.1, NULL); + clip = SV_FlyMove (ent, 0.1, NULL, SV_GenericHitSuperContentsMask(ent)); if (fabs(oldorg[1] - ent->fields.server->origin[1]) > 4 || fabs(oldorg[0] - ent->fields.server->origin[0]) > 4) @@ -1676,7 +1545,7 @@ void SV_WalkMove (prvm_edict_t *ent) VectorCopy (ent->fields.server->origin, start_origin); VectorCopy (ent->fields.server->velocity, start_velocity); - clip = SV_FlyMove (ent, sv.frametime, NULL); + clip = SV_FlyMove (ent, sv.frametime, NULL, SV_GenericHitSuperContentsMask(ent)); SV_CheckVelocity(ent); @@ -1724,7 +1593,7 @@ void SV_WalkMove (prvm_edict_t *ent) // move forward ent->fields.server->velocity[2] = 0; - clip = SV_FlyMove (ent, sv.frametime, stepnormal); + clip = SV_FlyMove (ent, sv.frametime, stepnormal, SV_GenericHitSuperContentsMask(ent)); ent->fields.server->velocity[2] += start_velocity[2]; SV_CheckVelocity(ent); @@ -2040,7 +1909,7 @@ void SV_Physics_Step (prvm_edict_t *ent) ent->fields.server->flags -= FL_ONGROUND; SV_AddGravity(ent); SV_CheckVelocity(ent); - SV_FlyMove(ent, sv.frametime, NULL); + SV_FlyMove(ent, sv.frametime, NULL, SV_GenericHitSuperContentsMask(ent)); SV_LinkEdict(ent, true); } } @@ -2051,7 +1920,7 @@ void SV_Physics_Step (prvm_edict_t *ent) SV_AddGravity(ent); SV_CheckVelocity(ent); - SV_FlyMove(ent, sv.frametime, NULL); + SV_FlyMove(ent, sv.frametime, NULL, SV_GenericHitSuperContentsMask(ent)); SV_LinkEdict(ent, true); // just hit ground @@ -2287,51 +2156,3 @@ void SV_Physics (void) if (!sv_freezenonclients.integer) sv.time += sv.frametime; } - - -trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore) -{ - int i; - float gravity; - vec3_t move, end; - vec3_t original_origin; - vec3_t original_velocity; - vec3_t original_angles; - vec3_t original_avelocity; - prvm_eval_t *val; - trace_t trace; - - VectorCopy(tossent->fields.server->origin , original_origin ); - VectorCopy(tossent->fields.server->velocity , original_velocity ); - VectorCopy(tossent->fields.server->angles , original_angles ); - VectorCopy(tossent->fields.server->avelocity, original_avelocity); - - val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity); - if (val != NULL && val->_float != 0) - gravity = val->_float; - else - gravity = 1.0; - gravity *= sv_gravity.value * 0.05; - - for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds - { - SV_CheckVelocity (tossent); - tossent->fields.server->velocity[2] -= gravity; - VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles); - VectorScale (tossent->fields.server->velocity, 0.05, move); - VectorAdd (tossent->fields.server->origin, move, end); - trace = SV_Move (tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent); - VectorCopy (trace.endpos, tossent->fields.server->origin); - - if (trace.fraction < 1) - break; - } - - VectorCopy(original_origin , tossent->fields.server->origin ); - VectorCopy(original_velocity , tossent->fields.server->velocity ); - VectorCopy(original_angles , tossent->fields.server->angles ); - VectorCopy(original_avelocity, tossent->fields.server->avelocity); - - return trace; -} - diff --git a/sv_user.c b/sv_user.c index f7d8b884..8ce2181d 100644 --- a/sv_user.c +++ b/sv_user.c @@ -68,7 +68,7 @@ void SV_SetIdealPitch (void) bottom[1] = top[1]; bottom[2] = top[2] - 160; - tr = SV_Move (top, vec3_origin, vec3_origin, bottom, MOVE_NOMONSTERS, host_client->edict); + tr = SV_Move (top, vec3_origin, vec3_origin, bottom, MOVE_NOMONSTERS, host_client->edict, SUPERCONTENTS_SOLID); // if looking at a wall, leave ideal the way is was if (tr.startsolid) return; @@ -134,7 +134,7 @@ void SV_UserFriction (void) start[2] = host_client->edict->fields.server->origin[2] + host_client->edict->fields.server->mins[2]; stop[2] = start[2] - 34; - trace = SV_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, host_client->edict); + trace = SV_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, host_client->edict, SV_GenericHitSuperContentsMask(host_client->edict)); if (trace.fraction == 1.0) friction = sv_friction.value*sv_edgefriction.value; diff --git a/svvm_cmds.c b/svvm_cmds.c index 74634725..f139e6f3 100644 --- a/svvm_cmds.c +++ b/svvm_cmds.c @@ -133,33 +133,22 @@ char *vm_sv_extensions = "TW_SV_STEPCONTROL " ; -/* -============== -PF_makevectors - -Writes new values for v_forward, v_up, and v_right based on angles -makevectors(vector) -============== -*/ -void PF_makevectors (void) -{ - AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up); -} - /* ================= -PF_setorigin +VM_SV_setorigin This is the only valid way to move an object without using the physics of the world (setting velocity and waiting). Directly changing origin will not set internal links correctly, so clipping would be messed up. This should be called when an object is spawned, and then only if it is teleported. setorigin (entity, origin) ================= */ -void PF_setorigin (void) +static void VM_SV_setorigin (void) { prvm_edict_t *e; float *org; + VM_SAFEPARMCOUNT(2, VM_setorigin); + e = PRVM_G_EDICT(OFS_PARM0); if (e == prog->edicts) { @@ -195,7 +184,7 @@ void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate) /* ================= -PF_setsize +VM_SV_setsize the size box is rotated by the current angle LordHavoc: no it isn't... @@ -203,11 +192,13 @@ LordHavoc: no it isn't... setsize (entity, minvector, maxvector) ================= */ -void PF_setsize (void) +static void VM_SV_setsize (void) { prvm_edict_t *e; float *min, *max; + VM_SAFEPARMCOUNT(3, VM_setsize); + e = PRVM_G_EDICT(OFS_PARM0); if (e == prog->edicts) { @@ -227,18 +218,20 @@ void PF_setsize (void) /* ================= -PF_setmodel +VM_SV_setmodel setmodel(entity, model) ================= */ static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16}; -void PF_setmodel (void) +static void VM_SV_setmodel (void) { prvm_edict_t *e; model_t *mod; int i; + VM_SAFEPARMCOUNT(2, VM_setmodel); + e = PRVM_G_EDICT(OFS_PARM0); if (e == prog->edicts) { @@ -269,19 +262,21 @@ void PF_setmodel (void) /* ================= -PF_sprint +VM_SV_sprint single print to a specific client sprint(clientent, value) ================= */ -void PF_sprint (void) +static void VM_SV_sprint (void) { client_t *client; int entnum; char string[VM_STRINGTEMP_LENGTH]; + VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint); + entnum = PRVM_G_EDICTNUM(OFS_PARM0); if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active) @@ -302,19 +297,21 @@ void PF_sprint (void) /* ================= -PF_centerprint +VM_SV_centerprint single print to a specific client centerprint(clientent, value) ================= */ -void PF_centerprint (void) +static void VM_SV_centerprint (void) { client_t *client; int entnum; char string[VM_STRINGTEMP_LENGTH]; + VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint); + entnum = PRVM_G_EDICTNUM(OFS_PARM0); if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active) @@ -334,17 +331,19 @@ void PF_centerprint (void) /* ================= -PF_particle +VM_SV_particle particle(origin, color, count) ================= */ -void PF_particle (void) +static void VM_SV_particle (void) { float *org, *dir; float color; float 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); @@ -355,17 +354,19 @@ void PF_particle (void) /* ================= -PF_ambientsound +VM_SV_ambientsound ================= */ -void PF_ambientsound (void) +static void VM_SV_ambientsound (void) { const char *samp; float *pos; float vol, attenuation; int soundnum, large; + VM_SAFEPARMCOUNT(4, VM_SV_ambientsound); + pos = PRVM_G_VECTOR (OFS_PARM0); samp = PRVM_G_STRING(OFS_PARM1); vol = PRVM_G_FLOAT(OFS_PARM2); @@ -401,7 +402,7 @@ void PF_ambientsound (void) /* ================= -PF_sound +VM_SV_sound Each entity can have eight independant sound sources, like voice, weapon, feet, etc. @@ -414,7 +415,7 @@ Larger attenuations will drop off. ================= */ -void PF_sound (void) +static void VM_SV_sound (void) { const char *sample; int channel; @@ -422,6 +423,8 @@ void PF_sound (void) int volume; float attenuation; + VM_SAFEPARMCOUNT(5, VM_SV_sound); + entity = PRVM_G_EDICT(OFS_PARM0); channel = (int)PRVM_G_FLOAT(OFS_PARM1); sample = PRVM_G_STRING(OFS_PARM2); @@ -451,22 +454,23 @@ void PF_sound (void) /* ================= -PF_traceline +VM_SV_traceline Used for use tracing and shot targeting Traces are blocked by bbox and exact bsp entityes, and also slide box entities if the tryents flag is set. -traceline (vector1, vector2, tryents) +traceline (vector1, vector2, movetype, ignore) ================= */ -void PF_traceline (void) +static void VM_SV_traceline (void) { float *v1, *v2; trace_t trace; int move; prvm_edict_t *ent; - prvm_eval_t *val; + + VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion prog->xfunction->builtinsprofile += 30; @@ -478,39 +482,15 @@ void PF_traceline (void) if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v1[2]) || IS_NAN(v2[2])) PRVM_ERROR("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent)); - trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent); - - prog->globals.server->trace_allsolid = trace.allsolid; - prog->globals.server->trace_startsolid = trace.startsolid; - prog->globals.server->trace_fraction = trace.fraction; - prog->globals.server->trace_inwater = trace.inwater; - prog->globals.server->trace_inopen = trace.inopen; - VectorCopy (trace.endpos, prog->globals.server->trace_endpos); - VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal); - prog->globals.server->trace_plane_dist = trace.plane.dist; - if (trace.ent) - prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent); - else - prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts); - if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dpstartcontents))) - val->_float = trace.startsupercontents; - if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitcontents))) - val->_float = trace.hitsupercontents; - if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitq3surfaceflags))) - val->_float = trace.hitq3surfaceflags; - if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphittexturename))) - { - if (trace.hittexture) - val->string = PRVM_SetTempString(trace.hittexture->name); - else - val->string = 0; - } + trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent, SV_GenericHitSuperContentsMask(ent)); + + VM_SetTraceGlobals(&trace); } /* ================= -PF_tracebox +VM_SV_tracebox Used for use tracing and shot targeting Traces are blocked by bbox and exact bsp entityes, and also slide box entities @@ -520,13 +500,14 @@ tracebox (vector1, vector mins, vector maxs, vector2, tryents) ================= */ // LordHavoc: added this for my own use, VERY useful, similar to traceline -void PF_tracebox (void) +static void VM_SV_tracebox (void) { float *v1, *v2, *m1, *m2; trace_t trace; int move; prvm_edict_t *ent; - prvm_eval_t *val; + + VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion prog->xfunction->builtinsprofile += 30; @@ -540,42 +521,64 @@ void PF_tracebox (void) if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v1[2]) || IS_NAN(v2[2])) PRVM_ERROR("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent)); - trace = SV_Move (v1, m1, m2, v2, move, ent); - - prog->globals.server->trace_allsolid = trace.allsolid; - prog->globals.server->trace_startsolid = trace.startsolid; - prog->globals.server->trace_fraction = trace.fraction; - prog->globals.server->trace_inwater = trace.inwater; - prog->globals.server->trace_inopen = trace.inopen; - VectorCopy (trace.endpos, prog->globals.server->trace_endpos); - VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal); - prog->globals.server->trace_plane_dist = trace.plane.dist; - if (trace.ent) - prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent); + trace = SV_Move (v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent)); + + VM_SetTraceGlobals(&trace); +} + +static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore) +{ + int i; + float gravity; + vec3_t move, end; + vec3_t original_origin; + vec3_t original_velocity; + vec3_t original_angles; + vec3_t original_avelocity; + prvm_eval_t *val; + trace_t trace; + + VectorCopy(tossent->fields.server->origin , original_origin ); + VectorCopy(tossent->fields.server->velocity , original_velocity ); + VectorCopy(tossent->fields.server->angles , original_angles ); + VectorCopy(tossent->fields.server->avelocity, original_avelocity); + + val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity); + if (val != NULL && val->_float != 0) + gravity = val->_float; else - prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts); - if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dpstartcontents))) - val->_float = trace.startsupercontents; - if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitcontents))) - val->_float = trace.hitsupercontents; - if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitq3surfaceflags))) - val->_float = trace.hitq3surfaceflags; - if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphittexturename))) - { - if (trace.hittexture) - val->string = PRVM_SetTempString(trace.hittexture->name); - else - val->string = 0; + gravity = 1.0; + gravity *= sv_gravity.value * 0.05; + + for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds + { + SV_CheckVelocity (tossent); + tossent->fields.server->velocity[2] -= gravity; + VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles); + VectorScale (tossent->fields.server->velocity, 0.05, move); + VectorAdd (tossent->fields.server->origin, move, end); + trace = SV_Move (tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent)); + VectorCopy (trace.endpos, tossent->fields.server->origin); + + if (trace.fraction < 1) + break; } + + VectorCopy(original_origin , tossent->fields.server->origin ); + VectorCopy(original_velocity , tossent->fields.server->velocity ); + VectorCopy(original_angles , tossent->fields.server->angles ); + VectorCopy(original_avelocity, tossent->fields.server->avelocity); + + return trace; } -extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore); -void PF_tracetoss (void) +static void VM_SV_tracetoss (void) { trace_t trace; prvm_edict_t *ent; prvm_edict_t *ignore; - prvm_eval_t *val; + + VM_SAFEPARMCOUNT(2, VM_SV_tracetoss); prog->xfunction->builtinsprofile += 600; @@ -589,54 +592,15 @@ void PF_tracetoss (void) trace = SV_Trace_Toss (ent, ignore); - prog->globals.server->trace_allsolid = trace.allsolid; - prog->globals.server->trace_startsolid = trace.startsolid; - prog->globals.server->trace_fraction = trace.fraction; - prog->globals.server->trace_inwater = trace.inwater; - prog->globals.server->trace_inopen = trace.inopen; - VectorCopy (trace.endpos, prog->globals.server->trace_endpos); - VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal); - prog->globals.server->trace_plane_dist = trace.plane.dist; - if (trace.ent) - prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent); - else - prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts); - if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dpstartcontents))) - val->_float = trace.startsupercontents; - if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitcontents))) - val->_float = trace.hitsupercontents; - if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitq3surfaceflags))) - val->_float = trace.hitq3surfaceflags; - if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphittexturename))) - { - if (trace.hittexture) - val->string = PRVM_SetTempString(trace.hittexture->name); - else - val->string = 0; - } -} - - -/* -================= -PF_checkpos - -Returns true if the given entity can move to the given position from it's -current position by walking or rolling. -FIXME: make work... -scalar checkpos (entity, vector) -================= -*/ -void PF_checkpos (void) -{ + VM_SetTraceGlobals(&trace); } //============================================================================ -int checkpvsbytes; -unsigned char checkpvs[MAX_MAP_LEAFS/8]; +static int checkpvsbytes; +static unsigned char checkpvs[MAX_MAP_LEAFS/8]; -int PF_newcheckclient (int check) +static int VM_SV_newcheckclient (int check) { int i; prvm_edict_t *ent; @@ -677,7 +641,7 @@ int PF_newcheckclient (int check) /* ================= -PF_checkclient +VM_SV_checkclient Returns a client (or object that has a client enemy) that would be a valid target. @@ -691,15 +655,17 @@ name checkclient () ================= */ int c_invis, c_notvis; -void PF_checkclient (void) +static void VM_SV_checkclient (void) { prvm_edict_t *ent, *self; vec3_t view; + VM_SAFEPARMCOUNT(0, VM_SV_checkclient); + // find a new check if on a new frame if (sv.time - sv.lastchecktime >= 0.1) { - sv.lastcheck = PF_newcheckclient (sv.lastcheck); + sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck); sv.lastchecktime = sv.time; } @@ -731,19 +697,21 @@ void PF_checkclient (void) /* ================= -PF_stuffcmd +VM_SV_stuffcmd Sends text over to the client's execution buffer stuffcmd (clientent, value, ...) ================= */ -void PF_stuffcmd (void) +static void VM_SV_stuffcmd (void) { int entnum; client_t *old; char string[VM_STRINGTEMP_LENGTH]; + VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd); + entnum = PRVM_G_EDICTNUM(OFS_PARM0); if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active) { @@ -761,14 +729,14 @@ void PF_stuffcmd (void) /* ================= -PF_findradius +VM_SV_findradius Returns a chain of entities that have origins within a spherical area findradius (origin, radius) ================= */ -void PF_findradius (void) +static void VM_SV_findradius (void) { prvm_edict_t *ent, *chain; vec_t radius, radius2; @@ -777,6 +745,8 @@ void PF_findradius (void) int numtouchedicts; prvm_edict_t *touchedicts[MAX_EDICTS]; + VM_SAFEPARMCOUNT(2, VM_SV_findradius); + chain = (prvm_edict_t *)prog->edicts; VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org); @@ -826,38 +796,37 @@ void PF_findradius (void) VM_RETURN_EDICT(chain); } -void PF_precache_file (void) -{ // precache_file is only used to copy files with qcc, it does nothing - PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0); -} - - -void PF_precache_sound (void) +static void VM_SV_precache_sound (void) { + VM_SAFEPARMCOUNT(1, VM_SV_precache_sound); SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2); PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0); } -void PF_precache_model (void) +static void VM_SV_precache_model (void) { + VM_SAFEPARMCOUNT(1, VM_SV_precache_model); SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2); PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0); } /* =============== -PF_walkmove +VM_SV_walkmove -float(float yaw, float dist) walkmove +float(float yaw, float dist[, settrace]) walkmove =============== */ -void PF_walkmove (void) +static void VM_SV_walkmove (void) { prvm_edict_t *ent; float yaw, dist; vec3_t move; mfunction_t *oldf; int oldself; + qboolean settrace; + + VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove); // assume failure if it returns early PRVM_G_FLOAT(OFS_RETURN) = 0; @@ -875,6 +844,7 @@ void PF_walkmove (void) } yaw = PRVM_G_FLOAT(OFS_PARM0); dist = PRVM_G_FLOAT(OFS_PARM1); + settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2); if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) ) return; @@ -889,7 +859,7 @@ void PF_walkmove (void) oldf = prog->xfunction; oldself = prog->globals.server->self; - PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true); + PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace); // restore program state @@ -899,17 +869,19 @@ void PF_walkmove (void) /* =============== -PF_droptofloor +VM_SV_droptofloor void() droptofloor =============== */ -void PF_droptofloor (void) +static void VM_SV_droptofloor (void) { 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 + // assume failure if it returns early PRVM_G_FLOAT(OFS_RETURN) = 0; @@ -928,7 +900,7 @@ void PF_droptofloor (void) VectorCopy (ent->fields.server->origin, end); end[2] -= 256; - trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent); + trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent)); if (trace.fraction != 1 || (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)) { @@ -945,18 +917,20 @@ void PF_droptofloor (void) /* =============== -PF_lightstyle +VM_SV_lightstyle void(float style, string value) lightstyle =============== */ -void PF_lightstyle (void) +static void VM_SV_lightstyle (void) { int style; const char *val; client_t *client; int j; + VM_SAFEPARMCOUNT(2, VM_SV_lightstyle); + style = (int)PRVM_G_FLOAT(OFS_PARM0); val = PRVM_G_STRING(OFS_PARM1); @@ -984,33 +958,35 @@ void PF_lightstyle (void) /* ============= -PF_checkbottom +VM_SV_checkbottom ============= */ -void PF_checkbottom (void) +static void VM_SV_checkbottom (void) { + VM_SAFEPARMCOUNT(0, VM_SV_checkbottom); PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0)); } /* ============= -PF_pointcontents +VM_SV_pointcontents ============= */ -void PF_pointcontents (void) +static void VM_SV_pointcontents (void) { + VM_SAFEPARMCOUNT(1, VM_SV_pointcontents); PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0))); } /* ============= -PF_aim +VM_SV_aim Pick a vector for the player to shoot along vector aim(entity, missilespeed) ============= */ -void PF_aim (void) +static void VM_SV_aim (void) { prvm_edict_t *ent, *check, *bestent; vec3_t start, dir, end, bestdir; @@ -1019,6 +995,8 @@ void PF_aim (void) float dist, bestdist; float speed; + VM_SAFEPARMCOUNT(2, VM_SV_aim); + // assume failure if it returns early VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN)); // if sv_aim is so high it can't possibly accept anything, skip out early @@ -1044,7 +1022,7 @@ void PF_aim (void) // try sending a trace straight VectorCopy (prog->globals.server->v_forward, dir); VectorMA (start, 2048, dir, end); - tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent); + tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY); if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) ) { @@ -1076,7 +1054,7 @@ void PF_aim (void) dist = DotProduct (dir, prog->globals.server->v_forward); if (dist < bestdist) continue; // to far to turn - tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent); + tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY); if (tr.ent == check) { // can shoot at this one bestdist = dist; @@ -1152,59 +1130,70 @@ sizebuf_t *WriteDest (void) return NULL; } -void PF_WriteByte (void) +static void VM_SV_WriteByte (void) { + VM_SAFEPARMCOUNT(2, VM_SV_WriteByte); MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1)); } -void PF_WriteChar (void) +static void VM_SV_WriteChar (void) { + VM_SAFEPARMCOUNT(2, VM_SV_WriteChar); MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1)); } -void PF_WriteShort (void) +static void VM_SV_WriteShort (void) { + VM_SAFEPARMCOUNT(2, VM_SV_WriteShort); MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1)); } -void PF_WriteLong (void) +static void VM_SV_WriteLong (void) { + VM_SAFEPARMCOUNT(2, VM_SV_WriteLong); MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1)); } -void PF_WriteAngle (void) +static void VM_SV_WriteAngle (void) { + VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle); MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol); } -void PF_WriteCoord (void) +static void VM_SV_WriteCoord (void) { + VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord); MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol); } -void PF_WriteString (void) +static void VM_SV_WriteString (void) { + VM_SAFEPARMCOUNT(2, VM_SV_WriteString); MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1)); } -void PF_WriteUnterminatedString (void) +static void VM_SV_WriteUnterminatedString (void) { + VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString); MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1)); } -void PF_WriteEntity (void) +static void VM_SV_WriteEntity (void) { + VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity); MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1)); } ////////////////////////////////////////////////////////// -void PF_makestatic (void) +static void VM_SV_makestatic (void) { prvm_edict_t *ent; int i, large; + VM_SAFEPARMCOUNT(1, VM_SV_makestatic); + ent = PRVM_G_EDICT(OFS_PARM0); if (ent == prog->edicts) { @@ -1250,15 +1239,17 @@ void PF_makestatic (void) /* ============== -PF_setspawnparms +VM_SV_setspawnparms ============== */ -void PF_setspawnparms (void) +static void VM_SV_setspawnparms (void) { prvm_edict_t *ent; int i; client_t *client; + VM_SAFEPARMCOUNT(0, VM_SV_setspawnparms); + ent = PRVM_G_EDICT(OFS_PARM0); i = PRVM_NUM_FOR_EDICT(ent); if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active) @@ -1275,7 +1266,7 @@ void PF_setspawnparms (void) /* ================= -PF_getlight +VM_SV_getlight Returns a color vector indicating the lighting at the requested point. @@ -1285,10 +1276,11 @@ Returns a color vector indicating the lighting at the requested point. getlight(vector) ================= */ -void PF_getlight (void) +static void VM_SV_getlight (void) { vec3_t ambientcolor, diffusecolor, diffusenormal; vec_t *p; + VM_SAFEPARMCOUNT(1, VM_SV_getlight); p = PRVM_G_VECTOR(OFS_PARM0); VectorClear(ambientcolor); VectorClear(diffusecolor); @@ -1298,29 +1290,6 @@ void PF_getlight (void) VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN)); } -void PF_registercvar (void) -{ - const char *name, *value; - name = PRVM_G_STRING(OFS_PARM0); - value = PRVM_G_STRING(OFS_PARM1); - PRVM_G_FLOAT(OFS_RETURN) = 0; - -// first check to see if it has already been defined - if (Cvar_FindVar (name)) - return; - -// check for overlap with a command - if (Cmd_Exists (name)) - { - VM_Warning("PF_registercvar: %s is a command\n", name); - return; - } - - Cvar_Get(name, value, 0); - - PRVM_G_FLOAT(OFS_RETURN) = 1; // success -} - typedef struct { unsigned char type; // 1/2/8 or other value if isn't used @@ -1435,11 +1404,13 @@ void VM_SV_WriteAutoSentStats (client_t *client, prvm_edict_t *ent, sizebuf_t *m // 1: string (4 stats carrying a total of 16 charactures) // 2: float (one stat, float converted to an integer for transportation) // 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!) -void PF_SV_AddStat (void) +static void VM_SV_AddStat (void) { int off, i; unsigned char type; + VM_SAFEPARMCOUNT(2, VM_SV_AddStat); + if(!vm_autosentstats) { vm_autosentstats = (autosentstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(autosentstat_t)); @@ -1477,16 +1448,17 @@ void PF_SV_AddStat (void) /* ================= -PF_copyentity +VM_SV_copyentity copies data from one entity to another copyentity(src, dst) ================= */ -void PF_copyentity (void) +static void VM_SV_copyentity (void) { prvm_edict_t *in, *out; + VM_SAFEPARMCOUNT(2, VM_SV_copyentity); in = PRVM_G_EDICT(OFS_PARM0); if (in == prog->edicts) { @@ -1509,25 +1481,27 @@ void PF_copyentity (void) VM_Warning("copyentity: can not modify free entity\n"); return; } - memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4); + memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4); + SV_LinkEdict(out, false); } /* ================= -PF_setcolor +VM_SV_setcolor sets the color of a client and broadcasts the update to all connected clients setcolor(clientent, value) ================= */ -void PF_setcolor (void) +static void VM_SV_setcolor (void) { client_t *client; int entnum, i; prvm_eval_t *val; + VM_SAFEPARMCOUNT(2, VM_SV_setcolor); entnum = PRVM_G_EDICTNUM(OFS_PARM0); i = (int)PRVM_G_FLOAT(OFS_PARM1); @@ -1557,15 +1531,16 @@ void PF_setcolor (void) /* ================= -PF_effect +VM_SV_effect effect(origin, modelname, startframe, framecount, framerate) ================= */ -void PF_effect (void) +static void VM_SV_effect (void) { int i; const char *s; + VM_SAFEPARMCOUNT(5, VM_SV_effect); s = PRVM_G_STRING(OFS_PARM1); if (!s[0]) { @@ -1595,8 +1570,9 @@ void PF_effect (void) 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)); } -void PF_te_blood (void) +static void VM_SV_te_blood (void) { + VM_SAFEPARMCOUNT(3, VM_SV_te_blood); if (PRVM_G_FLOAT(OFS_PARM2) < 1) return; MSG_WriteByte(&sv.datagram, svc_temp_entity); @@ -1613,8 +1589,9 @@ void PF_te_blood (void) MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255)); } -void PF_te_bloodshower (void) +static void VM_SV_te_bloodshower (void) { + VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower); if (PRVM_G_FLOAT(OFS_PARM3) < 1) return; MSG_WriteByte(&sv.datagram, svc_temp_entity); @@ -1633,8 +1610,9 @@ void PF_te_bloodshower (void) MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535)); } -void PF_te_explosionrgb (void) +static void VM_SV_te_explosionrgb (void) { + VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb); MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB); // origin @@ -1647,8 +1625,9 @@ void PF_te_explosionrgb (void) MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255)); } -void PF_te_particlecube (void) +static void VM_SV_te_particlecube (void) { + VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube); if (PRVM_G_FLOAT(OFS_PARM3) < 1) return; MSG_WriteByte(&sv.datagram, svc_temp_entity); @@ -1675,8 +1654,9 @@ void PF_te_particlecube (void) MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol); } -void PF_te_particlerain (void) +static void VM_SV_te_particlerain (void) { + VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain); if (PRVM_G_FLOAT(OFS_PARM3) < 1) return; MSG_WriteByte(&sv.datagram, svc_temp_entity); @@ -1699,8 +1679,9 @@ void PF_te_particlerain (void) MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4)); } -void PF_te_particlesnow (void) +static void VM_SV_te_particlesnow (void) { + VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow); if (PRVM_G_FLOAT(OFS_PARM3) < 1) return; MSG_WriteByte(&sv.datagram, svc_temp_entity); @@ -1723,8 +1704,9 @@ void PF_te_particlesnow (void) MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4)); } -void PF_te_spark (void) +static void VM_SV_te_spark (void) { + VM_SAFEPARMCOUNT(3, VM_SV_te_spark); if (PRVM_G_FLOAT(OFS_PARM2) < 1) return; MSG_WriteByte(&sv.datagram, svc_temp_entity); @@ -1741,8 +1723,9 @@ void PF_te_spark (void) MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255)); } -void PF_te_gunshotquad (void) +static void VM_SV_te_gunshotquad (void) { + VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad); MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD); // origin @@ -1751,8 +1734,9 @@ void PF_te_gunshotquad (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); } -void PF_te_spikequad (void) +static void VM_SV_te_spikequad (void) { + VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad); MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD); // origin @@ -1761,8 +1745,9 @@ void PF_te_spikequad (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); } -void PF_te_superspikequad (void) +static void VM_SV_te_superspikequad (void) { + VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad); MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD); // origin @@ -1771,8 +1756,9 @@ void PF_te_superspikequad (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); } -void PF_te_explosionquad (void) +static void VM_SV_te_explosionquad (void) { + VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad); MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD); // origin @@ -1781,8 +1767,9 @@ void PF_te_explosionquad (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); } -void PF_te_smallflash (void) +static void VM_SV_te_smallflash (void) { + VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash); MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_SMALLFLASH); // origin @@ -1791,8 +1778,9 @@ void PF_te_smallflash (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); } -void PF_te_customflash (void) +static void VM_SV_te_customflash (void) { + VM_SAFEPARMCOUNT(4, VM_SV_te_customflash); if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0)) return; MSG_WriteByte(&sv.datagram, svc_temp_entity); @@ -1811,8 +1799,9 @@ void PF_te_customflash (void) MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255)); } -void PF_te_gunshot (void) +static void VM_SV_te_gunshot (void) { + VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot); MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_GUNSHOT); // origin @@ -1821,8 +1810,9 @@ void PF_te_gunshot (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); } -void PF_te_spike (void) +static void VM_SV_te_spike (void) { + VM_SAFEPARMCOUNT(1, VM_SV_te_spike); MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_SPIKE); // origin @@ -1831,8 +1821,9 @@ void PF_te_spike (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); } -void PF_te_superspike (void) +static void VM_SV_te_superspike (void) { + VM_SAFEPARMCOUNT(1, VM_SV_te_superspike); MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE); // origin @@ -1841,8 +1832,9 @@ void PF_te_superspike (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); } -void PF_te_explosion (void) +static void VM_SV_te_explosion (void) { + VM_SAFEPARMCOUNT(1, VM_SV_te_explosion); MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_EXPLOSION); // origin @@ -1851,8 +1843,9 @@ void PF_te_explosion (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); } -void PF_te_tarexplosion (void) +static void VM_SV_te_tarexplosion (void) { + VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion); MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION); // origin @@ -1861,8 +1854,9 @@ void PF_te_tarexplosion (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); } -void PF_te_wizspike (void) +static void VM_SV_te_wizspike (void) { + VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike); MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_WIZSPIKE); // origin @@ -1871,8 +1865,9 @@ void PF_te_wizspike (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); } -void PF_te_knightspike (void) +static void VM_SV_te_knightspike (void) { + VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike); MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE); // origin @@ -1881,8 +1876,9 @@ void PF_te_knightspike (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); } -void PF_te_lavasplash (void) +static void VM_SV_te_lavasplash (void) { + VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash); MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_LAVASPLASH); // origin @@ -1891,8 +1887,9 @@ void PF_te_lavasplash (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); } -void PF_te_teleport (void) +static void VM_SV_te_teleport (void) { + VM_SAFEPARMCOUNT(1, VM_SV_te_teleport); MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_TELEPORT); // origin @@ -1901,8 +1898,9 @@ void PF_te_teleport (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); } -void PF_te_explosion2 (void) +static void VM_SV_te_explosion2 (void) { + VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2); MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_EXPLOSION2); // origin @@ -1914,8 +1912,9 @@ void PF_te_explosion2 (void) MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2)); } -void PF_te_lightning1 (void) +static void VM_SV_te_lightning1 (void) { + VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1); MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_LIGHTNING1); // owner entity @@ -1930,8 +1929,9 @@ void PF_te_lightning1 (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol); } -void PF_te_lightning2 (void) +static void VM_SV_te_lightning2 (void) { + VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2); MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_LIGHTNING2); // owner entity @@ -1946,8 +1946,9 @@ void PF_te_lightning2 (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol); } -void PF_te_lightning3 (void) +static void VM_SV_te_lightning3 (void) { + VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3); MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_LIGHTNING3); // owner entity @@ -1962,8 +1963,9 @@ void PF_te_lightning3 (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol); } -void PF_te_beam (void) +static void VM_SV_te_beam (void) { + VM_SAFEPARMCOUNT(3, VM_SV_te_beam); MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_BEAM); // owner entity @@ -1978,8 +1980,9 @@ void PF_te_beam (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol); } -void PF_te_plasmaburn (void) +static void VM_SV_te_plasmaburn (void) { + VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn); MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_PLASMABURN); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); @@ -1987,8 +1990,9 @@ void PF_te_plasmaburn (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); } -void PF_te_flamejet (void) +static void VM_SV_te_flamejet (void) { + VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet); MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_FLAMEJET); // org @@ -2059,10 +2063,11 @@ static msurface_t *getsurface(model_t *model, int surfacenum) //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434; -void PF_getsurfacenumpoints(void) +static void VM_SV_getsurfacenumpoints(void) { model_t *model; msurface_t *surface; + VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenumpoints); // return 0 if no such surface if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) { @@ -2074,12 +2079,13 @@ void PF_getsurfacenumpoints(void) PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices; } //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435; -void PF_getsurfacepoint(void) +static void VM_SV_getsurfacepoint(void) { prvm_edict_t *ed; model_t *model; msurface_t *surface; int pointnum; + VM_SAFEPARMCOUNT(3, VM_SV_getsurfacepoint); VectorClear(PRVM_G_VECTOR(OFS_RETURN)); ed = PRVM_G_EDICT(OFS_PARM0); if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) @@ -2092,11 +2098,12 @@ void PF_getsurfacepoint(void) VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN)); } //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436; -void PF_getsurfacenormal(void) +static void VM_SV_getsurfacenormal(void) { model_t *model; msurface_t *surface; vec3_t normal; + VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenormal); VectorClear(PRVM_G_VECTOR(OFS_RETURN)); if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) return; @@ -2109,17 +2116,18 @@ void PF_getsurfacenormal(void) VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN)); } //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437; -void PF_getsurfacetexture(void) +static void VM_SV_getsurfacetexture(void) { model_t *model; msurface_t *surface; + VM_SAFEPARMCOUNT(2, VM_SV_getsurfacetexture); PRVM_G_INT(OFS_RETURN) = OFS_NULL; if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) return; PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name); } //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438; -void PF_getsurfacenearpoint(void) +static void VM_SV_getsurfacenearpoint(void) { int surfacenum, best; vec3_t clipped, p; @@ -2128,6 +2136,7 @@ void PF_getsurfacenearpoint(void) model_t *model; msurface_t *surface; vec_t *point; + VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenearpoint); PRVM_G_FLOAT(OFS_RETURN) = -1; ed = PRVM_G_EDICT(OFS_PARM0); point = PRVM_G_VECTOR(OFS_PARM1); @@ -2167,12 +2176,13 @@ void PF_getsurfacenearpoint(void) PRVM_G_FLOAT(OFS_RETURN) = best; } //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439; -void PF_getsurfaceclippedpoint(void) +static void VM_SV_getsurfaceclippedpoint(void) { prvm_edict_t *ed; model_t *model; msurface_t *surface; vec3_t p, out; + VM_SAFEPARMCOUNT(3, VM_SV_te_getsurfaceclippedpoint); VectorClear(PRVM_G_VECTOR(OFS_RETURN)); ed = PRVM_G_EDICT(OFS_PARM0); if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) @@ -2186,10 +2196,11 @@ void PF_getsurfaceclippedpoint(void) //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 -void PF_clientcommand (void) +static void VM_SV_clientcommand (void) { client_t *temp_client; int i; + VM_SAFEPARMCOUNT(2, VM_SV_clientcommand); //find client for this entity i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1); @@ -2206,7 +2217,7 @@ void PF_clientcommand (void) } //void(entity e, entity tagentity, string tagname) setattachment = #443; // attachs e to a tag on tagentity (note: use "" to attach to entity origin/angles instead of a tag) -void PF_setattachment (void) +static void VM_SV_setattachment (void) { prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0); prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1); @@ -2214,6 +2225,7 @@ void PF_setattachment (void) prvm_eval_t *v; int modelindex; model_t *model; + VM_SAFEPARMCOUNT(3, VM_SV_setattachment); if (e == prog->edicts) { @@ -2391,12 +2403,17 @@ int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex) //float(entity ent, string tagname) gettagindex; -void PF_gettagindex (void) +static void VM_SV_gettagindex (void) { - prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0); - const char *tag_name = PRVM_G_STRING(OFS_PARM1); + prvm_edict_t *ent; + const char *tag_name; int modelindex, tag_index; + VM_SAFEPARMCOUNT(2, VM_SV_gettagindex); + + ent = PRVM_G_EDICT(OFS_PARM0); + tag_name = PRVM_G_STRING(OFS_PARM1); + if (ent == prog->edicts) { VM_Warning("gettagindex: can't affect world entity\n"); @@ -2422,13 +2439,18 @@ void PF_gettagindex (void) }; //vector(entity ent, float tagindex) gettaginfo; -void PF_gettaginfo (void) +static void VM_SV_gettaginfo (void) { - prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0); - int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1); + prvm_edict_t *e; + int tagindex; matrix4x4_t tag_matrix; int returncode; + VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo); + + e = PRVM_G_EDICT(OFS_PARM0); + tagindex = (int)PRVM_G_FLOAT(OFS_PARM1); + returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex); Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN)); @@ -2453,10 +2475,11 @@ void PF_gettaginfo (void) } //void(entity clent) dropclient (DP_SV_DROPCLIENT) -void PF_dropclient (void) +static void VM_SV_dropclient (void) { int clientnum; client_t *oldhostclient; + VM_SAFEPARMCOUNT(1, VM_SV_dropclient); clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1; if (clientnum < 0 || clientnum >= svs.maxclients) { @@ -2475,10 +2498,11 @@ void PF_dropclient (void) } //entity() spawnclient (DP_SV_BOTCLIENT) -void PF_spawnclient (void) +static void VM_SV_spawnclient (void) { int i; prvm_edict_t *ed; + VM_SAFEPARMCOUNT(0, VM_SV_spawnclient); prog->xfunction->builtinsprofile += 2; ed = prog->edicts; for (i = 0;i < svs.maxclients;i++) @@ -2498,9 +2522,10 @@ void PF_spawnclient (void) } //float(entity clent) clienttype (DP_SV_BOTCLIENT) -void PF_clienttype (void) +static void VM_SV_clienttype (void) { int clientnum; + 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; @@ -2512,9 +2537,100 @@ void PF_clienttype (void) PRVM_G_FLOAT(OFS_RETURN) = 2; } -void PF_edict_num (void) +/* +=============== +VM_SV_serverkey + +string(string key) serverkey +=============== +*/ +void VM_SV_serverkey(void) +{ + char string[VM_STRINGTEMP_LENGTH]; + 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(string); +} + +//#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC) +static void VM_SV_setmodelindex (void) +{ + prvm_edict_t *e; + model_t *mod; + int i; + VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex); + + e = PRVM_G_EDICT(OFS_PARM0); + if (e == prog->edicts) + { + VM_Warning("setmodelindex: can not modify world entity\n"); + return; + } + if (e->priv.server->free) + { + VM_Warning("setmodelindex: can not modify free entity\n"); + return; + } + i = (int)PRVM_G_FLOAT(OFS_PARM1); + if (i <= 0 || i > MAX_MODELS) + { + VM_Warning("setmodelindex: invalid modelindex\n"); + return; + } + if (!sv.model_precache[i][0]) + { + VM_Warning("setmodelindex: model not precached\n"); + return; + } + + e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]); + e->fields.server->modelindex = i; + + mod = sv.models[i]; + + if (mod) + { + if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer) + SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true); + else + SetMinMaxSize (e, quakemins, quakemaxs, true); + } + else + SetMinMaxSize (e, vec3_origin, vec3_origin, true); +} + +//#334 string(float mdlindex) modelnameforindex (EXT_CSQC) +static void VM_SV_modelnameforindex (void) +{ + int i; + VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex); + + PRVM_G_INT(OFS_RETURN) = OFS_NULL; + + i = (int)PRVM_G_FLOAT(OFS_PARM0); + if (i <= 0 || i > MAX_MODELS) + { + VM_Warning("modelnameforindex: invalid modelindex\n"); + return; + } + if (!sv.model_precache[i][0]) + { + VM_Warning("modelnameforindex: model not precached\n"); + return; + } + + PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]); +} + +//#335 float(string effectname) particleeffectnum (EXT_CSQC) +static void VM_SV_particleeffectnum (void) { - VM_RETURN_EDICT(PRVM_EDICT_NUM((int)PRVM_G_FLOAT(OFS_PARM0))); + int i; + VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum); + i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0)); + if (i == 0) + i = -1; + PRVM_G_FLOAT(OFS_RETURN) = i; } // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC) @@ -2542,257 +2658,510 @@ static void VM_SV_pointparticles (void) } prvm_builtin_t vm_sv_builtins[] = { -NULL, // #0 -PF_makevectors, // #1 void(vector ang) makevectors -PF_setorigin, // #2 void(entity e, vector o) setorigin -PF_setmodel, // #3 void(entity e, string m) setmodel -PF_setsize, // #4 void(entity e, vector min, vector max) setsize -NULL, // #5 void(entity e, vector min, vector max) setabssize -VM_break, // #6 void() break -VM_random, // #7 float() random -PF_sound, // #8 void(entity e, float chan, string samp) sound -VM_normalize, // #9 vector(vector v) normalize -VM_error, // #10 void(string e) error -VM_objerror, // #11 void(string e) objerror -VM_vlen, // #12 float(vector v) vlen -VM_vectoyaw, // #13 float(vector v) vectoyaw -VM_spawn, // #14 entity() spawn -VM_remove, // #15 void(entity e) remove -PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline -PF_checkclient, // #17 entity() clientlist -VM_find, // #18 entity(entity start, .string fld, string match) find -PF_precache_sound, // #19 void(string s) precache_sound -PF_precache_model, // #20 void(string s) precache_model -PF_stuffcmd, // #21 void(entity client, string s)stuffcmd -PF_findradius, // #22 entity(vector org, float rad) findradius -VM_bprint, // #23 void(string s) bprint -PF_sprint, // #24 void(entity client, string s) sprint -VM_dprint, // #25 void(string s) dprint -VM_ftos, // #26 void(string s) ftos -VM_vtos, // #27 void(string s) vtos -VM_coredump, // #28 void() coredump -VM_traceon, // #29 void() traceon -VM_traceoff, // #30 void() traceoff -VM_eprint, // #31 void(entity e) eprint -PF_walkmove, // #32 float(float yaw, float dist) walkmove -NULL, // #33 -PF_droptofloor, // #34 float() droptofloor -PF_lightstyle, // #35 void(float style, string value) lightstyle -VM_rint, // #36 float(float v) rint -VM_floor, // #37 float(float v) floor -VM_ceil, // #38 float(float v) ceil -NULL, // #39 -PF_checkbottom, // #40 float(entity e) checkbottom -PF_pointcontents, // #41 float(vector v) pointcontents -NULL, // #42 -VM_fabs, // #43 float(float f) fabs -PF_aim, // #44 vector(entity e, float speed) aim -VM_cvar, // #45 float(string s) cvar -VM_localcmd, // #46 void(string s) localcmd -VM_nextent, // #47 entity(entity e) nextent -PF_particle, // #48 void(vector o, vector d, float color, float count) particle -VM_changeyaw, // #49 void() ChangeYaw -NULL, // #50 -VM_vectoangles, // #51 vector(vector v) vectoangles -PF_WriteByte, // #52 void(float to, float f) WriteByte -PF_WriteChar, // #53 void(float to, float f) WriteChar -PF_WriteShort, // #54 void(float to, float f) WriteShort -PF_WriteLong, // #55 void(float to, float f) WriteLong -PF_WriteCoord, // #56 void(float to, float f) WriteCoord -PF_WriteAngle, // #57 void(float to, float f) WriteAngle -PF_WriteString, // #58 void(float to, string s) WriteString -PF_WriteEntity, // #59 void(float to, entity e) WriteEntity -VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) -VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) -VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) -VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) -PF_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) -VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) -NULL, // #66 -SV_MoveToGoal, // #67 void(float step) movetogoal -PF_precache_file, // #68 string(string s) precache_file -PF_makestatic, // #69 void(entity e) makestatic -VM_changelevel, // #70 void(string s) changelevel -NULL, // #71 -VM_cvar_set, // #72 void(string var, string val) cvar_set -PF_centerprint, // #73 void(entity client, strings) centerprint -PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound -PF_precache_model, // #75 string(string s) precache_model2 -PF_precache_sound, // #76 string(string s) precache_sound2 -PF_precache_file, // #77 string(string s) precache_file2 -PF_setspawnparms, // #78 void(entity e) setspawnparms -NULL, // #79 -NULL, // #80 -VM_stof, // #81 float(string s) stof (FRIK_FILE) -NULL, // #82 -NULL, // #83 -NULL, // #84 -NULL, // #85 -NULL, // #86 -NULL, // #87 -NULL, // #88 -NULL, // #89 -PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX) -VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC) -PF_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT) -PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR) -VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND) -VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND) -VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND) -VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW) -VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT) -VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system) -NULL, // #100 -NULL, // #101 -NULL, // #102 -NULL, // #103 -NULL, // #104 -NULL, // #105 -NULL, // #106 -NULL, // #107 -NULL, // #108 -NULL, // #109 -VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE) -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_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) -VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE) -e10, e10, e10, e10, e10, e10, e10, e10, // #120-199 +NULL, // #0 NULL function (not callable) (QUAKE) +VM_makevectors, // #1 void(vector ang) makevectors (QUAKE) +VM_SV_setorigin, // #2 void(entity e, vector o) setorigin (QUAKE) +VM_SV_setmodel, // #3 void(entity e, string m) setmodel (QUAKE) +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_normalize, // #9 vector(vector v) normalize (QUAKE) +VM_error, // #10 void(string e) error (QUAKE) +VM_objerror, // #11 void(string e) objerror (QUAKE) +VM_vlen, // #12 float(vector v) vlen (QUAKE) +VM_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE) +VM_spawn, // #14 entity() spawn (QUAKE) +VM_remove, // #15 void(entity e) remove (QUAKE) +VM_SV_traceline, // #16 float(vector v1, vector v2, float tryents) traceline (QUAKE) +VM_SV_checkclient, // #17 entity() checkclient (QUAKE) +VM_find, // #18 entity(entity start, .string fld, string match) find (QUAKE) +VM_SV_precache_sound, // #19 void(string s) precache_sound (QUAKE) +VM_SV_precache_model, // #20 void(string s) precache_model (QUAKE) +VM_SV_stuffcmd, // #21 void(entity client, string s, ...) stuffcmd (QUAKE) +VM_SV_findradius, // #22 entity(vector org, float rad) findradius (QUAKE) +VM_bprint, // #23 void(string s, ...) bprint (QUAKE) +VM_SV_sprint, // #24 void(entity client, string s, ...) sprint (QUAKE) +VM_dprint, // #25 void(string s, ...) dprint (QUAKE) +VM_ftos, // #26 string(float f) ftos (QUAKE) +VM_vtos, // #27 string(vector v) vtos (QUAKE) +VM_coredump, // #28 void() coredump (QUAKE) +VM_traceon, // #29 void() traceon (QUAKE) +VM_traceoff, // #30 void() traceoff (QUAKE) +VM_eprint, // #31 void(entity e) eprint (QUAKE) +VM_SV_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE) +NULL, // #33 (QUAKE) +VM_SV_droptofloor, // #34 float() droptofloor (QUAKE) +VM_SV_lightstyle, // #35 void(float style, string value) lightstyle (QUAKE) +VM_rint, // #36 float(float v) rint (QUAKE) +VM_floor, // #37 float(float v) floor (QUAKE) +VM_ceil, // #38 float(float v) ceil (QUAKE) +NULL, // #39 (QUAKE) +VM_SV_checkbottom, // #40 float(entity e) checkbottom (QUAKE) +VM_SV_pointcontents, // #41 float(vector v) pointcontents (QUAKE) +NULL, // #42 (QUAKE) +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_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, // #50 (QUAKE) +VM_vectoangles, // #51 vector(vector v) vectoangles (QUAKE) +VM_SV_WriteByte, // #52 void(float to, float f) WriteByte (QUAKE) +VM_SV_WriteChar, // #53 void(float to, float f) WriteChar (QUAKE) +VM_SV_WriteShort, // #54 void(float to, float f) WriteShort (QUAKE) +VM_SV_WriteLong, // #55 void(float to, float f) WriteLong (QUAKE) +VM_SV_WriteCoord, // #56 void(float to, float f) WriteCoord (QUAKE) +VM_SV_WriteAngle, // #57 void(float to, float f) WriteAngle (QUAKE) +VM_SV_WriteString, // #58 void(float to, string s) WriteString (QUAKE) +VM_SV_WriteEntity, // #59 void(float to, entity e) WriteEntity (QUAKE) +VM_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE) +VM_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE) +VM_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE) +VM_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE) +VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE) +VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE) +NULL, // #66 (QUAKE) +SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE) +VM_precache_file, // #68 string(string s) precache_file (QUAKE) +VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE) +VM_changelevel, // #70 void(string s) changelevel (QUAKE) +NULL, // #71 (QUAKE) +VM_cvar_set, // #72 void(string var, string val) cvar_set (QUAKE) +VM_SV_centerprint, // #73 void(entity client, strings) centerprint (QUAKE) +VM_SV_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE) +VM_SV_precache_model, // #75 string(string s) precache_model2 (QUAKE) +VM_SV_precache_sound, // #76 string(string s) precache_sound2 (QUAKE) +VM_precache_file, // #77 string(string s) precache_file2 (QUAKE) +VM_SV_setspawnparms, // #78 void(entity e) setspawnparms (QUAKE) +NULL, // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD) +NULL, // #80 string(entity e, string keyname) infokey (QUAKEWORLD) +VM_stof, // #81 float(string s) stof (FRIK_FILE) +NULL, // #82 void(vector where, float set) multicast (QUAKEWORLD) +NULL, // #83 (QUAKE) +NULL, // #84 (QUAKE) +NULL, // #85 (QUAKE) +NULL, // #86 (QUAKE) +NULL, // #87 (QUAKE) +NULL, // #88 (QUAKE) +NULL, // #89 (QUAKE) +VM_SV_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX) +VM_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC) +VM_SV_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT) +VM_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR) +VM_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND) +VM_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND) +VM_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND) +VM_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW) +VM_findfloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT) +VM_checkextension, // #99 float(string s) checkextension (the basis of the extension system) +// FrikaC and Telejano range #100-#199 +NULL, // #100 +NULL, // #101 +NULL, // #102 +NULL, // #103 +NULL, // #104 +NULL, // #105 +NULL, // #106 +NULL, // #107 +NULL, // #108 +NULL, // #109 +VM_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE) +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_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) +VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE) +NULL, // #120 +NULL, // #121 +NULL, // #122 +NULL, // #123 +NULL, // #124 +NULL, // #125 +NULL, // #126 +NULL, // #127 +NULL, // #128 +NULL, // #129 +NULL, // #130 +NULL, // #131 +NULL, // #132 +NULL, // #133 +NULL, // #134 +NULL, // #135 +NULL, // #136 +NULL, // #137 +NULL, // #138 +NULL, // #139 +NULL, // #140 +NULL, // #141 +NULL, // #142 +NULL, // #143 +NULL, // #144 +NULL, // #145 +NULL, // #146 +NULL, // #147 +NULL, // #148 +NULL, // #149 +NULL, // #150 +NULL, // #151 +NULL, // #152 +NULL, // #153 +NULL, // #154 +NULL, // #155 +NULL, // #156 +NULL, // #157 +NULL, // #158 +NULL, // #159 +NULL, // #160 +NULL, // #161 +NULL, // #162 +NULL, // #163 +NULL, // #164 +NULL, // #165 +NULL, // #166 +NULL, // #167 +NULL, // #168 +NULL, // #169 +NULL, // #170 +NULL, // #171 +NULL, // #172 +NULL, // #173 +NULL, // #174 +NULL, // #175 +NULL, // #176 +NULL, // #177 +NULL, // #178 +NULL, // #179 +NULL, // #180 +NULL, // #181 +NULL, // #182 +NULL, // #183 +NULL, // #184 +NULL, // #185 +NULL, // #186 +NULL, // #187 +NULL, // #188 +NULL, // #189 +NULL, // #190 +NULL, // #191 +NULL, // #192 +NULL, // #193 +NULL, // #194 +NULL, // #195 +NULL, // #196 +NULL, // #197 +NULL, // #198 +NULL, // #199 // FTEQW range #200-#299 -NULL, // #200 -NULL, // #201 -NULL, // #202 -NULL, // #203 -NULL, // #204 -NULL, // #205 -NULL, // #206 -NULL, // #207 -NULL, // #208 -NULL, // #209 -NULL, // #210 -NULL, // #211 -NULL, // #212 -NULL, // #213 -NULL, // #214 -NULL, // #215 -NULL, // #216 -NULL, // #217 -VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT) -NULL, // #219 -e10, // #220-#229 -e10, // #230-#239 -e10, // #240-#249 -e10, // #250-#259 -e10, // #260-#269 -e10, // #270-#279 -e10, // #280-#289 -e10, // #290-#299 -e10, // #300-309 -e10, // #310-319 -e10, // #320-329 -NULL, // #330 -NULL, // #331 -NULL, // #332 -NULL, // #333 -NULL, // #334 -NULL, // #335 -VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC) -VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC) -NULL, // #338 -VM_print, // #339 void(string, ...) print (DP_SV_PRINT) -e10, // #340-349 -e10, // #350-359 -e10, // #360-369 -e10, // #370-379 -e10, // #380-389 -e10, // #390-399 -VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY) -PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR) -VM_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN) -VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT) -PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT) -PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD) -PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER) -PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB) -PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE) -PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN) -PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW) -PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK) -PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1) -PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1) -PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1) -PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1) -PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH) -PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH) -PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS) -PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS) -PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS) -PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS) -PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS) -PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS) -PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS) -PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS) -PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS) -PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS) -PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS) -PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS) -PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS) -PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS) -VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS) -PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN) -PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE) -PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE) -PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE) -PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE) -PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE) -PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE) -PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND) -VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND) -VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND) -PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS) -VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH) -VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH) -VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH) -VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH) -VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING) -VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS) -VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS) -PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO) -PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO) -PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT) -PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT) -PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT) -PF_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING) -PF_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET) -NULL, // #458 -PF_edict_num, // #459 entity(float num) (??) -VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS) -VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS) -VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS) -VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS) -VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS) -VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS) -VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS) -VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS) -VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS) -VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS) -PF_SV_AddStat, // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC) -VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN) -VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN) -VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN) -VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN) -VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN) -VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS) -VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS) -VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME) -NULL, // #478 -NULL, // #479 -e10, e10 // #480-499 (LordHavoc) +NULL, // #200 +NULL, // #201 +NULL, // #202 +NULL, // #203 +NULL, // #204 +NULL, // #205 +NULL, // #206 +NULL, // #207 +NULL, // #208 +NULL, // #209 +NULL, // #210 +NULL, // #211 +NULL, // #212 +NULL, // #213 +NULL, // #214 +NULL, // #215 +NULL, // #216 +NULL, // #217 +VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT) +NULL, // #219 +NULL, // #220 +NULL, // #221 +VM_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS) +VM_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS) +NULL, // #224 +NULL, // #225 +NULL, // #226 +NULL, // #227 +VM_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS) +NULL, // #229 +NULL, // #230 +NULL, // #231 +VM_SV_AddStat, // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC) +NULL, // #233 +NULL, // #234 +NULL, // #235 +NULL, // #236 +NULL, // #237 +NULL, // #238 +NULL, // #239 +NULL, // #240 +NULL, // #241 +NULL, // #242 +NULL, // #243 +NULL, // #244 +NULL, // #245 +NULL, // #246 +NULL, // #247 +NULL, // #248 +NULL, // #249 +NULL, // #250 +NULL, // #251 +NULL, // #252 +NULL, // #253 +NULL, // #254 +NULL, // #255 +NULL, // #256 +NULL, // #257 +NULL, // #258 +NULL, // #259 +NULL, // #260 +NULL, // #261 +NULL, // #262 +NULL, // #263 +NULL, // #264 +NULL, // #265 +NULL, // #266 +NULL, // #267 +NULL, // #268 +NULL, // #269 +NULL, // #270 +NULL, // #271 +NULL, // #272 +NULL, // #273 +NULL, // #274 +NULL, // #275 +NULL, // #276 +NULL, // #277 +NULL, // #278 +NULL, // #279 +NULL, // #280 +NULL, // #281 +NULL, // #282 +NULL, // #283 +NULL, // #284 +NULL, // #285 +NULL, // #286 +NULL, // #287 +NULL, // #288 +NULL, // #289 +NULL, // #290 +NULL, // #291 +NULL, // #292 +NULL, // #293 +NULL, // #294 +NULL, // #295 +NULL, // #296 +NULL, // #297 +NULL, // #298 +NULL, // #299 +// CSQC range #300-#399 +NULL, // #300 void() clearscene (EXT_CSQC) +NULL, // #301 void(float mask) addentities (EXT_CSQC) +NULL, // #302 void(entity ent) addentity (EXT_CSQC) +NULL, // #303 float(float property, ...) setproperty (EXT_CSQC) +NULL, // #304 void() renderscene (EXT_CSQC) +NULL, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC) +NULL, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon +NULL, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex +NULL, // #308 void() R_EndPolygon +NULL, // #309 +NULL, // #310 vector (vector v) cs_unproject (EXT_CSQC) +NULL, // #311 vector (vector v) cs_project (EXT_CSQC) +NULL, // #312 +NULL, // #313 +NULL, // #314 +NULL, // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC) +NULL, // #316 float(string name) iscachedpic (EXT_CSQC) +NULL, // #317 string(string name, float trywad) precache_pic (EXT_CSQC) +NULL, // #318 vector(string picname) draw_getimagesize (EXT_CSQC) +NULL, // #319 void(string name) freepic (EXT_CSQC) +NULL, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC) +NULL, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC) +NULL, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC) +NULL, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC) +NULL, // #324 void(float x, float y, float width, float height) drawsetcliparea +NULL, // #325 void(void) drawresetcliparea +NULL, // #326 +NULL, // #327 +NULL, // #328 +NULL, // #329 +NULL, // #330 float(float stnum) getstatf (EXT_CSQC) +NULL, // #331 float(float stnum) getstati (EXT_CSQC) +NULL, // #332 string(float firststnum) getstats (EXT_CSQC) +VM_SV_setmodelindex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC) +VM_SV_modelnameforindex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC) +VM_SV_particleeffectnum, // #335 float(string effectname) particleeffectnum (EXT_CSQC) +VM_SV_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC) +VM_SV_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC) +NULL, // #338 void(string s, ...) centerprint (EXT_CSQC) +VM_print, // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT) +NULL, // #340 string(float keynum) keynumtostring (EXT_CSQC) +NULL, // #341 float(string keyname) stringtokeynum (EXT_CSQC) +NULL, // #342 string(float keynum) getkeybind (EXT_CSQC) +NULL, // #343 void(float usecursor) setcursormode (EXT_CSQC) +NULL, // #344 vector() getmousepos (EXT_CSQC) +NULL, // #345 float(float framenum) getinputstate (EXT_CSQC) +NULL, // #346 void(float sens) setsensitivityscaler (EXT_CSQC) +NULL, // #347 void() runstandardplayerphysics (EXT_CSQC) +NULL, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC) +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_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 +NULL, // #356 +NULL, // #357 +NULL, // #358 +NULL, // #359 +NULL, // #360 float() readbyte (EXT_CSQC) +NULL, // #361 float() readchar (EXT_CSQC) +NULL, // #362 float() readshort (EXT_CSQC) +NULL, // #363 float() readlong (EXT_CSQC) +NULL, // #364 float() readcoord (EXT_CSQC) +NULL, // #365 float() readangle (EXT_CSQC) +NULL, // #366 string() readstring (EXT_CSQC) +NULL, // #367 float() readfloat (EXT_CSQC) +NULL, // #368 +NULL, // #369 +NULL, // #370 +NULL, // #371 +NULL, // #372 +NULL, // #373 +NULL, // #374 +NULL, // #375 +NULL, // #376 +NULL, // #377 +NULL, // #378 +NULL, // #379 +NULL, // #380 +NULL, // #381 +NULL, // #382 +NULL, // #383 +NULL, // #384 +NULL, // #385 +NULL, // #386 +NULL, // #387 +NULL, // #388 +NULL, // #389 +NULL, // #390 +NULL, // #391 +NULL, // #392 +NULL, // #393 +NULL, // #394 +NULL, // #395 +NULL, // #396 +NULL, // #397 +NULL, // #398 +NULL, // #399 +// LordHavoc'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) +VM_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT) +VM_SV_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT) +VM_SV_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD) +VM_SV_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER) +VM_SV_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB) +VM_SV_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE) +VM_SV_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN) +VM_SV_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW) +VM_SV_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK) +VM_SV_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1) +VM_SV_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1) +VM_SV_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1) +VM_SV_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1) +VM_SV_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH) +VM_SV_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH) +VM_SV_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS) +VM_SV_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS) +VM_SV_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS) +VM_SV_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS) +VM_SV_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS) +VM_SV_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS) +VM_SV_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS) +VM_SV_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS) +VM_SV_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS) +VM_SV_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS) +VM_SV_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS) +VM_SV_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS) +VM_SV_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS) +VM_SV_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS) +VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS) +VM_SV_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN) +VM_SV_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE) +VM_SV_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE) +VM_SV_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE) +VM_SV_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE) +VM_SV_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE) +VM_SV_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE) +VM_SV_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND) +VM_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND) +VM_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND) +VM_SV_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS) +VM_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH) +VM_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH) +VM_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH) +VM_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH) +VM_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING) +VM_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS) +VM_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS) +VM_SV_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO) +VM_SV_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO) +VM_SV_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT) +VM_SV_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT) +VM_SV_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT) +VM_SV_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING) +VM_SV_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET) +NULL, // #458 +VM_ftoe, // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM) +VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS) +VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS) +VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS) +VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS) +VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS) +VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS) +VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS) +VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS) +VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS) +VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS) +NULL, // #470 +VM_asin, // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN) +VM_acos, // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN) +VM_atan, // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN) +VM_atan2, // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN) +VM_tan, // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN) +VM_strlennocol, // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS) +VM_strdecolorize, // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS) +VM_strftime, // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME) +NULL, // #479 +NULL, // #480 +NULL, // #481 +NULL, // #482 +NULL, // #483 +NULL, // #484 +NULL, // #485 +NULL, // #486 +NULL, // #487 +NULL, // #488 +NULL, // #489 +NULL, // #490 +NULL, // #491 +NULL, // #492 +NULL, // #493 +NULL, // #494 +NULL, // #495 +NULL, // #496 +NULL, // #497 +NULL, // #498 +NULL, // #499 }; const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t); diff --git a/todo b/todo index fb17e375..8bac0271 100644 --- a/todo +++ b/todo @@ -63,6 +63,7 @@ 0 bug darkplaces client: it has been reported that sometimes level changes on quakeworld servers don't load a map, this may be related to downloading? (Baker) 0 bug darkplaces client: name (and probably other userinfo properties) are not being set when entering a qw server? 0 bug darkplaces loader: make rtlight entity loader support q3map/q3map2 lights properly, they use a spawnflag for LINEAR mode, by default they use 1/(x*x) falloff (Carni, motorsep) +0 bug darkplaces physics: when riding a lift down (such as near the start of e1m1), the player is not being pulled down, unlike in quake, this can cause repeated fall damage on very fast lifts (scar3crow) 0 bug darkplaces readme: commandline options are slightly out of date, update them (Baker) 0 bug darkplaces readme: it would be a very good idea to add documentation of sv_gameplayfix_* cvars in the readme as a means to run broken mods (xaGe) 0 bug darkplaces renderer: GL13 path has broken handling of unlit surfaces in Nexuiz toxic.bsp - the small red light surfaces are black in GL13 path (m0rfar) diff --git a/view.c b/view.c index 4d40d8d4..91e0dc0d 100644 --- a/view.c +++ b/view.c @@ -423,7 +423,7 @@ void V_CalcRefdef (void) chase_dest[0] = vieworg[0] + forward[0] * dist; chase_dest[1] = vieworg[1] + forward[1] * dist; chase_dest[2] = vieworg[2] + forward[2] * dist + camup; - trace = CL_TraceBox(vieworg, vec3_origin, vec3_origin, chase_dest, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, false); + trace = CL_Move(vieworg, vec3_origin, vec3_origin, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false); VectorMAMAM(1, trace.endpos, 8, forward, 4, trace.plane.normal, vieworg); } else