From 816b0f1bb35be43b87bd2aa3250c216f868574a2 Mon Sep 17 00:00:00 2001 From: Tyler Young Date: Sun, 22 Jan 2023 16:33:01 -0500 Subject: [PATCH] Remove unnecessary files from source --- source/pr_cmds.c.bak | 3233 ------------------------------------------ source/sv_phys.c.bak | 1731 ---------------------- 2 files changed, 4964 deletions(-) delete mode 100644 source/pr_cmds.c.bak delete mode 100644 source/sv_phys.c.bak diff --git a/source/pr_cmds.c.bak b/source/pr_cmds.c.bak deleted file mode 100644 index 28118cd..0000000 --- a/source/pr_cmds.c.bak +++ /dev/null @@ -1,3233 +0,0 @@ -/* -Copyright (C) 1996-2001 Id Software, Inc. -Copyright (C) 2002-2009 John Fitzgibbons and others -Copyright (C) 2010-2014 QuakeSpasm developers - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#include "quakedef.h" - -#define STRINGTEMP_BUFFERS 64 -#define STRINGTEMP_LENGTH 1024 -static char pr_string_temp[STRINGTEMP_BUFFERS][STRINGTEMP_LENGTH]; -static byte pr_string_tempindex = 0; - -static char *PR_GetTempString (void) -{ - return pr_string_temp[(STRINGTEMP_BUFFERS-1) & ++pr_string_tempindex]; -} - -#define RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e)) - -#define MSG_BROADCAST 0 // unreliable to all -#define MSG_ONE 1 // reliable to one (msg_entity) -#define MSG_ALL 2 // reliable to all -#define MSG_INIT 3 // write to the init string - -extern char *pr_strings; - -/* -=============================================================================== - - BUILT-IN FUNCTIONS - -=============================================================================== -*/ - -static char *PF_VarString (int first) -{ - int i; - static char out[1024]; - size_t s; - - out[0] = 0; - s = 0; - for (i = first; i < pr_argc; i++) - { - s = q_strlcat(out, G_STRING((OFS_PARM0+i*3)), sizeof(out)); - if (s >= sizeof(out)) - { - Con_Warning("PF_VarString: overflow (string truncated)\n"); - return out; - } - } - if (s > 255) - { - if (!dev_overflows.varstring || dev_overflows.varstring + CONSOLE_RESPAM_TIME < realtime) - { - Con_DWarning("PF_VarString: %i characters exceeds standard limit of 255 (max = %d).\n", (int) s, (int)(sizeof(out) - 1)); - dev_overflows.varstring = realtime; - } - } - return out; -} - - -/* -================= -PF_error - -This is a TERMINAL error, which will kill off the entire server. -Dumps self. - -error(value) -================= -*/ -static void PF_error (void) -{ - char *s; - edict_t *ed; - - s = PF_VarString(0); - Con_Printf ("======SERVER ERROR in %s:\n%s\n", - PR_GetString(pr_xfunction->s_name), s); - ed = PROG_TO_EDICT(pr_global_struct->self); - ED_Print (ed); - - Host_Error ("Program error"); -} - -/* -================= -PF_objerror - -Dumps out self, then an error message. The program is aborted and self is -removed, but the level can continue. - -objerror(value) -================= -*/ -static void PF_objerror (void) -{ - char *s; - edict_t *ed; - - s = PF_VarString(0); - Con_Printf ("======OBJECT ERROR in %s:\n%s\n", - PR_GetString(pr_xfunction->s_name), s); - ed = PROG_TO_EDICT(pr_global_struct->self); - ED_Print (ed); - ED_Free (ed); - - //Host_Error ("Program error"); //johnfitz -- by design, this should not be fatal -} - - - -/* -============== -PF_makevectors - -Writes new values for v_forward, v_up, and v_right based on angles -makevectors(vector) -============== -*/ -static void PF_makevectors (void) -{ - AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up); -} - -/* -================= -PF_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) -================= -*/ -static void PF_setorigin (void) -{ - edict_t *e; - float *org; - - e = G_EDICT(OFS_PARM0); - org = G_VECTOR(OFS_PARM1); - VectorCopy (org, e->v.origin); - SV_LinkEdict (e, false); -} - - -static void SetMinMaxSize (edict_t *e, float *minvec, float *maxvec, qboolean rotate) -{ - float *angles; - vec3_t rmin, rmax; - float bounds[2][3]; - float xvector[2], yvector[2]; - float a; - vec3_t base, transformed; - int i, j, k, l; - - for (i = 0; i < 3; i++) - if (minvec[i] > maxvec[i]) - PR_RunError ("backwards mins/maxs"); - - rotate = false; // FIXME: implement rotation properly again - - if (!rotate) - { - VectorCopy (minvec, rmin); - VectorCopy (maxvec, rmax); - } - else - { - // find min / max for rotations - angles = e->v.angles; - - a = angles[1]/180 * M_PI; - - xvector[0] = cos(a); - xvector[1] = sin(a); - yvector[0] = -sin(a); - yvector[1] = cos(a); - - VectorCopy (minvec, bounds[0]); - VectorCopy (maxvec, bounds[1]); - - rmin[0] = rmin[1] = rmin[2] = 9999; - rmax[0] = rmax[1] = rmax[2] = -9999; - - for (i = 0; i <= 1; i++) - { - base[0] = bounds[i][0]; - for (j = 0; j <= 1; j++) - { - base[1] = bounds[j][1]; - for (k = 0; k <= 1; k++) - { - base[2] = bounds[k][2]; - - // transform the point - transformed[0] = xvector[0]*base[0] + yvector[0]*base[1]; - transformed[1] = xvector[1]*base[0] + yvector[1]*base[1]; - transformed[2] = base[2]; - - for (l = 0; l < 3; l++) - { - if (transformed[l] < rmin[l]) - rmin[l] = transformed[l]; - if (transformed[l] > rmax[l]) - rmax[l] = transformed[l]; - } - } - } - } - } - -// set derived values - VectorCopy (rmin, e->v.mins); - VectorCopy (rmax, e->v.maxs); - VectorSubtract (maxvec, minvec, e->v.size); - - SV_LinkEdict (e, false); -} - -/* -================= -PF_setsize - -the size box is rotated by the current angle - -setsize (entity, minvector, maxvector) -================= -*/ -static void PF_setsize (void) -{ - edict_t *e; - float *minvec, *maxvec; - - e = G_EDICT(OFS_PARM0); - minvec = G_VECTOR(OFS_PARM1); - maxvec = G_VECTOR(OFS_PARM2); - SetMinMaxSize (e, minvec, maxvec, false); -} - - -/* -================= -PF_setmodel - -setmodel(entity, model) -================= -*/ -static void PF_setmodel (void) -{ - int i; - const char *m, **check; - qmodel_t *mod; - edict_t *e; - - e = G_EDICT(OFS_PARM0); - m = G_STRING(OFS_PARM1); - -// check to see if model was properly precached - for (i = 0, check = sv.model_precache; *check; i++, check++) - { - if (!strcmp(*check, m)) - break; - } - - if (!*check) - { - PR_RunError ("no precache: %s", m); - } - e->v.model = PR_SetEngineString(*check); - e->v.modelindex = i; //SV_ModelIndex (m); - - mod = sv.models[ (int)e->v.modelindex]; // Mod_ForName (m, true); - - if (mod) - //johnfitz -- correct physics cullboxes for bmodels - { - if (mod->type == mod_brush) - SetMinMaxSize (e, mod->clipmins, mod->clipmaxs, true); - else - SetMinMaxSize (e, mod->mins, mod->maxs, true); - } - //johnfitz - else - SetMinMaxSize (e, vec3_origin, vec3_origin, true); -} - -/* -================= -PF_bprint - -broadcast print to everyone on server - -bprint(value) -================= -*/ -static void PF_bprint (void) -{ - char *s; - - s = PF_VarString(0); - SV_BroadcastPrintf ("%s", s); -} - -/* -================= -PF_sprint - -single print to a specific client - -sprint(clientent, value) -================= -*/ -static void PF_sprint (void) -{ - char *s; - client_t *client; - int entnum; - - entnum = G_EDICTNUM(OFS_PARM0); - s = PF_VarString(1); - - if (entnum < 1 || entnum > svs.maxclients) - { - Con_Printf ("tried to sprint to a non-client\n"); - return; - } - - client = &svs.clients[entnum-1]; - - MSG_WriteChar (&client->message,svc_print); - MSG_WriteString (&client->message, s ); -} - - -/* -================= -PF_centerprint - -single print to a specific client - -centerprint(clientent, value) -================= -*/ -static void PF_centerprint (void) -{ - char *s; - client_t *client; - int entnum; - - entnum = G_EDICTNUM(OFS_PARM0); - s = PF_VarString(1); - - if (entnum < 1 || entnum > svs.maxclients) - { - Con_Printf ("tried to sprint to a non-client\n"); - return; - } - - client = &svs.clients[entnum-1]; - - MSG_WriteChar (&client->message,svc_centerprint); - MSG_WriteString (&client->message, s); -} - - -/* -================= -PF_useprint - -Print a text depending on what it is fed with - -useprint(entity client, float type, float cost, float weapon) -================= -*/ -void PF_useprint (void) -{ - client_t *client; - int entnum, type, cost, weapon; - - entnum = G_EDICTNUM(OFS_PARM0); - type = G_FLOAT(OFS_PARM1); - cost = G_FLOAT(OFS_PARM2); - weapon = G_FLOAT(OFS_PARM3); - - - if (entnum < 1 || entnum > svs.maxclients) - { - Con_Printf ("tried to sprint to a non-client\n"); - return; - } - - client = &svs.clients[entnum-1]; - - MSG_WriteByte (&client->message,svc_useprint); - MSG_WriteByte (&client->message,type); - MSG_WriteShort (&client->message,cost); - MSG_WriteByte (&client->message,weapon); -} - - -/* -================= -PF_normalize - -vector normalize(vector) -================= -*/ -static void PF_normalize (void) -{ - float *value1; - vec3_t newvalue; - double new_temp; - - value1 = G_VECTOR(OFS_PARM0); - - new_temp = (double)value1[0] * value1[0] + (double)value1[1] * value1[1] + (double)value1[2]*value1[2]; - new_temp = sqrt (new_temp); - - if (new_temp == 0) - newvalue[0] = newvalue[1] = newvalue[2] = 0; - else - { - new_temp = 1 / new_temp; - newvalue[0] = value1[0] * new_temp; - newvalue[1] = value1[1] * new_temp; - newvalue[2] = value1[2] * new_temp; - } - - VectorCopy (newvalue, G_VECTOR(OFS_RETURN)); -} - -/* -================= -PF_vlen - -scalar vlen(vector) -================= -*/ -static void PF_vlen (void) -{ - float *value1; - double new_temp; - - value1 = G_VECTOR(OFS_PARM0); - - new_temp = (double)value1[0] * value1[0] + (double)value1[1] * value1[1] + (double)value1[2]*value1[2]; - new_temp = sqrt(new_temp); - - G_FLOAT(OFS_RETURN) = new_temp; -} - -/* -================= -PF_vectoyaw - -float vectoyaw(vector) -================= -*/ -static void PF_vectoyaw (void) -{ - float *value1; - float yaw; - - value1 = G_VECTOR(OFS_PARM0); - - if (value1[1] == 0 && value1[0] == 0) - yaw = 0; - else - { - yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI); - if (yaw < 0) - yaw += 360; - } - - G_FLOAT(OFS_RETURN) = yaw; -} - - -/* -================= -PF_vectoangles - -vector vectoangles(vector) -================= -*/ -static void PF_vectoangles (void) -{ - float *value1; - float forward; - float yaw, pitch; - - value1 = G_VECTOR(OFS_PARM0); - - if (value1[1] == 0 && value1[0] == 0) - { - yaw = 0; - if (value1[2] > 0) - pitch = 90; - else - pitch = 270; - } - else - { - yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI); - if (yaw < 0) - yaw += 360; - - forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]); - pitch = (int) (atan2(value1[2], forward) * 180 / M_PI); - if (pitch < 0) - pitch += 360; - } - - G_FLOAT(OFS_RETURN+0) = pitch; - G_FLOAT(OFS_RETURN+1) = yaw; - G_FLOAT(OFS_RETURN+2) = 0; -} - -/* -================= -PF_Random - -Returns a number from 0 <= num < 1 - -random() -================= -*/ -static void PF_random (void) -{ - float num; - - num = (rand() & 0x7fff) / ((float)0x7fff); - - G_FLOAT(OFS_RETURN) = num; -} - -/* -================= -PF_particle - -particle(origin, color, count) -================= -*/ -static void PF_particle (void) -{ - float *org, *dir; - float color; - float count; - - org = G_VECTOR(OFS_PARM0); - dir = G_VECTOR(OFS_PARM1); - color = G_FLOAT(OFS_PARM2); - count = G_FLOAT(OFS_PARM3); - SV_StartParticle (org, dir, color, count); -} - - -/* -================= -PF_ambientsound - -================= -*/ -static void PF_ambientsound (void) -{ - const char *samp, **check; - float *pos; - float vol, attenuation; - int i, soundnum; - int large = false; //johnfitz -- PROTOCOL_FITZQUAKE - - pos = G_VECTOR (OFS_PARM0); - samp = G_STRING(OFS_PARM1); - vol = G_FLOAT(OFS_PARM2); - attenuation = G_FLOAT(OFS_PARM3); - -// check to see if samp was properly precached - for (soundnum = 0, check = sv.sound_precache; *check; check++, soundnum++) - { - if (!strcmp(*check, samp)) - break; - } - - if (!*check) - { - Con_Printf ("no precache: %s\n", samp); - return; - } - - //johnfitz -- PROTOCOL_FITZQUAKE - if (soundnum > 255) - { - if (sv.protocol == PROTOCOL_NETQUAKE) - return; //don't send any info protocol can't support - else - large = true; - } - //johnfitz - -// add an svc_spawnambient command to the level signon packet - - //johnfitz -- PROTOCOL_FITZQUAKE - if (large) - MSG_WriteByte (&sv.signon,svc_spawnstaticsound2); - else - MSG_WriteByte (&sv.signon,svc_spawnstaticsound); - //johnfitz - - for (i = 0; i < 3; i++) - MSG_WriteCoord(&sv.signon, pos[i], sv.protocolflags); - - //johnfitz -- PROTOCOL_FITZQUAKE - if (large) - MSG_WriteShort(&sv.signon, soundnum); - else - MSG_WriteByte (&sv.signon, soundnum); - //johnfitz - - MSG_WriteByte (&sv.signon, vol*255); - MSG_WriteByte (&sv.signon, attenuation*64); - -} - -/* -================= -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. - -================= -*/ -static void PF_sound (void) -{ - const char *sample; - int channel; - edict_t *entity; - int volume; - float attenuation; - - entity = G_EDICT(OFS_PARM0); - channel = G_FLOAT(OFS_PARM1); - sample = G_STRING(OFS_PARM2); - volume = G_FLOAT(OFS_PARM3) * 255; - attenuation = 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); -} - -/* -================= -PF_break - -break() -================= -*/ -static void PF_break (void) -{ - Con_Printf ("break statement\n"); - *(int *)-4 = 0; // dump to debugger -// PR_RunError ("break statement"); -} - -/* -================= -PF_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) -================= -*/ -static void PF_traceline (void) -{ - float *v1, *v2; - trace_t trace; - int nomonsters; - edict_t *ent; - - v1 = G_VECTOR(OFS_PARM0); - v2 = G_VECTOR(OFS_PARM1); - nomonsters = G_FLOAT(OFS_PARM2); - ent = G_EDICT(OFS_PARM3); - - /* FIXME FIXME FIXME: Why do we hit this with certain progs.dat ?? */ - if (developer.value) { - if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || - IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2])) { - Con_Warning ("NAN in traceline:\nv1(%f %f %f) v2(%f %f %f)\nentity %d\n", - v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], NUM_FOR_EDICT(ent)); - } - } - - if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2])) - v1[0] = v1[1] = v1[2] = 0; - if (IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2])) - v2[0] = v2[1] = v2[2] = 0; - - trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters, ent); - - pr_global_struct->trace_allsolid = trace.allsolid; - pr_global_struct->trace_startsolid = trace.startsolid; - pr_global_struct->trace_fraction = trace.fraction; - pr_global_struct->trace_inwater = trace.inwater; - pr_global_struct->trace_inopen = trace.inopen; - VectorCopy (trace.endpos, pr_global_struct->trace_endpos); - VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal); - pr_global_struct->trace_plane_dist = trace.plane.dist; - if (trace.ent) - pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent); - else - pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts); -} - - -int TraceMove(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, edict_t *ent)//engine-sides -{ - if(start[0] == end[0] && start[1] == end[1] && start[2] == end[2]) - { - return 1; - } - vec3_t forward, up; - float HorDist; - vec3_t HorGoal; - vec3_t tempHorGoal; - - up[0] = 0; up[1] = 0; up[2] = 1; - HorGoal[0] = end[0]; HorGoal[1] = end[1]; HorGoal[2] = start[2]; - - VectorSubtract(HorGoal,start,forward); - HorDist = VectorLength(forward); - VectorNormalize(forward); - - vec3_t CurrentPos; - - VectorCopy(start,CurrentPos); - VectorCopy(HorGoal,tempHorGoal); - - float CurrentDist = 0;//2d distance from initial 3d positionvector - - trace_t trace1, trace2; - float tempDist; - vec3_t tempVec; - vec3_t tempVec2; - float i; - int STEPSIZEB = 18;//other declaration isn't declared yet - float SLOPELEN = 10.4;//18/tan(60) = 10.4, the the length of the triangle formed by the max walkable slope of 60 degrees. - int skip = 0; - int LoopBreak = 0; - - while(CurrentDist < HorDist) - { - if(LoopBreak > 20)//was 50, decreased this quite a bit. now it's 260 meters - { - //Con_Printf("AI Warning: There is a ledge that is greater than 650 meters.\n"); - return -1; - } - - trace1 = SV_Move(CurrentPos, mins, maxs, tempHorGoal, MOVE_NOMONSTERS, ent); - - VectorSubtract(tempHorGoal,CurrentPos,tempVec); - tempDist = trace1.fraction * VectorLength(tempVec); - //Check if we fell along the path - for(i = (maxs[0] * 1); i < tempDist; i += (maxs[0] * 1)) - { - VectorScale(forward,i,tempVec); - VectorAdd(tempVec,CurrentPos,tempVec); - VectorScale(up,-500,tempVec2);//500 inches is about 13 meters - VectorAdd(tempVec,tempVec2,tempVec2); - trace2 = SV_Move(tempVec, mins, maxs, tempVec2, MOVE_NOMONSTERS, ent); - if(trace2.fraction > 0) - { - VectorScale(up,trace2.fraction * -100,tempVec2); - VectorAdd(tempVec,tempVec2,CurrentPos); - VectorAdd(tempHorGoal,tempVec2,tempHorGoal); - skip = 1; - CurrentDist += i; - if(trace2.fraction == 1) - { - //We fell the full 13 meters!, we need to be careful here, - //because if we're checking over the void, then we could be stuck in an infinite loop and crash the game - //So we're going to keep track of how many times we fall 13 meters - LoopBreak++; - } - else - { - LoopBreak = 0; - } - break; - } - } - //If we fell at any location along path, then we don't try to step up - if(skip == 1) - { - trace2.fraction = 0; - skip = 0; - continue; - } - //We need to advance it as much as possible along path before step up - if(trace1.fraction > 0 && trace1.fraction < 1) - { - VectorCopy(trace1.endpos,CurrentPos); - trace1.fraction = 0; - } - //Check step up - if(trace1.fraction < 1) - { - VectorScale(up,STEPSIZEB,tempVec2); - VectorAdd(CurrentPos,tempVec2,tempVec); - VectorAdd(tempHorGoal,tempVec2,tempVec2); - trace2 = SV_Move(tempVec, mins, maxs, tempVec2, MOVE_NOMONSTERS, ent); - //10.4 is minimum length for a slope of 60 degrees, we need to at least advance this much to know the surface is walkable - VectorSubtract(tempVec2,tempVec,tempVec2); - if(trace2.fraction > (trace1.fraction + (SLOPELEN/VectorLength(tempVec2))) || trace2.fraction == 1) - { - VectorCopy(tempVec,CurrentPos); - tempHorGoal[2] = CurrentPos[2]; - continue; - } - else - { - return 0;//stepping up didn't advance so we've hit a wall, we failed - } - } - if(trace1.fraction == 1)//we've made it horizontally to our goal... so check if we've made it vertically... - { - if((end[2] - tempHorGoal[2] < STEPSIZEB) && (end[2] - tempHorGoal[2]) > -1 * STEPSIZEB) - return 1; - else return 0; - } - } - return 0; -} - -void PF_tracemove(void)//progs side -{ - float *start, *end, *mins, *maxs; - int nomonsters; - edict_t *ent; - - start = G_VECTOR(OFS_PARM0); - mins = G_VECTOR(OFS_PARM1); - maxs = G_VECTOR(OFS_PARM2); - end = G_VECTOR(OFS_PARM3); - nomonsters = G_FLOAT(OFS_PARM4); - ent = G_EDICT(OFS_PARM5); - - Con_DPrintf ("TraceMove start, "); - G_INT(OFS_RETURN) = TraceMove(start, mins, maxs, end,nomonsters,ent); - Con_DPrintf ("TM end\n"); - return; -} - -/* -================= -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) -================= -*/ -#if 0 -static void PF_checkpos (void) -{ -} -#endif - -//============================================================================ - -static byte *checkpvs; //ericw -- changed to malloc -static int checkpvs_capacity; - -static int PF_newcheckclient (int check) -{ - int i; - byte *pvs; - edict_t *ent; - mleaf_t *leaf; - vec3_t org; - int pvsbytes; - -// cycle to the next one - - if (check < 1) - check = 1; - if (check > svs.maxclients) - check = svs.maxclients; - - if (check == svs.maxclients) - i = 1; - else - i = check + 1; - - for ( ; ; i++) - { - if (i == svs.maxclients+1) - i = 1; - - ent = EDICT_NUM(i); - - if (i == check) - break; // didn't find anything else - - if (ent->free) - continue; - if (ent->v.health <= 0) - continue; - if ((int)ent->v.flags & FL_NOTARGET) - continue; - - // anything that is a client, or has a client as an enemy - break; - } - -// get the PVS for the entity - VectorAdd (ent->v.origin, ent->v.view_ofs, org); - leaf = Mod_PointInLeaf (org, sv.worldmodel); - pvs = Mod_LeafPVS (leaf, sv.worldmodel); - - pvsbytes = (sv.worldmodel->numleafs+7)>>3; - if (checkpvs == NULL || pvsbytes > checkpvs_capacity) - { - checkpvs_capacity = pvsbytes; - checkpvs = (byte *) realloc (checkpvs, checkpvs_capacity); - if (!checkpvs) - Sys_Error ("PF_newcheckclient: realloc() failed on %d bytes", checkpvs_capacity); - } - memcpy (checkpvs, pvs, pvsbytes); - - return i; -} - -/* -================= -PF_checkclient - -Returns a client (or object that has a client enemy) that would be a -valid target. - -If there are more than one valid options, they are cycled each frame - -If (self.origin + self.viewofs) is not in the PVS of the current target, -it is not returned at all. - -name checkclient () -================= -*/ -#define MAX_CHECK 16 -static int c_invis, c_notvis; -static void PF_checkclient (void) -{ - edict_t *ent, *self; - mleaf_t *leaf; - int l; - vec3_t view; - -// find a new check if on a new frame - if (sv.time - sv.lastchecktime >= 0.1) - { - sv.lastcheck = PF_newcheckclient (sv.lastcheck); - sv.lastchecktime = sv.time; - } - -// return check if it might be visible - ent = EDICT_NUM(sv.lastcheck); - if (ent->free || ent->v.health <= 0) - { - RETURN_EDICT(sv.edicts); - return; - } - -// if current entity can't possibly see the check entity, return 0 - self = PROG_TO_EDICT(pr_global_struct->self); - VectorAdd (self->v.origin, self->v.view_ofs, view); - leaf = Mod_PointInLeaf (view, sv.worldmodel); - l = (leaf - sv.worldmodel->leafs) - 1; - if ( (l < 0) || !(checkpvs[l>>3] & (1 << (l & 7))) ) - { - c_notvis++; - RETURN_EDICT(sv.edicts); - return; - } - -// might be able to see it - c_invis++; - RETURN_EDICT(ent); -} - -//============================================================================ - - -/* -================= -PF_stuffcmd - -Sends text over to the client's execution buffer - -stuffcmd (clientent, value) -================= -*/ -static void PF_stuffcmd (void) -{ - int entnum; - const char *str; - client_t *old; - - entnum = G_EDICTNUM(OFS_PARM0); - if (entnum < 1 || entnum > svs.maxclients) - PR_RunError ("Parm 0 not a client"); - str = G_STRING(OFS_PARM1); - - old = host_client; - host_client = &svs.clients[entnum-1]; - Host_ClientCommands ("%s", str); - host_client = old; -} - -/* -================= -PF_localcmd - -Sends text over to the client's execution buffer - -localcmd (string) -================= -*/ -static void PF_localcmd (void) -{ - const char *str; - - str = G_STRING(OFS_PARM0); - Cbuf_AddText (str); -} - -/* -================= -PF_cvar - -float cvar (string) -================= -*/ -static void PF_cvar (void) -{ - const char *str; - - str = G_STRING(OFS_PARM0); - - G_FLOAT(OFS_RETURN) = Cvar_VariableValue (str); -} - -/* -================= -PF_cvar_set - -float cvar (string) -================= -*/ -static void PF_cvar_set (void) -{ - const char *var, *val; - - var = G_STRING(OFS_PARM0); - val = G_STRING(OFS_PARM1); - - Cvar_Set (var, val); -} - -/* -================= -PF_findradius - -Returns a chain of entities that have origins within a spherical area - -findradius (origin, radius) -================= -*/ -static void PF_findradius (void) -{ - edict_t *ent, *chain; - float rad; - float *org; - vec3_t eorg; - int i, j; - - chain = (edict_t *)sv.edicts; - - org = G_VECTOR(OFS_PARM0); - rad = G_FLOAT(OFS_PARM1); - - ent = NEXT_EDICT(sv.edicts); - for (i = 1; i < sv.num_edicts; i++, ent = NEXT_EDICT(ent)) - { - if (ent->free) - continue; - if (ent->v.solid == SOLID_NOT) - continue; - for (j = 0; j < 3; j++) - eorg[j] = org[j] - (ent->v.origin[j] + (ent->v.mins[j] + ent->v.maxs[j]) * 0.5); - if (VectorLength(eorg) > rad) - continue; - - ent->v.chain = EDICT_TO_PROG(chain); - chain = ent; - } - - RETURN_EDICT(chain); -} - -/* -========= -PF_dprint -========= -*/ -static void PF_dprint (void) -{ - Con_DPrintf ("%s",PF_VarString(0)); -} - -static void PF_ftos (void) -{ - float v; - char *s; - - v = G_FLOAT(OFS_PARM0); - s = PR_GetTempString(); - if (v == (int)v) - sprintf (s, "%d",(int)v); - else - sprintf (s, "%5.1f",v); - G_INT(OFS_RETURN) = PR_SetEngineString(s); -} - -static void PF_fabs (void) -{ - float v; - v = G_FLOAT(OFS_PARM0); - G_FLOAT(OFS_RETURN) = fabs(v); -} - -static void PF_vtos (void) -{ - char *s; - - s = PR_GetTempString(); - sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]); - G_INT(OFS_RETURN) = PR_SetEngineString(s); -} - -static void PF_Spawn (void) -{ - edict_t *ed; - - ed = ED_Alloc(); - - RETURN_EDICT(ed); -} - -static void PF_Remove (void) -{ - edict_t *ed; - - ed = G_EDICT(OFS_PARM0); - ED_Free (ed); -} - - -/* -================= -PF_updateLimb - -updates zombies limb - -PF_updateLimb(zombieent, value. limbent) -================= -*/ -void PF_updateLimb (void) -{ - int limb; - int zombieent, limbent; - - zombieent = G_EDICTNUM(OFS_PARM0); - limb = G_FLOAT(OFS_PARM1); - limbent = G_EDICTNUM(OFS_PARM2); - MSG_WriteByte (&sv.reliable_datagram, svc_limbupdate); - MSG_WriteByte (&sv.reliable_datagram, limb); - MSG_WriteShort (&sv.reliable_datagram, zombieent); - MSG_WriteShort (&sv.reliable_datagram, limbent); -} - -// entity (entity start, .string field, string match) find = #5; -static void PF_Find (void) -{ - int e; - int f; - const char *s, *t; - edict_t *ed; - - e = G_EDICTNUM(OFS_PARM0); - f = G_INT(OFS_PARM1); - s = G_STRING(OFS_PARM2); - if (!s) - PR_RunError ("PF_Find: bad search string"); - - for (e++ ; e < sv.num_edicts ; e++) - { - ed = EDICT_NUM(e); - if (ed->free) - continue; - t = E_STRING(ed,f); - if (!t) - continue; - if (!strcmp(t,s)) - { - RETURN_EDICT(ed); - return; - } - } - - RETURN_EDICT(sv.edicts); -} - - -// entity (entity start, .float field, float match) findfloat = #98; -void PF_FindFloat (void) -{ - int e; - int f; - float s, t; - edict_t *ed; - - e = G_EDICTNUM(OFS_PARM0); - f = G_INT(OFS_PARM1); - s = G_FLOAT(OFS_PARM2); - if (!s) - PR_RunError ("PF_FindFloat: bad search float"); - - for (e++ ; e < sv.num_edicts ; e++) - { - ed = EDICT_NUM(e); - if (ed->free) - continue; - t = E_FLOAT(ed,f); - if (!t) - continue; - if (t == s) - { - RETURN_EDICT(ed); - return; - } - } - - RETURN_EDICT(sv.edicts); -} - -static void PR_CheckEmptyString (const char *s) -{ - if (s[0] <= ' ') - PR_RunError ("Bad string"); -} - -static void PF_precache_file (void) -{ // precache_file is only used to copy files with qcc, it does nothing - G_INT(OFS_RETURN) = G_INT(OFS_PARM0); -} - -static void PF_precache_sound (void) -{ - const char *s; - int i; - - if (sv.state != ss_loading) - PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions"); - - s = G_STRING(OFS_PARM0); - G_INT(OFS_RETURN) = G_INT(OFS_PARM0); - PR_CheckEmptyString (s); - - for (i = 0; i < MAX_SOUNDS; i++) - { - if (!sv.sound_precache[i]) - { - sv.sound_precache[i] = s; - return; - } - if (!strcmp(sv.sound_precache[i], s)) - return; - } - PR_RunError ("PF_precache_sound: overflow"); -} - -static void PF_precache_model (void) -{ - const char *s; - int i; - - if (sv.state != ss_loading) - PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions"); - - s = G_STRING(OFS_PARM0); - G_INT(OFS_RETURN) = G_INT(OFS_PARM0); - PR_CheckEmptyString (s); - - for (i = 0; i < MAX_MODELS; i++) - { - if (!sv.model_precache[i]) - { - sv.model_precache[i] = s; - sv.models[i] = Mod_ForName (s, true); - return; - } - if (!strcmp(sv.model_precache[i], s)) - return; - } - PR_RunError ("PF_precache_model: overflow"); -} - - -static void PF_coredump (void) -{ - ED_PrintEdicts (); -} - -static void PF_traceon (void) -{ - pr_trace = true; -} - -static void PF_traceoff (void) -{ - pr_trace = false; -} - -static void PF_eprint (void) -{ - ED_PrintNum (G_EDICTNUM(OFS_PARM0)); -} - -/* -=============== -PF_walkmove - -float(float yaw, float dist) walkmove -=============== -*/ -static void PF_walkmove (void) -{ - edict_t *ent; - float yaw, dist; - vec3_t move; - dfunction_t *oldf; - int oldself; - - ent = PROG_TO_EDICT(pr_global_struct->self); - yaw = G_FLOAT(OFS_PARM0); - dist = G_FLOAT(OFS_PARM1); - - if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) ) - { - G_FLOAT(OFS_RETURN) = 0; - return; - } - - yaw = yaw * M_PI * 2 / 360; - - move[0] = cos(yaw) * dist; - move[1] = sin(yaw) * dist; - move[2] = 0; - -// save program state, because SV_movestep may call other progs - oldf = pr_xfunction; - oldself = pr_global_struct->self; - - G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true); - - -// restore program state - pr_xfunction = oldf; - pr_global_struct->self = oldself; -} - -/* -=============== -PF_droptofloor - -void() droptofloor -=============== -*/ -static void PF_droptofloor (void) -{ - edict_t *ent; - vec3_t end; - trace_t trace; - - ent = PROG_TO_EDICT(pr_global_struct->self); - - VectorCopy (ent->v.origin, end); - end[2] -= 256; - - trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent); - - if (trace.fraction == 1 || trace.allsolid) - G_FLOAT(OFS_RETURN) = 0; - else - { - VectorCopy (trace.endpos, ent->v.origin); - SV_LinkEdict (ent, false); - ent->v.flags = (int)ent->v.flags | FL_ONGROUND; - ent->v.groundentity = EDICT_TO_PROG(trace.ent); - G_FLOAT(OFS_RETURN) = 1; - } -} - -/* -=============== -PF_lightstyle - -void(float style, string value) lightstyle -=============== -*/ -static void PF_lightstyle (void) -{ - int style; - const char *val; - client_t *client; - int j; - - style = G_FLOAT(OFS_PARM0); - val = G_STRING(OFS_PARM1); - -// bounds check to avoid clobbering sv struct - if (style < 0 || style >= MAX_LIGHTSTYLES) - { - Con_DWarning("PF_lightstyle: invalid style %d\n", style); - return; - } - -// change the string in sv - sv.lightstyles[style] = val; - -// send message to all clients on this server - if (sv.state != ss_active) - return; - - for (j = 0, client = svs.clients; j < svs.maxclients; j++, client++) - { - if (client->active || client->spawned) - { - MSG_WriteChar (&client->message, svc_lightstyle); - MSG_WriteChar (&client->message, style); - MSG_WriteString (&client->message, val); - } - } -} - -static void PF_rint (void) -{ - float f; - f = G_FLOAT(OFS_PARM0); - if (f > 0) - G_FLOAT(OFS_RETURN) = (int)(f + 0.5); - else - G_FLOAT(OFS_RETURN) = (int)(f - 0.5); -} - -static void PF_floor (void) -{ - G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0)); -} - -static void PF_ceil (void) -{ - G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0)); -} - - -/* -============= -PF_checkbottom -============= -*/ -static void PF_checkbottom (void) -{ - edict_t *ent; - - ent = G_EDICT(OFS_PARM0); - - G_FLOAT(OFS_RETURN) = SV_CheckBottom (ent); -} - -/* -============= -PF_pointcontents -============= -*/ -static void PF_pointcontents (void) -{ - float *v; - - v = G_VECTOR(OFS_PARM0); - - G_FLOAT(OFS_RETURN) = SV_PointContents (v); -} - -/* -============= -PF_nextent - -entity nextent(entity) -============= -*/ -static void PF_nextent (void) -{ - int i; - edict_t *ent; - - i = G_EDICTNUM(OFS_PARM0); - while (1) - { - i++; - if (i == sv.num_edicts) - { - RETURN_EDICT(sv.edicts); - return; - } - ent = EDICT_NUM(i); - if (!ent->free) - { - RETURN_EDICT(ent); - return; - } - } -} - -/* -============= -PF_aim - -Pick a vector for the player to shoot along -vector aim(entity, missilespeed) -============= -*/ -cvar_t sv_aim = {"sv_aim", "1", CVAR_NONE}; // ericw -- turn autoaim off by default. was 0.93 -static void PF_aim (void) -{ - edict_t *ent, *check, *bestent; - vec3_t start, dir, end, bestdir; - int i, j; - trace_t tr; - float dist, bestdist; - float speed; - - ent = G_EDICT(OFS_PARM0); - speed = G_FLOAT(OFS_PARM1); - (void) speed; /* variable set but not used */ - - VectorCopy (ent->v.origin, start); - start[2] += 20; - -// try sending a trace straight - VectorCopy (pr_global_struct->v_forward, dir); - VectorMA (start, 2048, dir, end); - tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent); - if (tr.ent && tr.ent->v.takedamage == DAMAGE_AIM - && (!teamplay.value || ent->v.team <= 0 || ent->v.team != tr.ent->v.team) ) - { - VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN)); - return; - } - -// try all possible entities - VectorCopy (dir, bestdir); - bestdist = sv_aim.value; - bestent = NULL; - - check = NEXT_EDICT(sv.edicts); - for (i = 1; i < sv.num_edicts; i++, check = NEXT_EDICT(check) ) - { - if (check->v.takedamage != DAMAGE_AIM) - continue; - if (check == ent) - continue; - if (teamplay.value && ent->v.team > 0 && ent->v.team == check->v.team) - continue; // don't aim at teammate - for (j = 0; j < 3; j++) - end[j] = check->v.origin[j] + 0.5 * (check->v.mins[j] + check->v.maxs[j]); - VectorSubtract (end, start, dir); - VectorNormalize (dir); - dist = DotProduct (dir, pr_global_struct->v_forward); - if (dist < bestdist) - continue; // to far to turn - tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent); - if (tr.ent == check) - { // can shoot at this one - bestdist = dist; - bestent = check; - } - } - - if (bestent) - { - VectorSubtract (bestent->v.origin, ent->v.origin, dir); - dist = DotProduct (dir, pr_global_struct->v_forward); - VectorScale (pr_global_struct->v_forward, dist, end); - end[2] = dir[2]; - VectorNormalize (end); - VectorCopy (end, G_VECTOR(OFS_RETURN)); - } - else - { - VectorCopy (bestdir, G_VECTOR(OFS_RETURN)); - } -} - -/* -============== -PF_changeyaw - -This was a major timewaster in progs, so it was converted to C -============== -*/ -void PF_changeyaw (void) -{ - edict_t *ent; - float ideal, current, move, speed; - - ent = PROG_TO_EDICT(pr_global_struct->self); - current = anglemod( ent->v.angles[1] ); - ideal = ent->v.ideal_yaw; - speed = ent->v.yaw_speed; - - if (current == ideal) - return; - move = ideal - current; - if (ideal > current) - { - if (move >= 180) - move = move - 360; - } - else - { - if (move <= -180) - move = move + 360; - } - if (move > 0) - { - if (move > speed) - move = speed; - } - else - { - if (move < -speed) - move = -speed; - } - - ent->v.angles[1] = anglemod (current + move); -} - -/* -=============================================================================== - -MESSAGE WRITING - -=============================================================================== -*/ - -static sizebuf_t *WriteDest (void) -{ - int entnum; - int dest; - edict_t *ent; - - dest = G_FLOAT(OFS_PARM0); - switch (dest) - { - case MSG_BROADCAST: - return &sv.datagram; - - case MSG_ONE: - ent = PROG_TO_EDICT(pr_global_struct->msg_entity); - entnum = NUM_FOR_EDICT(ent); - if (entnum < 1 || entnum > svs.maxclients) - PR_RunError ("WriteDest: not a client"); - return &svs.clients[entnum-1].message; - - case MSG_ALL: - return &sv.reliable_datagram; - - case MSG_INIT: - return &sv.signon; - - default: - PR_RunError ("WriteDest: bad destination"); - break; - } - - return NULL; -} - -static void PF_WriteByte (void) -{ - MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1)); -} - -static void PF_WriteChar (void) -{ - MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1)); -} - -static void PF_WriteShort (void) -{ - MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1)); -} - -static void PF_WriteLong (void) -{ - MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1)); -} - -static void PF_WriteAngle (void) -{ - MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1), sv.protocolflags); -} - -static void PF_WriteCoord (void) -{ - MSG_WriteCoord (WriteDest(), G_FLOAT(OFS_PARM1), sv.protocolflags); -} - -static void PF_WriteString (void) -{ - MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1)); -} - -static void PF_WriteEntity (void) -{ - MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1)); -} - -//============================================================================= - -static void PF_makestatic (void) -{ - edict_t *ent; - int i; - int bits = 0; //johnfitz -- PROTOCOL_FITZQUAKE - - ent = G_EDICT(OFS_PARM0); - - //johnfitz -- don't send invisible static entities - if (ent->alpha == ENTALPHA_ZERO) { - ED_Free (ent); - return; - } - //johnfitz - - //johnfitz -- PROTOCOL_FITZQUAKE - if (sv.protocol == PROTOCOL_NETQUAKE) - { - if (SV_ModelIndex(PR_GetString(ent->v.model)) & 0xFF00 || (int)(ent->v.frame) & 0xFF00) - { - ED_Free (ent); - return; //can't display the correct model & frame, so don't show it at all - } - } - else - { - if (SV_ModelIndex(PR_GetString(ent->v.model)) & 0xFF00) - bits |= B_LARGEMODEL; - if ((int)(ent->v.frame) & 0xFF00) - bits |= B_LARGEFRAME; - if (ent->alpha != ENTALPHA_DEFAULT) - bits |= B_ALPHA; - //if (ent->light_lev != 0) - // bits |= B_LIGHTLEVEL; - } - - if (bits) - { - MSG_WriteByte (&sv.signon, svc_spawnstatic2); - MSG_WriteByte (&sv.signon, bits); - } - else - MSG_WriteByte (&sv.signon, svc_spawnstatic); - - if (bits & B_LARGEMODEL) - MSG_WriteShort (&sv.signon, SV_ModelIndex(PR_GetString(ent->v.model))); - else - MSG_WriteByte (&sv.signon, SV_ModelIndex(PR_GetString(ent->v.model))); - - if (bits & B_LARGEFRAME) - MSG_WriteShort (&sv.signon, ent->v.frame); - else - MSG_WriteByte (&sv.signon, ent->v.frame); - //johnfitz - - MSG_WriteByte (&sv.signon, ent->v.colormap); - MSG_WriteByte (&sv.signon, ent->v.skin); - for (i = 0; i < 3; i++) - { - MSG_WriteCoord(&sv.signon, ent->v.origin[i], sv.protocolflags); - MSG_WriteAngle(&sv.signon, ent->v.angles[i], sv.protocolflags); - } - - //johnfitz -- PROTOCOL_FITZQUAKE - if (bits & B_ALPHA) - MSG_WriteByte (&sv.signon, ent->alpha); - //johnfitz - - // NZP START - //if (bits & B_LIGHTLEVEL) - // MSG_WriteByte (&sv.signon, ent->light_lev); - // NZP END - -// throw the entity away now - ED_Free (ent); -} - -//============================================================================= - -/* -============== -PF_setspawnparms -============== -*/ -static void PF_setspawnparms (void) -{ - edict_t *ent; - int i; - client_t *client; - - ent = G_EDICT(OFS_PARM0); - i = NUM_FOR_EDICT(ent); - if (i < 1 || i > svs.maxclients) - PR_RunError ("Entity is not a client"); - - // copy spawn parms out of the client_t - client = svs.clients + (i-1); - - for (i = 0; i < NUM_SPAWN_PARMS; i++) - (&pr_global_struct->parm1)[i] = client->spawn_parms[i]; -} - -/* -============== -PF_changelevel -============== -*/ -static void PF_changelevel (void) -{ - const char *s; - -// make sure we don't issue two changelevels - if (svs.changelevel_issued) - return; - svs.changelevel_issued = true; - - s = G_STRING(OFS_PARM0); - Cbuf_AddText (va("changelevel %s\n",s)); -} - -static void PF_Fixme (void) -{ - PR_RunError ("unimplemented builtin"); -} - - -/* -================= -Main_Waypoint functin - -This is where the magic happens -================= -*/ - - -int closedset[MAX_WAYPOINTS]; // The set of nodes already evaluated. -int openset[MAX_WAYPOINTS];//Actual sorted open list -int opensetRef[MAX_WAYPOINTS];//Reference values of open list -int opensetLength;//equivalent of javaScript's array[].length; -#define MaxZombies 16 - -zombie_ai zombie_list[MaxZombies]; - -//Debug// -void printSortedOpenSet() -{ - Con_Printf("Sorted!: "); - int qr; - for(qr = 0; qr < opensetLength; qr++) - { - Con_Printf("%i, ",(int)waypoints[openset[qr]].f_score); - } - Con_Printf("\n"); -} -//------// - - -void RemoveWayFromList (int listnumber, int waynum) -{ - if(listnumber == 1) - { - //Con_DPrintf ("RemoveWayFromList: closedset[%i] = %i\n", waynum, 0); - closedset[waynum] = 0; - return; - } - - int i; - int s; - if(listnumber == 2) - { - for(i = 0; i < opensetLength; i++) - { - if(openset[i] == waynum) - { - openset[i] = 0; - opensetRef[waynum] = 0; - - for(s = i; s < opensetLength; s++) - { - openset[s] = openset[s+1]; - } - opensetLength -= 1; - return; - } - } - } -} - -void CompareOpenLists() -{ - int refCount, count; - refCount = 0; - count = 0; - int i; - for(i = 0; i < MAX_WAYPOINTS; i++) - { - if(openset[i]) - count++; - if(opensetRef[i]) - refCount++; - } - if(count != refCount || count != opensetLength || refCount != opensetLength) - Con_Printf("%i%i%i\n",count, refCount,opensetLength); -} - - -int AddWayToList (int listnumber, int waynum)//blubs binary sorting -{ - if(listnumber == 1)//closed list - { - //Con_DPrintf ("AddWayToList: closedset[%i] = %i\n", waynum, 1); - closedset[waynum] = 1; - return 1; - } - - if(listnumber == 2)//openlist - { - int min, max, test; - min = -1; - max = opensetLength; - float wayVal = waypoints[waynum].f_score; - - while(max > min) - { - if(max - min == 1) - { - int i; - for(i = opensetLength; i > max ; i--) - { - openset[i] = openset[i-1]; - } - openset[max] = waynum; - opensetLength += 1; - opensetRef[waynum] = 1; - //printSortedOpenSet(); for debug only - return max; - } - test = (int)((min + max)/2); - if(wayVal > waypoints[openset[test]].f_score) - { - min = test; - } - else if(wayVal < waypoints[openset[test]].f_score) - { - max = test; - } - if(wayVal == waypoints[openset[test]].f_score) - { - max = test; - min = test - 1; - } - } - } - return -1; -} - -int GetLowestFromOpenSet() -{ - return openset[0]; -} - -int CheckIfEmptyList (int listnumber) -{ - int i; - - for (i = 0; i < MAX_WAYPOINTS; i++) - { - if (listnumber == 1) - { - if (closedset[i]) - { - //Con_DPrintf ("CheckIfEmptyList: closedset[%i]\n", i); - return 0; - } - } - else if (listnumber == 2) - { - if (openset[i]) - { - //Con_DPrintf ("CheckIfEmptyList: openset[%i]\n", i); - return 0; - } - } - } - return 1; -} - -int CheckIfWayInList (int listnumber, int waynum) -{ - if(listnumber == 1) - { - if(closedset[waynum]) - { - //Con_DPrintf ("CheckIfWayInList: closedset[%i] = %i\n", waynum, 1); - return 1; - } - } - if(listnumber == 2) - { - if(opensetRef[waynum]) - { - //Con_DPrintf ("CheckIfWayInList: openset[%i] = %i\n", waynum, 1); - return 1; - } - } - return 0; -} - -float heuristic_cost_estimate (int start_way, int end_way) -{ - //for now we will just look the distance between. - return VecLength2(waypoints[start_way].origin, waypoints[end_way].origin); -} - - -int proces_list[MAX_WAYPOINTS]; - -void reconstruct_path(int start_node, int current_node) -{ - int i, s, current; - current = current_node; - s = 0; - - Con_DPrintf ("\n"); - Con_DPrintf ("reconstruct_path: start_node = %i, current_node = %i\n\n", start_node, current_node); - for (i = 0;i < MAX_WAYPOINTS; i++) - { - //if (closedset[i]) - // Con_DPrintf ("reconstruct_path: closedset[%i] = %i\n", i, closedset[i]); - proces_list[i] = 0; - } - proces_list[s] = -1;//-1 means the enemy is the last waypoint - s = 1; - while (1) - { - //Con_DPrintf("\nreconstruct_path: current = %i, waypoints[current].came_from = %i\n", current, waypoints[current].came_from); - proces_list[s] = current;//blubs, we now add the first waypoint to the path list - if (current == start_node) - { - Con_DPrintf("reconstruct_path: path done!\n"); - break; - } - if (CheckIfWayInList (1, waypoints[current].came_from)) - { - //Con_DPrintf("reconstruct_path: waypoints[current].came_from %i is in list!\n", waypoints[current].came_from); - for (i = 0;i < 8; i++) - { - //Con_DPrintf("reconstruct_path for loop: waypoints[waypoints[current].came_from].target_id[i] = %i, current = %i\n", waypoints[waypoints[current].came_from].target_id[i], current) - if (waypoints[waypoints[current].came_from].target_id[i] == current) - { - //Con_DPrintf("reconstruct_path: current %i is viable target!\n", current); - current = waypoints[current].came_from;//woohoo, this waypoint is viable. So set it now as the current one - break; - } - } - } - else - { - //Con_DPrintf("reconstruct_path: skipped waypoint %i\n", waypoints[current].came_from); - break; - } - s++; - } - Con_DPrintf("\nreconstruct_path: dumping the final list\n"); - for (s = MAX_WAYPOINTS - 1; s > -1; s--) - { - //if (proces_list[s]) - //Con_DPrintf("reconstruct_path final: s = %i, proces_list[s] = %i\n", s, proces_list[s]); - } -} - -int Pathfind (int start_way, int end_way)//note thease 2 are ARRAY locations. Not the waypoints names. -{ - int current, last_way;//current is for the waypoint array, last_way is a way that was used last - float tentative_g_score, tentative_f_score; - int i; - last_way = 0; - for (i = 0; i < MAX_WAYPOINTS;i++)// clear all the waypoints - { - openset[i] = 0; - opensetRef[i] = 0; - closedset[i] = 0; - waypoints[i].f_score = 0; - waypoints[i].g_score = 0; - waypoints[i].came_from = 0; - } - opensetLength = 0; - - waypoints[start_way].g_score = 0; // Cost from start along best known path. - // Estimated total cost from start to goal through y. - waypoints[start_way].f_score = waypoints[start_way].g_score + heuristic_cost_estimate(start_way, end_way); - - AddWayToList (2, start_way);// The set of tentative nodes to be evaluated, initially containing the start node - - while (!CheckIfEmptyList (2)) - { - //Con_DPrintf("\n"); - current = GetLowestFromOpenSet(); - //Con_DPrintf("Pathfind current: %i, f_score: %f, g_score: %f\n", current, waypoints[current].f_score, waypoints[current].g_score); - if (current == end_way) - { - Con_DPrintf("Pathfind goal reached\n"); - reconstruct_path(start_way, end_way); - return 1; - } - AddWayToList (1, current); - RemoveWayFromList (2, current); - - for (i = 0;i < 8; i++) - { - - //Con_DPrintf("Pathfind for start\n"); - - if (!waypoints[waypoints[current].target_id[i]].open) - { - //if (waypoints[current].target_id[i]) - //Con_DPrintf("Pathfind for: %i, waypoints[waypoints[current].target_id[i]].open = %i, current = %i\n", waypoints[current].target_id[i], waypoints[waypoints[current].target_id[i]].open, current); - continue; - } - - tentative_g_score = waypoints[current].g_score + waypoints[current].dist[i]; - tentative_f_score = tentative_g_score + heuristic_cost_estimate(waypoints[current].target_id[i], end_way); - //Con_DPrintf("Pathfind for: %i, t_f_score: %f, t_g_score: %f\n", waypoints[current].target_id[i], tentative_f_score, tentative_g_score); - - //if (CheckIfWayInList (1, waypoints[current].target_id[i]) && tentative_f_score >= waypoints[waypoints[current].target_id[i]].f_score) - if (CheckIfWayInList (1, waypoints[current].target_id[i]))//it was the above, but why do we care about this waypoint if it's already in the closed list? we never check 2 waypoints twice m8, the first iteration that we reach this waypoint is also the fastest way, so lets not EVER check it again. - { - //if (CheckIfWayInList (1, waypoints[current].target_id[i])) - //Con_DPrintf("Pathfind: waypoint %i in closed list\n", waypoints[current].target_id[i]); - continue; - } - - if(tentative_f_score < waypoints[waypoints[current].target_id[i]].f_score) - { - //Con_DPrintf("Pathfind waypoint is better\n"); - waypoints[waypoints[current].target_id[i]].g_score = tentative_g_score; - waypoints[waypoints[current].target_id[i]].f_score = tentative_f_score; - } - - if (!CheckIfWayInList (2, waypoints[current].target_id[i])) - { - //Con_DPrintf("Pathfind waypoint not in list\n"); - waypoints[waypoints[current].target_id[i]].g_score = tentative_g_score; - waypoints[waypoints[current].target_id[i]].f_score = tentative_f_score; - - waypoints[waypoints[current].target_id[i]].came_from = current; - AddWayToList (2, waypoints[current].target_id[i]); - //Con_DPrintf("Pathfind: %i added to the openset with waypoints[current].came_from = %i, current = %i\n", waypoints[current].target_id[i], waypoints[current].came_from, current); - } - } - last_way = current; - } - return 0; -} - - -/* -================= -Do_Pathfind - -float Do_Pathfind (entity zombie, entity target) -================= -*/ -void Do_Pathfind (void) -{ - float best_dist; - float dist; - int i, s, best, best_target; - trace_t trace; - edict_t *ent; - edict_t *zombie; - int entnum; - - entnum = G_EDICTNUM(OFS_PARM0); - - best = 0; - Con_DPrintf("Starting Do_Pathfind\n"); //we first need to look for closest point for both zombie and the player - zombie = G_EDICT(OFS_PARM0); - ent = G_EDICT(OFS_PARM1); - - best_dist = 1000000000; - dist = 0; - - for (i = 0; i < MAX_WAYPOINTS; i++) - { - if (waypoints[i].used && waypoints[i].open) - { - trace = SV_Move (zombie->v.origin, vec3_origin, vec3_origin, waypoints[i].origin, 1, zombie); - if (trace.fraction >= 1) - { - dist = VecLength2(waypoints[i].origin, zombie->v.origin); - - if(dist < best_dist) - { - best_dist = dist; - best = i; - } - } - } - } - - best_dist = 1000000000; - dist = 0; - best_target = 0; - for (i = 0; i < MAX_WAYPOINTS; i++) - { - if (waypoints[i].used && waypoints[i].open) - { - trace = SV_Move (ent->v.origin, vec3_origin, vec3_origin, waypoints[i].origin, 1, ent); - if (trace.fraction >= 1) - { - dist = VecLength2(waypoints[i].origin, ent->v.origin); - - if(dist < best_dist) - { - best_dist = dist; - best_target = i; - } - } - } - } - Con_DPrintf("Starting waypoint: %i, Ending waypoint: %i\n", best, best_target); - if (Pathfind(best, best_target)) - { - for (i = 0; i < MaxZombies; i++) - { - if (entnum == zombie_list[i].zombienum) - { - for (s = 0; s < MAX_WAYPOINTS; s++) - { - zombie_list[i].pathlist[s] = proces_list[s]; - } - break; - } - if (i == MaxZombies - 1)//zombie was not in list - { - for (i = 0; i < MaxZombies; i++) - { - if (!zombie_list[i].zombienum) - { - zombie_list[i].zombienum = entnum; - for (s = 0; s < MAX_WAYPOINTS; s++) - { - zombie_list[i].pathlist[s] = proces_list[s]; - } - break; - } - } - break; - } - } - - if(zombie_list[i].pathlist[2] == 0 && zombie_list[i].pathlist[1] != 0)//then we are at player's waypoint! - { - Con_DPrintf("We are at player's waypoint already!\n"); - G_FLOAT(OFS_RETURN) = -1; - return; - } - - Con_DPrintf("Path found!\n"); - G_FLOAT(OFS_RETURN) = 1; - } - else - { - Con_DPrintf("Path not found!\n"); - G_FLOAT(OFS_RETURN) = 0; - } -} - -/* -================= -Open_Waypoint - -void Open_Waypoint (string, string, string, string, string, string, string, string) -================= -*/ -void Open_Waypoint (void) -{ - int i, t; - char *p = G_STRING(OFS_PARM0); - - //Con_DPrintf("Open_Waypoint\n"); - for (i = 1; i < MAX_WAYPOINTS; i++) - { - if (waypoints[i].special[0])//no need to open without tag - { - if (!strcmp(p, waypoints[i].special)) - { - waypoints[i].open = 1; - //Con_DPrintf("Open_Waypoint: %i, opened\n", i); - t = 1; - } - else - continue; - } - } - //if (t == 0) - //{ - //Con_DPrintf("Open_Waypoint: no waypoints opened\n"); - //} -} - - -/* -================= -Get_Waypoint_Near - -vector Get_Waypoint_Near (entity) -================= -*/ -void Get_Waypoint_Near (void) -{ - float best_dist; - float dist; - int i, best; - trace_t trace; - edict_t *ent; - - best = 0; - Con_DPrintf("Starting Get_Waypoint_Near\n"); - ent = G_EDICT(OFS_PARM0); - best_dist = 1000000000; - dist = 0; - - for (i = 0; i < MAX_WAYPOINTS; i++) - { - if (waypoints[i].open) - { - trace = SV_Move (ent->v.origin, vec3_origin, vec3_origin, waypoints[i].origin, 1, ent); - dist = VecLength2(waypoints[i].origin, ent->v.origin); - - //Con_DPrintf("Waypoint: %i, distance: %f, fraction: %f\n", i, dist, trace.fraction); - if (trace.fraction >= 1) - { - if(dist < best_dist) - { - best_dist = dist; - best = i; - } - } - } - } - Con_DPrintf("'%5.1f %5.1f %5.1f', %f is %f, (%i, %i)\n", waypoints[best].origin[0],waypoints[best].origin[1], waypoints[best].origin[2], best_dist, dist, i, best); - VectorCopy (waypoints[best].origin, G_VECTOR(OFS_RETURN)); -} - - -/* -================= -Get_Next_Waypoint This function will return the next waypoint in zombies path and then remove it from the list - -vector Get_Next_Waypoint (entity) -================= -*/ -void Get_Next_Waypoint (void) -{ - int i, s; - s = 0;//useless initialize, because compiler likes to yell at me - int entnum; - edict_t *ent;//blubs added - vec3_t move; - float *start,*mins, *maxs; - int currentWay = 0; - //int zomb = 0; - int skippedWays = 0; - - move [0] = 0; - move [1] = 0; - move [2] = 0; - - entnum = G_EDICTNUM(OFS_PARM0); - ent = G_EDICT(OFS_PARM0);//blubsadded - start = G_VECTOR(OFS_PARM1); - mins = G_VECTOR(OFS_PARM2); - maxs = G_VECTOR(OFS_PARM3); - - mins[0] -= 2; - mins[1] -= 2; - - maxs[0] += 2; - maxs[1] += 2; - - - for (i = 0; i < MaxZombies; i++) - { - if (entnum == zombie_list[i].zombienum) - { - for (s = MAX_WAYPOINTS - 1; s > -1; s--) - { - if (zombie_list[i].pathlist[s]) - { - zombie_list[i].pathlist[s] = 0;//This is get_next, so remove our current waypoint from the list. - - if(s == 1) - { - VectorCopy (move, G_VECTOR(OFS_RETURN));//we are at our last waypoint, so just return 0,0,0, this should never happen anyways, because we'll make pathfind return something else - Con_Printf("Warning, only one waypoint in path!\n"); - return; - } - s-= 1; - currentWay = s;//We want the next waypoint - break; - } - } - break; - } - } - //s is the index in our path, so if s == 1 - - if(s == -1 || s == 0) - { - //-1? - //then that means only player was in path, this is just in case... - //we are at our last waypoint, so just return 0,0,0, this should never happen anyways, because we'll make pathfind return something else - //0? - //only 1 waypoint left in path, we can't possibly smooth the path in this scenario. - //next waypoint in any case is going to be player, so.... - VectorCopy (move, G_VECTOR(OFS_RETURN)); - return; - } - - int iterations = 5;//that's how many segments per waypoint, pretty important number - float Scale = 0.5; - float curScale = 1; - float Scalar = Scale; - float TraceResult; - vec3_t toAdd; - vec3_t curStart; - vec3_t temp; - int q; - VectorCopy(waypoints[zombie_list[i].pathlist[currentWay]].origin,temp); - VectorCopy(temp,move); - - while(1) - { - //Con_Printf("Main Vector Start: %f, %f, %f Vector End: %f, %f, %f\n",start[0],start[1],start[2],waypoints[zombie_list[i].pathlist[currentWay]].origin[0],waypoints[zombie_list[i].pathlist[currentWay]].origin[1],waypoints[zombie_list[i].pathlist[currentWay]].origin[2]); - TraceResult = TraceMove(start,mins,maxs,waypoints[zombie_list[i].pathlist[currentWay]].origin,MOVE_NOMONSTERS,ent); - if(TraceResult == 1) - { - VectorCopy(waypoints[zombie_list[i].pathlist[currentWay]].origin,move); - if(currentWay == 1)//we're at the end of the list, we better not go out of bounds, was 0, now 1, since 0 is for player index - { - break; - } - currentWay -= 1; - skippedWays += 1; - } - else - { - if(skippedWays > 0) - { - VectorCopy(waypoints[zombie_list[i].pathlist[currentWay + 1]].origin,temp); - VectorCopy(temp,curStart); - VectorSubtract(waypoints[zombie_list[i].pathlist[currentWay]].origin,curStart,toAdd); - for(q = 0;q < iterations; q++) - { - curScale *= Scalar; - VectorScale(toAdd,curScale,temp); - VectorAdd(temp,curStart,temp); - TraceResult = TraceMove(start,mins,maxs,temp,MOVE_NOMONSTERS,ent); - if(TraceResult ==1) - { - Scalar = Scale + 1; - VectorCopy(temp,move); - } - else - { - Scalar = Scale; - } - } - } - break; - } - } - - Con_DPrintf("Get Next Way returns: list[%i], waypoint:%i\n",s,waypoints[zombie_list[i].pathlist[s]]); - - //VectorCopy(waypoints[zombie_list[i].pathlist[s]].origin,move); //for old get_next_way - zombie_list[i].pathlist[s] = 0; - - //Con_Printf("Skipped %i waypoints, we're moving to the %f percentage in between 2 waypoints\n",skippedWays,curScale); - //Con_DPrintf("'%5.1f %5.1f %5.1f'\n", move[0], move[1], move[2]); - VectorCopy (move, G_VECTOR(OFS_RETURN)); -} -/* -================= -Get_First_Waypoint This function will return the waypoint waypoint in zombies path and then remove it from the list - -vector Get_First_Waypoint (entity) -================= -*/ -void Get_First_Waypoint (void) -{ - int i, s; - s = 0;//useless initialize, because compiler likes to yell at me - int entnum; - edict_t *ent;//blubs added - vec3_t move; - float *start,*mins, *maxs; - int currentWay = 0; - //int zomb = 0; - int skippedWays = 0; - - move [0] = 0; - move [1] = 0; - move [2] = 0; - - entnum = G_EDICTNUM(OFS_PARM0); - ent = G_EDICT(OFS_PARM0);//blubsadded - start = G_VECTOR(OFS_PARM1); - mins = G_VECTOR(OFS_PARM2); - maxs = G_VECTOR(OFS_PARM3); - - mins[0] -= 2; - mins[1] -= 2; - - maxs[0] += 2; - maxs[1] += 2; - - - for (i = 0; i < MaxZombies; i++) - { - if (entnum == zombie_list[i].zombienum) - { - for (s = MAX_WAYPOINTS - 1; s > -1; s--) - { - if (zombie_list[i].pathlist[s]) - { - currentWay = s; - break; - } - } - break; - } - } - - if(s == 0) - { - //0? - //currentway is player, just return world - VectorCopy (move, G_VECTOR(OFS_RETURN)); - return; - } - //1? only one way in list, we can't possibly smooth list when we only have one... - - int iterations = 5;//that's how many segments per waypoint, pretty important number - float Scale = 0.5; - float curScale = 1; - float Scalar = Scale; - float TraceResult; - vec3_t toAdd; - vec3_t curStart; - vec3_t temp; - int q; - VectorCopy(waypoints[zombie_list[i].pathlist[currentWay]].origin,temp); - VectorCopy(temp,move); - - while(1) - { - //Con_Printf("Main Vector Start: %f, %f, %f Vector End: %f, %f, %f\n",start[0],start[1],start[2],waypoints[zombie_list[i].pathlist[currentWay]].origin[0],waypoints[zombie_list[i].pathlist[currentWay]].origin[1],waypoints[zombie_list[i].pathlist[currentWay]].origin[2]); - TraceResult = TraceMove(start,mins,maxs,waypoints[zombie_list[i].pathlist[currentWay]].origin,MOVE_NOMONSTERS,ent); - if(TraceResult == 1) - { - VectorCopy(waypoints[zombie_list[i].pathlist[currentWay]].origin,move); - if(currentWay == 1)//we're at the end of the list, we better not go out of bounds//was 0, now 1 since 0 is for enemy - { - break; - } - currentWay -= 1; - skippedWays += 1; - } - else - { - if(skippedWays > 0) - { - VectorCopy(waypoints[zombie_list[i].pathlist[currentWay + 1]].origin,temp); - VectorCopy(temp,curStart); - VectorSubtract(waypoints[zombie_list[i].pathlist[currentWay]].origin,curStart,toAdd); - for(q = 0;q < iterations; q++) - { - curScale *= Scalar; - VectorScale(toAdd,curScale,temp); - VectorAdd(temp,curStart,temp); - //Con_Printf("subVector Start: %f, %f, %f Vector End: %f, %f, %f\n",start[0],start[1],start[2],temp[0],temp[1],temp[2]); - TraceResult = TraceMove(start,mins,maxs,temp,MOVE_NOMONSTERS,ent); - if(TraceResult ==1) - { - Scalar = Scale + 1; - VectorCopy(temp,move); - } - else - { - Scalar = Scale; - }//we need a way to go back to the other value if it doesn't work!, so lets work with temp, but RETURN a different value other than temp! - } - } - break; - } - } - - Con_DPrintf("Get First Way returns: %i\n",s); - //VectorCopy(waypoints[zombie_list[i].pathlist[s]].origin,move);//for old get_first_way - zombie_list[i].pathlist[s] = 0; - //Con_Printf("Skipped %i waypoints, we're moving to the %f percentage in between 2 waypoints\n",skippedWays,curScale); - //Con_DPrintf("'%5.1f %5.1f %5.1f'\n", move[0], move[1], move[2]); - VectorCopy (move, G_VECTOR(OFS_RETURN)); -} - - -// 2001-09-20 QuakeC file access by FrikaC/Maddes start -/* -================= -PF_fopen - -float fopen (string,float) -================= -*/ -void PF_fopen (void) -{ - char *p = G_STRING(OFS_PARM0); - char *ftemp; - int fmode = G_FLOAT(OFS_PARM1); - int h = 0, fsize = 0; - - switch (fmode) - { - case 0: // read - Sys_FileOpenRead (va("%s/%s",com_gamedir, p), &h); - G_FLOAT(OFS_RETURN) = (float) h; - return; - case 1: // append -- this is nasty - // copy whole file into the zone - fsize = Sys_FileOpenRead(va("%s/%s",com_gamedir, p), &h); - if (h == -1) - { - h = Sys_FileOpenWrite(va("%s/%s",com_gamedir, p)); - G_FLOAT(OFS_RETURN) = (float) h; - return; - } - ftemp = Z_Malloc(fsize + 1); - Sys_FileRead(h, ftemp, fsize); - Sys_FileClose(h); - // spit it back out - h = Sys_FileOpenWrite(va("%s/%s",com_gamedir, p)); - Sys_FileWrite(h, ftemp, fsize); - Z_Free(ftemp); // free it from memory - G_FLOAT(OFS_RETURN) = (float) h; // return still open handle - return; - default: // write - h = Sys_FileOpenWrite (va("%s/%s", com_gamedir, p)); - G_FLOAT(OFS_RETURN) = (float) h; - return; - } -} - - -/* -================= -PF_fclose - -void fclose (float) -================= -*/ -void PF_fclose (void) -{ - int h = (int)G_FLOAT(OFS_PARM0); - Sys_FileClose(h); -} - -/* -================= -PF_fgets - -string fgets (float) -================= -*/ -void PF_fgets (void) -{ - // reads one line (up to a \n) into a string - int h; - int i; - int count; - char buffer; - char *s; - s = PR_GetTempString(); - - h = (int)G_FLOAT(OFS_PARM0); - - count = Sys_FileRead(h, &buffer, 1); - if (count && buffer == '\r') // carriage return - { - count = Sys_FileRead(h, &buffer, 1); // skip - } - if (!count) // EndOfFile - { - Sys_FileClose(h); - G_INT(OFS_RETURN) = OFS_NULL; // void string - return; - } - - i = 0; - while (count && buffer != '\n') - { - if (i < STRINGTEMP_LENGTH-1) // no place for character in temp string - { - s[i++] = buffer; - } - - // read next character - count = Sys_FileRead(h, &buffer, 1); - if (count && buffer == '\r') // carriage return - { - count = Sys_FileRead(h, &buffer, 1); // skip - } - }; - - G_INT(OFS_RETURN) = PR_SetEngineString(s); -} - -/* -================= -PF_fputs - -void fputs (float,string) -================= -*/ -void PF_fputs (void) -{ - // writes to file, like bprint - float handle = G_FLOAT(OFS_PARM0); - char *str = PF_VarString(1); - Sys_FileWrite (handle, str, strlen(str)); -} -// 2001-09-20 QuakeC file access by FrikaC/Maddes end - -/* -================= -PF_strzone - -string strzone (string) -================= -*/ -void PF_strzone (void) -{ - char *m, *p; - char *s; - s = PR_GetTempString(); - - m = G_STRING(OFS_PARM0); - p = Z_Malloc(strlen(m) + 1); - strcpy(p, m); - strcpy(s, p); - - G_INT(OFS_RETURN) = PR_SetEngineString(s); -} - -/* -================= -PF_strunzone - -string strunzone (string) -================= -*/ -void PF_strunzone (void) -{ - // naievil -- no more. - //Z_Free(G_STRING(OFS_PARM0)); - pr_string_tempindex--; - G_INT(OFS_PARM0) = OFS_NULL; // empty the def -}; - -/* -================= -PF_strtrim - -string strtrim (string) -================= -*/ -void PF_strtrim (void) -{ - char *m; - m = G_STRING(OFS_PARM0); - - char *c; - char *s; - c = m; - - while (c != '\0' && *c == ' ') - c++; - m = c; - - c = m + strlen (m) - 1; - while (c >= m) - { - if (*c == ' ') - *c = '\0'; - else - break; - c--; - } - - s = PR_GetTempString(); - strcpy(s, m); - - G_INT(OFS_RETURN) = PR_SetEngineString(s); -}; - - -/* -================= -PF_strlen - -float strlen (string) -================= -*/ -void PF_strlen (void) -{ - char *p = G_STRING(OFS_PARM0); - G_FLOAT(OFS_RETURN) = strlen(p); -} - -/* -================= -PF_substring - -string substring (string, float, float) -================= -*/ -void PF_substring (void) -{ - int offset, length; - int maxoffset; - char *p; - char *s; - - s = PR_GetTempString(); - - - p = G_STRING(OFS_PARM0); - offset = (int)G_FLOAT(OFS_PARM1); // for some reason, Quake doesn't like G_INT - length = (int)G_FLOAT(OFS_PARM2); - - // cap values - maxoffset = strlen(p); - if (offset > maxoffset) - { - offset = maxoffset; - } - if (offset < 0) - offset = 0; - if (length >= STRINGTEMP_LENGTH) - length = STRINGTEMP_LENGTH-1; - if (length < 0) - length = 0; - - p += offset; - strncpy(s, p, length); - G_INT(OFS_RETURN) = PR_SetEngineString(s); -} - -/* -================= -PF_strcat - -string strcat (string, string) -================= -*/ - -char M_pr_string_temp[STRINGTEMP_LENGTH]; -// 2001-10-25 Enhanced temp string handling by Maddes - -static void PF_strcat (void) -{ - char *s1, *s2, *s; - int maxlen; - // 2001-10-25 Enhanced temp string handling by Maddes - - s1 = G_STRING(OFS_PARM0); - s2 = G_STRING(OFS_PARM1); - s = PR_GetTempString(); - - - // 2001-10-25 Enhanced temp string handling by Maddes start - M_pr_string_temp[0] = 0; - if (strlen(s1) < STRINGTEMP_LENGTH) - { - strcpy(M_pr_string_temp, s1); - } - else - { - strncpy(M_pr_string_temp, s1, STRINGTEMP_LENGTH); - M_pr_string_temp[STRINGTEMP_LENGTH-1] = 0; - } - - maxlen = STRINGTEMP_LENGTH - strlen(M_pr_string_temp) - 1; // -1 is EndOfString - if (maxlen > 0) - { - if (maxlen > strlen(s2)) - { - strcat (M_pr_string_temp, s2); - } - else - { - strncat (M_pr_string_temp, s2, maxlen); - M_pr_string_temp[STRINGTEMP_LENGTH-1] = 0; - } - } - - strcpy(s, M_pr_string_temp); - G_INT(OFS_RETURN) = PR_SetEngineString(s); -} - -/* -================= -PF_stof - -float stof (string) -================= -*/ -// thanks Zoid, taken from QuakeWorld -void PF_stof (void) -{ - char *s; - - s = G_STRING(OFS_PARM0); - G_FLOAT(OFS_RETURN) = atof(s); -} - - -/* -================= -PF_stov - -vector stov (string) -================= -*/ -void PF_stov (void) -{ - char *v; - int i; - vec3_t d; - - v = G_STRING(OFS_PARM0); - - for (i=0; i<3; i++) - { - while(v && (v[0] == ' ' || v[0] == '\'')) //skip unneeded data - v++; - d[i] = atof(v); - while (v && v[0] != ' ') // skip to next space - v++; - } - VectorCopy (d, G_VECTOR(OFS_RETURN)); -} - -/* -================= -PF_tokenize - -float tokenize (string) = #441 -================= -*/ -//KRIMZON_SV_PARSECLIENTCOMMAND added both of these -// refined to work on psp on 2017-DEC-09 -// ...and then again on switch on 2019-MAY-03 -void PF_tokenize (void) -{ - char *m = G_STRING(OFS_PARM0); - Cmd_TokenizeString(m); - G_FLOAT(OFS_RETURN) = Cmd_Argc(); -}; - -/* -================= -PF_argv - -string argv (float num) = #442 -================= -*/ -void PF_ArgV (void) -{ - char tempc[256]; - char *s; - s = PR_GetTempString(); - - strcpy(tempc, Cmd_Argv(G_FLOAT(OFS_PARM0))); - strcpy(s, tempc); - G_INT(OFS_RETURN) = PR_SetEngineString(s); -} -#ifdef VITA -/* -================= -PF_rumble - -void rumble (float,float) -================= -*/ -void PF_rumble (void) -{ - // writes to file, like bprint - float intensity_small = G_FLOAT(OFS_PARM0); - float intensity_large = G_FLOAT(OFS_PARM1); - float duration = G_FLOAT(OFS_PARM2); - IN_StartRumble(intensity_small, intensity_large, duration); -} -#endif - -static builtin_t pr_builtin[] = -{ - PF_Fixme, - PF_makevectors, // void(entity e) makevectors = #1 - PF_setorigin, // void(entity e, vector o) setorigin = #2 - PF_setmodel, // void(entity e, string m) setmodel = #3 - PF_setsize, // void(entity e, vector min, vector max) setsize = #4 - PF_Fixme, // void(entity e, vector min, vector max) setabssize = #5 - PF_break, // void() break = #6 - PF_random, // float() random = #7 - PF_sound, // void(entity e, float chan, string samp) sound = #8 - PF_normalize, // vector(vector v) normalize = #9 - PF_error, // void(string e) error = #10 - PF_objerror, // void(string e) objerror = #11 - PF_vlen, // float(vector v) vlen = #12 - PF_vectoyaw, // float(vector v) vectoyaw = #13 - PF_Spawn, // entity() spawn = #14 - PF_Remove, // void(entity e) remove = #15 - PF_traceline, // float(vector v1, vector v2, float tryents) traceline = #16 - PF_checkclient, // entity() clientlist = #17 - PF_Find, // entity(entity start, .string fld, string match) find = #18 - PF_precache_sound, // void(string s) precache_sound = #19 - PF_precache_model, // void(string s) precache_model = #20 - PF_stuffcmd, // void(entity client, string s)stuffcmd = #21 - PF_findradius, // entity(vector org, float rad) findradius = #22 - PF_bprint, // void(string s) bprint = #23 - PF_sprint, // void(entity client, string s) sprint = #24 - PF_dprint, // void(string s) dprint = #25 - PF_ftos, // void(string s) ftos = #26 - PF_vtos, // void(string s) vtos = #27 - PF_coredump, - PF_traceon, - PF_traceoff, - PF_eprint, // void(entity e) debug print an entire entity - PF_walkmove, // float(float yaw, float dist) walkmove - PF_updateLimb, // #33 - PF_droptofloor, // #34 - PF_lightstyle, // #35 - PF_rint, // #36 - PF_floor, // #37 - PF_ceil, // #38 - PF_Fixme, // #39 - PF_checkbottom, // #40 - PF_pointcontents, // #41 - PF_Fixme, // #42 - PF_fabs, // #43 - PF_aim, // #44 - PF_cvar, // #45 - PF_localcmd, // #46 - PF_nextent, // #47 - PF_particle, // #48 - PF_changeyaw, // #49 - PF_Fixme, // #50 - PF_vectoangles, // #51 - PF_WriteByte, // #52 - PF_WriteChar, // #53 - PF_WriteShort, // #54 - PF_WriteLong, // #55 - PF_WriteCoord, // #56 - PF_WriteAngle, // #57 - PF_WriteString, // #58 - PF_WriteEntity, // #59 - PF_Fixme, // #60 - PF_Fixme, // #61 - PF_Fixme, // #62 - PF_Fixme, // #63 - PF_Fixme, // #64 - PF_Fixme, // #65 - PF_Fixme, // #66 - SV_MoveToGoal, // #67 - PF_precache_file, // #68 - PF_makestatic, // #69 - PF_changelevel, // #70 - PF_Fixme, // #71 - PF_cvar_set, // #72 - PF_centerprint, // #73 - PF_ambientsound, // #74 - PF_precache_model, // #75 - PF_precache_sound, // #76 precache_sound2 is different only for qcc - PF_precache_file, // #77 - PF_setspawnparms, // #78 - NULL, // #79 - NULL, // #80 - PF_stof, // #81 - NULL, // #82 - Get_Waypoint_Near, // #83 - Do_Pathfind, // #84 - Open_Waypoint, // #85 - Get_Next_Waypoint, // #86 - PF_useprint, // #87 - Get_First_Waypoint, // #88 - NULL, // #89 - NULL, // #90 - NULL, // #91 - NULL, // #92 - NULL, // #93 - NULL, // #94 - NULL, // #95 - NULL, // #96 - NULL, // #97 - PF_FindFloat, // #98 - PF_tracemove, // #99 sB reenabled - NULL, // #100 - NULL, // #101 - NULL, // #102 - NULL, // #103 - NULL, // #104 - NULL, // #105 - NULL, // #106 - NULL, // #107 - NULL, // #108 - NULL, // #109 - PF_fopen, // #110 - PF_fclose, // #111 - PF_fgets, // #112 - PF_fputs, // #113 - PF_strlen, // #114 - PF_strcat, // #115 - PF_substring, // #116 - PF_stov, // #117 - PF_strzone, // #118 - PF_strunzone, // #119 - PF_strtrim, // #120 - NULL, // #121 - NULL, // #122 - NULL, // #123 - NULL, // #124 - NULL, // #125 - NULL, // #126 - NULL, // #127 - NULL, // #128 - NULL, // #129 - PF_tokenize, // #130 - PF_ArgV, // #131 -#ifdef VITA - PF_rumble // #132 -#endif -}; - -builtin_t *pr_builtins = pr_builtin; -int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]); - diff --git a/source/sv_phys.c.bak b/source/sv_phys.c.bak deleted file mode 100644 index 8d222e8..0000000 --- a/source/sv_phys.c.bak +++ /dev/null @@ -1,1731 +0,0 @@ -/* -Copyright (C) 1996-2001 Id Software, Inc. -Copyright (C) 2002-2009 John Fitzgibbons and others -Copyright (C) 2010-2014 QuakeSpasm developers - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// sv_phys.c - -#include "quakedef.h" - -/* - - -pushmove objects do not obey gravity, and do not interact with each other or trigger fields, but block normal movement and push normal objects when they move. - -onground is set for toss objects when they come to a complete rest. it is set for steping or walking objects - -doors, plats, etc are SOLID_BSP, and MOVETYPE_PUSH -bonus items are SOLID_TRIGGER touch, and MOVETYPE_TOSS -corpses are SOLID_NOT and MOVETYPE_TOSS -crates are SOLID_BBOX and MOVETYPE_TOSS -walking monsters are SOLID_SLIDEBOX and MOVETYPE_STEP -flying/floating monsters are SOLID_SLIDEBOX and MOVETYPE_FLY - -solid_edge items only clip against bsp models. - -*/ - -cvar_t sv_friction = {"sv_friction","4",CVAR_NOTIFY|CVAR_SERVERINFO}; -cvar_t sv_stopspeed = {"sv_stopspeed","100",CVAR_NONE}; -cvar_t sv_gravity = {"sv_gravity","800",CVAR_NOTIFY|CVAR_SERVERINFO}; -cvar_t sv_maxvelocity = {"sv_maxvelocity","2000",CVAR_NONE}; -cvar_t sv_nostep = {"sv_nostep","0",CVAR_NONE}; -cvar_t sv_freezenonclients = {"sv_freezenonclients","0",CVAR_NONE}; - - -#define MOVE_EPSILON 0.01 - -void SV_Physics_Toss (edict_t *ent); - -/* -================ -SV_CheckAllEnts -================ -*/ -void SV_CheckAllEnts (void) -{ - int e; - edict_t *check; - -// see if any solid entities are inside the final position - check = NEXT_EDICT(sv.edicts); - for (e=1 ; efree) - continue; - if (check->v.movetype == MOVETYPE_PUSH - || check->v.movetype == MOVETYPE_NONE - || check->v.movetype == MOVETYPE_FOLLOW - || check->v.movetype == MOVETYPE_NOCLIP) - continue; - - if (SV_TestEntityPosition (check)) - Con_Printf ("entity in invalid position\n"); - } -} - -/* -================ -SV_CheckVelocity -================ -*/ -void SV_CheckVelocity (edict_t *ent) -{ - int i; - -// -// bound velocity -// - for (i=0 ; i<3 ; i++) - { - if (IS_NAN(ent->v.velocity[i])) - { - Con_Printf ("Got a NaN velocity on %s\n", PR_GetString(ent->v.classname)); - ent->v.velocity[i] = 0; - } - if (IS_NAN(ent->v.origin[i])) - { - Con_Printf ("Got a NaN origin on %s\n", PR_GetString(ent->v.classname)); - ent->v.origin[i] = 0; - } - if (ent->v.velocity[i] > sv_maxvelocity.value) - ent->v.velocity[i] = sv_maxvelocity.value; - else if (ent->v.velocity[i] < -sv_maxvelocity.value) - ent->v.velocity[i] = -sv_maxvelocity.value; - } -} - -/* -============= -SV_RunThink - -Runs thinking code if time. There is some play in the exact time the think -function will be called, because it is called before any movement is done -in a frame. Not used for pushmove objects, because they must be exact. -Returns false if the entity removed itself. -============= -*/ -qboolean SV_RunThink (edict_t *ent) -{ - float thinktime; - - thinktime = ent->v.nextthink; - if (thinktime <= 0 || thinktime > sv.time + host_frametime) - return true; - - if (thinktime < sv.time) - thinktime = sv.time; // don't let things stay in the past. - // it is possible to start that way - // by a trigger with a local time. - - - ent->v.nextthink = 0; - pr_global_struct->time = thinktime; - pr_global_struct->self = EDICT_TO_PROG(ent); - pr_global_struct->other = EDICT_TO_PROG(sv.edicts); - PR_ExecuteProgram (ent->v.think); - - - return !ent->free; -} - -/* -================== -SV_Impact - -Two entities have touched, so run their touch functions -================== -*/ -void SV_Impact (edict_t *e1, edict_t *e2) -{ - int old_self, old_other; - - old_self = pr_global_struct->self; - old_other = pr_global_struct->other; - - pr_global_struct->time = sv.time; - if (e1->v.touch && e1->v.solid != SOLID_NOT) - { - pr_global_struct->self = EDICT_TO_PROG(e1); - pr_global_struct->other = EDICT_TO_PROG(e2); - PR_ExecuteProgram (e1->v.touch); - } - - if (e2->v.touch && e2->v.solid != SOLID_NOT) - { - pr_global_struct->self = EDICT_TO_PROG(e2); - pr_global_struct->other = EDICT_TO_PROG(e1); - PR_ExecuteProgram (e2->v.touch); - } - - pr_global_struct->self = old_self; - pr_global_struct->other = old_other; -} - - -/* -================== -ClipVelocity - -Slide off of the impacting object -returns the blocked flags (1 = floor, 2 = step / wall) -================== -*/ -#define STOP_EPSILON 0.1 - -int ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce) -{ - float backoff; - float change; - int i, blocked; - - blocked = 0; - if (normal[2] > 0) - blocked |= 1; // floor - if (!normal[2]) - blocked |= 2; // step - - backoff = DotProduct (in, normal) * overbounce; - - for (i=0 ; i<3 ; i++) - { - change = normal[i]*backoff; - out[i] = in[i] - change; - if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON) - out[i] = 0; - } - - return blocked; -} - - -/* -============ -SV_FlyMove - -The basic solid body movement clip that slides along multiple planes -Returns the clipflags if the velocity was modified (hit something solid) -1 = floor -2 = wall / step -4 = dead stop -If steptrace is not NULL, the trace of any vertical wall hit will be stored -============ -*/ -#define MAX_CLIP_PLANES 5 -int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace) -{ - int bumpcount, numbumps; - vec3_t dir; - float d; - int numplanes; - vec3_t planes[MAX_CLIP_PLANES]; - vec3_t primal_velocity, original_velocity, new_velocity; - int i, j; - trace_t trace; - vec3_t end; - float time_left; - int blocked; - - numbumps = 4; - - blocked = 0; - VectorCopy (ent->v.velocity, original_velocity); - VectorCopy (ent->v.velocity, primal_velocity); - numplanes = 0; - - time_left = time; - - for (bumpcount=0 ; bumpcountv.velocity[0] && !ent->v.velocity[1] && !ent->v.velocity[2]) - break; - - for (i=0 ; i<3 ; i++) - end[i] = ent->v.origin[i] + time_left * ent->v.velocity[i]; - - trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NOMONSTERS, ent);//Editted by blubs, we do want to ignore monsters in the trace - - if (trace.allsolid) - { // entity is trapped in another solid - VectorCopy (vec3_origin, ent->v.velocity); - return 3; - } - - if (trace.fraction > 0) - { // actually covered some distance - VectorCopy (trace.endpos, ent->v.origin); - VectorCopy (ent->v.velocity, original_velocity); - numplanes = 0; - } - - if (trace.fraction == 1) - break; // moved the entire distance - - if (!trace.ent) - Sys_Error ("SV_FlyMove: !trace.ent"); - - if (trace.plane.normal[2] > 0.7) - { - blocked |= 1; // floor - if (trace.ent->v.solid == SOLID_BSP) - { - ent->v.flags = (int)ent->v.flags | FL_ONGROUND; - ent->v.groundentity = EDICT_TO_PROG(trace.ent); - } - } - if (!trace.plane.normal[2]) - { - blocked |= 2; // step - if (steptrace) - *steptrace = trace; // save for player extrafriction - } - -// -// run the impact function -// - SV_Impact (ent, trace.ent); - if (ent->free) - break; // removed by the impact function - - - time_left -= time_left * trace.fraction; - - // cliped to another plane - if (numplanes >= MAX_CLIP_PLANES) - { // this shouldn't really happen - VectorCopy (vec3_origin, ent->v.velocity); - return 3; - } - - VectorCopy (trace.plane.normal, planes[numplanes]); - numplanes++; - -// -// modify original_velocity so it parallels all of the clip planes -// - for (i=0 ; iv.velocity); - } - else - { // go along the crease - if (numplanes != 2) - { -// Con_Printf ("clip velocity, numplanes == %i\n",numplanes); - VectorCopy (vec3_origin, ent->v.velocity); - return 7; - } - CrossProduct (planes[0], planes[1], dir); - d = DotProduct (dir, ent->v.velocity); - VectorScale (dir, d, ent->v.velocity); - } - -// -// if original velocity is against the original velocity, stop dead -// to avoid tiny occilations in sloping corners -// - if (DotProduct (ent->v.velocity, primal_velocity) <= 0) - { - VectorCopy (vec3_origin, ent->v.velocity); - return blocked; - } - } - - return blocked; -} - - -/* -============ -SV_AddGravity - -============ -*/ -void SV_AddGravity (edict_t *ent) -{ - float ent_gravity; - eval_t *val; - - val = GetEdictFieldValue(ent, "gravity"); - if (val && val->_float) - ent_gravity = val->_float; - else - ent_gravity = 1.0; - - ent->v.velocity[2] -= ent_gravity * sv_gravity.value * host_frametime; -} - - -/* -=============================================================================== - -PUSHMOVE - -=============================================================================== -*/ - -/* -============ -SV_AllowPushRotate -Allows to change entity yaw? -============ -*/ -qboolean SV_AllowPushRotate( edict_t *ent ) -{ - qmodel_t *mod; - - mod = sv.models[ (int)ent->v.modelindex ]; - if(!mod || mod->type != mod_brush) - return true; - - return /*(mod->flags & MODEL_HAS_ORIGIN) ? true :*/ false; -} - -/* -============ -SV_PushEntity - -Does not change the entities velocity at all -============ -*/ -trace_t SV_PushEntity (edict_t *ent, vec3_t push, vec3_t apush) -{ - trace_t trace; - vec3_t end; - - VectorAdd (ent->v.origin, push, end); - - if (ent->v.movetype == MOVETYPE_FLYMISSILE) - trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_MISSILE, ent); - else if (ent->v.solid == SOLID_TRIGGER || ent->v.solid == SOLID_NOT) - // only clip against bmodels - trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NOMONSTERS, ent); - else - trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent); - - if( trace.fraction != 0.0f ) - { - VectorCopy( trace.endpos, ent->v.origin ); - - if( apush[YAW] && ( (int)ent->v.flags & FL_CLIENT )) - { - ent->v.avelocity[1] += apush[1]; - ent->v.fixangle = 2; - } - - // don't rotate pushables! - if( SV_AllowPushRotate( ent )) - ent->v.angles[YAW] += trace.fraction * apush[YAW]; - } - - SV_LinkEdict (ent, true); - - if (trace.ent) - SV_Impact (ent, trace.ent); - - return trace; -} - - -/* -============ -SV_PushMove -============ -*/ -edict_t *moved_edict[MAX_EDICTS]; -vec3_t moved_from[MAX_EDICTS]; -edict_t * SV_PushMove (edict_t *pusher, float movetime) //sB modified to match dquake -{ - int i, e, oldsolid; - edict_t *check, *block; - vec3_t mins, maxs, move; - vec3_t entorig, pushorig; - int num_moved; - edict_t **moved_edict; //johnfitz -- dynamically allocate - vec3_t *moved_from; //johnfitz -- dynamically allocate - int mark; //johnfitz - - if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2]) - { - pusher->v.ltime += movetime; - return NULL; - } - - for (i=0 ; i<3 ; i++) - { - move[i] = pusher->v.velocity[i] * movetime; - mins[i] = pusher->v.absmin[i] + move[i]; - maxs[i] = pusher->v.absmax[i] + move[i]; - } - - VectorCopy (pusher->v.origin, pushorig); - -// move the pusher to it's final position - - VectorAdd (pusher->v.origin, move, pusher->v.origin); - SV_LinkEdict (pusher, false); - pusher->v.ltime += movetime; - oldsolid = pusher->v.solid; - - // non-solid pushers can't push anything - if( pusher->v.solid == SOLID_NOT ) - return NULL; -/* - //johnfitz -- dynamically allocate - mark = Hunk_LowMark (); - moved_edict = (edict_t **) Hunk_Alloc (sv.num_edicts*sizeof(edict_t *)); - moved_from = (vec3_t *) Hunk_Alloc (sv.num_edicts*sizeof(vec3_t)); - //johnfitz -*/ -// see if any solid entities are inside the final position - num_moved = 0; - check = NEXT_EDICT(sv.edicts); - for (e=1 ; efree) - continue; - if (check->v.movetype == MOVETYPE_PUSH - || check->v.movetype == MOVETYPE_NONE - || check->v.movetype == MOVETYPE_NOCLIP) - continue; - - // if the entity is standing on the pusher, it will definately be moved - if ( ! ( ((int)check->v.flags & FL_ONGROUND) - && PROG_TO_EDICT(check->v.groundentity) == pusher) ) - { - if ( check->v.absmin[0] >= maxs[0] - || check->v.absmin[1] >= maxs[1] - || check->v.absmin[2] >= maxs[2] - || check->v.absmax[0] <= mins[0] - || check->v.absmax[1] <= mins[1] - || check->v.absmax[2] <= mins[2] ) - continue; - - // see if the ent's bbox is inside the pusher's final position - if (!SV_TestEntityPosition (check)) - continue; - } - - // remove the onground flag for non-players - if (check->v.movetype != MOVETYPE_WALK) - check->v.flags = (int)check->v.flags & ~FL_ONGROUND; - - VectorCopy (check->v.origin, entorig); - VectorCopy (check->v.origin, moved_from[num_moved]); - moved_edict[num_moved] = check; - num_moved++; - - // try moving the contacted entity - pusher->v.solid = SOLID_NOT; - SV_PushEntity (check, move, vec3_origin); - pusher->v.solid = oldsolid; - - // if it is still inside the pusher, block - block = SV_TestEntityPosition (check); - if (block) - { // fail the move - if (check->v.mins[0] == check->v.maxs[0]) - continue; - if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER) - { // corpse - check->v.mins[0] = check->v.mins[1] = 0; - VectorCopy (check->v.mins, check->v.maxs); - continue; - } - - VectorCopy (entorig, check->v.origin); - SV_LinkEdict (check, true); - - VectorCopy (pushorig, pusher->v.origin); - SV_LinkEdict (pusher, false); - pusher->v.ltime -= movetime; - - // if the pusher has a "blocked" function, call it - // otherwise, just stay in place until the obstacle is gone - if (pusher->v.blocked) - { - pr_global_struct->self = EDICT_TO_PROG(pusher); - pr_global_struct->other = EDICT_TO_PROG(check); - PR_ExecuteProgram (pusher->v.blocked); - } - - // move back any entities we already moved - for (i=0 ; iv.origin); - SV_LinkEdict (moved_edict[i], (moved_edict[i] == check) ? true : false); - } - //Hunk_FreeToLowMark (mark); //johnfitz - return check; - } - } - - //Hunk_FreeToLowMark (mark); //johnfitz - return NULL; - -} - -/* -============ -SV_PushRotate - -============ -*/ -edict_t * SV_PushRotate (edict_t *pusher, float movetime) -{ - int i, e, oldsolid; - matrix4x4 start_l, end_l;; - edict_t *check, *block; - vec3_t move, amove; - vec3_t entorig, pushorig; - int num_moved; - vec3_t org, org2, temp; - - if (!pusher->v.avelocity[0] && !pusher->v.avelocity[1] && !pusher->v.avelocity[2]) - { - pusher->v.ltime += movetime; - return NULL; - } - - for (i = 0; i < 3; i++) - amove[i] = pusher->v.avelocity[i] * movetime; - - // create pusher initial position - Matrix4x4_CreateFromEntity( start_l, pusher->v.angles, pusher->v.origin, 1.0f ); - - VectorCopy (pusher->v.angles, pushorig); - - // move the pusher to it's final position - VectorAdd (pusher->v.angles, amove, pusher->v.angles); - pusher->v.ltime += movetime; - SV_LinkEdict (pusher, false); - oldsolid = pusher->v.solid; - - // non-solid pushers can't push anything - if( pusher->v.solid == SOLID_NOT ) - return NULL; - - // create pusher final position - Matrix4x4_CreateFromEntity( end_l, pusher->v.angles, pusher->v.origin, 1.0f ); - - // see if any solid entities are inside the final position - num_moved = 0; - check = NEXT_EDICT (sv.edicts); - - for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT (check)) - { - if (check->free) - continue; - - if (check->v.movetype == MOVETYPE_PUSH - || check->v.movetype == MOVETYPE_NONE - || check->v.movetype == MOVETYPE_FOLLOW - || check->v.movetype == MOVETYPE_NOCLIP) - continue; - - // if the entity is standing on the pusher, it will definately be moved - if (!(((int) check->v.flags & FL_ONGROUND) && PROG_TO_EDICT (check->v.groundentity) == pusher)) - { - if (check->v.absmin[0] >= pusher->v.absmax[0] - || check->v.absmin[1] >= pusher->v.absmax[1] - || check->v.absmin[2] >= pusher->v.absmax[2] - || check->v.absmax[0] <= pusher->v.absmin[0] - || check->v.absmax[1] <= pusher->v.absmin[1] - || check->v.absmax[2] <= pusher->v.absmin[2]) - continue; - - // see if the ent's bbox is inside the pusher's final position - if (!SV_TestEntityPosition (check)) - continue; - } - - // remove the onground flag for non-players - if (check->v.movetype != MOVETYPE_WALK) - check->v.flags = (int) check->v.flags & ~FL_ONGROUND; - - VectorCopy (check->v.origin, entorig); - VectorCopy (check->v.origin, moved_from[num_moved]); - - moved_edict[num_moved] = check; - num_moved++; - - // calculate destination position - //if( check->v.movetype == MOVETYPE_PUSHSTEP ) - // VectorAverage( check->v.absmin, check->v.absmax, org ); - //else - VectorCopy( check->v.origin, org ); - - Matrix4x4_VectorITransform( start_l, org, temp ); - Matrix4x4_VectorTransform( end_l, temp, org2 ); - VectorSubtract( org2, org, move ); - - // try moving the contacted entity - pusher->v.solid = SOLID_NOT; - SV_PushEntity (check, move, amove); - pusher->v.solid = oldsolid; - - - // if it is still inside the pusher, block - block = SV_TestEntityPosition (check); - - if (block) - { - // fail the move - if (check->v.mins[0] == check->v.maxs[0]) - continue; - - if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER) - { - // corpse - check->v.mins[0] = check->v.mins[1] = 0; - VectorCopy (check->v.mins, check->v.maxs); - continue; - } - - VectorCopy (entorig, check->v.origin); - SV_LinkEdict (check, true); - - VectorCopy (pushorig, pusher->v.angles); - SV_LinkEdict (pusher, false); - pusher->v.ltime -= movetime; - - // if the pusher has a "blocked" function, call it - // otherwise, just stay in place until the obstacle is gone - if (pusher->v.blocked) - { - pr_global_struct->self = EDICT_TO_PROG (pusher); - pr_global_struct->other = EDICT_TO_PROG (check); - PR_ExecuteProgram (pusher->v.blocked); - } - - // move back any entities we already moved - for (i = 0; i < num_moved; i++) - { - VectorCopy (moved_from[i], moved_edict[i]->v.origin); - VectorSubtract (moved_edict[i]->v.angles, amove, moved_edict[i]->v.angles); - SV_LinkEdict (moved_edict[i], (moved_edict[i] == check) ? true : false); - } - return check; - } - else - { - VectorAdd (check->v.angles, amove, check->v.angles); - } - - } - return NULL; -} - -/* -================ -SV_Physics_Pusher - -================ -*/ -void SV_Physics_Pusher (edict_t *ent) //sB modified to match dquake -{ - float thinktime; - float oldltime; - float movetime; - - oldltime = ent->v.ltime; - - thinktime = ent->v.nextthink; - if (thinktime < ent->v.ltime + host_frametime) - { - movetime = thinktime - ent->v.ltime; - if (movetime < 0) - movetime = 0; - } - else - movetime = host_frametime; - - if (ent->v.avelocity[0] || ent->v.avelocity[1] || ent->v.avelocity[2]) - SV_PushRotate (ent, host_frametime); - - if (movetime) - SV_PushMove (ent, movetime); // advances ent->v.ltime if not blocked - - - if (thinktime > oldltime && thinktime <= ent->v.ltime) - { - ent->v.nextthink = 0; - pr_global_struct->time = sv.time; - pr_global_struct->self = EDICT_TO_PROG(ent); - pr_global_struct->other = EDICT_TO_PROG(sv.edicts); - PR_ExecuteProgram (ent->v.think); - if (ent->free) - return; - } - -} - - -/* -=============================================================================== - -CLIENT MOVEMENT - -=============================================================================== -*/ - -/* -============= -SV_CheckStuck - -This is a big hack to try and fix the rare case of getting stuck in the world -clipping hull. -============= -*/ -void SV_CheckStuck (edict_t *ent) -{ - int i, j; - int z; - vec3_t org; - - if (!SV_TestEntityPosition(ent)) - { - VectorCopy (ent->v.origin, ent->v.oldorigin); - return; - } - - VectorCopy (ent->v.origin, org); - VectorCopy (ent->v.oldorigin, ent->v.origin); - if (!SV_TestEntityPosition(ent)) - { - Con_DPrintf ("Unstuck.\n"); - SV_LinkEdict (ent, true); - return; - } - - for (z=0 ; z< 18 ; z++) - for (i=-1 ; i <= 1 ; i++) - for (j=-1 ; j <= 1 ; j++) - { - ent->v.origin[0] = org[0] + i; - ent->v.origin[1] = org[1] + j; - ent->v.origin[2] = org[2] + z; - if (!SV_TestEntityPosition(ent)) - { - Con_DPrintf ("Unstuck.\n"); - SV_LinkEdict (ent, true); - return; - } - } - - VectorCopy (org, ent->v.origin); - Con_DPrintf ("player is stuck.\n"); -} - - -/* -============= -SV_CheckWater -============= -*/ -qboolean SV_CheckWater (edict_t *ent) -{ - vec3_t point; - int cont; - - point[0] = ent->v.origin[0]; - point[1] = ent->v.origin[1]; - point[2] = ent->v.origin[2] + ent->v.mins[2] + 1; - - ent->v.waterlevel = 0; - ent->v.watertype = CONTENTS_EMPTY; - cont = SV_PointContents (point); - if (cont <= CONTENTS_WATER) - { - ent->v.watertype = cont; - ent->v.waterlevel = 1; - point[2] = ent->v.origin[2] + (ent->v.mins[2] + ent->v.maxs[2])*0.5; - cont = SV_PointContents (point); - if (cont <= CONTENTS_WATER) - { - ent->v.waterlevel = 2; - point[2] = ent->v.origin[2] + ent->v.view_ofs[2]; - cont = SV_PointContents (point); - if (cont <= CONTENTS_WATER) - ent->v.waterlevel = 3; - } - } - - return ent->v.waterlevel > 1; -} - -/* -============ -SV_WallFriction - -============ -*/ -void SV_WallFriction (edict_t *ent, trace_t *trace) -{ - vec3_t forward, right, up; - float d, i; - vec3_t into, side; - - AngleVectors (ent->v.v_angle, forward, right, up); - d = DotProduct (trace->plane.normal, forward); - - d += 0.5; - if (d >= 0) - return; - -// cut the tangential velocity - i = DotProduct (trace->plane.normal, ent->v.velocity); - VectorScale (trace->plane.normal, i, into); - VectorSubtract (ent->v.velocity, into, side); - - ent->v.velocity[0] = side[0] * (1 + d); - ent->v.velocity[1] = side[1] * (1 + d); -} - -/* -===================== -SV_TryUnstick - -Player has come to a dead stop, possibly due to the problem with limited -float precision at some angle joins in the BSP hull. - -Try fixing by pushing one pixel in each direction. - -This is a hack, but in the interest of good gameplay... -====================== -*/ -int SV_TryUnstick (edict_t *ent, vec3_t oldvel) -{ - int i; - vec3_t oldorg; - vec3_t dir; - int clip; - trace_t steptrace; - - VectorCopy (ent->v.origin, oldorg); - VectorCopy (vec3_origin, dir); - - for (i=0 ; i<8 ; i++) - { -// try pushing a little in an axial direction - switch (i) - { - case 0: dir[0] = 2; dir[1] = 0; break; - case 1: dir[0] = 0; dir[1] = 2; break; - case 2: dir[0] = -2; dir[1] = 0; break; - case 3: dir[0] = 0; dir[1] = -2; break; - case 4: dir[0] = 2; dir[1] = 2; break; - case 5: dir[0] = -2; dir[1] = 2; break; - case 6: dir[0] = 2; dir[1] = -2; break; - case 7: dir[0] = -2; dir[1] = -2; break; - } - - SV_PushEntity (ent, dir, vec3_origin); - -// retry the original move - ent->v.velocity[0] = oldvel[0]; - ent->v. velocity[1] = oldvel[1]; - ent->v. velocity[2] = 0; - clip = SV_FlyMove (ent, 0.1, &steptrace); - - if ( fabs(oldorg[1] - ent->v.origin[1]) > 4 - || fabs(oldorg[0] - ent->v.origin[0]) > 4 ) - { -//Con_DPrintf ("unstuck!\n"); - return clip; - } - -// go back to the original pos and try again - VectorCopy (oldorg, ent->v.origin); - } - - VectorCopy (vec3_origin, ent->v.velocity); - return 7; // still not moving -} - -/* -===================== -SV_WalkMove - -Only used by players -====================== -*/ -#define STEPSIZE 18 -void SV_WalkMove (edict_t *ent) -{ - vec3_t upmove, downmove; - vec3_t oldorg, oldvel; - vec3_t nosteporg, nostepvel; - int clip; - int oldonground; - trace_t steptrace, downtrace; - -// -// do a regular slide move unless it looks like you ran into a step -// - oldonground = (int)ent->v.flags & FL_ONGROUND; - ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND; - - VectorCopy (ent->v.origin, oldorg); - VectorCopy (ent->v.velocity, oldvel); - - clip = SV_FlyMove (ent, host_frametime, &steptrace); - - if ( !(clip & 2) ) - return; // move didn't block on a step - - if (!oldonground && ent->v.waterlevel == 0) - return; // don't stair up while jumping - - if (ent->v.movetype != MOVETYPE_WALK) - return; // gibbed by a trigger - - if (sv_nostep.value) - return; - - if ( (int)sv_player->v.flags & FL_WATERJUMP ) - return; - - VectorCopy (ent->v.origin, nosteporg); - VectorCopy (ent->v.velocity, nostepvel); - -// -// try moving up and forward to go up a step -// - VectorCopy (oldorg, ent->v.origin); // back to start pos - - VectorCopy (vec3_origin, upmove); - VectorCopy (vec3_origin, downmove); - upmove[2] = STEPSIZE; - downmove[2] = -STEPSIZE + oldvel[2]*host_frametime; - -// move up - SV_PushEntity (ent, upmove, vec3_origin); // FIXME: don't link? - -// move forward - ent->v.velocity[0] = oldvel[0]; - ent->v. velocity[1] = oldvel[1]; - ent->v. velocity[2] = 0; - clip = SV_FlyMove (ent, host_frametime, &steptrace); - -// check for stuckness, possibly due to the limited precision of floats -// in the clipping hulls - if (clip) - { - if ( fabs(oldorg[1] - ent->v.origin[1]) < 0.03125 - && fabs(oldorg[0] - ent->v.origin[0]) < 0.03125 ) - { // stepping up didn't make any progress - clip = SV_TryUnstick (ent, oldvel); - } - } - -// extra friction based on view angle - if ( clip & 2 ) - SV_WallFriction (ent, &steptrace); - -// move down - downtrace = SV_PushEntity (ent, downmove, vec3_origin); // FIXME: don't link? - - if (downtrace.plane.normal[2] > 0.7) - { - if (ent->v.solid == SOLID_BSP) - { - ent->v.flags = (int)ent->v.flags | FL_ONGROUND; - ent->v.groundentity = EDICT_TO_PROG(downtrace.ent); - } - } - else - { -// if the push down didn't end up on good ground, use the move without -// the step up. This happens near wall / slope combinations, and can -// cause the player to hop up higher on a slope too steep to climb - VectorCopy (nosteporg, ent->v.origin); - VectorCopy (nostepvel, ent->v.velocity); - } -} - -/* -================= -SV_Physics_Walk - -Blubswillrule - -A physics/velocity based walking method for monsters (zombies) - - -The following functions are duplicates from player modified for use by monsters -======================================================================================================================================================== -*/ - -/* -============ -SV_PushMonsterEntity - -duplicate of SV_PushEntity: used for monster velocities. - -Does not change the entities velocity at all -============ -*/ -trace_t SV_PushMonsterEntity (edict_t *ent, vec3_t push) -{ - trace_t trace; - vec3_t end; - - VectorAdd (ent->v.origin, push, end); - - trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NOMONSTERS, ent); - - VectorCopy (trace.endpos, ent->v.origin); - //SV_LinkEdict (ent, true); we don't need to link it here - - if (trace.ent) - SV_Impact (ent, trace.ent); - - return trace; -} - -/* -===================== -SV_MonsterWalkMove - -duplicate SV_WalkMove: Only used by monsters who move by velocity -====================== -*/ -void SV_MonsterWalkMove (edict_t *ent) -{ - vec3_t upmove, downmove; - vec3_t oldorg, oldvel; - vec3_t nosteporg, nostepvel; - int clip; - int oldonground; - trace_t steptrace, downtrace; - -// -// do a regular slide move unless it looks like you ran into a step -// - oldonground = (int)ent->v.flags & FL_ONGROUND; - ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND; - - VectorCopy (ent->v.origin, oldorg); - VectorCopy (ent->v.velocity, oldvel); - - clip = SV_FlyMove (ent, host_frametime, &steptrace); - - if ( !(clip & 2) ) - return; // move didn't block on a step - - //if (!oldonground && ent->v.waterlevel == 0) - // return; // don't stair up while jumping - - if (ent->v.movetype != MOVETYPE_WALK) - return; // gibbed by a trigger - - VectorCopy (ent->v.origin, nosteporg); - VectorCopy (ent->v.velocity, nostepvel); -// -// try moving up and forward to go up a step -// - VectorCopy (oldorg, ent->v.origin); // back to start pos - - VectorCopy (vec3_origin, upmove); - VectorCopy (vec3_origin, downmove); - upmove[2] = STEPSIZE; - downmove[2] = -STEPSIZE + oldvel[2]*host_frametime; - -// move up - SV_PushMonsterEntity (ent, upmove); // FIXME: don't link? - -// move forward - ent->v.velocity[0] = oldvel[0]; - ent->v. velocity[1] = oldvel[1]; - ent->v. velocity[2] = 0; - clip = SV_FlyMove (ent, host_frametime, &steptrace); - -// check for stuckness, possibly due to the limited precision of floats -// in the clipping hulls - /*if (clip) - { - if ( fabsf(oldorg[1] - ent->v.origin[1]) < 0.03125 && fabsf(oldorg[0] - ent->v.origin[0]) < 0.03125 ) - { // stepping up didn't make any progress - clip = SV_TryUnstick (ent, oldvel); - } - }*/ - -// extra friction based on view angle - if ( clip & 2 ) - SV_WallFriction (ent, &steptrace); - -// move down - downtrace = SV_PushMonsterEntity (ent, downmove); // FIXME: don't link? - - if (downtrace.plane.normal[2] > 0.7) - { - if (downtrace.ent->v.solid == SOLID_BSP) - { - ent->v.flags = (int)ent->v.flags | FL_ONGROUND; - ent->v.groundentity = EDICT_TO_PROG(downtrace.ent); - } - } - else - { -// if the push down didn't end up on good ground, use the move without -// the step up. This happens near wall / slope combinations, and can -// cause the player to hop up higher on a slope too steep to climb - VectorCopy (nosteporg, ent->v.origin); - VectorCopy (nostepvel, ent->v.velocity); - } -} - -//Creating a duplicate SV_TestEntityPosition, one that does not check for monsters. -//============= -edict_t *SV_TestEntityPosition_NOMONSTERS(edict_t *ent) -{ - trace_t trace; - - trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, MOVE_NOMONSTERS, ent); - - if (trace.startsolid) - return sv.edicts; - - return NULL; -} -//============= -//Creating a duplicate checkstuck that uses the above modified SV_TestEntityPosition_NOMONSTERS - -//Also adds checking of the entities v.zoom value -//1: used setorigin, so don't adjust for a collision -//0: not in collision -//============= - -void SV_CheckStuck_IgnoreMonsters (edict_t *ent) -{ - int i, j; - int z; - vec3_t org; - - if (!SV_TestEntityPosition_NOMONSTERS(ent)) - { - VectorCopy (ent->v.origin, ent->v.oldorigin); - ent->v.zoom = 0; - return; - } - - if(ent->v.zoom == 1)//if used setorigin - { - VectorCopy (ent->v.origin, ent->v.oldorigin); - return;//we don't care to adjust for stuckness, whoever used setorigin in qc better handle that - } - VectorCopy (ent->v.origin, org); - VectorCopy (ent->v.oldorigin, ent->v.origin); - if (!SV_TestEntityPosition_NOMONSTERS(ent)) - { - Con_DPrintf ("zombie unstuck from bsp hull or non-monster entity.\n"); - SV_LinkEdict (ent, true); - return; - } - - for (z=0 ; z< 18 ; z++) - for (i=-1 ; i <= 1 ; i++) - for (j=-1 ; j <= 1 ; j++) - { - ent->v.origin[0] = org[0] + i; - ent->v.origin[1] = org[1] + j; - ent->v.origin[2] = org[2] + z; - if (!SV_TestEntityPosition_NOMONSTERS(ent)) - { - Con_DPrintf ("zombie unstuck from bsp hull or non-monster entity.\n"); - SV_LinkEdict (ent, true); - return; - } - } - - VectorCopy (org, ent->v.origin); - Con_DPrintf ("zombie is stuck in bsp hull or non-monster entity.\n"); -} - -//============================= -//PushAwayZombies -//blubswillrule -//Makes sure zombies are not inside of each other -//glorified version of PF_FindRadius -//============================= -void SV_PushAwayZombies(edict_t *ent) -{ - edict_t *other_ent; - float rad = 23;//approx. length of bbox corner - float *org = ent->v.origin; - vec3_t eorg; - int i, j; - - other_ent = NEXT_EDICT(sv.edicts); - for (i=1 ; ifree) - continue; - //if (ent->v.solid == SOLID_NOT) - // continue; - if( other_ent->v.solid != SOLID_CORPSE) - continue; - if( other_ent->v.movetype != MOVETYPE_WALK) - continue; - for (j=0 ; j<3 ; j++) - eorg[j] = org[j] - (other_ent->v.origin[j] + (other_ent->v.mins[j] + other_ent->v.maxs[j])*0.5); - if (Length(eorg) > rad) - { - //Con_Printf ("Length Greater than bbox corner. \n"); - continue; - } - //Process nearby zombie - for(j = 0; j < 2; j++)//only x & y - { - Con_Printf ("Pushing Zombie \n"); - other_ent->v.velocity[j] += (other_ent->v.origin[j] - ent->v.origin[j]) * 0.01;//push away other zombie was 0.001 - //ent->v.velocity[j] += (ent->v.origin[j] - other_ent->v.origin[j]) * 0.01;//push away self - } - } -} -//============================= - -void SV_Physics_Walk(edict_t *ent) -{ - //if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) ) - // SV_AddGravity (ent); - //Slight modification of AddGravity below - - //Zombie bbox is actually smaller, but the movement needs to pretend it is bigger - vec3_t old_mins; - vec3_t old_maxs; - - if(!SV_RunThink(ent)) - return; - - VectorCopy(ent->v.mins,old_mins); - VectorCopy(ent->v.maxs,old_maxs); - - //'-16,-16,-32', '16,16,40' sB reenabled PushAwayZombies - ent->v.mins[0] = -16; ent->v.mins[1] = -16; ent->v.mins[2] = -32; - ent->v.maxs[0] = 16; ent->v.maxs[1] = 16; ent->v.maxs[2] = 40; - - //if (!((int)ent->v.flags & (FL_ONGROUND))) - //{ - ent->v.velocity[2] -= 1.0 * sv_gravity.value * host_frametime; - SV_CheckVelocity (ent); - //} - - //SV_CheckStuck_IgnoreMonsters(ent); - //PushAwayZombies causes too high of a drop in framerate - //SV_PushAwayZombies(ent); - SV_MonsterWalkMove(ent); - - - //checking for ground beneath us - trace_t downtrace; - vec3_t groundlocation; - VectorCopy(ent->v.origin,groundlocation); - groundlocation[2] = -STEPSIZE + ent->v.velocity[2]*host_frametime; - - downtrace = SV_Move(ent->v.origin,ent->v.mins,ent->v.maxs,groundlocation, MOVE_NOMONSTERS,ent); - - if(!downtrace.allsolid && !downtrace.startsolid) - { - VectorCopy (downtrace.endpos, ent->v.origin); - - ent->v.flags = (int) ent->v.flags & ~FL_ONGROUND; - if (downtrace.plane.normal[2] > 0.7) - { - if(downtrace.ent) - { - if (downtrace.ent->v.solid == SOLID_BSP) - { - ent->v.flags = (int) ent->v.flags | FL_ONGROUND; - ent->v.groundentity = EDICT_TO_PROG(downtrace.ent); - ent->v.velocity[2] = 0; - } - } - } - } - - //restoring the bounding boxes - VectorCopy(old_mins,ent->v.mins); - VectorCopy(old_maxs,ent->v.maxs); - - SV_LinkEdict(ent,true); -} - - -/* -================ -SV_Physics_Client - -Player character actions -================ -*/ -void SV_Physics_Client (edict_t *ent, int num) -{ - if ( ! svs.clients[num-1].active ) - return; // unconnected slot - -// -// call standard client pre-think -// - pr_global_struct->time = sv.time; - pr_global_struct->self = EDICT_TO_PROG(ent); - PR_ExecuteProgram (pr_global_struct->PlayerPreThink); - -// -// do a move -// - SV_CheckVelocity (ent); - -// -// decide which move function to call -// - switch ((int)ent->v.movetype) - { - case MOVETYPE_NONE: - if (!SV_RunThink (ent)) - return; - break; - - case MOVETYPE_WALK: - if (!SV_RunThink (ent)) - return; - if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) ) - SV_AddGravity (ent); - SV_CheckStuck (ent); - SV_WalkMove (ent); - break; - - case MOVETYPE_TOSS: - case MOVETYPE_BOUNCE: - SV_Physics_Toss (ent); - break; - - case MOVETYPE_FLY: - if (!SV_RunThink (ent)) - return; - SV_FlyMove (ent, host_frametime, NULL); - break; - - case MOVETYPE_NOCLIP: - if (!SV_RunThink (ent)) - return; - VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin); - break; - - default: - Sys_Error ("SV_Physics_client: bad movetype %i", (int)ent->v.movetype); - } - -// -// call standard player post-think -// - SV_LinkEdict (ent, true); - - pr_global_struct->time = sv.time; - pr_global_struct->self = EDICT_TO_PROG(ent); - PR_ExecuteProgram (pr_global_struct->PlayerPostThink); -} - -//============================================================================ - -/* -============= -SV_Physics_None - -Non moving objects can only think -============= -*/ -void SV_Physics_None (edict_t *ent) -{ -// regular thinking - SV_RunThink (ent); -} - -/* -============= -SV_Physics_Noclip - -A moving object that doesn't obey physics -============= -*/ -void SV_Physics_Noclip (edict_t *ent) -{ -// regular thinking - if (!SV_RunThink (ent)) - return; - - VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles); - VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin); - - SV_LinkEdict (ent, false); -} - -/* -============================================================================== - -TOSS / BOUNCE - -============================================================================== -*/ - -/* -============= -SV_CheckWaterTransition - -============= -*/ -void SV_CheckWaterTransition (edict_t *ent) -{ - int cont; - - cont = SV_PointContents (ent->v.origin); - - if (!ent->v.watertype) - { // just spawned here - ent->v.watertype = cont; - ent->v.waterlevel = 1; - return; - } - - if (cont <= CONTENTS_WATER) - { - if (ent->v.watertype == CONTENTS_EMPTY) - { // just crossed into water - //SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1); - } - ent->v.watertype = cont; - ent->v.waterlevel = 1; - } - else - { - if (ent->v.watertype != CONTENTS_EMPTY) - { // just crossed into water - //SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1); - } - ent->v.watertype = CONTENTS_EMPTY; - ent->v.waterlevel = cont; - } -} - -/* -============= -SV_Physics_Toss - -Toss, bounce, and fly movement. When onground, do nothing. -============= -*/ -void SV_Physics_Toss (edict_t *ent) -{ - trace_t trace; - vec3_t move; - float backoff; - - // regular thinking - if (!SV_RunThink (ent)) - return; - -// if onground, return without moving - if ( ((int)ent->v.flags & FL_ONGROUND) ) - return; - - SV_CheckVelocity (ent); - -// add gravity - if (ent->v.movetype != MOVETYPE_FLY - && ent->v.movetype != MOVETYPE_FLYMISSILE) - SV_AddGravity (ent); - -// move angles - VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles); - -// move origin - VectorScale (ent->v.velocity, host_frametime, move); - trace = SV_PushEntity (ent, move, vec3_origin); - if (trace.fraction == 1) - return; - if (ent->free) - return; - - if (ent->v.movetype == MOVETYPE_BOUNCE) - backoff = 1.5; - else - backoff = 1; - - ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff); - -// stop if on ground - if (trace.plane.normal[2] > 0.7) - { - if (ent->v.velocity[2] < 60 || ent->v.movetype != MOVETYPE_BOUNCE) - { - ent->v.flags = (int)ent->v.flags | FL_ONGROUND; - ent->v.groundentity = EDICT_TO_PROG(trace.ent); - VectorCopy (vec3_origin, ent->v.velocity); - VectorCopy (vec3_origin, ent->v.avelocity); - } - } - -// check for in water - SV_CheckWaterTransition (ent); -} - -/* -=============================================================================== - -STEPPING MOVEMENT - -=============================================================================== -*/ - -/* -============= -SV_Physics_Step - -Monsters freefall when they don't have a ground entity, otherwise -all movement is done with discrete steps. - -This is also used for objects that have become still on the ground, but -will fall if the floor is pulled out from under them. -============= -*/ -void SV_Physics_Step (edict_t *ent) -{ - qboolean hitsound; - -// freefall if not onground - if ( ! ((int)ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM) ) ) - { - if (ent->v.velocity[2] < sv_gravity.value*-0.1) - hitsound = true; - else - hitsound = false; - - SV_AddGravity (ent); - SV_CheckVelocity (ent); - SV_FlyMove (ent, host_frametime, NULL); - SV_LinkEdict (ent, true); - - if ( (int)ent->v.flags & FL_ONGROUND ) // just hit ground - { - //if (hitsound) - // SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1); - } - } - -// regular thinking - SV_RunThink (ent); - - SV_CheckWaterTransition (ent); -} - - -//============================================================================ - -/* -================ -SV_Physics - -================ -*/ -void SV_Physics (void) -{ - int i; - int entity_cap; // For sv_freezenonclients - edict_t *ent; - -// let the progs know that a new frame has started - pr_global_struct->self = EDICT_TO_PROG(sv.edicts); - pr_global_struct->other = EDICT_TO_PROG(sv.edicts); - pr_global_struct->time = sv.time; - PR_ExecuteProgram (pr_global_struct->StartFrame); - -//SV_CheckAllEnts (); - -// -// treat each object in turn -// - ent = sv.edicts; - -/* if (sv_freezenonclients.value) - entity_cap = svs.maxclients + 1; // Only run physics on clients and the world - else - entity_cap = sv.num_edicts; -*/ - for (i=0 ; ifree) - continue; - - if (pr_global_struct->force_retouch) - { - SV_LinkEdict (ent, true); // force retouch even for stationary - } - - if (i > 0 && i <= svs.maxclients) - SV_Physics_Client (ent, i); - else if (ent->v.movetype == MOVETYPE_PUSH) - SV_Physics_Pusher (ent); - else if (ent->v.movetype == MOVETYPE_NONE) - SV_Physics_None (ent); - else if (ent->v.movetype == MOVETYPE_NOCLIP) - SV_Physics_Noclip (ent); - else if (ent->v.movetype == MOVETYPE_STEP) - SV_Physics_Step (ent); - else if(ent->v.movetype == MOVETYPE_WALK) - SV_Physics_Walk(ent); - else if (ent->v.movetype == MOVETYPE_TOSS - || ent->v.movetype == MOVETYPE_BOUNCE - || ent->v.movetype == MOVETYPE_FLY - || ent->v.movetype == MOVETYPE_FLYMISSILE) - SV_Physics_Toss (ent); - else - Sys_Error ("SV_Physics: bad movetype %i", (int)ent->v.movetype); - } - - if (EndFrame) - { - // let the progs know that the frame has ended - pr_global_struct->self = EDICT_TO_PROG(sv.edicts); - pr_global_struct->other = EDICT_TO_PROG(sv.edicts); - pr_global_struct->time = sv.time; - PR_ExecuteProgram (EndFrame); - - } - - if (pr_global_struct->force_retouch) - pr_global_struct->force_retouch--; - - if (!sv_freezenonclients.value) - sv.time += host_frametime; -}