Add basic builtins

This commit is contained in:
Ryan Baldwin 2022-06-19 12:20:34 -07:00
parent eec97d147c
commit 063d9d6ed6
11 changed files with 640 additions and 175 deletions

Binary file not shown.

Binary file not shown.

View File

@ -35,36 +35,45 @@ char *svc_strings[] =
"svc_stufftext", // [string] stuffed into client's console buffer
// the string should be \n terminated
"svc_setangle", // [vec3] set the view angle to this absolute value
"svc_serverinfo", // [long] version
// [string] signon string
// [string]..[0]model cache [string]...[0]sounds cache
// [string]..[0]item cache
"svc_lightstyle", // [byte] [string]
"svc_updatename", // [byte] [string]
"svc_updatefrags", // [byte] [short]
"svc_updatepoints", // [byte] [short]
"svc_clientdata", // <shortbits + data>
"svc_stopsound", // <see code>
"svc_updatecolors", // [byte] [byte]
"", // [byte] [byte]
"svc_particle", // [vec3] <variable>
"svc_damage", // [byte] impact [byte] blood [vec3] from
"svc_spawnstatic",
"OBSOLETE svc_spawnbinary",
"svc_spawnbaseline",
"svc_temp_entity", // <variable>
"svc_setpause",
"svc_signonnum",
"svc_centerprint",
"svc_killedmonster",
"svc_foundsecret",
"svc_spawnstaticsound",
"svc_intermission",
"svc_finale", // [string] music [string] text
"svc_cdtrack", // [byte] track [byte] looptrack
"svc_sellscreen",
"svc_cutscene"
"svc_cutscene",
"svc_weaponfire",
"svc_hitmark",
"svc_skybox", // [string] skyname
"svc_useprint",
"svc_updatekills",
"svc_limbupdate",
"svc_fog", // 41 // [byte] start [byte] end [byte] red [byte] green [byte] blue [float] time
"svc_bspdecal", //42 // [string] name [byte] decal_size [coords] pos
"svc_achievement", //43
"svc_songegg", //44 [string] track name
"svc_maxammo" //45
};
//=============================================================================
@ -710,6 +719,31 @@ void CL_ParseStaticSound (void)
}
/*
===================
CL_ParseLimbUpdate
===================
*/
void CL_ParseLimbUpdate (void)
{
int limb = MSG_ReadByte();
int zombieent = MSG_ReadShort();
int limbent = MSG_ReadShort();
switch (limb)
{
case 0://head
cl_entities[zombieent].z_head = limbent;
break;
case 1://larm
cl_entities[zombieent].z_larm = limbent;
break;
case 2://rarm
cl_entities[zombieent].z_rarm = limbent;
break;
}
}
#define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
/*
@ -957,6 +991,10 @@ void CL_ParseServerMessage (void)
case svc_sellscreen:
Cmd_ExecuteString ("help", src_command);
break;
case svc_limbupdate:
CL_ParseLimbUpdate();
break;
}
}
}

View File

@ -395,10 +395,8 @@ void Mod_LoadTextures (lump_t *l)
}
else
{
Con_Printf("Loading texture %s\n", mt->name);
if (loadmodel->bspversion == HL_BSPVERSION)
{
Con_Printf("Loading as HLBSP\n");
if (1)//((data = WAD3_LoadTexture(mt)))
{
texture_mode = GL_LINEAR_MIPMAP_NEAREST;
@ -414,7 +412,6 @@ void Mod_LoadTextures (lump_t *l)
}
else
{
Con_Printf("Loading as QBSP\n");
texture_mode = GL_LINEAR_MIPMAP_NEAREST; //_LINEAR;
tx->gl_texturenum = GL_LoadTexture (mt->name, tx->width, tx->height, (byte *)(tx+1), true, false, 1);
texture_mode = GL_LINEAR;

View File

@ -315,6 +315,11 @@ void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
up[2] = cr*cp;
}
float VectorLength (vec3_t v)
{
return sqrtf(DotProduct(v, v));
}
int VectorCompare (vec3_t v1, vec3_t v2)
{
int i;
@ -382,6 +387,13 @@ vec_t Length(vec3_t v)
return length;
}
float VecLength2(vec3_t v1, vec3_t v2)
{
vec3_t k;
VectorSubtract(v1, v2, k);
return sqrt(k[0]*k[0] + k[1]*k[1] + k[2]*k[2]);
}
float VectorNormalize (vec3_t v)
{
float length, ilength;

View File

@ -53,6 +53,8 @@ void _VectorCopy (vec3_t in, vec3_t out);
int VectorCompare (vec3_t v1, vec3_t v2);
vec_t Length (vec3_t v);
void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross);
float VectorLength (vec3_t v);
float VecLength2(vec3_t v1, vec3_t v2);
float VectorNormalize (vec3_t v); // returns vector length
void VectorInverse (vec3_t v);
void VectorScale (vec3_t in, vec_t scale, vec3_t out);

View File

@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "quakedef.h"
#define PR_MAX_TEMPSTRING 2048 // 2001-10-25 Enhanced temp string handling by Maddes
#define RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e))
/*
@ -30,17 +31,32 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
===============================================================================
*/
char pr_varstring_temp[PR_MAX_TEMPSTRING]; // 2001-10-25 Enhanced temp string handling by Maddes
char *PF_VarString (int first)
{
int i;
static char out[256];
out[0] = 0;
for (i=first ; i<pr_argc ; i++)
// 2001-10-25 Enhanced temp string handling by Maddes start
int maxlen;
char *add;
pr_varstring_temp[0] = 0;
for (i=first ; i < pr_argc ; i++)
{
strcat (out, G_STRING((OFS_PARM0+i*3)));
maxlen = PR_MAX_TEMPSTRING - strlen(pr_varstring_temp) - 1; // -1 is EndOfString
add = G_STRING((OFS_PARM0+i*3));
if (maxlen > strlen(add))
{
strcat (pr_varstring_temp, add);
}
else
{
strncat (pr_varstring_temp, add, maxlen);
pr_varstring_temp[PR_MAX_TEMPSTRING-1] = 0;
break; // can stop here
}
}
return out;
return pr_varstring_temp;
// 2001-10-25 Enhanced temp string handling by Maddes end
}
@ -664,6 +680,174 @@ void PF_TraceToss (void)
}
#endif
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;
}
void PF_tracebox (void)
{
float *v1, *v2, *mins, *maxs;
trace_t trace;
int nomonsters;
edict_t *ent;
v1 = G_VECTOR(OFS_PARM0);
mins = G_VECTOR(OFS_PARM1);
maxs = G_VECTOR(OFS_PARM2);
v2 = G_VECTOR(OFS_PARM3);
nomonsters = G_FLOAT(OFS_PARM4);
ent = G_EDICT(OFS_PARM5);
trace = SV_Move (v1, mins, maxs, 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);
}
/*
=================
@ -947,13 +1131,11 @@ void PF_vtos (void)
G_INT(OFS_RETURN) = pr_string_temp - pr_strings;
}
#ifdef QUAKE2
void PF_etos (void)
{
sprintf (pr_string_temp, "entity %i", G_EDICTNUM(OFS_PARM0));
G_INT(OFS_RETURN) = pr_string_temp - pr_strings;
}
#endif
void PF_Spawn (void)
{
@ -970,6 +1152,220 @@ void PF_Remove (void)
ED_Free (ed);
}
// 2001-09-20 QuakeC string manipulation by FrikaC/Maddes start
/*
=================
PF_strzone
string strzone (string)
=================
*/
void PF_strzone (void)
{
char *m, *p;
m = G_STRING(OFS_PARM0);
p = Z_Malloc(strlen(m) + 1);
strcpy(p, m);
G_INT(OFS_RETURN) = p - pr_strings;
}
/*
=================
PF_strunzone
string strunzone (string)
=================
*/
void PF_strunzone (void)
{
Z_Free(G_STRING(OFS_PARM0));
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;
c = m;
while (c != '\0' && *c == ' ')
c++;
m = c;
c = m + strlen (m) - 1;
while (c >= m)
{
if (*c == ' ')
*c = '\0';
else
break;
c--;
}
G_INT(OFS_RETURN) = m - pr_strings;
};
/*
=================
PF_strlen
float strlen (string)
=================
*/
void PF_strlen (void)
{
char *p = G_STRING(OFS_PARM0);
G_FLOAT(OFS_RETURN) = strlen(p);
}
/*
=================
PF_strcat
string strcat (string, string)
=================
*/
void PF_strcat (void)
{
char *s1, *s2;
int maxlen; // 2001-10-25 Enhanced temp string handling by Maddes
s1 = G_STRING(OFS_PARM0);
s2 = PF_VarString(1);
// 2001-10-25 Enhanced temp string handling by Maddes start
pr_string_temp[0] = 0;
if (strlen(s1) < PR_MAX_TEMPSTRING)
{
strcpy(pr_string_temp, s1);
}
else
{
strncpy(pr_string_temp, s1, PR_MAX_TEMPSTRING);
pr_string_temp[PR_MAX_TEMPSTRING-1] = 0;
}
maxlen = PR_MAX_TEMPSTRING - strlen(pr_string_temp) - 1; // -1 is EndOfString
if (maxlen > 0)
{
if (maxlen > strlen(s2))
{
strcat (pr_string_temp, s2);
}
else
{
strncat (pr_string_temp, s2, maxlen);
pr_string_temp[PR_MAX_TEMPSTRING-1] = 0;
}
}
// 2001-10-25 Enhanced temp string handling by Maddes end
G_INT(OFS_RETURN) = pr_string_temp - pr_strings;
}
/*
=================
PF_substring
string substring (string, float, float)
=================
*/
void PF_substring (void)
{
int offset, length;
int maxoffset; // 2001-10-25 Enhanced temp string handling by Maddes
char *p;
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;
// 2001-10-25 Enhanced temp string handling by Maddes start
if (length >= PR_MAX_TEMPSTRING)
length = PR_MAX_TEMPSTRING-1;
// 2001-10-25 Enhanced temp string handling by Maddes end
if (length < 0)
length = 0;
p += offset;
strncpy(pr_string_temp, p, length);
pr_string_temp[length]=0;
G_INT(OFS_RETURN) = pr_string_temp - pr_strings;
}
/*
=================
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_Set_Zombie
void Set_Zombie (entity)
=================
*/
void PF_Set_Zombie (void)
{
//int entitynum = G_EDICT(OFS_PARM0);
}
// entity (entity start, .string field, string match) find = #5;
void PF_Find (void)
@ -1053,6 +1449,38 @@ void PF_Find (void)
}
#endif
// 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);
}
void PR_CheckEmptyString (char *s)
{
if (s[0] <= ' ')
@ -1446,6 +1874,50 @@ void PF_changeyaw (void)
ent->v.angles[1] = anglemod (current + move);
}
/*
==============
PF_GetSoundLen
Get the lenght of the sound (useful for things like radio)
==============
*/
void PF_GetSoundLen (void)
{
char *name;
name = G_STRING(OFS_PARM0);
char namebuffer[256];
byte *data;
wavinfo_t info;
byte stackbuf[1*1024]; // avoid dirtying the cache heap
//Con_Printf ("S_LoadSound: %x\n", (int)stackbuf);
// load it in
Q_strcpy(namebuffer, "");
Q_strcat(namebuffer, name);
data = COM_LoadStackFile(namebuffer, stackbuf, sizeof(stackbuf));
if (!data)
{
Con_Printf ("Couldn't load %s\n", namebuffer);
G_FLOAT(OFS_RETURN) = -1;
return;
}
info = GetWavinfo (name, data, com_filesize);
if (info.channels != 1)
{
Con_Printf ("%s is a stereo sample\n",name);
G_FLOAT(OFS_RETURN) = -1;
return;
}
G_FLOAT(OFS_RETURN) = (float)info.samples/(float)info.rate;
}
#ifdef QUAKE2
/*
==============
@ -1665,144 +2137,6 @@ void PF_changelevel (void)
}
#ifdef QUAKE2
#define CONTENT_WATER -3
#define CONTENT_SLIME -4
#define CONTENT_LAVA -5
#define FL_IMMUNE_WATER 131072
#define FL_IMMUNE_SLIME 262144
#define FL_IMMUNE_LAVA 524288
#define CHAN_VOICE 2
#define CHAN_BODY 4
#define ATTN_NORM 1
void PF_WaterMove (void)
{
edict_t *self;
int flags;
int waterlevel;
int watertype;
float drownlevel;
float damage = 0.0;
self = PROG_TO_EDICT(pr_global_struct->self);
if (self->v.movetype == MOVETYPE_NOCLIP)
{
self->v.air_finished = sv.time + 12;
G_FLOAT(OFS_RETURN) = damage;
return;
}
if (self->v.health < 0)
{
G_FLOAT(OFS_RETURN) = damage;
return;
}
if (self->v.deadflag == DEAD_NO)
drownlevel = 3;
else
drownlevel = 1;
flags = (int)self->v.flags;
waterlevel = (int)self->v.waterlevel;
watertype = (int)self->v.watertype;
if (!(flags & (FL_IMMUNE_WATER + FL_GODMODE)))
if (((flags & FL_SWIM) && (waterlevel < drownlevel)) || (waterlevel >= drownlevel))
{
if (self->v.air_finished < sv.time)
if (self->v.pain_finished < sv.time)
{
self->v.dmg = self->v.dmg + 2;
if (self->v.dmg > 15)
self->v.dmg = 10;
// T_Damage (self, world, world, self.dmg, 0, FALSE);
damage = self->v.dmg;
self->v.pain_finished = sv.time + 1.0;
}
}
else
{
if (self->v.air_finished < sv.time)
// sound (self, CHAN_VOICE, "player/gasp2.wav", 1, ATTN_NORM);
SV_StartSound (self, CHAN_VOICE, "player/gasp2.wav", 255, ATTN_NORM);
else if (self->v.air_finished < sv.time + 9)
// sound (self, CHAN_VOICE, "player/gasp1.wav", 1, ATTN_NORM);
SV_StartSound (self, CHAN_VOICE, "player/gasp1.wav", 255, ATTN_NORM);
self->v.air_finished = sv.time + 12.0;
self->v.dmg = 2;
}
if (!waterlevel)
{
if (flags & FL_INWATER)
{
// play leave water sound
// sound (self, CHAN_BODY, "misc/outwater.wav", 1, ATTN_NORM);
SV_StartSound (self, CHAN_BODY, "misc/outwater.wav", 255, ATTN_NORM);
self->v.flags = (float)(flags &~FL_INWATER);
}
self->v.air_finished = sv.time + 12.0;
G_FLOAT(OFS_RETURN) = damage;
return;
}
if (watertype == CONTENT_LAVA)
{ // do damage
if (!(flags & (FL_IMMUNE_LAVA + FL_GODMODE)))
if (self->v.dmgtime < sv.time)
{
if (self->v.radsuit_finished < sv.time)
self->v.dmgtime = sv.time + 0.2;
else
self->v.dmgtime = sv.time + 1.0;
// T_Damage (self, world, world, 10*self.waterlevel, 0, TRUE);
damage = (float)(10*waterlevel);
}
}
else if (watertype == CONTENT_SLIME)
{ // do damage
if (!(flags & (FL_IMMUNE_SLIME + FL_GODMODE)))
if (self->v.dmgtime < sv.time && self->v.radsuit_finished < sv.time)
{
self->v.dmgtime = sv.time + 1.0;
// T_Damage (self, world, world, 4*self.waterlevel, 0, TRUE);
damage = (float)(4*waterlevel);
}
}
if ( !(flags & FL_INWATER) )
{
// player enter water sound
if (watertype == CONTENT_LAVA)
// sound (self, CHAN_BODY, "player/inlava.wav", 1, ATTN_NORM);
SV_StartSound (self, CHAN_BODY, "player/inlava.wav", 255, ATTN_NORM);
if (watertype == CONTENT_WATER)
// sound (self, CHAN_BODY, "player/inh2o.wav", 1, ATTN_NORM);
SV_StartSound (self, CHAN_BODY, "player/inh2o.wav", 255, ATTN_NORM);
if (watertype == CONTENT_SLIME)
// sound (self, CHAN_BODY, "player/slimbrn2.wav", 1, ATTN_NORM);
SV_StartSound (self, CHAN_BODY, "player/slimbrn2.wav", 255, ATTN_NORM);
self->v.flags = (float)(flags | FL_INWATER);
self->v.dmgtime = 0;
}
if (! (flags & FL_WATERJUMP) )
{
// self.velocity = self.velocity - 0.8*self.waterlevel*frametime*self.velocity;
VectorMA (self->v.velocity, -0.8 * self->v.waterlevel * host_frametime, self->v.velocity, self->v.velocity);
}
G_FLOAT(OFS_RETURN) = damage;
}
void PF_sin (void)
@ -1819,13 +2153,34 @@ void PF_sqrt (void)
{
G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
}
#endif
void PF_Fixme (void)
{
PR_RunError ("unimplemented bulitin");
}
/*
=================
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);
}
builtin_t pr_builtin[] =
@ -1863,7 +2218,7 @@ PF_traceon,
PF_traceoff,
PF_eprint, // void(entity e) debug print an entire entity
PF_walkmove, // float(float yaw, float dist) walkmove
PF_Fixme, // float(float yaw, float dist) walkmove
PF_updateLimb, // #33
PF_droptofloor,
PF_lightstyle,
PF_rint,
@ -1880,7 +2235,7 @@ PF_localcmd,
PF_nextent,
PF_particle,
PF_changeyaw,
PF_Fixme,
PF_GetSoundLen,
PF_vectoangles,
PF_WriteByte,
@ -1892,30 +2247,20 @@ PF_WriteAngle,
PF_WriteString,
PF_WriteEntity,
#ifdef QUAKE2
PF_sin,
PF_cos,
PF_sqrt,
PF_changepitch,
PF_TraceToss,
PF_Fixme,//PF_changepitch,
PF_Fixme,//PF_TraceToss,
PF_etos,
PF_WaterMove,
#else
PF_Fixme,
PF_Fixme,
PF_Fixme,
PF_Fixme,
PF_Fixme,
PF_Fixme,
PF_Fixme,
#endif
PF_Fixme,//PF_WaterMove,
SV_MoveToGoal,
PF_precache_file,
PF_makestatic,
PF_changelevel,
PF_Fixme,
SV_MoveToOrigin, // #71
PF_cvar_set,
PF_centerprint,
@ -1926,7 +2271,31 @@ PF_precache_model,
PF_precache_sound, // precache_sound2 is different only for qcc
PF_precache_file,
PF_setspawnparms
PF_setspawnparms,
PF_Fixme, // #79
PF_Fixme, // #80
PF_stof, // #81
PF_Fixme, // #82
PF_Fixme, // #83
PF_Fixme, // #84
PF_Fixme, // #86
PF_Fixme, // #87
PF_Fixme, // #88
PF_Fixme, // #89
PF_tracebox, // #90
PF_Fixme, // #91
PF_Fixme, // #92
PF_Fixme, // #93
PF_Fixme, // #94
PF_Fixme, // #95
PF_Fixme, // #96
PF_Fixme, // #97
PF_FindFloat, // #98
PF_tracemove, // #99
PF_Fixme, // #100
PF_Fixme, // #101
PF_Fixme, // #102
PF_Fixme, // #103
};
builtin_t *pr_builtins = pr_builtin;

View File

@ -129,6 +129,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define svc_sellscreen 33
#define svc_cutscene 34
#define svc_weaponfire 35
#define svc_hitmark 36
#define svc_skybox 37 // [string] skyname
#define svc_useprint 38 // [string] to put in center of the screen
#define svc_updatekills 39 // [string] to put in center of the screen
#define svc_limbupdate 40
#define svc_fog 41 // [byte] start [byte] end [byte] red [byte] green [byte] blue [float] time
#define svc_bspdecal 42 // [string] name [byte] decal_size [coords] pos
#define svc_achievement 43 // [string] name [byte] decal_size [coords] pos
#define svc_songegg 44 // [string] track name
#define svc_maxammo 45
//
// client to server

View File

@ -67,6 +67,11 @@ typedef struct entity_s
struct mnode_s *topnode; // for bmodels, first world node
// that splits bmodel, or NULL if
// not split
int z_head;
int z_larm;
int z_rarm;
} entity_t;
// !!! if this is changed, it must be changed in asm_draw.h too !!!

View File

@ -246,6 +246,7 @@ qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink);
void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg);
void SV_MoveToGoal (void);
void SV_MoveToOrigin (void);
void SV_CheckForNewClients (void);
void SV_RunClients (void);

View File

@ -425,3 +425,33 @@ void SV_MoveToGoal (void)
}
}
/*
======================
SV_MoveToOrigin
======================
*/
void SV_MoveToOrigin (void)
{
edict_t *ent, *goal;
float dist;
ent = PROG_TO_EDICT(pr_global_struct->self);
goal = PROG_TO_EDICT(ent->v.goalentity);
dist = G_FLOAT(OFS_PARM0);
if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
{
G_FLOAT(OFS_RETURN) = 0;
return;
}
// if the next step hits the enemy, return immediately
if ( PROG_TO_EDICT(ent->v.enemy) != sv.edicts && SV_CloseEnough (ent, goal, dist) )
return;
// bump around...
if ((rand()&3)==1 || !SV_StepDirection (ent, ent->v.ideal_yaw, dist))
SV_NewChaseDir (ent, goal, dist);
}