From ae2afd01afe8d6b96db3062b512bd10243cf0856 Mon Sep 17 00:00:00 2001 From: g-cont Date: Sat, 29 Sep 2007 00:00:00 +0400 Subject: [PATCH] 29 Sep 2007 --- changelog.log | 4 + common/bsplib/bsplib.h | 1 - common/common/mdllib.h | 1 - common/common/spritegen.c | 1 - common/common/studio_utils.c | 2 - debug.bat | 2 +- engine/client/cl_newfx.c | 1 - engine/common.h | 6 +- engine/common/net_msg.c | 25 +- engine/engine.dsp | 4 - engine/engine.h | 3 - engine/server/server.h | 2 +- engine/server/sv_edict.h | 1 + engine/server/sv_ents.c | 2 +- engine/server/sv_game.c | 80 +- engine/server/sv_init.c | 6 +- engine/server/sv_phys.c | 2638 -------------------------- engine/server/sv_physics.c | 1244 +++++++++++- engine/server/sv_send.c | 4 +- engine/server/sv_spawn.c | 2 +- engine/server/tstent.c | 16 - engine/vid_dll.c | 2 +- public/activity.h | 135 -- public/activitymap.h | 127 -- public/basemath.h | 2 +- public/basetypes.h | 6 +- public/bspmodel.h | 228 --- public/{studio.h => ref_format.h} | 295 ++- public/ref_system.h | 226 ++- public/sprite.h | 59 - release.bat | 4 +- render/gl_local.h | 3 - render/glw_imp.c | 10 +- vprogs/PROGS.SRC | 1 + vprogs/client.c | 3 +- vprogs/defs.c | 1 + vprogs/ents/funcs/func_areaportal.c | 20 + vprogs/ents/funcs/func_mover.c | 12 +- vprogs/ents/funcs/func_path_corner.c | 4 +- vprogs/ents/funcs/funcs.c | 6 +- 40 files changed, 1863 insertions(+), 3326 deletions(-) delete mode 100644 engine/server/sv_phys.c delete mode 100644 engine/server/tstent.c delete mode 100644 public/activity.h delete mode 100644 public/activitymap.h delete mode 100644 public/bspmodel.h rename public/{studio.h => ref_format.h} (52%) delete mode 100644 public/sprite.h create mode 100644 vprogs/ents/funcs/func_areaportal.c diff --git a/changelog.log b/changelog.log index 9a6778b3..16f2648e 100644 --- a/changelog.log +++ b/changelog.log @@ -9,6 +9,8 @@ SV_ClipToLinks SV_ClipMoveToEntities Глобальные задачи: 1. Полная отладка PRVM 2. Пофиксить зависание bsplib при работе +3. Отладка и имплементация физики (physic.dll) + Текущие задачи: 1. Перенести основные части gamed.dll в движок OK @@ -41,6 +43,8 @@ SV_ClipToLinks SV_ClipMoveToEntities //================================================== // то, что уже готово //================================================== ++Добавлены func_areaportal ++исправлен overflow при компиляции в release +подключена система использования gl_ext при загрузке DDS Текстур по двум критериям(наличие расширения и наличие Pow2) -убран последний DDS FPU формат +исправлен баг с загрузкой BGRA_32 текстур diff --git a/common/bsplib/bsplib.h b/common/bsplib/bsplib.h index 360fa2fc..c14cdbc7 100644 --- a/common/bsplib/bsplib.h +++ b/common/bsplib/bsplib.h @@ -7,7 +7,6 @@ #include "platform.h" #include -#include #include #include "utils.h" diff --git a/common/common/mdllib.h b/common/common/mdllib.h index 721fd35d..afc7eb3d 100644 --- a/common/common/mdllib.h +++ b/common/common/mdllib.h @@ -8,7 +8,6 @@ #include "platform.h" #include #include "utils.h" -#include "studio.h" #define FILEBUFFER (2 * 1024 * 1024) #define MAXTRIANGLES 2048 //TODO: tune this diff --git a/common/common/spritegen.c b/common/common/spritegen.c index 102392a8..a438bd25 100644 --- a/common/common/spritegen.c +++ b/common/common/spritegen.c @@ -6,7 +6,6 @@ #include "platform.h" #include #include "utils.h" -#include #define MAX_BUFFER_SIZE ((sizeof(frames) * MAX_FRAMES) + (MAX_FRAME_DIM * 2 * MAX_FRAMES)) #define MAX_FRAMES 1024 diff --git a/common/common/studio_utils.c b/common/common/studio_utils.c index 23aa02e8..f9d70d56 100644 --- a/common/common/studio_utils.c +++ b/common/common/studio_utils.c @@ -4,8 +4,6 @@ //======================================================================= #include "mdllib.h" -#include "activity.h" -#include "activitymap.h" int used[MAXSTUDIOTRIANGLES]; // the command list holds counts and s/t values short commands[MAXSTUDIOTRIANGLES * 13]; //that are valid for every frame diff --git a/debug.bat b/debug.bat index ea768d5a..a6a1b401 100644 --- a/debug.bat +++ b/debug.bat @@ -55,5 +55,5 @@ if exist server.dat move server.dat D:\Xash3D\xash\server.dat echo Build succeeded! echo Please wait. Xash is now loading cd D:\Xash3D\ -xash.exe +map skytest -log -debug -dev 4 +xash.exe +map qctest -log -debug :done \ No newline at end of file diff --git a/engine/client/cl_newfx.c b/engine/client/cl_newfx.c index b3572dd4..04d1a892 100644 --- a/engine/client/cl_newfx.c +++ b/engine/client/cl_newfx.c @@ -20,7 +20,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // cl_newfx.c -- MORE entity effects parsing and management #include "client.h" -#include "studio.h" extern cparticle_t *active_particles, *free_particles; extern cparticle_t particles[MAX_PARTICLES]; diff --git a/engine/common.h b/engine/common.h index 4f4e8f1e..205411f1 100644 --- a/engine/common.h +++ b/engine/common.h @@ -56,10 +56,12 @@ typedef struct sizebuf_s int errorcount; // cause by errors } sizebuf_t; +#define SZ_GetSpace(buf, len) _SZ_GetSpace(buf, len, __FILE__, __LINE__ ) +#define SZ_Write(buf, data, len) _SZ_Write(buf, data, len, __FILE__, __LINE__ ) void SZ_Init (sizebuf_t *buf, byte *data, int length); void SZ_Clear (sizebuf_t *buf); -void *SZ_GetSpace (sizebuf_t *buf, int length); -void SZ_Write (sizebuf_t *buf, void *data, int length); +void *_SZ_GetSpace (sizebuf_t *buf, int length, const char *filename, int fileline); +void _SZ_Write (sizebuf_t *buf, void *data, int length, const char *filename, int fileline); void SZ_Print (sizebuf_t *buf, char *data); // strcats onto the sizebuf //============================================================================ diff --git a/engine/common/net_msg.c b/engine/common/net_msg.c index 3de83254..141590e8 100644 --- a/engine/common/net_msg.c +++ b/engine/common/net_msg.c @@ -25,7 +25,7 @@ void _MSG_WriteChar (sizebuf_t *sb, int c, const char *filename, int fileline) if (c < -128 || c > 127) Msg("MSG_WriteChar: range error %d (called at %s:%i)\n", c, filename, fileline); - buf = SZ_GetSpace (sb, 1); + buf = _SZ_GetSpace (sb, 1, filename, fileline ); buf[0] = c; } @@ -36,7 +36,7 @@ void _MSG_WriteByte (sizebuf_t *sb, int c, const char *filename, int fileline) if (c < 0 || c > 255) Msg("MSG_WriteByte: range error %d (called at %s:%i)\n", c, filename, fileline); - buf = SZ_GetSpace (sb, 1); + buf = _SZ_GetSpace (sb, 1, filename, fileline); buf[0] = c; } @@ -47,7 +47,7 @@ void _MSG_WriteShort (sizebuf_t *sb, int c, const char *filename, int fileline) if (c < -32767 || c > 32767) Msg("MSG_WriteShort: range error %d (called at %s:%i)\n", c, filename, fileline); - buf = SZ_GetSpace (sb, 2); + buf = _SZ_GetSpace (sb, 2, filename, fileline); buf[0] = c&0xff; buf[1] = c>>8; } @@ -59,7 +59,7 @@ void _MSG_WriteWord (sizebuf_t *sb, int c, const char *filename, int fileline) if (c < 0 || c > 65535) Msg("MSG_WriteWord: range error %d (called at %s:%i)\n", c, filename, fileline); - buf = SZ_GetSpace (sb, 2); + buf = _SZ_GetSpace (sb, 2, filename, fileline); buf[0] = c&0xff; buf[1] = c>>8; } @@ -68,7 +68,7 @@ void _MSG_WriteLong (sizebuf_t *sb, int c, const char *filename, int fileline) { byte *buf; - buf = SZ_GetSpace (sb, 4); + buf = _SZ_GetSpace (sb, 4, filename, fileline); buf[0] = (c>>0 ) & 0xff; buf[1] = (c>>8 ) & 0xff; buf[2] = (c>>16) & 0xff; @@ -83,21 +83,20 @@ void _MSG_WriteFloat (sizebuf_t *sb, float f, const char *filename, int fileline int l; } dat; - dat.f = f; dat.l = LittleLong (dat.l); - SZ_Write (sb, &dat.l, 4); + _SZ_Write (sb, &dat.l, 4, filename, fileline); } void _MSG_WriteString (sizebuf_t *sb, char *s, const char *filename, int fileline) { if (!s || !*s) _MSG_WriteChar (sb, 0, filename, fileline ); - else SZ_Write (sb, s, strlen(s)+1); + else _SZ_Write (sb, s, strlen(s)+1, filename, fileline); } void _MSG_WriteUnterminatedString (sizebuf_t *sb, const char *s, const char *filename, int fileline) { - if (s && *s) SZ_Write (sb, (byte *)s, (int)strlen(s)); + if (s && *s) _SZ_Write (sb, (byte *)s, (int)strlen(s), filename, fileline); } void _MSG_WriteCoord (sizebuf_t *sb, float f, const char *filename, int fileline) @@ -508,7 +507,7 @@ void SZ_Clear (sizebuf_t *buf) buf->overflowed = false; } -void *SZ_GetSpace (sizebuf_t *buf, int length) +void *_SZ_GetSpace (sizebuf_t *buf, int length, const char *filename, int fileline ) { void *data; @@ -517,7 +516,7 @@ void *SZ_GetSpace (sizebuf_t *buf, int length) if (length > buf->maxsize) Host_Error("SZ_GetSpace: length[%i] > buffer maxsize [%i]\n", length, buf->maxsize ); - MsgWarn("SZ_GetSpace: overflow [cursize %d maxsize %d]\n", buf->cursize + length, buf->maxsize ); + MsgWarn("SZ_GetSpace: overflow [cursize %d maxsize %d], called at %s:%i\n", buf->cursize + length, buf->maxsize, filename, fileline ); SZ_Clear (buf); buf->overflowed = true; } @@ -527,9 +526,9 @@ void *SZ_GetSpace (sizebuf_t *buf, int length) return data; } -void SZ_Write (sizebuf_t *buf, void *data, int length) +void _SZ_Write (sizebuf_t *buf, void *data, int length, const char *filename, int fileline) { - Mem_Copy(SZ_GetSpace(buf, length), data, length); + Mem_Copy(_SZ_GetSpace(buf, length, filename, fileline), data, length); } void SZ_Print (sizebuf_t *buf, char *data) diff --git a/engine/engine.dsp b/engine/engine.dsp index c5f39698..09e0f8a4 100644 --- a/engine/engine.dsp +++ b/engine/engine.dsp @@ -262,10 +262,6 @@ SOURCE=.\server\sv_main.c # End Source File # Begin Source File -SOURCE=.\server\sv_phys.c -# End Source File -# Begin Source File - SOURCE=.\server\sv_physics.c # End Source File # Begin Source File diff --git a/engine/engine.h b/engine/engine.h index ed5ec14d..580e6264 100644 --- a/engine/engine.h +++ b/engine/engine.h @@ -19,9 +19,6 @@ //register new types #include "basetypes.h" #include "basemath.h" -#include "studio.h" -#include "sprite.h" -#include "bspmodel.h" #include #include "vprogs.h" #include "const.h" diff --git a/engine/server/server.h b/engine/server/server.h index 23dedaff..22f44458 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -242,7 +242,7 @@ void SV_PrepWorldFrame (void); void SV_Physics (edict_t *ent); void SV_DropToFloor (edict_t *ent); void SV_CheckGround (edict_t *ent); - +bool SV_MoveStep (edict_t *ent, vec3_t move, bool relink); // // sv_send.c // diff --git a/engine/server/sv_edict.h b/engine/server/sv_edict.h index 9ad6b3ba..0493ef53 100644 --- a/engine/server/sv_edict.h +++ b/engine/server/sv_edict.h @@ -23,6 +23,7 @@ #define AI_ACTOR (1<<10) // disable ai for actor #define AI_DRIVER (1<<11) // npc or player driving vehcicle or train #define AI_SPECTATOR (1<<12) // spectator mode for clients +#define AI_WATERJUMP (1<<13) // npc or player take out of water // edict->solid values typedef enum diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index 7533db73..d529d7d5 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -40,7 +40,7 @@ void SV_UpdateEntityState( edict_t *ent) VectorCopy (ent->progs.sv->old_origin, ent->priv.sv->s.old_origin); ent->priv.sv->s.modelindex = (int)ent->progs.sv->modelindex; - ent->priv.sv->s.weaponmodel = SV_ModelIndex(PRVM_GetString(ent->progs.sv->weaponmodel)); + ent->priv.sv->s.weaponmodel = 0; // attached weaponmodel ent->priv.sv->s.skin = (short)ent->progs.sv->skin; // studio model skin ent->priv.sv->s.body = (byte)ent->progs.sv->body; // studio model submodel diff --git a/engine/server/sv_game.c b/engine/server/sv_game.c index c6957dd5..102592a6 100644 --- a/engine/server/sv_game.c +++ b/engine/server/sv_game.c @@ -91,7 +91,7 @@ void SetMinMaxSize (edict_t *e, float *min, float *max, bool rotate) //test for stats void PF_SetStats( void ) { - edict_t *e; + edict_t *e; int stat_num; const char *string; short value; @@ -195,6 +195,15 @@ void PF_setmodel( void ) SV_SetModel( e, PRVM_G_STRING(OFS_PARM1) ); } +void PF_areaportalstate( void ) +{ + int portalnum = (int)PRVM_G_FLOAT(OFS_PARM0); + bool state = (bool)PRVM_G_FLOAT(OFS_PARM1); + + CM_SetAreaPortalState( portalnum, state ); + Msg("protal %d, state %s\n", portalnum, state ? "open" : "close" ); +} + /* ================= PF_sprint @@ -337,7 +346,7 @@ void PF_sound (void) if (volume < 0 || volume > 255) { - VM_Warning("SV_StartSound: volume must be in range 0-1\n"); + VM_Warning("SV_StartSound: volume must be in range 0 - 255\n"); return; } @@ -354,7 +363,7 @@ void PF_sound (void) } sound_idx = SV_SoundIndex( sample ); - SV_StartSound (NULL, entity, channel, sound_idx, volume, attenuation, 0 ); + SV_StartSound (NULL, entity, channel, sound_idx, volume / 255.0f, attenuation, 0 ); } /* @@ -682,47 +691,28 @@ void PF_findradius (void) { edict_t *ent, *chain; vec_t radius, radius2; - vec3_t org, eorg, mins, maxs; + vec3_t org, eorg; int i; - int numtouchedicts; - edict_t *touchedicts[MAX_EDICTS]; - chain = (edict_t *)prog->edicts; VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org); radius = PRVM_G_FLOAT(OFS_PARM1); radius2 = radius * radius; - mins[0] = org[0] - (radius + 1); - mins[1] = org[1] - (radius + 1); - mins[2] = org[2] - (radius + 1); - maxs[0] = org[0] + (radius + 1); - maxs[1] = org[1] + (radius + 1); - maxs[2] = org[2] + (radius + 1); - - numtouchedicts = 0;//SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts); - - if (numtouchedicts > MAX_EDICTS) + ent = prog->edicts; + for (i = 1; i < prog->num_edicts ; i++, ent = PRVM_NEXT_EDICT(ent)) { - // this never happens - MsgWarn("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS); - numtouchedicts = MAX_EDICTS; - } - for (i = 0; i < numtouchedicts; i++) - { - ent = touchedicts[i]; - prog->xfunction->builtinsprofile++; - - if (ent->progs.sv->solid == SOLID_NOT) continue; + if (ent->priv.sv->free) continue; + if (ent->progs.sv->solid == SOLID_NOT) continue; VectorSubtract(org, ent->progs.sv->origin, eorg); VectorMAMAM(1, eorg, 0.5f, ent->progs.sv->mins, 0.5f, ent->progs.sv->maxs, eorg); + if (DotProduct(eorg, eorg) < radius2) { ent->progs.sv->chain = PRVM_EDICT_TO_PROG(chain); chain = ent; } } - VM_RETURN_EDICT(chain); } @@ -756,6 +746,7 @@ void PF_walkmove (void) { edict_t *ent; float yaw, dist; + vec3_t move; mfunction_t *oldf; int oldpev; @@ -780,11 +771,17 @@ void PF_walkmove (void) if (!((int)ent->progs.sv->aiflags & (AI_ONGROUND|AI_FLY|AI_SWIM))) 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 = prog->xfunction; oldpev = prog->globals.server->pev; - PRVM_G_FLOAT(OFS_RETURN) = SV_WalkMove(ent, yaw, dist); + PRVM_G_FLOAT(OFS_RETURN) = SV_MoveStep(ent, move, true); // restore program state prog->xfunction = oldf; @@ -801,6 +798,8 @@ void() droptofloor void PF_droptofloor (void) { edict_t *ent; + vec3_t end; + trace_t trace; // assume failure if it returns early PRVM_G_FLOAT(OFS_RETURN) = 0; @@ -817,10 +816,25 @@ void PF_droptofloor (void) return; } - SV_DropToFloor( ent ); + VectorCopy (ent->progs.sv->origin, end); + end[2] -= 256; + trace = SV_Trace(ent->progs.sv->origin, ent->progs.sv->mins, ent->progs.sv->maxs, end, ent, MASK_SOLID ); - ent->progs.sv->aiflags = (int)ent->progs.sv->aiflags | AI_ONGROUND; - PRVM_G_FLOAT(OFS_RETURN) = 1; + if (trace.startsolid) + { + VM_Warning("droptofloor: %s startsolid at %g %g %g\n", PRVM_GetString(ent->progs.sv->classname), ent->progs.sv->origin[0], ent->progs.sv->origin[1], ent->progs.sv->origin[2]); + SV_FreeEdict (ent); + return; + } + + if (trace.fraction != 1) + { + VectorCopy (trace.endpos, ent->progs.sv->origin); + SV_LinkEdict (ent); + ent->progs.sv->aiflags = (int)ent->progs.sv->aiflags | AI_ONGROUND; + ent->progs.sv->groundentity = PRVM_EDICT_TO_PROG(trace.ent); + PRVM_G_FLOAT(OFS_RETURN) = 1; + } } /* @@ -1368,7 +1382,7 @@ VM_traceon, // #29 void() traceon VM_traceoff, // #30 void() traceoff VM_eprint, // #31 void(entity e) eprint PF_walkmove, // #32 float(float yaw, float dist) walkmove -NULL, // #33 +PF_areaportalstate, // #33 PF_droptofloor, // #34 float() droptofloor PF_lightstyle, // #35 void(float style, string value) lightstyle VM_rint, // #36 float(float v) rint diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index 687025cf..abdc075f 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -137,7 +137,7 @@ SV_FindIndex */ int SV_FindIndex (const char *name, int start, int end, bool create) { - int i; + int i = 0; if (!name || !name[0]) return 0; @@ -148,7 +148,7 @@ int SV_FindIndex (const char *name, int start, int end, bool create) if (i == end) { - MsgWarn ("SV_FindIndex: %d out range [%d - %d]\n", start, end ); + MsgWarn ("SV_FindIndex: %d out of range [%d - %d]\n", start, end ); return 0; } @@ -160,7 +160,7 @@ int SV_FindIndex (const char *name, int start, int end, bool create) // send the update to everyone SZ_Clear (&sv.multicast); MSG_Begin(svc_configstring); - MSG_WriteShort (&sv.multicast, start+i); + MSG_WriteShort (&sv.multicast, start + i); MSG_WriteString (&sv.multicast, (char *)name); MSG_Send(MSG_ALL_R, vec3_origin, NULL ); } diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c deleted file mode 100644 index b0683f88..00000000 --- a/engine/server/sv_phys.c +++ /dev/null @@ -1,2638 +0,0 @@ -#include "engine.h" -#include "server.h" - -#define STEPSIZE 18 -bool wasonground; -bool onconveyor; - -//damage types -#define DMG_CRUSH 20 -#define DMG_FALL 22 - -#define random() ((rand () & 0x7fff) / ((float)0x7fff)) -#define crandom() (2.0 * (random() - 0.5)) - -bool CanDamage (edict_t *targ, edict_t *inflictor) -{ - return false; -} - -void T_Damage (edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir, vec3_t point, vec3_t normal, int damage, int knockback, int dflags, int mod) -{ -} -void T_RadiusDamage (edict_t *inflictor, edict_t *attacker, float damage, edict_t *ignore, float radius, int mod, double dmg_slope) -{ -} - - -/* -============= -SV_CheckBottom - -Returns false if any part of the bottom of the entity is off an edge that -is not a staircase. - -============= -*/ -int c_yes, c_no; - -bool SV_CheckBottom (edict_t *ent) -{ - vec3_t mins, maxs, start, stop; - trace_t trace; - int x, y; - float mid, bottom; - - VectorAdd (ent->progs.sv->origin, ent->progs.sv->mins, mins); - VectorAdd (ent->progs.sv->origin, ent->progs.sv->maxs, maxs); - - // if all of the points under the corners are solid world, don't bother - // with the tougher checks - // the corners must be within 16 of the midpoint - start[2] = mins[2] - 1; - - for (x = 0; x <= 1; x++) - { - for (y = 0; y <= 1; y++) - { - start[0] = x ? maxs[0] : mins[0]; - start[1] = y ? maxs[1] : mins[1]; - if (SV_PointContents(start) != CONTENTS_SOLID) - goto realcheck; - } - } - - c_yes++; - return true; // we got out easy - -realcheck: - c_no++; - - // check it for real... - start[2] = mins[2]; - - // the midpoint must be within 16 of the bottom - start[0] = stop[0] = (mins[0] + maxs[0])*0.5; - start[1] = stop[1] = (mins[1] + maxs[1])*0.5; - stop[2] = start[2] - 2*STEPSIZE; - trace = SV_Trace (start, vec3_origin, vec3_origin, stop, ent, MASK_MONSTERSOLID); - - if (trace.fraction == 1.0) - return false; - mid = bottom = trace.endpos[2]; - - // the corners must be within 16 of the midpoint - for (x = 0; x <= 1; x++) - { - for ( y = 0; y <= 1; y++) - { - start[0] = stop[0] = x ? maxs[0] : mins[0]; - start[1] = stop[1] = y ? maxs[1] : mins[1]; - - trace = SV_Trace (start, vec3_origin, vec3_origin, stop, ent, MASK_MONSTERSOLID); - - if (trace.fraction != 1.0 && trace.endpos[2] > bottom) - bottom = trace.endpos[2]; - if (trace.fraction == 1.0 || mid - trace.endpos[2] > STEPSIZE) - return false; - } - } - - c_yes++; - return true; -} - -/* -================ -droptofloor -================ -*/ -void SV_DropToFloor (edict_t *ent) -{ - trace_t tr; - vec3_t v, dest; - - VectorClear(ent->progs.sv->origin_offset); - ent->progs.sv->solid = SOLID_BBOX; - ent->priv.sv->clipmask |= MASK_MONSTERSOLID; - if(!ent->progs.sv->health) ent->progs.sv->health = 20; - ent->progs.sv->takedamage = DAMAGE_YES; - - ent->progs.sv->movetype = MOVETYPE_TOSS; - - VectorSet(v, 0, 0, -128); - VectorAdd (ent->progs.sv->origin, v, dest); - - tr = SV_Trace (ent->progs.sv->origin, ent->progs.sv->mins, ent->progs.sv->maxs, dest, ent, MASK_SOLID); - if (tr.startsolid) - { - Msg("SV_DropToFloor: %s startsolid at %g %g %g\n", PRVM_GetString(ent->progs.sv->classname), ent->progs.sv->origin[0], ent->progs.sv->origin[1], ent->progs.sv->origin[2]); - SV_FreeEdict (ent); - return; - } - tr.endpos[2] += 1; - ent->progs.sv->mins[2] -= 1; - ent->progs.sv->groundentity = PRVM_EDICT_TO_PROG(tr.ent); - VectorCopy (tr.endpos, ent->progs.sv->origin); - - SV_LinkEdict (ent); -} - -void SV_CheckGround (edict_t *ent) -{ - vec3_t point; - trace_t trace; - - if ((int)ent->progs.sv->aiflags & (AI_SWIM|AI_FLY)) return; - if (ent->progs.sv->velocity[2] > 100) - { - ent->progs.sv->groundentity = 0; - return; - } - - // if the hull point one-quarter unit down is solid the entity is on ground - point[0] = ent->progs.sv->origin[0]; - point[1] = ent->progs.sv->origin[1]; - point[2] = ent->progs.sv->origin[2] - 0.25; - - trace = SV_Trace (ent->progs.sv->origin, ent->progs.sv->mins, ent->progs.sv->maxs, point, ent, MASK_MONSTERSOLID); - - // check steepness - if ( trace.plane.normal[2] < 0.7 && !trace.startsolid) - { - ent->progs.sv->groundentity = 0; - return; - } - - // Lazarus: The following 2 lines were in the original code and commented out - // by id. However, the effect of this is that a player walking over - // a dead monster who is laying on a brush model will cause the - // dead monster to drop through the brush model. This change *may* - // have other consequences, though, so watch out for this. - - ent->progs.sv->groundentity = PRVM_EDICT_TO_PROG(trace.ent); - if (!trace.startsolid && !trace.allsolid) - { - VectorCopy (trace.endpos, ent->progs.sv->origin); - ent->progs.sv->groundentity = PRVM_EDICT_TO_PROG(trace.ent); - ent->progs.sv->velocity[2] = trace.ent->progs.sv->velocity[2]; - } -} - -// -//================= -// other_FallingDamage -// Identical to player's P_FallingDamage... except of course ent doesn't have to be a player -//================= -// -void SV_FallingDamage (edict_t *ent) -{ - float delta; - float fall_time, fall_value; - int damage; - vec3_t dir; - - if (ent->progs.sv->movetype == MOVETYPE_NOCLIP) - return; - - if ((ent->progs.sv->post_velocity[2] < 0) && (ent->progs.sv->velocity[2] > ent->progs.sv->post_velocity[2]) && (!ent->progs.sv->groundentity)) - { - delta = ent->progs.sv->post_velocity[2]; - } - else - { - if (!ent->progs.sv->groundentity) - return; - delta = ent->progs.sv->velocity[2] - ent->progs.sv->post_velocity[2]; - } - delta = delta*delta * 0.0001; - - // never take falling damage if completely underwater - if (ent->progs.sv->waterlevel == 3) return; - if (ent->progs.sv->waterlevel == 2) delta *= 0.25; - if (ent->progs.sv->waterlevel == 1) delta *= 0.5; - - if (delta < 1) return; - - if (delta < 15) - { - ent->priv.sv->event = EV_FOOTSTEP; - return; - } - - fall_value = delta*0.5; - if (fall_value > 40) fall_value = 40; - fall_time = sv.time + 0.3f; //FALL_TIME - - if (delta > 30) - { - damage = (delta-30)/2; - if (damage < 1) damage = 1; - VectorSet (dir, 0, 0, 1); - - T_Damage (ent, prog->edicts, prog->edicts, dir, ent->progs.sv->origin, vec3_origin, damage, 0, 0, DMG_FALL); - } -} - -/* -============= -SV_MoveStep - -Called by monster program code. -The move will be adjusted for slopes and stairs, but if the move isn't -possible, no move is done, false is returned, and -pr_global_struct->trace_normal is set to the normal of the blocking wall -============= -*/ -//FIXME since we need to test end position contents here, can we avoid doing -//it again later in catagorize position? -bool SV_MoveStep (edict_t *ent, vec3_t move, bool relink) -{ - float dz; - vec3_t oldorg, neworg, end; - trace_t trace; - int i; - float stepsize; - float jumpheight; - vec3_t test; - int contents; - - bool canjump; - float d1, d2; - int jump; // 1=jump up, -1=jump down - vec3_t forward, up; - vec3_t dir; - vec_t dist; - edict_t *target; - - // try the move - VectorCopy (ent->progs.sv->origin, oldorg); - VectorAdd (ent->progs.sv->origin, move, neworg); - - AngleVectors(ent->progs.sv->angles,forward, NULL, up); - if(ent->progs.sv->enemy) - target = PRVM_PROG_TO_EDICT(ent->progs.sv->enemy); - else if(ent->progs.sv->movetarget) - target = PRVM_PROG_TO_EDICT(ent->progs.sv->movetarget); - else - target = NULL; - - // flying monsters don't step up - if ((int)ent->progs.sv->aiflags & (AI_SWIM | AI_FLY) ) - { - // try one move with vertical motion, then one without - for (i = 0; i < 2; i++) - { - VectorAdd (ent->progs.sv->origin, move, neworg); - if (i == 0 && ent->progs.sv->enemy) - { - if (!ent->progs.sv->goalentity) - ent->progs.sv->goalentity = ent->progs.sv->enemy; - dz = ent->progs.sv->origin[2] - PRVM_PROG_TO_EDICT(ent->progs.sv->goalentity)->progs.sv->origin[2]; - if (PRVM_PROG_TO_EDICT(ent->progs.sv->goalentity)->priv.sv->client) - { - if (dz > 40) neworg[2] -= 8; - if (!(((int)ent->progs.sv->aiflags & AI_SWIM) && (ent->progs.sv->waterlevel < 2))) - if (dz < 30) neworg[2] += 8; - } - else - { - if (dz > 8) neworg[2] -= 8; - else if (dz > 0) neworg[2] -= dz; - else if (dz < -8) neworg[2] += 8; - else neworg[2] += dz; - } - } - trace = SV_Trace (ent->progs.sv->origin, ent->progs.sv->mins, ent->progs.sv->maxs, neworg, ent, MASK_MONSTERSOLID); - - // fly monsters don't enter water voluntarily - if ((int)ent->progs.sv->aiflags & AI_FLY) - { - if (!ent->progs.sv->waterlevel) - { - test[0] = trace.endpos[0]; - test[1] = trace.endpos[1]; - test[2] = trace.endpos[2] + ent->progs.sv->mins[2] + 1; - contents = SV_PointContents(test); - if (contents & MASK_WATER) - return false; - } - } - - // swim monsters don't exit water voluntarily - if ((int)ent->progs.sv->aiflags & AI_SWIM) - { - if (ent->progs.sv->waterlevel < 2) - { - test[0] = trace.endpos[0]; - test[1] = trace.endpos[1]; - test[2] = trace.endpos[2] + ent->progs.sv->mins[2] + 1; - contents = SV_PointContents(test); - if (!(contents & MASK_WATER)) - return false; - } - } - - if (trace.fraction == 1) - { - VectorCopy (trace.endpos, ent->progs.sv->origin); - if (relink) - { - SV_LinkEdict(ent); - SV_TouchTriggers (ent); - } - return true; - } - - if (!ent->progs.sv->enemy) - break; - } - - return false; - } - - // push down from a step height above the wished position - if (!((int)ent->progs.sv->aiflags & AI_NOSTEP)) - stepsize = STEPSIZE; - else stepsize = 1; - - neworg[2] += stepsize; - VectorCopy (neworg, end); - end[2] -= stepsize*2; - - trace = SV_Trace (neworg, ent->progs.sv->mins, ent->progs.sv->maxs, end, ent, MASK_MONSTERSOLID); - - // Determine whether monster is capable of and/or should jump - jump = 0; - if((ent->progs.sv->jump) && !((int)ent->progs.sv->aiflags & AI_DUCKED)) - { - // Don't jump if path is blocked by monster or player. Otherwise, - // monster might attempt to jump OVER the monster/player, which - // ends up looking a bit goofy. Also don't jump if the monster's - // movement isn't deliberate (target=NULL) - if(trace.ent && (trace.ent->priv.sv->client || ((int)trace.ent->progs.sv->flags & FL_MONSTER))) - canjump = false; - else if(target) - { - // Never jump unless it places monster closer to his goal - vec3_t dir; - VectorSubtract(target->progs.sv->origin, oldorg, dir); - d1 = VectorLength(dir); - VectorSubtract(target->progs.sv->origin, trace.endpos, dir); - d2 = VectorLength(dir); - if(d2 < d1) - canjump = true; - else - canjump = false; - } - else canjump = false; - } - else canjump = false; - - if (trace.allsolid) - { - if(canjump && (ent->progs.sv->jumpup > 0)) - { - neworg[2] += ent->progs.sv->jumpup - stepsize; - trace = SV_Trace (neworg, ent->progs.sv->mins, ent->progs.sv->maxs, end, ent, MASK_MONSTERSOLID); - if (!trace.allsolid && !trace.startsolid && trace.fraction > 0 && (trace.plane.normal[2] > 0.9)) - { - if(!trace.ent || (!trace.ent->priv.sv->client && !((int)trace.ent->progs.sv->flags & FL_MONSTER) && !((int)trace.ent->progs.sv->flags & FL_DEADMONSTER))) - { - // Good plane to jump on. Make sure monster is more or less facing - // the obstacle to avoid cutting-corners jumps - trace_t tr; - vec3_t p2; - - VectorMA(ent->progs.sv->origin,1024,forward,p2); - tr = SV_Trace(ent->progs.sv->origin,ent->progs.sv->mins,ent->progs.sv->maxs,p2,ent,MASK_MONSTERSOLID); - if(DotProduct(tr.plane.normal,forward) < -0.95) - { - jump = 1; - jumpheight = trace.endpos[2] - ent->progs.sv->origin[2]; - } - else return false; - } - } - else return false; - } - else return false; - } - - if (trace.startsolid) - { - neworg[2] -= stepsize; - trace = SV_Trace (neworg, ent->progs.sv->mins, ent->progs.sv->maxs, end, ent, MASK_MONSTERSOLID); - if (trace.allsolid || trace.startsolid) - return false; - } - - - // don't go in to water - // Lazarus: misc_actors don't go swimming, but wading is fine - if ((int)ent->progs.sv->aiflags & AI_ACTOR) - { - // First check for lava/slime under feet - but only if we're not already in - // a liquid - test[0] = trace.endpos[0]; - test[1] = trace.endpos[1]; - if (ent->progs.sv->waterlevel == 0) - { - test[2] = trace.endpos[2] + ent->progs.sv->mins[2] + 1; - contents = SV_PointContents(test); - if (contents & (CONTENTS_LAVA | CONTENTS_SLIME)) - return false; - } - test[2] = trace.endpos[2] + ent->progs.sv->view_ofs[2] - 1; //FIXME - contents = SV_PointContents(test); - if (contents & MASK_WATER) - return false; - } - else if (ent->progs.sv->waterlevel == 0) - { - test[0] = trace.endpos[0]; - test[1] = trace.endpos[1]; - test[2] = trace.endpos[2] + ent->progs.sv->mins[2] + 1; - contents = SV_PointContents(test); - - if (contents & MASK_WATER) - return false; - } - - // Lazarus: Don't intentionally walk into lasers. - dist = VectorLength(move); - if(dist > 0.) - { - edict_t *e; - trace_t laser_trace; - vec_t delta; - vec3_t laser_mins, laser_maxs; - vec3_t laser_start, laser_end; - vec3_t monster_mins, monster_maxs; - - for(i = maxclients->value + 1; i < prog->num_edicts; i++) - { - e = PRVM_EDICT_NUM(i); - if(e->priv.sv->free) continue; - if(!PRVM_GetString(e->progs.sv->classname)) continue; - if(strcmp(PRVM_GetString(e->progs.sv->classname), "env_laser")) continue; - if(!PF_inpvs(ent->progs.sv->origin,e->progs.sv->origin)) - continue; - // Check to see if monster is ALREADY in the path of this laser. - // If so, allow the move so he can get out. - VectorMA(e->progs.sv->origin, 2048, e->progs.sv->movedir, laser_end); - laser_trace = SV_Trace(e->progs.sv->origin,NULL,NULL,laser_end,NULL,CONTENTS_SOLID|CONTENTS_MONSTER); - if(laser_trace.ent == ent) - continue; - VectorCopy(laser_trace.endpos,laser_end); - laser_mins[0] = min(e->progs.sv->origin[0],laser_end[0]); - laser_mins[1] = min(e->progs.sv->origin[1],laser_end[1]); - laser_mins[2] = min(e->progs.sv->origin[2],laser_end[2]); - laser_maxs[0] = max(e->progs.sv->origin[0],laser_end[0]); - laser_maxs[1] = max(e->progs.sv->origin[1],laser_end[1]); - laser_maxs[2] = max(e->progs.sv->origin[2],laser_end[2]); - monster_mins[0] = min(oldorg[0],trace.endpos[0]) + ent->progs.sv->mins[0]; - monster_mins[1] = min(oldorg[1],trace.endpos[1]) + ent->progs.sv->mins[1]; - monster_mins[2] = min(oldorg[2],trace.endpos[2]) + ent->progs.sv->mins[2]; - monster_maxs[0] = max(oldorg[0],trace.endpos[0]) + ent->progs.sv->maxs[0]; - monster_maxs[1] = max(oldorg[1],trace.endpos[1]) + ent->progs.sv->maxs[1]; - monster_maxs[2] = max(oldorg[2],trace.endpos[2]) + ent->progs.sv->maxs[2]; - if( monster_maxs[0] < laser_mins[0] ) continue; - if( monster_maxs[1] < laser_mins[1] ) continue; - if( monster_maxs[2] < laser_mins[2] ) continue; - if( monster_mins[0] > laser_maxs[0] ) continue; - if( monster_mins[1] > laser_maxs[1] ) continue; - if( monster_mins[2] > laser_maxs[2] ) continue; - // If we arrive here, some part of the bounding box surrounding - // monster's total movement intersects laser bounding box. - // If laser is parallel to x, y, or z, we definitely - // know this move will put monster in path of laser - if ( (e->progs.sv->movedir[0] == 1.) || (e->progs.sv->movedir[1] == 1.) || (e->progs.sv->movedir[2] == 1.)) - return false; - // Shift psuedo laser towards monster's current position up to - // the total distance he's proposing moving. - delta = min(16,dist); - VectorCopy(move,dir); - VectorNormalize(dir); - while(delta < dist+15.875) - { - if(delta > dist) delta = dist; - VectorMA(e->progs.sv->origin, -delta,dir,laser_start); - VectorMA(e->progs.sv->old_origin,-delta,dir,laser_end); - laser_trace = SV_Trace(laser_start,NULL,NULL,laser_end,prog->edicts,CONTENTS_SOLID|CONTENTS_MONSTER); - if(laser_trace.ent == ent) - return false; - delta += 16; - } - } - } - if ((trace.fraction == 1) && !jump && canjump && (ent->progs.sv->jumpdn > 0)) - { - end[2] = oldorg[2] + move[2] - ent->progs.sv->jumpdn; - trace = SV_Trace (neworg, ent->progs.sv->mins, ent->progs.sv->maxs, end, ent, MASK_MONSTERSOLID | MASK_WATER); - if(trace.fraction < 1 && (trace.plane.normal[2] > 0.9) && (trace.contents & MASK_SOLID) && (neworg[2] - 16 > trace.endpos[2])) - { - if(!trace.ent || (!trace.ent->priv.sv->client && !((int)trace.ent->progs.sv->flags & FL_MONSTER) && !((int)trace.ent->progs.sv->flags & FL_DEADMONSTER))) - jump = -1; - } - } - - - if ((trace.fraction == 1) && !jump) - { - // if monster had the ground pulled out, go ahead and fall - if ((int)ent->progs.sv->aiflags & AI_PARTIALONGROUND ) - { - VectorAdd (ent->progs.sv->origin, move, ent->progs.sv->origin); - if (relink) - { - SV_LinkEdict(ent); - SV_TouchTriggers (ent); - } - ent->progs.sv->groundentity = 0; - return true; - } - return false; // walked off an edge - } - - // check point traces down for dangling corners - VectorCopy (trace.endpos, ent->progs.sv->origin); - - if(!jump) - { - bool skip = false; - // if monster CAN jump down, and a position just a bit forward would be - // a good jump-down spot, allow (briefly) !M_CheckBottom - if (canjump && target && (target->progs.sv->origin[2] < ent->progs.sv->origin[2]) && (ent->progs.sv->jumpdn > 0)) - { - vec3_t p1, p2; - trace_t tr; - - VectorMA(oldorg,48,forward,p1); - tr = SV_Trace(ent->progs.sv->origin, ent->progs.sv->mins, ent->progs.sv->maxs, p1, ent, MASK_MONSTERSOLID); - if(tr.fraction == 1) - { - p2[0] = p1[0]; - p2[1] = p1[1]; - p2[2] = p1[2] - ent->progs.sv->jumpdn; - tr = SV_Trace(p1,ent->progs.sv->mins,ent->progs.sv->maxs,p2,ent,MASK_MONSTERSOLID | MASK_WATER); - if(tr.fraction < 1 && (tr.plane.normal[2] > 0.9) && (tr.contents & MASK_SOLID) && (p1[2] - 16 > tr.endpos[2])) - { - if(!tr.ent || (!tr.ent->priv.sv->client && !((int)tr.ent->progs.sv->flags & FL_MONSTER) && !((int)tr.ent->progs.sv->flags & FL_DEADMONSTER))) - { - VectorSubtract(target->progs.sv->origin, tr.endpos, dir); - d2 = VectorLength(dir); - if(d2 < d1) - skip = true; - } - } - } - - } - if (!skip) - { - if (!SV_CheckBottom (ent)) - { - if ( (int)ent->progs.sv->aiflags & AI_PARTIALONGROUND ) - { // entity had floor mostly pulled out from underneath it - // and is trying to correct - if (relink) - { - SV_LinkEdict (ent); - SV_TouchTriggers (ent); - } - return true; - } - VectorCopy (oldorg, ent->progs.sv->origin); - return false; - } - } - } - - if ((int)ent->progs.sv->aiflags & AI_PARTIALONGROUND ) - { - (int)ent->progs.sv->aiflags &= ~AI_PARTIALONGROUND; - } - ent->progs.sv->groundentity = PRVM_EDICT_TO_PROG(trace.ent); - - // the move is ok - if(jump) - { - VectorScale(move, 10, ent->progs.sv->velocity); - if(jump > 0) - { -//ent->progs.sv->jump(ent); - ent->progs.sv->velocity[2] = 2.5*jumpheight + 80; - } - else - { - ent->progs.sv->velocity[2] = max(ent->progs.sv->velocity[2],100); - if(oldorg[2] - ent->progs.sv->origin[2] > 48) - ent->progs.sv->origin[2] = oldorg[2] + ent->progs.sv->velocity[2]*0.1f; - } - if(relink) - { - SV_LinkEdict (ent); - SV_TouchTriggers (ent); - } - } - else if (relink) - { - SV_LinkEdict (ent); - SV_TouchTriggers (ent); - } - return true; -} - -/* -=============== -SV_WalkMove -=============== -*/ -bool SV_WalkMove (edict_t *ent, float yaw, float dist) -{ - vec3_t move; - - if (!((int)ent->progs.sv->aiflags & (AI_ONGROUND|AI_FLY|AI_SWIM))) - return false; - - yaw = yaw * M_PI*2 / 360; - - move[0] = cos(yaw)*dist; - move[1] = sin(yaw)*dist; - move[2] = 0; - - return SV_MoveStep(ent, move, true); -} - -/* -============ -SV_TestEntityPosition - -============ -*/ -edict_t *SV_TestEntityPosition (edict_t *ent) -{ - trace_t trace; - int mask; - - if (ent->priv.sv->clipmask) mask = ent->priv.sv->clipmask; - else mask = MASK_SOLID; - - if(ent->progs.sv->solid == SOLID_BSP) - { - vec3_t org, mins, maxs; - VectorAdd(ent->progs.sv->origin, ent->progs.sv->origin_offset, org); - VectorSubtract(ent->progs.sv->mins, ent->progs.sv->origin_offset, mins); - VectorSubtract(ent->progs.sv->maxs, ent->progs.sv->origin_offset, maxs); - trace = SV_Trace (org, mins, maxs, org, ent, mask); - } - else trace = SV_Trace (ent->progs.sv->origin, ent->progs.sv->mins, ent->progs.sv->maxs, ent->progs.sv->origin, ent, mask); - - if (trace.startsolid) - { - // Lazarus - work around for players/monsters standing on dead monsters causing - // those monsters to gib when rotating brush models are in the vicinity - if ( ((int)ent->progs.sv->flags & FL_DEADMONSTER) && (trace.ent->priv.sv->client || ((int)trace.ent->progs.sv->flags & FL_MONSTER))) - return NULL; - - // Lazarus - return a bit more useful info than simply "g_edicts" - if(trace.ent) return trace.ent; - else return prog->edicts; - } - - return NULL; -} - -/* -================ -SV_CheckVelocity -================ -*/ -void SV_CheckVelocity (edict_t *ent) -{ - if(VectorLength(ent->progs.sv->velocity) > sv_maxvelocity->value) - { - VectorNormalize(ent->progs.sv->velocity); - VectorScale(ent->progs.sv->velocity, sv_maxvelocity->value, ent->progs.sv->velocity); - } -} - -/* -============= -SV_RunThink - -Runs thinking code for this frame if necessary -============= -*/ -bool SV_RunThink (edict_t *ent) -{ - float thinktime; - - thinktime = ent->progs.sv->nextthink; - if (thinktime <= 0 || thinktime > sv.time + sv.frametime) - return true; - - // don't let things stay in the past. - // it is possible to start that way by a trigger with a local time. - if (thinktime < sv.time) thinktime = sv.time; - - ent->progs.sv->nextthink = 0; //reset thinktime - prog->globals.server->time = thinktime; - prog->globals.server->pev = PRVM_EDICT_TO_PROG(ent); - prog->globals.server->other = PRVM_EDICT_TO_PROG(prog->edicts); - PRVM_ExecuteProgram (ent->progs.sv->think, "QC function pev->think is missing"); - - return !ent->priv.sv->free; -} - -/* -================== -SV_Impact - -Two entities have touched, so run their touch functions -================== -*/ -void SV_Impact (edict_t *e1, trace_t *trace) -{ - edict_t *e2 = (edict_t *)trace->ent; - - PRVM_PUSH_GLOBALS; - - prog->globals.server->time = sv.time; - if (!e1->priv.sv->free && !e2->priv.sv->free && e1->progs.sv->touch && e1->progs.sv->solid != SOLID_NOT) - { - prog->globals.server->pev = PRVM_EDICT_TO_PROG(e1); - prog->globals.server->other = PRVM_EDICT_TO_PROG(e2); - prog->globals.server->time = sv.time; - prog->globals.server->trace_allsolid = trace->allsolid; - prog->globals.server->trace_startsolid = trace->startsolid; - prog->globals.server->trace_fraction = trace->fraction; - prog->globals.server->trace_contents = trace->contents; - VectorCopy (trace->endpos, prog->globals.server->trace_endpos); - VectorCopy (trace->plane.normal, prog->globals.server->trace_plane_normal); - prog->globals.server->trace_plane_dist = trace->plane.dist; - if (trace->ent) prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace->ent); - else prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts); - PRVM_ExecuteProgram (e1->progs.sv->touch, "QC function pev->touch is missing"); - } - if (!e1->priv.sv->free && !e2->priv.sv->free && e2->progs.sv->touch && e2->progs.sv->solid != SOLID_NOT) - { - prog->globals.server->pev = PRVM_EDICT_TO_PROG(e2); - prog->globals.server->other = PRVM_EDICT_TO_PROG(e1); - prog->globals.server->time = sv.time; - prog->globals.server->trace_allsolid = false; - prog->globals.server->trace_startsolid = false; - prog->globals.server->trace_fraction = 1; - prog->globals.server->trace_contents = trace->contents; - VectorCopy (e2->progs.sv->origin, prog->globals.server->trace_endpos); - VectorSet (prog->globals.server->trace_plane_normal, 0, 0, 1); - prog->globals.server->trace_plane_dist = 0; - prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(e1); - PRVM_ExecuteProgram (e2->progs.sv->touch, "QC function pev->touch is missing"); - } - - PRVM_POP_GLOBALS; -} - - -/* -================== -ClipVelocity - -Slide off of the impacting object -returns the blocked flags (1 = floor, 2 = step / wall) -================== -*/ -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 -============ -*/ -#define MAX_CLIP_PLANES 5 -int SV_FlyMove (edict_t *ent, float time, int mask) -{ - edict_t *hit; - 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; - int num_retries = 0; - -retry: - numbumps = 4; - - blocked = 0; - VectorCopy (ent->progs.sv->velocity, original_velocity); - VectorCopy (ent->progs.sv->velocity, primal_velocity); - numplanes = 0; - - time_left = time; - - ent->progs.sv->groundentity = 0; - for (bumpcount = 0; bumpcount < numbumps; bumpcount++) - { - for (i = 0; i < 3; i++) end[i] = ent->progs.sv->origin[i] + time_left * ent->progs.sv->velocity[i]; - - trace = SV_Trace (ent->progs.sv->origin, ent->progs.sv->mins, ent->progs.sv->maxs, end, ent, mask); - - if (trace.allsolid) - { - // entity is trapped in another solid - VectorCopy (vec3_origin, ent->progs.sv->velocity); - return 3; - } - - if (trace.fraction > 0) - { - // actually covered some distance - VectorCopy (trace.endpos, ent->progs.sv->origin); - VectorCopy (ent->progs.sv->velocity, original_velocity); - numplanes = 0; - } - - if (trace.fraction == 1) - break; // moved the entire distance - - hit = trace.ent; - - // Lazarus: If the pushed entity is a conveyor, raise us up and - // try again - if (!num_retries && wasonground) - { - if ((hit->progs.sv->movetype == MOVETYPE_CONVEYOR) && (trace.plane.normal[2] > 0.7)) - { - vec3_t above; - - VectorCopy(end,above); - above[2] += 32; - trace = SV_Trace (above, ent->progs.sv->mins, ent->progs.sv->maxs, end, ent, mask); - VectorCopy (trace.endpos,end); - end[2] += 1; - VectorSubtract (end,ent->progs.sv->origin,ent->progs.sv->velocity); - VectorScale (ent->progs.sv->velocity,1.0/time_left,ent->progs.sv->velocity); - num_retries++; - goto retry; - } - } - - // if blocked by player AND on a conveyor - if (hit && hit->priv.sv->client && onconveyor) - { - vec3_t player_dest; - trace_t ptrace; - - if(ent->progs.sv->mass > hit->progs.sv->mass) - { - VectorMA (hit->progs.sv->origin,time_left,ent->progs.sv->velocity,player_dest); - ptrace = SV_Trace(hit->progs.sv->origin,hit->progs.sv->mins,hit->progs.sv->maxs,player_dest,hit,hit->priv.sv->clipmask); - if(ptrace.fraction == 1.0) - { - VectorCopy(player_dest,hit->progs.sv->origin); - SV_LinkEdict(hit); - goto retry; - } - } - blocked |= 8; - } - - if (trace.plane.normal[2] > 0.7) - { - blocked |= 1; // floor - if ( hit->progs.sv->solid == SOLID_BSP) - { - ent->progs.sv->groundentity = PRVM_EDICT_TO_PROG(hit); - } - } - if (!trace.plane.normal[2]) - { - blocked |= 2; // step - } - - // run the impact function - SV_Impact (ent, &trace); - if (ent->priv.sv->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->progs.sv->velocity); - blocked |= 3; - return blocked; - } - - VectorCopy (trace.plane.normal, planes[numplanes]); - numplanes++; - - // modify original_velocity so it parallels all of the clip planes - for (i=0 ; iprogs.sv->velocity); - } - else - { // go along the crease - if (numplanes != 2) - { -// gi.dprintf ("clip velocity, numplanes == %i\n",numplanes); - VectorCopy (vec3_origin, ent->progs.sv->velocity); - blocked |= 7; - return blocked; - } - CrossProduct (planes[0], planes[1], dir); - d = DotProduct (dir, ent->progs.sv->velocity); - VectorScale (dir, d, ent->progs.sv->velocity); - } - - // if original velocity is against the original velocity, stop dead - // to avoid tiny occilations in sloping corners - if (DotProduct (ent->progs.sv->velocity, primal_velocity) <= 0) - { - VectorCopy (vec3_origin, ent->progs.sv->velocity); - return blocked; - } - } - - return blocked; -} - -/* -============ -SV_PushableMove - -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 -============ -*/ -#define MAX_CLIP_PLANES 5 -int SV_PushableMove (edict_t *ent, float time, int mask) -{ - edict_t *hit; - 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; - int num_retries = 0; - - // Corrective stuff added for bmodels with no origin brush - vec3_t mins, maxs; - vec3_t origin; - -retry: - - numbumps = 4; - ent->progs.sv->bouncetype = 0; - - blocked = 0; - VectorCopy (ent->progs.sv->velocity, original_velocity); - VectorCopy (ent->progs.sv->velocity, primal_velocity); - numplanes = 0; - - time_left = time; - - VectorAdd(ent->progs.sv->origin,ent->progs.sv->origin_offset,origin); - VectorCopy(ent->progs.sv->size,maxs); - VectorScale(maxs,0.5,maxs); - VectorNegate(maxs,mins); - - ent->progs.sv->groundentity = 0; - - for (bumpcount=0 ; bumpcountprogs.sv->velocity[i]; - - trace = SV_Trace (origin, mins, maxs, end, ent, mask); - - if (trace.allsolid) - { - // entity is trapped in another solid - VectorCopy (vec3_origin, ent->progs.sv->velocity); - return 3; - } - - if (trace.fraction > 0) - { - // actually covered some distance - VectorCopy (trace.endpos, origin); - VectorSubtract (origin, ent->progs.sv->origin_offset, ent->progs.sv->origin); - VectorCopy (ent->progs.sv->velocity, original_velocity); - numplanes = 0; - } - - if (trace.fraction == 1) - break; // moved the entire distance - - hit = trace.ent; - - // Lazarus: If the pushed entity is a conveyor, raise us up and - // try again - if (!num_retries && wasonground) - { - if ((hit->progs.sv->movetype == MOVETYPE_CONVEYOR) && (trace.plane.normal[2] > 0.7)) - { - vec3_t above; - - VectorCopy(end,above); - above[2] += 32; - trace = SV_Trace (above, mins, maxs, end, ent, mask); - VectorCopy (trace.endpos,end); - VectorSubtract (end,origin,ent->progs.sv->velocity); - VectorScale (ent->progs.sv->velocity,1.0/time_left,ent->progs.sv->velocity); - num_retries++; - goto retry; - } - } - - // if blocked by player AND on a conveyor - if (hit->priv.sv->client && onconveyor) - { - vec3_t player_dest; - trace_t ptrace; - - if(ent->progs.sv->mass > hit->progs.sv->mass) - { - VectorMA (hit->progs.sv->origin,time_left,ent->progs.sv->velocity,player_dest); - ptrace = SV_Trace(hit->progs.sv->origin,hit->progs.sv->mins,hit->progs.sv->maxs,player_dest,hit,hit->priv.sv->clipmask); - if(ptrace.fraction == 1.0) - { - VectorCopy(player_dest,hit->progs.sv->origin); - SV_LinkEdict(hit); - goto retry; - } - } - blocked |= 8; - } - - if (trace.plane.normal[2] > 0.7) - { - // Lazarus: special case - if this ent or the impact ent is - // in water, motion is NOT blocked. - if((hit->progs.sv->movetype != MOVETYPE_PUSHABLE) || ((ent->progs.sv->waterlevel==0) && (hit->progs.sv->waterlevel==0))) - { - blocked |= 1; // floor - if ( hit->progs.sv->solid == SOLID_BSP) - { - ent->progs.sv->groundentity = PRVM_EDICT_TO_PROG(hit); - } - } - } - if (!trace.plane.normal[2]) - { - blocked |= 2; // step - } - - // run the impact function - SV_Impact (ent, &trace); - if (ent->priv.sv->free) break; // removed by the impact function - - time_left -= time_left * trace.fraction; - - // clipped to another plane - if (numplanes >= MAX_CLIP_PLANES) - { - // this shouldn't really happen - VectorCopy (vec3_origin, ent->progs.sv->velocity); - blocked |= 3; - return blocked; - } - - VectorCopy (trace.plane.normal, planes[numplanes]); - numplanes++; - - // modify original_velocity so it parallels all of the clip planes - for (i = 0; i < numplanes; i++) - { - // DH: experimenting here. 1 is no bounce, - // 1.5 bounces like a grenade, 2 is a superball - if(ent->progs.sv->bouncetype == 1) - { - ClipVelocity (original_velocity, planes[i], new_velocity, 1.4); - // stop small oscillations - if (new_velocity[2] < 60) - { - ent->progs.sv->groundentity = PRVM_EDICT_TO_PROG(trace.ent); - VectorCopy (vec3_origin, new_velocity); - } - else - { - // add a bit of random horizontal motion - if(!new_velocity[0]) new_velocity[0] = crandom() * new_velocity[2]/4; - if(!new_velocity[1]) new_velocity[1] = crandom() * new_velocity[2]/4; - } - } - else if(ent->progs.sv->bouncetype == 2) - { - VectorCopy(ent->progs.sv->velocity, new_velocity); - } - else - { - ClipVelocity (original_velocity, planes[i], new_velocity, 1); - } - for (j = 0; j < numplanes; j++) - { - if ((j != i) && !VectorCompare (planes[i], planes[j])) - { - if (DotProduct (new_velocity, planes[j]) < 0) - break; // not ok - } - } - if (j == numplanes) break; - } - - if (i != numplanes) - { - // go along this plane - VectorCopy (new_velocity, ent->progs.sv->velocity); - } - else - { // go along the crease - if (numplanes != 2) - { - VectorCopy (vec3_origin, ent->progs.sv->velocity); - blocked |= 7; - return blocked; - } - CrossProduct (planes[0], planes[1], dir); - d = DotProduct (dir, ent->progs.sv->velocity); - VectorScale (dir, d, ent->progs.sv->velocity); - } - - // if velocity is against the original velocity, stop dead - // to avoid tiny occilations in sloping corners - if( !ent->progs.sv->bouncetype ) - { - if (DotProduct (ent->progs.sv->velocity, primal_velocity) <= 0) - { - VectorCopy (vec3_origin, ent->progs.sv->velocity); - return blocked; - } - } - } - return blocked; -} - -/* -============ -SV_AddGravity - -============ -*/ -void SV_AddGravity (edict_t *ent) -{ - ent->progs.sv->velocity[2] -= ent->progs.sv->gravity * sv_gravity->value * 0.1; -} - -/* -=============================================================================== - -PUSHMOVE - -=============================================================================== -*/ - -/* -================================================= -SV_PushEntity - -Does not change the entities velocity at all - -called for MOVETYPE_TOSS - MOVETYPE_BOUNCE - MOVETYPE_FLY -================================================= -*/ -trace_t SV_PushEntity (edict_t *ent, vec3_t push) -{ - trace_t trace; - vec3_t start; - vec3_t end; - int mask; - int num_retries=0; - - VectorCopy (ent->progs.sv->origin, start); - VectorAdd (start, push, end); - - if (ent->priv.sv->clipmask) - mask = ent->priv.sv->clipmask; - else - mask = MASK_SOLID; - -retry: - trace = SV_Trace (start, ent->progs.sv->mins, ent->progs.sv->maxs, end, ent, mask); - - VectorCopy (trace.endpos, ent->progs.sv->origin); - SV_LinkEdict (ent); - - if (trace.fraction != 1.0) - { - SV_Impact (ent, &trace); - - // if the pushed entity went away and the pusher is still there - if (trace.ent->priv.sv->free && !ent->priv.sv->free) - { - // move the pusher back and try again - VectorCopy (start, ent->progs.sv->origin); - SV_LinkEdict (ent); - goto retry; - } - - // Lazarus: If the pushed entity is a conveyor, raise us up and - // try again - if (!num_retries && wasonground) - { - if ((trace.ent->progs.sv->movetype == MOVETYPE_CONVEYOR) && (trace.plane.normal[2] > 0.7) && !trace.startsolid) - { - vec3_t above; - VectorCopy(end,above); - above[2] += 32; - trace = SV_Trace (above, ent->progs.sv->mins, ent->progs.sv->maxs, end, ent, mask); - VectorCopy (trace.endpos, end); - VectorCopy (start, ent->progs.sv->origin); - SV_LinkEdict(ent); - num_retries++; - goto retry; - } - } - if(onconveyor && !trace.ent->priv.sv->client) - { - // If blocker can be damaged, destroy it. Otherwise destroy blockee. - if(trace.ent->progs.sv->takedamage == DAMAGE_YES) - T_Damage(trace.ent, ent, ent, vec3_origin, trace.ent->progs.sv->origin, vec3_origin, 100000, 1, 0, DMG_CRUSH); - else T_Damage(ent, trace.ent, trace.ent, vec3_origin, ent->progs.sv->origin, vec3_origin, 100000, 1, 0, DMG_CRUSH); - } - - } - if (!ent->priv.sv->free) SV_TouchTriggers (ent); - - return trace; -} - -typedef struct -{ - edict_t *ent; - vec3_t origin; - vec3_t angles; - float deltayaw; - -} pushed_t; - -pushed_t pushed[MAX_EDICTS], *pushed_p; -edict_t *obstacle; - -void MoveRiders_r(edict_t *platform, edict_t *ignore, vec3_t move, vec3_t amove, bool turn) -{ - int i; - edict_t *rider; - - for(i = 1, rider = PRVM_EDICT_NUM(i); i <= prog->num_edicts; i++, rider = PRVM_EDICT_NUM(i)) - { - if((rider->progs.sv->groundentity == PRVM_EDICT_TO_PROG(platform)) && (rider != ignore)) - { - VectorAdd(rider->progs.sv->origin, move, rider->progs.sv->origin); - if (turn && (amove[YAW] != 0.)) - { - if(!rider->priv.sv->client) rider->progs.sv->angles[YAW] += amove[YAW]; - else - { - rider->progs.sv->angles[YAW] += amove[YAW]; - rider->priv.sv->client->ps.pmove.delta_angles[YAW] += ANGLE2SHORT(amove[YAW]); - rider->priv.sv->client->ps.pmove.pm_type = PM_FREEZE; - rider->priv.sv->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION; - } - } - SV_LinkEdict(rider); - - if(SV_TestEntityPosition(rider)) - { - // Move is blocked. Since this is for riders, not pushees, - // it should be ok to just back the move for this rider off - VectorSubtract(rider->progs.sv->origin,move,rider->progs.sv->origin); - if(turn && (amove[YAW] != 0.)) - { - rider->progs.sv->angles[YAW] -= amove[YAW]; - if(rider->priv.sv->client) - { - rider->priv.sv->client->ps.pmove.delta_angles[YAW] -= ANGLE2SHORT(amove[YAW]); - rider->priv.sv->client->ps.viewangles[YAW] -= amove[YAW]; - } - } - SV_LinkEdict(rider); - } - else - { - // move this rider's riders - MoveRiders_r(rider, ignore, move, amove, turn); - } - } - } -} - -/* -============ -RealBoundingBox - -Returns the actual bounding box of a bmodel. This is a big improvement over -what q2 normally does with rotating bmodels - q2 sets absmin, absmax to a cube -that will completely contain the bmodel at *any* rotation on *any* axis, whether -the bmodel can actually rotate to that angle or not. This leads to a lot of -false block tests in SV_Push if another bmodel is in the vicinity. -============ -*/ -void RealBoundingBox(edict_t *ent, vec3_t mins, vec3_t maxs) -{ - vec3_t forward, left, up, f1, l1, u1; - vec3_t p[8]; - int i, j, k, j2, k4; - - for(k = 0; k < 2; k++) - { - k4 = k * 4; - if(k) p[k4][2] = ent->progs.sv->maxs[2]; - else p[k4][2] = ent->progs.sv->mins[2]; - - p[k4 + 1][2] = p[k4][2]; - p[k4 + 2][2] = p[k4][2]; - p[k4 + 3][2] = p[k4][2]; - - for(j = 0; j < 2; j++) - { - j2 = j * 2; - if(j) p[j2+k4][1] = ent->progs.sv->maxs[1]; - else p[j2+k4][1] = ent->progs.sv->mins[1]; - p[j2 + k4 + 1][1] = p[j2 + k4][1]; - - for(i = 0; i < 2; i++) - { - if(i) p[i + j2 + k4][0] = ent->progs.sv->maxs[0]; - else p[i + j2 + k4][0] = ent->progs.sv->mins[0]; - } - } - } - - AngleVectors(ent->progs.sv->angles, forward, left, up); - - for(i = 0; i < 8; i++) - { - VectorScale(forward, p[i][0], f1); - VectorScale(left, -p[i][1], l1); - VectorScale(up, p[i][2], u1); - VectorAdd(ent->progs.sv->origin, f1, p[i]); - VectorAdd(p[i], l1, p[i]); - VectorAdd(p[i], u1, p[i]); - } - - VectorCopy(p[0],mins); - VectorCopy(p[0],maxs); - - for(i = 1; i < 8; i++) - { - mins[0] = min(mins[0], p[i][0]); - mins[1] = min(mins[1], p[i][1]); - mins[2] = min(mins[2], p[i][2]); - maxs[0] = max(maxs[0], p[i][0]); - maxs[1] = max(maxs[1], p[i][1]); - maxs[2] = max(maxs[2], p[i][2]); - } -} - -/* -============ -SV_Push - -Objects need to be moved back on a failed push, -otherwise riders would continue to slide. -============ -*/ -bool SV_Push (edict_t *pusher, vec3_t move, vec3_t amove) -{ - int i, e; - edict_t *check, *block; - vec3_t mins, maxs; - pushed_t *p; - vec3_t org, org2, org_check, forward, right, up; - vec3_t move2={0,0,0}; - vec3_t move3={0,0,0}; - vec3_t realmins, realmaxs; - bool turn = true; - trace_t tr; - - // clamp the move to 1/8 units, so the position will - // be accurate for client side prediction - for (i = 0; i < 3; i++) - { - float temp; - temp = move[i]*8.0; - if (temp > 0.0) temp += 0.5; - else temp -= 0.5; - move[i] = 0.125 * (int)temp; - } - - // find the bounding box - for (i = 0; i < 3; i++) - { - mins[i] = pusher->progs.sv->absmin[i] + move[i]; - maxs[i] = pusher->progs.sv->absmax[i] + move[i]; - } - - // we need this for pushing things later - VectorSubtract (vec3_origin, amove, org); - AngleVectors (org, forward, right, up); - - // save the pusher's original position - pushed_p->ent = pusher; - VectorCopy (pusher->progs.sv->origin, pushed_p->origin); - VectorCopy (pusher->progs.sv->angles, pushed_p->angles); - if (pusher->priv.sv->client) pushed_p->deltayaw = pusher->priv.sv->client->ps.pmove.delta_angles[YAW]; - pushed_p++; - - // move the pusher to it's final position - VectorAdd (pusher->progs.sv->origin, move, pusher->progs.sv->origin); - VectorAdd (pusher->progs.sv->angles, amove, pusher->progs.sv->angles); - SV_LinkEdict (pusher); - - // Lazarus: Standard Q2 takes a horrible shortcut - // with rotating brush models, setting - // absmin and absmax to a cube that would - // contain the brush model if it could - // rotate around ANY axis. The result is - // a lot of false hits on intersections, - // particularly when you have multiple - // rotating brush models in the same area. - // RealBoundingBox gives us the actual - // bounding box at the current angles. - RealBoundingBox(pusher,realmins,realmaxs); - - // see if any solid entities are inside the final position - check = PRVM_EDICT_NUM( 1 ); - - for (e = 1; e < prog->num_edicts; e++, check = PRVM_EDICT_NUM(e)) - { - if (check->priv.sv->free) continue; - if (check == PRVM_PROG_TO_EDICT(pusher->progs.sv->owner)) continue; - if (check->progs.sv->movetype == MOVETYPE_PUSH || check->progs.sv->movetype == MOVETYPE_NONE || check->progs.sv->movetype == MOVETYPE_NOCLIP) - continue; - - if (!check->priv.sv->area.prev) - continue; // not linked in anywhere - - // if the entity is standing on the pusher, it will definitely be moved - if (check->progs.sv->groundentity != PRVM_EDICT_TO_PROG(pusher)) - { - // see if the ent needs to be tested - if ( check->progs.sv->absmin[0] >= realmaxs[0] - || check->progs.sv->absmin[1] >= realmaxs[1] - || check->progs.sv->absmin[2] >= realmaxs[2] - || check->progs.sv->absmax[0] <= realmins[0] - || check->progs.sv->absmax[1] <= realmins[1] - || check->progs.sv->absmax[2] <= realmins[2] ) - continue; - - // see if the ent's bbox is inside the pusher's final position - if (!SV_TestEntityPosition (check)) - continue; - } - - // Lazarus: func_tracktrain-specific stuff - // If train is *driven*, then hurt monsters/players it touches NOW - // rather than waiting to be blocked. - if (((int)pusher->progs.sv->flags & FL_TRACKTRAIN) && pusher->progs.sv->owner && (((int)check->progs.sv->flags & FL_MONSTER) || check->priv.sv->client) && (check->progs.sv->groundentity != PRVM_EDICT_TO_PROG(pusher))) - { - vec3_t dir; - VectorSubtract(check->progs.sv->origin,pusher->progs.sv->origin,dir); - dir[2] += 16; - VectorNormalize(dir); - T_Damage (check, pusher, pusher, dir, check->progs.sv->origin, vec3_origin, pusher->progs.sv->dmg, 1, 0, DMG_CRUSH); - } - - if ((pusher->progs.sv->movetype == MOVETYPE_PUSH) || (check->progs.sv->groundentity == PRVM_EDICT_TO_PROG(pusher))) - { - // move this entity - pushed_p->ent = check; - VectorCopy (check->progs.sv->origin, pushed_p->origin); - VectorCopy (check->progs.sv->angles, pushed_p->angles); - pushed_p++; - - // try moving the contacted entity - VectorAdd (check->progs.sv->origin, move, check->progs.sv->origin); - // Lazarus: if turn_rider is set, do it. We don't do this by default - // 'cause it can be a fairly drastic change in gameplay - if (turn && (check->progs.sv->groundentity == PRVM_EDICT_TO_PROG(pusher))) - { - if(!check->priv.sv->client) - { - check->progs.sv->angles[YAW] += amove[YAW]; - } - else - { - if(amove[YAW] != 0.) - { - check->priv.sv->client->ps.pmove.delta_angles[YAW] += ANGLE2SHORT(amove[YAW]); - check->priv.sv->client->ps.viewangles[YAW] += amove[YAW]; - - // PM_FREEZE makes the turn smooth, even though it will - // be turned off by ClientThink in the very next video frame - check->priv.sv->client->ps.pmove.pm_type = PM_FREEZE; - // PMF_NO_PREDICTION overrides .exe's client physics, which - // really doesn't like for us to change player angles. Note - // that this isn't strictly necessary, since Lazarus 1.7 and - // later automatically turn prediction off (in ClientThink) when - // player is riding a MOVETYPE_PUSH - check->priv.sv->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION; - } - if(amove[PITCH] != 0.) - { - float delta_yaw; - float pitch = amove[PITCH]; - - delta_yaw = check->progs.sv->angles[YAW] - pusher->progs.sv->angles[YAW]; - delta_yaw *= M_PI / 180.; - pitch *= cos(delta_yaw); - check->priv.sv->client->ps.pmove.delta_angles[PITCH] += ANGLE2SHORT(pitch); - check->priv.sv->client->ps.viewangles[PITCH] += pitch; - check->priv.sv->client->ps.pmove.pm_type = PM_FREEZE; - check->priv.sv->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION; - } - } - } - - // Lazarus: This is where we attempt to move check due to a rotation, WITHOUT embedding - // check in pusher (or anything else) - if(check->progs.sv->groundentity == PRVM_EDICT_TO_PROG(pusher)) - { - if((amove[PITCH] != 0) || (amove[YAW] != 0) || (amove[ROLL] != 0)) - { - // figure movement due to the pusher's amove - VectorAdd(check->progs.sv->origin,check->progs.sv->origin_offset,org_check); - VectorSubtract (org_check, pusher->progs.sv->origin, org); - org2[0] = DotProduct (org, forward); - org2[1] = -DotProduct (org, right); - org2[2] = DotProduct (org, up); - VectorSubtract (org2, org, move2); - VectorAdd (check->progs.sv->origin, move2, check->progs.sv->origin); - if((amove[PITCH] != 0) || (amove[ROLL] != 0)) - { - VectorCopy(check->progs.sv->origin,org); - org[2] += 2*check->progs.sv->mins[2]; - tr = SV_Trace(check->progs.sv->origin,vec3_origin,vec3_origin,org,check,MASK_SOLID); - if(!tr.startsolid && tr.fraction < 1) - check->progs.sv->origin[2] = tr.endpos[2] - check->progs.sv->mins[2] + fabs(tr.plane.normal[0])*check->progs.sv->size[0]/2 + fabs(tr.plane.normal[1])*check->progs.sv->size[1]/2; - - // Lazarus: func_tracktrain is a special case. Since we KNOW (if the map was - // constructed properly) that "post_origin" is a safe position, we - // can infer that there should be a safe (not embedded) position - // somewhere between post_origin and the proposed new location. - if(((int)pusher->progs.sv->flags & FL_TRACKTRAIN) && (check->priv.sv->client || ((int)check->progs.sv->flags & FL_MONSTER))) - { - vec3_t f,l,u; - - AngleVectors(pusher->progs.sv->angles, f, l, u); - VectorScale(f,pusher->progs.sv->post_origin[0],f); - VectorScale(l,-pusher->progs.sv->post_origin[1],l); - VectorAdd(pusher->progs.sv->origin,f,org); - VectorAdd(org,l,org); - org[2] += pusher->progs.sv->post_origin[2] + 1; - org[2] += 16 * ( fabs(u[0]) + fabs(u[1]) ); - tr = SV_Trace(org,check->progs.sv->mins,check->progs.sv->maxs,check->progs.sv->origin,check,MASK_SOLID); - if(!tr.startsolid) - { - VectorCopy(tr.endpos,check->progs.sv->origin); - VectorCopy(check->progs.sv->origin,org); - org[2] -= 128; - tr = SV_Trace(check->progs.sv->origin,check->progs.sv->mins,check->progs.sv->maxs,org,check,MASK_SOLID); - if(tr.fraction > 0) - VectorCopy(tr.endpos,check->progs.sv->origin); - } - } - } - } - } - - // may have pushed them off an edge - if (check->progs.sv->groundentity != PRVM_EDICT_TO_PROG(pusher)) check->progs.sv->groundentity = 0; - - block = SV_TestEntityPosition (check); - - if (block && ((int)pusher->progs.sv->flags & FL_TRACKTRAIN) && (check->priv.sv->client || ((int)check->progs.sv->flags & FL_MONSTER)) && (check->progs.sv->groundentity == PRVM_EDICT_TO_PROG(pusher))) - { - // Lazarus: Last hope. If this doesn't get rider out of the way he's - // gonna be stuck. - vec3_t f,l,u; - - AngleVectors(pusher->progs.sv->angles, f, l, u); - VectorScale(f,pusher->progs.sv->post_origin[0],f); - VectorScale(l,-pusher->progs.sv->post_origin[1],l); - VectorAdd(pusher->progs.sv->origin,f,org); - VectorAdd(org,l,org); - org[2] += pusher->progs.sv->post_origin[2] + 1; - org[2] += 16 * ( fabs(u[0]) + fabs(u[1]) ); - tr = SV_Trace(org,check->progs.sv->mins,check->progs.sv->maxs,check->progs.sv->origin,check,MASK_SOLID); - if(!tr.startsolid) - { - VectorCopy(tr.endpos,check->progs.sv->origin); - VectorCopy(check->progs.sv->origin,org); - org[2] -= 128; - tr = SV_Trace(check->progs.sv->origin,check->progs.sv->mins,check->progs.sv->maxs,org,check,MASK_SOLID); - if(tr.fraction > 0) - VectorCopy(tr.endpos,check->progs.sv->origin); - block = SV_TestEntityPosition (check); - } - } - - if (!block) - { // pushed ok - SV_LinkEdict (check); - // Lazarus: Move check riders, and riders of riders, and... well, you get the pic - VectorAdd(move, move2, move3); - MoveRiders_r(check,NULL,move3,amove,turn); - continue; // impact? - } - - // if it is ok to leave in the old position, do it - // this is only relevent for riding entities, not pushed - VectorSubtract (check->progs.sv->origin, move, check->progs.sv->origin); - VectorSubtract (check->progs.sv->origin, move2, check->progs.sv->origin); - if(turn) - { - // Argh! - angle - check->progs.sv->angles[YAW] -= amove[YAW]; - if(check->priv.sv->client) - { - check->priv.sv->client->ps.pmove.delta_angles[YAW] -= ANGLE2SHORT(amove[YAW]); - check->priv.sv->client->ps.viewangles[YAW] -= amove[YAW]; - } - } - - block = SV_TestEntityPosition (check); - if (!block) - { - pushed_p--; - continue; - } - } - - // save off the obstacle so we can call the block function - obstacle = check; - - // move back any entities we already moved - // go backwards, so if the same entity was pushed - // twice, it goes back to the original position - for (p=pushed_p-1 ; p>=pushed ; p--) - { - VectorCopy (p->origin, p->ent->progs.sv->origin); - VectorCopy (p->angles, p->ent->progs.sv->angles); - if (p->ent->priv.sv->client) - { - p->ent->priv.sv->client->ps.pmove.delta_angles[YAW] = p->deltayaw; - } - SV_LinkEdict (p->ent); - } - return false; - } - - //FIXME: is there a better way to handle this? - // see if anything we moved has touched a trigger - for (p = pushed_p - 1; p >= pushed; p--) - SV_TouchTriggers (p->ent); - return true; -} - -/* -================ -SV_Physics_Pusher - -Bmodel objects don't interact with each other, but -push all box objects -================ -*/ -void SV_Physics_Pusher (edict_t *ent) -{ - vec3_t move, amove; - edict_t *part = ent; - - // make sure all team slaves can move before commiting - // any moves or calling any think functions - // if the move is blocked, all moved objects will be backed out - pushed_p = pushed; - - if (part->progs.sv->velocity[0] || part->progs.sv->velocity[1] || part->progs.sv->velocity[2] || part->progs.sv->avelocity[0] || part->progs.sv->avelocity[1] || part->progs.sv->avelocity[2]) - { - // object is moving - VectorScale (part->progs.sv->velocity, sv.frametime, move); - VectorScale (part->progs.sv->avelocity, sv.frametime, amove); - - SV_Push(part, move, amove); // move was blocked - } - - if (pushed_p > &pushed[MAX_EDICTS]) - PRVM_ERROR("pushed_p > &pushed[MAX_EDICTS], memory corrupted"); - - SV_RunThink (part); -} - -//================================================================== - -/* -============= -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->progs.sv->angles, 0.1f, ent->progs.sv->avelocity, ent->progs.sv->angles); - VectorMA (ent->progs.sv->origin, 0.1f, ent->progs.sv->velocity, ent->progs.sv->origin); - - SV_LinkEdict(ent); -} - -/* -============================================================================== - -TOSS / BOUNCE - -============================================================================== -*/ - -/* -============= -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; - bool wasinwater; - bool isinwater; - vec3_t old_origin; - - // regular thinking - SV_RunThink (ent); - - if (ent->progs.sv->groundentity) wasonground = true; - - if (ent->progs.sv->velocity[2] > 0) ent->progs.sv->groundentity = 0; - - // check for the groundentity going away - if (ent->progs.sv->groundentity) - if (PRVM_PROG_TO_EDICT(ent->progs.sv->groundentity)->priv.sv->free) - ent->progs.sv->groundentity = 0; - - // Lazarus: conveyor - if (ent->progs.sv->groundentity && (PRVM_PROG_TO_EDICT(ent->progs.sv->groundentity)->progs.sv->movetype == MOVETYPE_CONVEYOR)) - { - vec3_t point, end; - trace_t tr; - edict_t *ground = PRVM_PROG_TO_EDICT(ent->progs.sv->groundentity); - - VectorCopy(ent->progs.sv->origin,point); - point[2] += 1; - VectorCopy(point,end); - end[2] -= 256; - tr = SV_Trace (point, ent->progs.sv->mins, ent->progs.sv->maxs, end, ent, MASK_SOLID); - // tr.ent HAS to be ground, but just in case we screwed something up: - if(tr.ent == ground) - { - onconveyor = true; - ent->progs.sv->velocity[0] = ground->progs.sv->movedir[0] * ground->progs.sv->speed; - ent->progs.sv->velocity[1] = ground->progs.sv->movedir[1] * ground->progs.sv->speed; - if(tr.plane.normal[2] > 0) - { - ent->progs.sv->velocity[2] = ground->progs.sv->speed * sqrt(1.0 - tr.plane.normal[2]*tr.plane.normal[2]) / tr.plane.normal[2]; - if(DotProduct(ground->progs.sv->movedir,tr.plane.normal) > 0) - { - // then we're moving down - ent->progs.sv->velocity[2] = -ent->progs.sv->velocity[2]; - } - } - VectorScale (ent->progs.sv->velocity, 0.1f, move); - trace = SV_PushEntity (ent, move); - if (ent->priv.sv->free) return; - SV_CheckGround(ent); - } - } - - // if onground, return without moving - if ( ent->progs.sv->groundentity ) - return; - - VectorCopy (ent->progs.sv->origin, old_origin); - - SV_CheckVelocity (ent); - - // add gravity - if (ent->progs.sv->movetype != MOVETYPE_FLY) - SV_AddGravity (ent); - - // move angles - VectorMA (ent->progs.sv->angles, 0.1f, ent->progs.sv->avelocity, ent->progs.sv->angles); - - // move origin - VectorScale (ent->progs.sv->velocity, 0.1f, move); - trace = SV_PushEntity (ent, move); - if (ent->priv.sv->free) return; - - if (trace.fraction < 1 ) - { - if (ent->progs.sv->movetype == MOVETYPE_BOUNCE) - backoff = 1.0 + 0.5f; - else if(trace.plane.normal[2] <= 0.7) // Lazarus - don't stop on steep incline - backoff = 1.5; - else - backoff = 1; - - ClipVelocity (ent->progs.sv->velocity, trace.plane.normal, ent->progs.sv->velocity, backoff); - - // stop if on ground - if (trace.plane.normal[2] > 0.7) - { - if (ent->progs.sv->velocity[2] < 60.0f || (ent->progs.sv->movetype != MOVETYPE_BOUNCE) ) - { - ent->progs.sv->groundentity = PRVM_EDICT_TO_PROG(trace.ent); - VectorCopy (vec3_origin, ent->progs.sv->velocity); - VectorCopy (vec3_origin, ent->progs.sv->avelocity); - } - } - } - - // check for water transition - wasinwater = ((int)ent->progs.sv->watertype & MASK_WATER); - ent->progs.sv->watertype = SV_PointContents (ent->progs.sv->origin); - isinwater = (int)ent->progs.sv->watertype & MASK_WATER; - - if (isinwater) ent->progs.sv->waterlevel = 1; - else ent->progs.sv->waterlevel = 0; - - if (!wasinwater && isinwater) - SV_StartSound(old_origin, prog->edicts, CHAN_AUTO, SV_SoundIndex("misc/h2ohit1.wav"), 1, 1, 0); - else if (wasinwater && !isinwater) - SV_StartSound(ent->progs.sv->origin, prog->edicts, CHAN_AUTO, SV_SoundIndex("misc/h2ohit1.wav"), 1, 1, 0); -} - -/* -=============================================================================== - -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. -FIXME: is this true? -============= -*/ -//FIXME: hacked in for E3 demo -#define sv_stopspeed 100 -#define sv_friction 6 -#define sv_waterfriction 1 - -void SV_AddRotationalFriction (edict_t *ent) -{ - int n; - float adjustment; - - VectorMA (ent->progs.sv->angles, 0.1f, ent->progs.sv->avelocity, ent->progs.sv->angles); - adjustment = 0.1f * sv_stopspeed * sv_friction; - - for (n = 0; n < 3; n++) - { - if (ent->progs.sv->avelocity[n] > 0) - { - ent->progs.sv->avelocity[n] -= adjustment; - if (ent->progs.sv->avelocity[n] < 0) - ent->progs.sv->avelocity[n] = 0; - } - else - { - ent->progs.sv->avelocity[n] += adjustment; - if (ent->progs.sv->avelocity[n] > 0) - ent->progs.sv->avelocity[n] = 0; - } - } -} - -#define WATER_DENSITY 0.00190735 - -float RiderMass(edict_t *platform) -{ - float mass = 0; - int i; - edict_t *rider; - trace_t trace; - vec3_t point; - - for(i = 1, rider = PRVM_EDICT_NUM(i); i <= prog->num_edicts; i++, rider = PRVM_EDICT_NUM(i)) - { - if(rider == platform) continue; - if(rider->priv.sv->free) continue; - if(rider->progs.sv->groundentity == PRVM_EDICT_TO_PROG(platform)) - { - mass += rider->progs.sv->mass; - mass += RiderMass(rider); - } - else if (rider->progs.sv->movetype == MOVETYPE_PUSHABLE ) - { - // Bah - special case for func_pushable riders. Swimming - // func_pushables don't really have a groundentity, even - // though they may be sitting on another swimming - // func_pushable, which is what we need to know. - VectorCopy(rider->progs.sv->origin,point); - point[2] -= 0.25; - trace = SV_Trace (rider->progs.sv->origin, rider->progs.sv->mins, rider->progs.sv->maxs, point, rider, MASK_MONSTERSOLID); - if ( trace.plane.normal[2] < 0.7 && !trace.startsolid) - continue; - if (!trace.startsolid && !trace.allsolid) - { - if(trace.ent == platform) - { - mass += rider->progs.sv->mass; - mass += RiderMass(rider); - } - } - } - } - return mass; -} - -void SV_Physics_Step (edict_t *ent) -{ - bool hitsound = false; - float *vel; - float speed, newspeed, control; - float friction, volume; - edict_t *ground; - edict_t *e; - int cont; - int mask; - int i; - int oldwaterlevel; - vec3_t point, end; - vec3_t old_origin, move; - - // airborne monsters should always check for ground - if (!ent->progs.sv->groundentity) SV_CheckGround (ent); - - oldwaterlevel = ent->progs.sv->waterlevel; - - VectorCopy(ent->progs.sv->origin, old_origin); - - // Lazarus: If density hasn't been calculated yet, do so now - if (ent->progs.sv->mass > 0 && ent->progs.sv->density == 0.) - { - volume = ent->progs.sv->size[0] * ent->progs.sv->size[1] * ent->progs.sv->size[2]; - ent->progs.sv->density = ent->progs.sv->mass/volume; - } - - // If not a monster, then determine whether we're in water. - // (monsters take care of this in g_monster.c) - if (!((int)ent->progs.sv->flags & FL_MONSTER) && ((int)ent->progs.sv->aiflags && AI_SWIM) ) - { - point[0] = (ent->progs.sv->absmax[0] + ent->progs.sv->absmin[0])/2; - point[1] = (ent->progs.sv->absmax[1] + ent->progs.sv->absmin[1])/2; - point[2] = ent->progs.sv->absmin[2] + 1; - cont = SV_PointContents (point); - if (!(cont & MASK_WATER)) - { - ent->progs.sv->waterlevel = 0; - ent->progs.sv->watertype = 0; - } - else { - ent->progs.sv->watertype = cont; - ent->progs.sv->waterlevel = 1; - point[2] = ent->progs.sv->absmin[2] + ent->progs.sv->size[2]/2; - cont = SV_PointContents (point); - if (cont & MASK_WATER) - { - ent->progs.sv->waterlevel = 2; - point[2] = ent->progs.sv->absmax[2]; - cont = SV_PointContents (point); - if (cont & MASK_WATER) ent->progs.sv->waterlevel = 3; - } - } - } - - ground = PRVM_PROG_TO_EDICT(ent->progs.sv->groundentity); - - SV_CheckVelocity (ent); - - if (ground) wasonground = true; - - if (ent->progs.sv->avelocity[0] || ent->progs.sv->avelocity[1] || ent->progs.sv->avelocity[2]) - SV_AddRotationalFriction (ent); - - // add gravity except: - // flying monsters - // swimming monsters who are in the water - if (!wasonground) - { - if (!((int)ent->progs.sv->aiflags & AI_FLY)) - { - if (!(((int)ent->progs.sv->aiflags & AI_SWIM) && (ent->progs.sv->waterlevel > 2))) - { - if (ent->progs.sv->velocity[2] < sv_gravity->value*-0.1) - hitsound = true; - if (ent->progs.sv->waterlevel == 0) - SV_AddGravity (ent); - } - } - } - - // friction for flying monsters that have been given vertical velocity - if (((int)ent->progs.sv->aiflags & AI_FLY) && (ent->progs.sv->velocity[2] != 0)) - { - speed = fabs(ent->progs.sv->velocity[2]); - control = speed < sv_stopspeed ? sv_stopspeed : speed; - friction = sv_friction/3; - newspeed = speed - (0.1f * control * friction); - if (newspeed < 0) newspeed = 0; - newspeed /= speed; - ent->progs.sv->velocity[2] *= newspeed; - } - - // friction for swimming monsters that have been given vertical velocity - if (ent->progs.sv->movetype != MOVETYPE_PUSHABLE) - { - // Lazarus: This is id's swag at drag. It works mostly, but for submerged - // crates we can do better. - if (((int)ent->progs.sv->aiflags & AI_SWIM) && (ent->progs.sv->velocity[2] != 0)) - { - speed = fabs(ent->progs.sv->velocity[2]); - control = speed < sv_stopspeed ? sv_stopspeed : speed; - newspeed = speed - (0.1f * control * sv_waterfriction * ent->progs.sv->waterlevel); - if (newspeed < 0) newspeed = 0; - newspeed /= speed; - ent->progs.sv->velocity[2] *= newspeed; - } - } - - // Lazarus: Floating stuff - if ((ent->progs.sv->movetype == MOVETYPE_PUSHABLE) && ((int)ent->progs.sv->aiflags && AI_SWIM) && (ent->progs.sv->waterlevel)) - { - float waterlevel; - float rider_mass, total_mass; - trace_t tr; - float Accel, Area, Drag, Force; - - VectorCopy(point,end); - if(ent->progs.sv->waterlevel < 3) - { - point[2] = ent->progs.sv->absmax[2]; - end[2] = ent->progs.sv->absmin[2]; - tr = SV_Trace(point,NULL,NULL,end,ent,MASK_WATER); - waterlevel = tr.endpos[2]; - } - else - { - // Not right, but really all we need to know - waterlevel = ent->progs.sv->absmax[2] + 1; - } - rider_mass = RiderMass(ent); - total_mass = rider_mass + ent->progs.sv->mass; - Area = ent->progs.sv->size[0] * ent->progs.sv->size[1]; - if(waterlevel < ent->progs.sv->absmax[2]) - { - // A portion of crate is above water - // For partially submerged crates, use same psuedo-friction thing used - // on other entities. This isn't really correct, but then neither is - // our drag calculation used for fully submerged crates good for this - // situation - if (ent->progs.sv->velocity[2] != 0) - { - speed = fabs(ent->progs.sv->velocity[2]); - control = speed < sv_stopspeed ? sv_stopspeed : speed; - newspeed = speed - (0.1f * control * sv_waterfriction * ent->progs.sv->waterlevel); - if (newspeed < 0) newspeed = 0; - newspeed /= speed; - ent->progs.sv->velocity[2] *= newspeed; - } - - // Apply physics and bob AFTER friction, or the damn thing will never move. - Force = -total_mass + ((waterlevel-ent->progs.sv->absmin[2]) * Area * WATER_DENSITY); - Accel = Force * sv_gravity->value/total_mass; - ent->progs.sv->velocity[2] += Accel*0.1f; - } - else - { - // Crate is fully submerged - Force = -total_mass + volume * WATER_DENSITY; - if(sv_gravity->value) - { - Drag = 0.00190735 * 1.05 * Area * (ent->progs.sv->velocity[2]*ent->progs.sv->velocity[2])/sv_gravity->value; - if(Drag > fabs(Force)) - { - // Drag actually CAN be > total weight, but if we do this we tend to - // get crates flying back out of the water after being dropped from some - // height - Drag = fabs(Force); - } - if(ent->progs.sv->velocity[2] > 0) - Drag = -Drag; - Force += Drag; - } - Accel = Force * sv_gravity->value/total_mass; - ent->progs.sv->velocity[2] += Accel*0.1f; - } - - if((int)ent->progs.sv->watertype & MASK_CURRENT) - { - // Move with current, relative to mass. Mass=400 or less - // will move at 50 units/sec. - float v; - int current; - - if(ent->progs.sv->mass > 400) v = 0.125 * ent->progs.sv->mass; - else v = 50.; - current = (int)ent->progs.sv->watertype & MASK_CURRENT; - switch (current) - { - case CONTENTS_CURRENT_0: ent->progs.sv->velocity[0] = v; break; - case CONTENTS_CURRENT_90: ent->progs.sv->velocity[1] = v; break; - case CONTENTS_CURRENT_180: ent->progs.sv->velocity[0] = -v; break; - case CONTENTS_CURRENT_270: ent->progs.sv->velocity[1] = -v; break; - case CONTENTS_CURRENT_UP : ent->progs.sv->velocity[2] = max(v, ent->progs.sv->velocity[2]); - case CONTENTS_CURRENT_DOWN: ent->progs.sv->velocity[2] = min(-v, ent->progs.sv->velocity[2]); - } - } - } - - // Conveyor - if (wasonground && (ground->progs.sv->movetype == MOVETYPE_CONVEYOR)) - { - trace_t tr; - - VectorCopy(ent->progs.sv->origin,point); - point[2] += 1; - VectorCopy(point,end); - end[2] -= 256; - tr = SV_Trace (point, ent->progs.sv->mins, ent->progs.sv->maxs, end, ent, MASK_SOLID); - // tr.ent HAS to be ground, but just in case we screwed something up: - if(tr.ent == ground) - { - onconveyor = true; - ent->progs.sv->velocity[0] = ground->progs.sv->movedir[0] * ground->progs.sv->speed; - ent->progs.sv->velocity[1] = ground->progs.sv->movedir[1] * ground->progs.sv->speed; - if(tr.plane.normal[2] > 0) - { - ent->progs.sv->velocity[2] = ground->progs.sv->speed * sqrt(1.0 - tr.plane.normal[2]*tr.plane.normal[2]) / tr.plane.normal[2]; - if(DotProduct(ground->progs.sv->movedir,tr.plane.normal) > 0) - { - // Then we're moving down. - ent->progs.sv->velocity[2] = -ent->progs.sv->velocity[2] + 2; - } - } - } - } - - if (ent->progs.sv->velocity[2] || ent->progs.sv->velocity[1] || ent->progs.sv->velocity[0]) - { - int block; - // apply friction - // let dead monsters who aren't completely onground slide - - if ((wasonground) || ((int)ent->progs.sv->aiflags & (AI_SWIM|AI_FLY))) - - if (!onconveyor) - { - if (!(ent->progs.sv->health <= 0.0 && !SV_CheckBottom(ent))) - { - vel = ent->progs.sv->velocity; - speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]); - if (speed) - { - friction = sv_friction; - - control = speed < sv_stopspeed ? sv_stopspeed : speed; - newspeed = speed - 0.1f*control*friction; - - if (newspeed < 0) newspeed = 0; - newspeed /= speed; - - vel[0] *= newspeed; - vel[1] *= newspeed; - } - } - } - - if ((int)ent->progs.sv->flags & FL_MONSTER) mask = MASK_MONSTERSOLID; - else if(ent->progs.sv->movetype == MOVETYPE_PUSHABLE) mask = MASK_MONSTERSOLID | MASK_PLAYERSOLID; - else if(ent->priv.sv->clipmask) mask = ent->priv.sv->clipmask; // Lazarus edition - else mask = MASK_SOLID; - - if (ent->progs.sv->movetype == MOVETYPE_PUSHABLE) - { - block = SV_PushableMove (ent, 0.1f, mask); - if(block && !(block & 8) && onconveyor) - { - T_Damage(ent, prog->edicts, prog->edicts, vec3_origin, ent->progs.sv->origin, vec3_origin, 100000, 1, 0, DMG_CRUSH); - if(ent->priv.sv->free) return; - } - } - else - { - block = SV_FlyMove (ent, 0.1f, mask); - if(block && !(block & 8) && onconveyor) - { - T_Damage (ent, prog->edicts, prog->edicts, vec3_origin, ent->progs.sv->origin, vec3_origin, 100000, 1, 0, DMG_CRUSH); - if(ent->priv.sv->free) return; - } - } - SV_LinkEdict (ent); - SV_TouchTriggers (ent); - if (ent->priv.sv->free) return; - - if (ent->progs.sv->groundentity && !wasonground && hitsound) - { - SV_StartSound (NULL, ent, 0, SV_SoundIndex("world/land.wav"), 1, 1, 0); - } - - // Move func_pushable riders - if(ent->progs.sv->movetype == MOVETYPE_PUSHABLE) - { - trace_t tr; - - if(ent->progs.sv->bouncetype == 2) VectorMA(old_origin,0.1f,ent->progs.sv->velocity,ent->progs.sv->origin); - VectorSubtract(ent->progs.sv->origin,old_origin,move); - for(i = 1, e = PRVM_EDICT_NUM(i); i < prog->num_edicts; i++, e = PRVM_EDICT_NUM(i)) - { - if(e==ent) continue; - if(e->progs.sv->groundentity == PRVM_EDICT_TO_PROG(ent)) - { - VectorAdd(e->progs.sv->origin,move,end); - tr = SV_Trace(e->progs.sv->origin, e->progs.sv->mins, e->progs.sv->maxs, end, ent, MASK_SOLID); - VectorCopy(tr.endpos,e->progs.sv->origin); - SV_LinkEdict(e); - } - } - } - } - else if(ent->progs.sv->movetype == MOVETYPE_PUSHABLE) - { - // We run touch function for non-moving func_pushables every frame - // to see if they are touching, for example, a trigger_mass - SV_TouchTriggers(ent); - if(ent->priv.sv->free) return; - } - - - // Lazarus: Add falling damage for entities that can be damaged - if( ent->progs.sv->takedamage ) - { - SV_FallingDamage(ent); - VectorCopy(ent->progs.sv->velocity,ent->progs.sv->post_velocity); - } - - if ((!oldwaterlevel && ent->progs.sv->waterlevel) && !ent->progs.sv->groundentity) - { - if( ((int)ent->progs.sv->watertype & CONTENTS_SLIME) || ((int)ent->progs.sv->watertype & CONTENTS_WATER) ) - SV_StartSound (NULL, ent, CHAN_BODY, SV_SoundIndex("player/watr_in.wav"), 1, ATTN_NORM, 0); - else if((int)ent->progs.sv->watertype & CONTENTS_MUD) - SV_StartSound (NULL, ent, CHAN_BODY, SV_SoundIndex("mud/mud_in2.wav"), 1, ATTN_NORM, 0); - } - - // regular thinking - SV_RunThink (ent); - VectorCopy(ent->progs.sv->velocity,ent->progs.sv->post_velocity); -} - -//============================================================================ -/* -============ -SV_DebrisEntity - -Does not change the entities velocity at all -============ -*/ -trace_t SV_DebrisEntity (edict_t *ent, vec3_t push) -{ - trace_t trace; - vec3_t start; - vec3_t end; - vec3_t v1, v2; - vec_t dot, speed1, speed2; - float scale; - int damage; - int mask; - - VectorCopy (ent->progs.sv->origin, start); - VectorAdd (start, push, end); - if(ent->priv.sv->clipmask) mask = ent->priv.sv->clipmask; - else mask = MASK_SHOT; - - trace = SV_Trace (start, ent->progs.sv->mins, ent->progs.sv->maxs, end, ent, mask); - VectorCopy (trace.endpos, ent->progs.sv->origin); - SV_LinkEdict (ent); - - if (trace.fraction != 1.0) - { - if( (trace.surface) && (trace.surface->flags & SURF_SKY)) - { - SV_FreeEdict(ent); - return trace; - } - if(trace.ent->priv.sv->client || ((int)trace.ent->progs.sv->flags & FL_MONSTER) ) - { - // touching a player or monster - // if rock has no mass we really don't care who it hits - if(!ent->progs.sv->mass) return trace; - speed1 = VectorLength(ent->progs.sv->velocity); - if(!speed1) return trace; - speed2 = VectorLength(trace.ent->progs.sv->velocity); - VectorCopy(ent->progs.sv->velocity,v1); - VectorNormalize(v1); - VectorCopy(trace.ent->progs.sv->velocity,v2); - VectorNormalize(v2); - dot = -DotProduct(v1,v2); - speed1 += speed2 * dot; - if(speed1 <= 0) return trace; - scale = (float)ent->progs.sv->mass/200.*speed1; - VectorMA(trace.ent->progs.sv->velocity,scale,v1,trace.ent->progs.sv->velocity); - // Take a swag at it... - - if(speed1 > 100) - { - damage = (int)(ent->progs.sv->mass * speed1 / 5000.); - if(damage) T_Damage(trace.ent, prog->edicts, prog->edicts, v1, trace.ent->progs.sv->origin, vec3_origin, damage, 0, 0, DMG_CRUSH); - } - - PRVM_PUSH_GLOBALS; - - prog->globals.server->pev = PRVM_EDICT_TO_PROG(ent); - prog->globals.server->other = PRVM_EDICT_TO_PROG(trace.ent); //correct ? - prog->globals.server->time = sv.time; - prog->globals.server->trace_allsolid = trace.allsolid; - prog->globals.server->trace_startsolid = trace.startsolid; - prog->globals.server->trace_fraction = trace.fraction; - prog->globals.server->trace_contents = trace.contents; - VectorCopy (trace.endpos, prog->globals.server->trace_endpos); - VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal); - prog->globals.server->trace_plane_dist = trace.plane.dist; - if (trace.ent) prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent); - else prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts); - PRVM_ExecuteProgram (ent->progs.sv->touch, "QC function pev->touch is missing"); - PRVM_POP_GLOBALS; - - SV_LinkEdict(trace.ent); - } - else - { - SV_Impact (ent, &trace); - } - } - return trace; -} - -/* -============= -SV_Physics_Debris - -Toss, bounce, and fly movement. When onground, do nothing. -============= -*/ -void SV_Physics_Debris (edict_t *ent) -{ - trace_t trace; - vec3_t move; - float backoff; - bool wasinwater; - bool isinwater; - vec3_t old_origin; - - // regular thinking - SV_RunThink (ent); - - if (ent->progs.sv->velocity[2] > 0) - ent->progs.sv->groundentity = 0; - - // check for the groundentity going away - if (ent->progs.sv->groundentity) - if (PRVM_PROG_TO_EDICT(ent->progs.sv->groundentity)->priv.sv->free) - ent->progs.sv->groundentity = 0; - - // if onground, return without moving - if ( ent->progs.sv->groundentity ) - return; - - VectorCopy (ent->progs.sv->origin, old_origin); - SV_CheckVelocity (ent); - SV_AddGravity (ent); - - // move angles - VectorMA (ent->progs.sv->angles, 0.1f, ent->progs.sv->avelocity, ent->progs.sv->angles); - - // move origin - VectorScale (ent->progs.sv->velocity, 0.1f, move); - trace = SV_DebrisEntity (ent, move); - if (ent->priv.sv->free) return; - - if (trace.fraction < 1) - { - backoff = 1.0; - ClipVelocity (ent->progs.sv->velocity, trace.plane.normal, ent->progs.sv->velocity, backoff); - - // stop if on ground - if (trace.plane.normal[2] > 0.3) - { - if (ent->progs.sv->velocity[2] < 60) - { - ent->progs.sv->groundentity = PRVM_EDICT_TO_PROG(trace.ent); - VectorCopy (vec3_origin, ent->progs.sv->velocity); - VectorCopy (vec3_origin, ent->progs.sv->avelocity); - } - } - } - - // check for water transition - wasinwater = ((int)ent->progs.sv->watertype & MASK_WATER); - ent->progs.sv->watertype = SV_PointContents (ent->progs.sv->origin); - isinwater = (int)ent->progs.sv->watertype & MASK_WATER; - - if (isinwater) ent->progs.sv->waterlevel = 1; - else ent->progs.sv->waterlevel = 0; - - if (!wasinwater && isinwater) SV_StartSound (old_origin, prog->edicts, CHAN_AUTO, SV_SoundIndex("misc/h2ohit1.wav"), 1, 1, 0); - else if (wasinwater && !isinwater) SV_StartSound (ent->progs.sv->origin, prog->edicts, CHAN_AUTO, SV_SoundIndex("misc/h2ohit1.wav"), 1, 1, 0); - -} - -/* -==================== -SV_Physics_Conveyor - -REAL simple - all we do is check for player riders and adjust their position. -Only gotcha here is we have to make sure we don't end up embedding player in -*another* object that's being moved by the conveyor. - -==================== -*/ -void SV_Physics_Conveyor(edict_t *ent) -{ - edict_t *player; - int i; - trace_t tr; - vec3_t v, move; - vec3_t point, end; - - VectorScale(ent->progs.sv->movedir,ent->progs.sv->speed,v); - VectorScale(v, 0.1f, move); - - for(i = 0; i < maxclients->value; i++) - { - player = PRVM_EDICT_NUM(i) + 1; - if(player->priv.sv->free) continue; - if(!player->progs.sv->groundentity) continue; - if(player->progs.sv->groundentity != PRVM_EDICT_TO_PROG(ent)) continue; - - // Look below player; make sure he's on a conveyor - VectorCopy(player->progs.sv->origin,point); - point[2] += 1; - VectorCopy(point,end); - end[2] -= 256; - - tr = SV_Trace (point, player->progs.sv->mins, player->progs.sv->maxs, end, player, MASK_SOLID); - // tr.ent HAS to be conveyor, but just in case we screwed something up: - if(tr.ent == ent) - { - if(tr.plane.normal[2] > 0) - { - v[2] = ent->progs.sv->speed * sqrt(1.0 - tr.plane.normal[2]*tr.plane.normal[2]) / tr.plane.normal[2]; - if(DotProduct(ent->progs.sv->movedir,tr.plane.normal) > 0) - { - // then we're moving down - v[2] = -v[2]; - } - move[2] = v[2] * 0.1f; - } - VectorAdd(player->progs.sv->origin,move,end); - tr = SV_Trace(player->progs.sv->origin,player->progs.sv->mins,player->progs.sv->maxs,end,player,player->priv.sv->clipmask); - VectorCopy(tr.endpos,player->progs.sv->origin); - SV_LinkEdict(player); - } - } -} - -void SV_Physics(edict_t *ent) -{ - wasonground = false; - onconveyor = false; - - switch ((int)ent->progs.sv->movetype) - { - case MOVETYPE_NONE: - SV_Physics_None (ent); - break; - case MOVETYPE_PUSH: - SV_MovetypePush (ent); - //SV_Physics_Pusher (ent); - break; - case MOVETYPE_NOCLIP: - SV_Physics_Noclip (ent); - break; - case MOVETYPE_STEP: - SV_Physics_Step (ent); - break; - case MOVETYPE_TOSS: - case MOVETYPE_BOUNCE: - case MOVETYPE_FLY: - SV_Physics_Toss (ent); - break; - case MOVETYPE_WALK: - SV_Physics_None(ent); - break; - case MOVETYPE_CONVEYOR: - SV_Physics_Conveyor(ent); - break; - default: - PRVM_ERROR ("SV_Physics: bad movetype %i", (int)ent->progs.sv->movetype); - } -} \ No newline at end of file diff --git a/engine/server/sv_physics.c b/engine/server/sv_physics.c index dbd6c585..3f0cd343 100644 --- a/engine/server/sv_physics.c +++ b/engine/server/sv_physics.c @@ -6,6 +6,8 @@ #include "engine.h" #include "server.h" +#define STEPSIZE 18 + /* ============ SV_ClampMove @@ -28,6 +30,749 @@ void SV_ClampAngle( vec3_t angle ) angle[2] -= SV_ANGLE_FRAC * floor(angle[2] * CL_ANGLE_FRAC); } +/* +============ +SV_CalcBBox + +Returns the actual bounding box of a bmodel. This is a big improvement over +what q2 normally does with rotating bmodels - q2 sets absmin, absmax to a cube +that will completely contain the bmodel at *any* rotation on *any* axis, whether +the bmodel can actually rotate to that angle or not. This leads to a lot of +false block tests in SV_Push if another bmodel is in the vicinity. +============ +*/ +void SV_CalcBBox(edict_t *ent, vec3_t mins, vec3_t maxs) +{ + vec3_t forward, left, up, f1, l1, u1; + vec3_t p[8]; + int i, j, k, j2, k4; + + for(k = 0; k < 2; k++) + { + k4 = k * 4; + if(k) p[k4][2] = ent->progs.sv->maxs[2]; + else p[k4][2] = ent->progs.sv->mins[2]; + + p[k4 + 1][2] = p[k4][2]; + p[k4 + 2][2] = p[k4][2]; + p[k4 + 3][2] = p[k4][2]; + + for(j = 0; j < 2; j++) + { + j2 = j * 2; + if(j) p[j2+k4][1] = ent->progs.sv->maxs[1]; + else p[j2+k4][1] = ent->progs.sv->mins[1]; + p[j2 + k4 + 1][1] = p[j2 + k4][1]; + + for(i = 0; i < 2; i++) + { + if(i) p[i + j2 + k4][0] = ent->progs.sv->maxs[0]; + else p[i + j2 + k4][0] = ent->progs.sv->mins[0]; + } + } + } + + AngleVectors(ent->progs.sv->angles, forward, left, up); + + for(i = 0; i < 8; i++) + { + VectorScale(forward, p[i][0], f1); + VectorScale(left, -p[i][1], l1); + VectorScale(up, p[i][2], u1); + VectorAdd(ent->progs.sv->origin, f1, p[i]); + VectorAdd(p[i], l1, p[i]); + VectorAdd(p[i], u1, p[i]); + } + + VectorCopy(p[0],mins); + VectorCopy(p[0],maxs); + + for(i = 1; i < 8; i++) + { + mins[0] = min(mins[0], p[i][0]); + mins[1] = min(mins[1], p[i][1]); + mins[2] = min(mins[2], p[i][2]); + maxs[0] = max(maxs[0], p[i][0]); + maxs[1] = max(maxs[1], p[i][1]); + maxs[2] = max(maxs[2], p[i][2]); + } +} + +/* +================== +ClipVelocity + +Slide off of the impacting object +returns the blocked flags (1 = floor, 2 = step / wall) +================== +*/ +void SV_ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce) +{ + int i; + float backoff; + + backoff = -DotProduct (in, normal) * overbounce; + VectorMA(in, backoff, normal, out); + + for (i = 0; i < 3; i++) + { + if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON) + out[i] = 0; + } +} + +/* +============= +SV_CheckBottom + +Returns false if any part of the bottom of the entity is off an edge that +is not a staircase. + +============= +*/ +int c_yes, c_no; + +bool SV_CheckBottom (edict_t *ent) +{ + vec3_t mins, maxs, start, stop; + trace_t trace; + int x, y; + float mid, bottom; + + VectorAdd (ent->progs.sv->origin, ent->progs.sv->mins, mins); + VectorAdd (ent->progs.sv->origin, ent->progs.sv->maxs, maxs); + + // if all of the points under the corners are solid world, don't bother + // with the tougher checks + // the corners must be within 16 of the midpoint + start[2] = mins[2] - 1; + + for (x = 0; x <= 1; x++) + { + for (y = 0; y <= 1; y++) + { + start[0] = x ? maxs[0] : mins[0]; + start[1] = y ? maxs[1] : mins[1]; + if (SV_PointContents(start) != CONTENTS_SOLID) + goto realcheck; + } + } + + c_yes++; + return true; // we got out easy + +realcheck: + c_no++; + + // check it for real... + start[2] = mins[2]; + + // the midpoint must be within 16 of the bottom + start[0] = stop[0] = (mins[0] + maxs[0])*0.5; + start[1] = stop[1] = (mins[1] + maxs[1])*0.5; + stop[2] = start[2] - 2*STEPSIZE; + trace = SV_Trace (start, vec3_origin, vec3_origin, stop, ent, MASK_MONSTERSOLID); + + if (trace.fraction == 1.0) + return false; + mid = bottom = trace.endpos[2]; + + // the corners must be within 16 of the midpoint + for (x = 0; x <= 1; x++) + { + for ( y = 0; y <= 1; y++) + { + start[0] = stop[0] = x ? maxs[0] : mins[0]; + start[1] = stop[1] = y ? maxs[1] : mins[1]; + + trace = SV_Trace (start, vec3_origin, vec3_origin, stop, ent, MASK_MONSTERSOLID); + + if (trace.fraction != 1.0 && trace.endpos[2] > bottom) + bottom = trace.endpos[2]; + if (trace.fraction == 1.0 || mid - trace.endpos[2] > STEPSIZE) + return false; + } + } + + c_yes++; + return true; +} + +/* +====================== +SV_FixCheckBottom + +====================== +*/ +void SV_FixCheckBottom (edict_t *ent) +{ + ent->progs.sv->aiflags = (int)ent->progs.sv->aiflags | AI_PARTIALONGROUND; +} + + +void SV_CheckVelocity (edict_t *ent) +{ + int i; + float wishspeed; + + // bound velocity + for (i = 0; i < 3; i++) + { + if (IS_NAN(ent->progs.sv->velocity[i])) + { + MsgWarn("Got a NaN velocity on %s\n", PRVM_GetString(ent->progs.sv->classname)); + ent->progs.sv->velocity[i] = 0; + } + if (IS_NAN(ent->progs.sv->origin[i])) + { + MsgWarn("Got a NaN origin on %s\n", PRVM_GetString(ent->progs.sv->classname)); + ent->progs.sv->origin[i] = 0; + } + } + + // LordHavoc: max velocity fix, inspired by Maddes's source fixes, but this is faster + wishspeed = DotProduct(ent->progs.sv->velocity, ent->progs.sv->velocity); + if (wishspeed > sv_maxvelocity->value * sv_maxvelocity->value) + { + wishspeed = sv_maxvelocity->value / sqrt(wishspeed); + ent->progs.sv->velocity[0] *= wishspeed; + ent->progs.sv->velocity[1] *= wishspeed; + ent->progs.sv->velocity[2] *= wishspeed; + } +} + +/* +============ +SV_WallFriction + +============ +*/ +void SV_WallFriction (edict_t *ent, float *stepnormal) +{ + float d, i; + vec3_t forward, into, side; + + AngleVectors (ent->progs.sv->v_angle, forward, NULL, NULL); + if ((d = DotProduct (stepnormal, forward) + 0.5) < 0) + { + // cut the tangential velocity + i = DotProduct (stepnormal, ent->progs.sv->velocity); + VectorScale (stepnormal, i, into); + VectorSubtract (ent->progs.sv->velocity, into, side); + ent->progs.sv->velocity[0] = side[0] * (1 + d); + ent->progs.sv->velocity[1] = side[1] * (1 + d); + } +} + +/* +================== +SV_Impact + +Two entities have touched, so run their touch functions +================== +*/ +void SV_Impact (edict_t *e1, trace_t *trace) +{ + edict_t *e2 = (edict_t *)trace->ent; + + PRVM_PUSH_GLOBALS; + + prog->globals.server->time = sv.time; + if (!e1->priv.sv->free && !e2->priv.sv->free && e1->progs.sv->touch && e1->progs.sv->solid != SOLID_NOT) + { + prog->globals.server->pev = PRVM_EDICT_TO_PROG(e1); + prog->globals.server->other = PRVM_EDICT_TO_PROG(e2); + prog->globals.server->time = sv.time; + prog->globals.server->trace_allsolid = trace->allsolid; + prog->globals.server->trace_startsolid = trace->startsolid; + prog->globals.server->trace_fraction = trace->fraction; + prog->globals.server->trace_contents = trace->contents; + VectorCopy (trace->endpos, prog->globals.server->trace_endpos); + VectorCopy (trace->plane.normal, prog->globals.server->trace_plane_normal); + prog->globals.server->trace_plane_dist = trace->plane.dist; + if (trace->ent) prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace->ent); + else prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts); + PRVM_ExecuteProgram (e1->progs.sv->touch, "QC function pev->touch is missing"); + } + if (!e1->priv.sv->free && !e2->priv.sv->free && e2->progs.sv->touch && e2->progs.sv->solid != SOLID_NOT) + { + prog->globals.server->pev = PRVM_EDICT_TO_PROG(e2); + prog->globals.server->other = PRVM_EDICT_TO_PROG(e1); + prog->globals.server->time = sv.time; + prog->globals.server->trace_allsolid = false; + prog->globals.server->trace_startsolid = false; + prog->globals.server->trace_fraction = 1; + prog->globals.server->trace_contents = trace->contents; + VectorCopy (e2->progs.sv->origin, prog->globals.server->trace_endpos); + VectorSet (prog->globals.server->trace_plane_normal, 0, 0, 1); + prog->globals.server->trace_plane_dist = 0; + prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(e1); + PRVM_ExecuteProgram (e2->progs.sv->touch, "QC function pev->touch is missing"); + } + + PRVM_POP_GLOBALS; +} + +/* +============ +SV_TestEntityPosition + +============ +*/ +edict_t *SV_TestEntityPosition (edict_t *ent) +{ + trace_t trace; + int mask; + + if (ent->priv.sv->clipmask) mask = ent->priv.sv->clipmask; + else mask = MASK_SOLID; + + if(ent->progs.sv->solid == SOLID_BSP) + { + vec3_t org, mins, maxs; + VectorAdd(ent->progs.sv->origin, ent->progs.sv->origin_offset, org); + VectorSubtract(ent->progs.sv->mins, ent->progs.sv->origin_offset, mins); + VectorSubtract(ent->progs.sv->maxs, ent->progs.sv->origin_offset, maxs); + trace = SV_Trace (org, mins, maxs, org, ent, mask); + } + else trace = SV_Trace (ent->progs.sv->origin, ent->progs.sv->mins, ent->progs.sv->maxs, ent->progs.sv->origin, ent, mask); + + if (trace.startsolid) + { + // Lazarus - work around for players/monsters standing on dead monsters causing + // those monsters to gib when rotating brush models are in the vicinity + if ( ((int)ent->progs.sv->flags & FL_DEADMONSTER) && (trace.ent->priv.sv->client || ((int)trace.ent->progs.sv->flags & FL_MONSTER))) + return NULL; + + // Lazarus - return a bit more useful info than simply "g_edicts" + if(trace.ent) return trace.ent; + else return prog->edicts; + } + + return NULL; +} + +/* +============= +SV_CheckStuck + +This is a big hack to try and fix the rare case of getting stuck in the world +clipping hull. +============= +*/ +static void SV_CheckStuck (edict_t *ent) +{ + int i, j, z; + vec3_t org; + + if (!SV_TestEntityPosition(ent)) + { + VectorCopy (ent->progs.sv->origin, ent->progs.sv->old_origin); + return; + } + + VectorCopy (ent->progs.sv->origin, org); + VectorCopy (ent->progs.sv->old_origin, ent->progs.sv->origin); + if (!SV_TestEntityPosition(ent)) + { + MsgWarn("Unstuck player entity %i (classname \"%s\") by restoring old_origin.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->progs.sv->classname)); + SV_LinkEdict (ent); + return; + } + + for (z=-1 ; z< 18 ; z++) + for (i=-1 ; i <= 1 ; i++) + for (j=-1 ; j <= 1 ; j++) + { + ent->progs.sv->origin[0] = org[0] + i; + ent->progs.sv->origin[1] = org[1] + j; + ent->progs.sv->origin[2] = org[2] + z; + if (!SV_TestEntityPosition(ent)) + { + MsgWarn("Unstuck player entity %i (classname \"%s\") with offset %f %f %f.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->progs.sv->classname), (float)i, (float)j, (float)z); + SV_LinkEdict (ent); + return; + } + } + + VectorCopy (org, ent->progs.sv->origin); + MsgWarn("Stuck player entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->progs.sv->classname)); +} + +static void SV_UnstickEntity (edict_t *ent) +{ + int x, y, z; + vec3_t org; + + // if not stuck in a bmodel, just return + if (!SV_TestEntityPosition(ent)) + return; + + VectorCopy (ent->progs.sv->origin, org); + + for (z = -1; z < 18; z += 6) + { + for (x = -1; x <= 1; x++) + { + for (y = -1; y <= 1; y++) + { + ent->progs.sv->origin[0] = org[0] + x; + ent->progs.sv->origin[1] = org[1] + y; + ent->progs.sv->origin[2] = org[2] + z; + if (!SV_TestEntityPosition(ent)) + { + MsgDev(D_INFO, "Unstuck entity %i (classname \"%s\") with offset %f %f %f.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->progs.sv->classname), (float)x, (float)y, (float)z); + SV_LinkEdict (ent); + return; + } + } + } + } + + VectorCopy (org, ent->progs.sv->origin); + MsgDev(D_INFO, "Stuck entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->progs.sv->classname)); +} + +/* +============= +SV_CheckWater +============= +*/ +bool SV_CheckWater (edict_t *ent) +{ + int cont; + vec3_t point; + + point[0] = ent->progs.sv->origin[0]; + point[1] = ent->progs.sv->origin[1]; + point[2] = ent->progs.sv->origin[2] + ent->progs.sv->mins[2] + 1; + + ent->progs.sv->waterlevel = 0; + ent->progs.sv->watertype = CONTENTS_NONE; + cont = SV_PointContents(point); + if (cont & (MASK_WATER)) + { + ent->progs.sv->watertype = cont; + ent->progs.sv->waterlevel = 1; + point[2] = ent->progs.sv->origin[2] + (ent->progs.sv->mins[2] + ent->progs.sv->maxs[2])*0.5; + if (SV_PointContents(point) & (MASK_WATER)) + { + ent->progs.sv->waterlevel = 2; + point[2] = ent->progs.sv->origin[2] + ent->progs.sv->view_ofs[2]; + if (SV_PointContents(point) & (MASK_WATER)) + ent->progs.sv->waterlevel = 3; + } + } + return ent->progs.sv->waterlevel > 1; +} + + +/* +============ +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 stepnormal is not NULL, the plane normal of any vertical wall hit will be stored +============ +*/ +#define MAX_CLIP_PLANES 32 +int SV_FlyMove (edict_t *ent, float time, float *stepnormal) +{ + int blocked = 0, bumpcount; + int i, j, mask, impact, numplanes = 0; + float d, time_left; + vec3_t dir, end, planes[MAX_CLIP_PLANES], primal_velocity, original_velocity, new_velocity; + trace_t trace; + + VectorCopy(ent->progs.sv->velocity, original_velocity); + VectorCopy(ent->progs.sv->velocity, primal_velocity); + + //setup trace mask + if ((int)ent->progs.sv->flags & FL_MONSTER) mask = MASK_MONSTERSOLID; + else if(ent->progs.sv->movetype == MOVETYPE_PUSHABLE) mask = MASK_MONSTERSOLID | MASK_PLAYERSOLID; + else if(ent->priv.sv->clipmask) mask = ent->priv.sv->clipmask; + else mask = MASK_SOLID; + + numplanes = 0; + time_left = time; + for (bumpcount = 0;bumpcount < MAX_CLIP_PLANES;bumpcount++) + { + if (!ent->progs.sv->velocity[0] && !ent->progs.sv->velocity[1] && !ent->progs.sv->velocity[2]) + break; + + VectorMA(ent->progs.sv->origin, time_left, ent->progs.sv->velocity, end); + trace = SV_Trace (ent->progs.sv->origin, ent->progs.sv->mins, ent->progs.sv->maxs, end, ent, mask); + + // break if it moved the entire distance + if (trace.fraction == 1) + { + VectorCopy(trace.endpos, ent->progs.sv->origin); + break; + } + + if (!trace.ent) + { + Con_Printf ("SV_FlyMove: !trace.ent"); + trace.ent = prog->edicts; + } + + if (((int) ent->progs.sv->aiflags & AI_ONGROUND) && ent->progs.sv->groundentity == PRVM_EDICT_TO_PROG(trace.ent)) + impact = false; + else + { + ent->progs.sv->aiflags = (int)ent->progs.sv->aiflags & ~AI_ONGROUND; + impact = true; + } + + if (trace.plane.normal[2]) + { + if (trace.plane.normal[2] > 0.7) + { + // floor + blocked |= 1; + ent->progs.sv->aiflags = (int)ent->progs.sv->aiflags | AI_ONGROUND; + ent->progs.sv->groundentity = PRVM_EDICT_TO_PROG(trace.ent); + } + } + else + { + // step + blocked |= 2; + // save the trace for player extrafriction + if (stepnormal) VectorCopy(trace.plane.normal, stepnormal); + } + + if (trace.fraction >= 0.001) + { + // actually covered some distance + VectorCopy(trace.endpos, ent->progs.sv->origin); + VectorCopy(ent->progs.sv->velocity, original_velocity); + numplanes = 0; + } + + // run the impact function + if (impact) + { + SV_Impact(ent, &trace); + // break if removed by the impact function + if (ent->priv.sv->free) + break; + } + + time_left *= 1 - trace.fraction; + + // clipped to another plane + if (numplanes >= MAX_CLIP_PLANES) + { + // this shouldn't really happen + VectorClear(ent->progs.sv->velocity); + blocked = 3; + break; + } + + VectorCopy(trace.plane.normal, planes[numplanes]); + numplanes++; + + // modify original_velocity so it parallels all of the clip planes + for (i = 0; i < numplanes; i++) + { + SV_ClipVelocity(original_velocity, planes[i], new_velocity, 1); + for (j = 0; j < numplanes; j++) + { + if (j != i) // not ok + { + if (DotProduct(new_velocity, planes[j]) < 0) + break; + } + } + if (j == numplanes) break; + } + + if (i != numplanes) + { + // go along this plane + VectorCopy(new_velocity, ent->progs.sv->velocity); + } + else + { + // go along the crease + if (numplanes != 2) + { + VectorClear(ent->progs.sv->velocity); + blocked = 7; + break; + } + CrossProduct(planes[0], planes[1], dir); + // LordHavoc: thanks to taniwha of QuakeForge for pointing out this fix for slowed falling in corners + VectorNormalize(dir); + d = DotProduct(dir, ent->progs.sv->velocity); + VectorScale(dir, d, ent->progs.sv->velocity); + } + + // if current velocity is against the original velocity, + // stop dead to avoid tiny occilations in sloping corners + if (DotProduct(ent->progs.sv->velocity, primal_velocity) <= 0) + { + VectorClear(ent->progs.sv->velocity); + break; + } + } + + // LordHavoc: this came from QW and allows you to get out of water more easily + if((int)ent->progs.sv->aiflags & AI_WATERJUMP) + VectorCopy(primal_velocity, ent->progs.sv->velocity); + return blocked; +} + +/* +============ +SV_AddGravity + +============ +*/ +void SV_AddGravity (edict_t *ent) +{ + ent->progs.sv->velocity[2] -= ent->progs.sv->gravity * sv_gravity->value * sv.frametime; +} + +/* +============= +SV_RunThink + +Runs thinking code for this frame if necessary +============= +*/ +bool SV_RunThink (edict_t *ent) +{ + float thinktime; + + thinktime = ent->progs.sv->nextthink; + if (thinktime <= 0 || thinktime > sv.time + sv.frametime) + return true; + + // don't let things stay in the past. + // it is possible to start that way by a trigger with a local time. + if (thinktime < sv.time) thinktime = sv.time; + + ent->progs.sv->nextthink = 0; //reset thinktime + prog->globals.server->time = thinktime; + prog->globals.server->pev = PRVM_EDICT_TO_PROG(ent); + prog->globals.server->other = PRVM_EDICT_TO_PROG(prog->edicts); + PRVM_ExecuteProgram (ent->progs.sv->think, "QC function pev->think is missing"); + + return !ent->priv.sv->free; +} + +/* +============= +SV_MoveStep + +Called by monster program code. +The move will be adjusted for slopes and stairs, but if the move isn't +possible, no move is done, false is returned, and +prog->globals.server->trace_normal is set to the normal of the blocking wall +============= +*/ +bool SV_MoveStep (edict_t *ent, vec3_t move, bool relink) +{ + float dz; + vec3_t oldorg, neworg, end, traceendpos; + trace_t trace; + int i; + edict_t *enemy; + + // try the move + VectorCopy (ent->progs.sv->origin, oldorg); + VectorAdd (ent->progs.sv->origin, move, neworg); + + // flying monsters don't step up + if ((int)ent->progs.sv->aiflags & (AI_SWIM | AI_FLY) ) + { + // try one move with vertical motion, then one without + for (i = 0; i < 2; i++) + { + VectorAdd (ent->progs.sv->origin, move, neworg); + enemy = PRVM_PROG_TO_EDICT(ent->progs.sv->enemy); + if (i == 0 && enemy != prog->edicts) + { + dz = ent->progs.sv->origin[2] - PRVM_PROG_TO_EDICT(ent->progs.sv->enemy)->progs.sv->origin[2]; + if (dz > 40) neworg[2] -= 8; + if (dz < 30) neworg[2] += 8; + } + trace = SV_Trace(ent->progs.sv->origin, ent->progs.sv->mins, ent->progs.sv->maxs, neworg, ent, MASK_SOLID); + + if (trace.fraction == 1) + { + VectorCopy(trace.endpos, traceendpos); + if (((int)ent->progs.sv->aiflags & AI_SWIM) && !(SV_PointContents(traceendpos) & MASK_WATER)) + return false; // swim monster left water + + VectorCopy (traceendpos, ent->progs.sv->origin); + if (relink) SV_LinkEdict (ent); + return true; + } + if (enemy == prog->edicts) break; + } + return false; + } + + // push down from a step height above the wished position + neworg[2] += STEPSIZE; + VectorCopy (neworg, end); + end[2] -= STEPSIZE * 2; + + trace = SV_Trace(neworg, ent->progs.sv->mins, ent->progs.sv->maxs, end, ent, MASK_SOLID ); + + if (trace.startsolid) + { + neworg[2] -= STEPSIZE; + trace = SV_Trace(neworg, ent->progs.sv->mins, ent->progs.sv->maxs, end, ent, MASK_SOLID); + if (trace.startsolid) return false; + } + if (trace.fraction == 1) + { + // if monster had the ground pulled out, go ahead and fall + if ((int)ent->progs.sv->aiflags & AI_PARTIALONGROUND ) + { + VectorAdd (ent->progs.sv->origin, move, ent->progs.sv->origin); + if (relink) SV_LinkEdict (ent); + ent->progs.sv->aiflags = (int)ent->progs.sv->aiflags & ~AI_ONGROUND; + return true; + } + return false; // walked off an edge + } + + // check point traces down for dangling corners + VectorCopy (trace.endpos, ent->progs.sv->origin); + + if (!SV_CheckBottom (ent)) + { + if ((int)ent->progs.sv->aiflags & AI_PARTIALONGROUND ) + { + // entity had floor mostly pulled out from underneath it + // and is trying to correct + if (relink) SV_LinkEdict(ent); + return true; + } + VectorCopy (oldorg, ent->progs.sv->origin); + return false; + } + + if ( (int)ent->progs.sv->aiflags & AI_PARTIALONGROUND ) + ent->progs.sv->aiflags = (int)ent->progs.sv->aiflags & ~AI_PARTIALONGROUND; + + ent->progs.sv->groundentity = PRVM_EDICT_TO_PROG(trace.ent); + + // the move is ok + if (relink) SV_LinkEdict(ent); + return true; +} + + /* ============ SV_PushEntity @@ -37,12 +782,17 @@ Does not change the entities velocity at all */ trace_t SV_MovePushEntity (edict_t *ent, vec3_t push, bool failonbmodelstartsolid) { - trace_t trace; - vec3_t end; + trace_t trace; + vec3_t end; + int mask; VectorAdd (ent->progs.sv->origin, push, end); - trace = SV_Trace(ent->progs.sv->origin, ent->progs.sv->mins, ent->progs.sv->maxs, end, ent, MASK_SOLID ); + if (ent->progs.sv->solid == SOLID_TRIGGER || ent->progs.sv->solid == SOLID_NOT) + mask = MASK_MONSTERSOLID; // only clip against bmodels + else mask = MASK_SOLID; + + trace = SV_Trace(ent->progs.sv->origin, ent->progs.sv->mins, ent->progs.sv->maxs, end, ent, mask ); if (trace.startstuck && failonbmodelstartsolid) return trace; VectorCopy (trace.endpos, ent->progs.sv->origin); @@ -65,8 +815,6 @@ void SV_MovePush(edict_t *pusher, float movetime) float savesolid, movetime2, pushltime; vec3_t mins, maxs, move, move1, moveangle, pushorig, pushang, a, forward, left, up, org; int num_moved; - int numcheckentities; - static edict_t *checkentities[MAX_EDICTS]; cmodel_t *pushermodel; trace_t trace; @@ -115,7 +863,9 @@ void SV_MovePush(edict_t *pusher, float movetime) mins[i] = pusher->progs.sv->absmin[i] + move1[i]; maxs[i] = pusher->progs.sv->absmax[i] + move1[i]; } - + + //SV_CalcBBox(pusher, mins, maxs ); + VectorNegate (moveangle, a); AngleVectorsFLU(a, forward, left, up); //stupid quake bug @@ -135,10 +885,9 @@ void SV_MovePush(edict_t *pusher, float movetime) // see if any solid entities are inside the final position num_moved = 0; - numcheckentities = 0;//SV_EntitiesInBox(mins, maxs, MAX_EDICTS, checkentities); - for (e = 0;e < numcheckentities; e++) + for (e = 0; e < prog->num_edicts; e++) { - edict_t *check = checkentities[e]; + edict_t *check = PRVM_PROG_TO_EDICT(e); if (check->progs.sv->movetype == MOVETYPE_NONE || check->progs.sv->movetype == MOVETYPE_PUSH || check->progs.sv->movetype == MOVETYPE_FOLLOW || check->progs.sv->movetype == MOVETYPE_NOCLIP) continue; @@ -166,8 +915,7 @@ void SV_MovePush(edict_t *pusher, float movetime) VectorSubtract (org2, org, move); VectorAdd (move, move1, move); } - else - VectorCopy (move1, move); + else VectorCopy (move1, move); VectorCopy (check->progs.sv->origin, check->progs.sv->post_origin); VectorCopy (check->progs.sv->angles, check->progs.sv->post_angles); @@ -246,13 +994,56 @@ void SV_MovePush(edict_t *pusher, float movetime) SV_ClampAngle( pusher->progs.sv->angles ); } +/* +============= +SV_PhysicsFollow + +Entities that are "stuck" to another entity +============= +*/ +void SV_PhysicsFollow (edict_t *ent) +{ + vec3_t vf, vr, vu, angles, v; + edict_t *e; + + // regular thinking + if (!SV_RunThink (ent)) return; + + // LordHavoc: implemented rotation on MOVETYPE_FOLLOW objects + e = PRVM_PROG_TO_EDICT(ent->progs.sv->aiment); + if (VectorCompare(e->progs.sv->angles, ent->progs.sv->punchangle)) + { + // quick case for no rotation + VectorAdd(e->progs.sv->origin, ent->progs.sv->view_ofs, ent->progs.sv->origin); + } + else + { + angles[0] = -ent->progs.sv->punchangle[0]; + angles[1] = ent->progs.sv->punchangle[1]; + angles[2] = ent->progs.sv->punchangle[2]; + AngleVectors (angles, vf, vr, vu); + v[0] = ent->progs.sv->view_ofs[0] * vf[0] + ent->progs.sv->view_ofs[1] * vr[0] + ent->progs.sv->view_ofs[2] * vu[0]; + v[1] = ent->progs.sv->view_ofs[0] * vf[1] + ent->progs.sv->view_ofs[1] * vr[1] + ent->progs.sv->view_ofs[2] * vu[1]; + v[2] = ent->progs.sv->view_ofs[0] * vf[2] + ent->progs.sv->view_ofs[1] * vr[2] + ent->progs.sv->view_ofs[2] * vu[2]; + angles[0] = -e->progs.sv->angles[0]; + angles[1] = e->progs.sv->angles[1]; + angles[2] = e->progs.sv->angles[2]; + AngleVectors (angles, vf, vr, vu); + ent->progs.sv->origin[0] = v[0] * vf[0] + v[1] * vf[1] + v[2] * vf[2] + e->progs.sv->origin[0]; + ent->progs.sv->origin[1] = v[0] * vr[0] + v[1] * vr[1] + v[2] * vr[2] + e->progs.sv->origin[1]; + ent->progs.sv->origin[2] = v[0] * vu[0] + v[1] * vu[1] + v[2] * vu[2] + e->progs.sv->origin[2]; + } + VectorAdd (e->progs.sv->angles, ent->progs.sv->v_angle, ent->progs.sv->angles); + SV_LinkEdict (ent); +} + /* ================ -SV_MovetypePush +SV_PhysicsPush ================ */ -void SV_MovetypePush (edict_t *ent) +void SV_PhysicsPush(edict_t *ent) { float thinktime, oldltime, movetime; @@ -277,4 +1068,431 @@ void SV_MovetypePush (edict_t *ent) prog->globals.server->other = PRVM_EDICT_TO_PROG(prog->edicts); PRVM_ExecuteProgram (ent->progs.sv->think, "QC function pev->think is missing"); } +} + +/* +============================================================================== + +TOSS / BOUNCE + +============================================================================== +*/ + +/* +============= +SV_CheckWaterTransition + +============= +*/ +void SV_CheckWaterTransition (edict_t *ent) +{ + int cont = SV_PointContents(ent->progs.sv->origin); + + if (!ent->progs.sv->watertype) + { + // just spawned here + ent->progs.sv->watertype = cont; + ent->progs.sv->waterlevel = 1; + return; + } + + // check if the entity crossed into or out of water + if ((int)ent->progs.sv->watertype & MASK_WATER) + { + Msg("water splash!\n"); + //SV_StartSound (ent, 0, "", 255, 1); + } + + if (cont & MASK_WATER) + { + ent->progs.sv->watertype = cont; + ent->progs.sv->waterlevel = 1; + } + else + { + ent->progs.sv->watertype = CONTENTS_NONE; + ent->progs.sv->waterlevel = 0; + } +} + +/* +============= +SV_PhysicsToss + +Toss, bounce, and fly movement. When onground, do nothing. +============= +*/ +void SV_PhysicsToss (edict_t *ent) +{ + trace_t trace; + vec3_t move; + + SV_CheckVelocity (ent); + + // add gravity + if (ent->progs.sv->movetype == MOVETYPE_TOSS || ent->progs.sv->movetype == MOVETYPE_BOUNCE) + SV_AddGravity (ent); + + // move angles + VectorMA (ent->progs.sv->angles, sv.frametime, ent->progs.sv->avelocity, ent->progs.sv->angles); + + // move origin + VectorScale (ent->progs.sv->velocity, sv.frametime, move); + trace = SV_MovePushEntity (ent, move, true); + if (ent->priv.sv->free) return; + + if (trace.startstuck) + { + // try to unstick the entity + SV_UnstickEntity(ent); + trace = SV_MovePushEntity (ent, move, false); + if (ent->priv.sv->free) return; + } + + if (trace.fraction < 1) + { + if (ent->progs.sv->movetype == MOVETYPE_BOUNCE) + { + float d; + SV_ClipVelocity (ent->progs.sv->velocity, trace.plane.normal, ent->progs.sv->velocity, 1.5); + d = DotProduct(trace.plane.normal, ent->progs.sv->velocity); + if (trace.plane.normal[2] > 0.7 && fabs(d) < 60) + { + ent->progs.sv->aiflags = (int)ent->progs.sv->aiflags | AI_ONGROUND; + ent->progs.sv->groundentity = PRVM_EDICT_TO_PROG(trace.ent); + VectorClear (ent->progs.sv->velocity); + VectorClear (ent->progs.sv->avelocity); + } + else ent->progs.sv->aiflags = (int)ent->progs.sv->aiflags & ~AI_ONGROUND; + } + else + { + SV_ClipVelocity (ent->progs.sv->velocity, trace.plane.normal, ent->progs.sv->velocity, 1.0); + if (trace.plane.normal[2] > 0.7) + { + ent->progs.sv->aiflags = (int)ent->progs.sv->aiflags | AI_ONGROUND; + ent->progs.sv->groundentity = PRVM_EDICT_TO_PROG(trace.ent); + VectorClear (ent->progs.sv->velocity); + VectorClear (ent->progs.sv->avelocity); + } + else ent->progs.sv->aiflags = (int)ent->progs.sv->aiflags & ~AI_ONGROUND; + } + } + + // check for in water + SV_CheckWaterTransition (ent); +} + +/* +=============================================================================== + +STEPPING MOVEMENT + +=============================================================================== +*/ + +/* +============= +SV_PhysicsStep + +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_PhysicsStep (edict_t *ent) +{ + int aiflags = (int)ent->progs.sv->aiflags; + + // don't fall at all if fly/swim + if (!(aiflags & (AI_FLY | AI_SWIM))) + { + if (aiflags & AI_ONGROUND) + { + // freefall if onground and moving upward + // freefall if not standing on a world surface (it may be a lift or trap door) + if (ent->progs.sv->groundentity) + { + ent->progs.sv->aiflags -= AI_ONGROUND; + SV_AddGravity(ent); + SV_CheckVelocity(ent); + SV_FlyMove(ent, sv.frametime, NULL); + SV_LinkEdict(ent); + } + } + else + { + // freefall if not onground + int hitsound = ent->progs.sv->velocity[2] < sv_gravity->value * -0.1; + + SV_AddGravity(ent); + SV_CheckVelocity(ent); + SV_FlyMove(ent, sv.frametime, NULL); + SV_LinkEdict(ent); + + // just hit ground + if (hitsound && (int)ent->progs.sv->aiflags & AI_ONGROUND) + { + Msg("hit on ground\n"); + //SV_StartSound(ent, 0, sv_sound_land.string, 255, 1); + } + } + } + + // regular thinking + SV_RunThink(ent); + SV_CheckWaterTransition(ent); +} + +/* +===================== +SV_WalkMove + +Only used by players +====================== +*/ +void SV_WalkMove (edict_t *ent) +{ + int clip, oldonground, originalmove_clip, originalmove_flags, originalmove_groundentity; + vec3_t upmove, downmove, start_origin, start_velocity, stepnormal, originalmove_origin, originalmove_velocity; + trace_t downtrace; + + SV_CheckVelocity(ent); + + // do a regular slide move unless it looks like you ran into a step + oldonground = (int)ent->progs.sv->aiflags & AI_ONGROUND; + ent->progs.sv->aiflags = (int)ent->progs.sv->aiflags & ~AI_ONGROUND; + + VectorCopy (ent->progs.sv->origin, start_origin); + VectorCopy (ent->progs.sv->velocity, start_velocity); + + clip = SV_FlyMove (ent, sv.frametime, NULL); + SV_CheckVelocity(ent); + + VectorCopy(ent->progs.sv->origin, originalmove_origin); + VectorCopy(ent->progs.sv->velocity, originalmove_velocity); + originalmove_clip = clip; + originalmove_flags = (int)ent->progs.sv->aiflags; + originalmove_groundentity = ent->progs.sv->groundentity; + + if ((int)ent->progs.sv->aiflags & AI_WATERJUMP) return; + + // if move didn't block on a step, return + if (clip & 2) + { + // if move was not trying to move into the step, return + if (fabs(start_velocity[0]) < CL_COORD_FRAC && fabs(start_velocity[1]) < CL_COORD_FRAC) + return; + + if (ent->progs.sv->movetype != MOVETYPE_FLY) + { + // return if gibbed by a trigger + if (ent->progs.sv->movetype != MOVETYPE_WALK) + return; + + // only step up while jumping if that is enabled + if (!oldonground && ent->progs.sv->waterlevel == 0) + return; + } + + // try moving up and forward to go up a step + // back to start pos + VectorCopy (start_origin, ent->progs.sv->origin); + VectorCopy (start_velocity, ent->progs.sv->velocity); + + // move up + VectorClear (upmove); + upmove[2] = STEPSIZE; + // FIXME: don't link? + SV_MovePushEntity(ent, upmove, false); + + // move forward + ent->progs.sv->velocity[2] = 0; + clip = SV_FlyMove (ent, sv.frametime, stepnormal); + ent->progs.sv->velocity[2] += start_velocity[2]; + + SV_CheckVelocity(ent); + + // check for stuckness, possibly due to the limited precision of floats + // in the clipping hulls + if (clip && fabs(originalmove_origin[1] - ent->progs.sv->origin[1]) < CL_COORD_FRAC && fabs(originalmove_origin[0] - ent->progs.sv->origin[0]) < CL_COORD_FRAC) + { + //Msg("wall\n"); + // stepping up didn't make any progress, revert to original move + VectorCopy(originalmove_origin, ent->progs.sv->origin); + VectorCopy(originalmove_velocity, ent->progs.sv->velocity); + //clip = originalmove_clip; + ent->progs.sv->aiflags = originalmove_flags; + ent->progs.sv->groundentity = originalmove_groundentity; + // now try to unstick if needed + //clip = SV_TryUnstick (ent, oldvel); + return; + } + + //Msg("step - "); + + // extra friction based on view angle + if (clip & 2) SV_WallFriction (ent, stepnormal); + } + // skip out if stepdown is enabled, moving downward, not in water, and the move started onground and ended offground + else if (ent->progs.sv->waterlevel < 2 && start_velocity[2] < CL_COORD_FRAC && oldonground && !((int)ent->progs.sv->aiflags & AI_ONGROUND)) + return; + + // move down + VectorClear (downmove); + downmove[2] = -STEPSIZE + start_velocity[2]*sv.frametime; + // FIXME: don't link? + downtrace = SV_MovePushEntity (ent, downmove, false); + + if (downtrace.fraction < 1 && downtrace.plane.normal[2] > 0.7) + { + // this has been disabled so that you can't jump when you are stepping + // up while already jumping (also known as the Quake2 stair jump bug) + } + else + { + //Con_Printf("slope\n"); + // 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(originalmove_origin, ent->progs.sv->origin); + VectorCopy(originalmove_velocity, ent->progs.sv->velocity); + //clip = originalmove_clip; + ent->progs.sv->aiflags = originalmove_flags; + ent->progs.sv->groundentity = originalmove_groundentity; + } + + SV_CheckVelocity(ent); +} + +/* +==================== +SV_Physics_Conveyor + +REAL simple - all we do is check for player riders and adjust their position. +Only gotcha here is we have to make sure we don't end up embedding player in +*another* object that's being moved by the conveyor. + +==================== +*/ +void SV_Physics_Conveyor(edict_t *ent) +{ + edict_t *player; + int i; + trace_t tr; + vec3_t v, move; + vec3_t point, end; + + VectorScale(ent->progs.sv->movedir,ent->progs.sv->speed,v); + VectorScale(v, 0.1f, move); + + for(i = 0; i < maxclients->value; i++) + { + player = PRVM_EDICT_NUM(i) + 1; + if(player->priv.sv->free) continue; + if(!player->progs.sv->groundentity) continue; + if(player->progs.sv->groundentity != PRVM_EDICT_TO_PROG(ent)) continue; + + // Look below player; make sure he's on a conveyor + VectorCopy(player->progs.sv->origin,point); + point[2] += 1; + VectorCopy(point,end); + end[2] -= 256; + + tr = SV_Trace (point, player->progs.sv->mins, player->progs.sv->maxs, end, player, MASK_SOLID); + // tr.ent HAS to be conveyor, but just in case we screwed something up: + if(tr.ent == ent) + { + if(tr.plane.normal[2] > 0) + { + v[2] = ent->progs.sv->speed * sqrt(1.0 - tr.plane.normal[2]*tr.plane.normal[2]) / tr.plane.normal[2]; + if(DotProduct(ent->progs.sv->movedir, tr.plane.normal) > 0) + { + // then we're moving down + v[2] = -v[2]; + } + move[2] = v[2] * 0.1f; + } + VectorAdd(player->progs.sv->origin,move,end); + tr = SV_Trace(player->progs.sv->origin,player->progs.sv->mins,player->progs.sv->maxs,end,player,player->priv.sv->clipmask); + VectorCopy(tr.endpos,player->progs.sv->origin); + SV_LinkEdict(player); + } + } +} + +/* +============= +SV_PhysicsNoclip + +A moving object that doesn't obey physics +============= +*/ +void SV_PhysicsNoclip(edict_t *ent) +{ + // regular thinking + if (!SV_RunThink (ent)) return; + + VectorMA (ent->progs.sv->angles, sv.frametime, ent->progs.sv->avelocity, ent->progs.sv->angles); + VectorMA (ent->progs.sv->origin, sv.frametime, ent->progs.sv->velocity, ent->progs.sv->origin); + + SV_LinkEdict(ent); +} + + +/* +============= +SV_PhysicsNone + +Non moving objects can only think +============= +*/ +void SV_PhysicsNone (edict_t *ent) +{ + if (ent->progs.sv->nextthink > 0 && ent->progs.sv->nextthink <= sv.time + sv.frametime) + SV_RunThink (ent); +} + +void SV_Physics(edict_t *ent) +{ + switch ((int)ent->progs.sv->movetype) + { + case MOVETYPE_NONE: + SV_PhysicsNone(ent); + break; + case MOVETYPE_PUSH: + SV_PhysicsPush(ent); + break; + case MOVETYPE_NOCLIP: + SV_PhysicsNoclip(ent); + break; + case MOVETYPE_FOLLOW: + SV_PhysicsFollow(ent); + break; + case MOVETYPE_STEP: + SV_PhysicsStep (ent); + break; + case MOVETYPE_TOSS: + case MOVETYPE_BOUNCE: + case MOVETYPE_FLY: + SV_PhysicsToss(ent); + break; + case MOVETYPE_WALK: + if(SV_RunThink (ent)) + { + if (!SV_CheckWater(ent) && ! ((int)ent->progs.sv->aiflags & AI_WATERJUMP) ) + SV_AddGravity (ent); + SV_CheckStuck (ent); + SV_WalkMove (ent); + SV_LinkEdict (ent); + }; + break; + case MOVETYPE_CONVEYOR: + SV_Physics_Conveyor(ent); + break; + default: + PRVM_ERROR ("SV_Physics: bad movetype %i", (int)ent->progs.sv->movetype); + } } \ No newline at end of file diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 69aa83a6..526e85d3 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -232,8 +232,8 @@ void _MSG_Send (msgtype_t to, vec3_t origin, edict_t *ent, const char *filename, if ( mask && (!(mask[cluster>>3] & (1<<(cluster&7))))) continue; } - if (reliable) SZ_Write (&client->netchan.message, sv.multicast.data, sv.multicast.cursize); - else SZ_Write (&client->datagram, sv.multicast.data, sv.multicast.cursize); + if (reliable) _SZ_Write (&client->netchan.message, sv.multicast.data, sv.multicast.cursize, filename, fileline); + else _SZ_Write (&client->datagram, sv.multicast.data, sv.multicast.cursize, filename, fileline); } SZ_Clear (&sv.multicast); } diff --git a/engine/server/sv_spawn.c b/engine/server/sv_spawn.c index af176d75..6c7cbedc 100644 --- a/engine/server/sv_spawn.c +++ b/engine/server/sv_spawn.c @@ -47,7 +47,7 @@ void SV_PutClientInServer (edict_t *ent) client->ps.fov = 90; client->ps.fov = bound(1, client->ps.fov, 160); - client->ps.gunindex = SV_ModelIndex("models/weapons/v_eagle.mdl"); + client->ps.gunindex = SV_ModelIndex(PRVM_GetString(ent->progs.sv->weaponmodel)); // clear entity state values ent->progs.sv->effects = 0; diff --git a/engine/server/tstent.c b/engine/server/tstent.c deleted file mode 100644 index 63982997..00000000 --- a/engine/server/tstent.c +++ /dev/null @@ -1,16 +0,0 @@ -void SP_info_player_start (edict_t *ent){} -void SP_info_player_deathmatch (edict_t *ent){} -void SP_worldspawn (edict_t *ent) -{ - // help icon for statusbar - SV_ImageIndex ("i_help"); - SV_ImageIndex ("help"); - SV_ImageIndex ("field_3"); -} - -void SP_func_wall(edict_t *self) -{ - self->priv.sv->solid = SOLID_BSP; - PF_setmodel (self, self->priv.sv->model); - SV_LinkEdict(self); -} \ No newline at end of file diff --git a/engine/vid_dll.c b/engine/vid_dll.c index 09585bc1..97ca1134 100644 --- a/engine/vid_dll.c +++ b/engine/vid_dll.c @@ -502,7 +502,7 @@ void VID_InitRender( void ) CreateRender = (void *)render_dll.main; re = CreateRender( &ri ); - if(!re->Init( global_hInstance, MainWndProc )) Sys_Error("can't init render.dll\n"); + if(!re->Init( global_hInstance, MainWndProc )) Sys_Error("VID_InitRender: can't init render.dll\nUpdate your opengl drivers\n"); reflib_active = true; } diff --git a/public/activity.h b/public/activity.h deleted file mode 100644 index c6d3ae88..00000000 --- a/public/activity.h +++ /dev/null @@ -1,135 +0,0 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ - -#ifndef ACTIVITY_H -#define ACTIVITY_H - - -typedef enum { - ACT_RESET = 0, // Set m_Activity to this invalid value to force a reset to m_IdealActivity - ACT_IDLE = 1, - ACT_GUARD, - ACT_WALK, - ACT_RUN, - ACT_FLY, // Fly (and flap if appropriate) - ACT_SWIM, - ACT_HOP, // vertical jump - ACT_LEAP, // long forward jump - ACT_FALL, - ACT_LAND, - ACT_STRAFE_LEFT, - ACT_STRAFE_RIGHT, - ACT_ROLL_LEFT, // tuck and roll, left - ACT_ROLL_RIGHT, // tuck and roll, right - ACT_TURN_LEFT, // turn quickly left (stationary) - ACT_TURN_RIGHT, // turn quickly right (stationary) - ACT_CROUCH, // the act of crouching down from a standing position - ACT_CROUCHIDLE, // holding body in crouched position (loops) - ACT_STAND, // the act of standing from a crouched position - ACT_USE, - ACT_SIGNAL1, - ACT_SIGNAL2, - ACT_SIGNAL3, - ACT_TWITCH, - ACT_COWER, - ACT_SMALL_FLINCH, - ACT_BIG_FLINCH, - ACT_RANGE_ATTACK1, - ACT_RANGE_ATTACK2, - ACT_MELEE_ATTACK1, - ACT_MELEE_ATTACK2, - ACT_RELOAD, - ACT_ARM, // pull out gun, for instance - ACT_DISARM, // reholster gun - ACT_EAT, // monster chowing on a large food item (loop) - ACT_DIESIMPLE, - ACT_DIEBACKWARD, - ACT_DIEFORWARD, - ACT_DIEVIOLENT, - ACT_BARNACLE_HIT, // barnacle tongue hits a monster - ACT_BARNACLE_PULL, // barnacle is lifting the monster ( loop ) - ACT_BARNACLE_CHOMP, // barnacle latches on to the monster - ACT_BARNACLE_CHEW, // barnacle is holding the monster in its mouth ( loop ) - ACT_SLEEP, - ACT_INSPECT_FLOOR, // for active idles, look at something on or near the floor - ACT_INSPECT_WALL, // for active idles, look at something directly ahead of you ( doesn't HAVE to be a wall or on a wall ) - ACT_IDLE_ANGRY, // alternate idle animation in which the monster is clearly agitated. (loop) - ACT_WALK_HURT, // limp (loop) - ACT_RUN_HURT, // limp (loop) - ACT_HOVER, // Idle while in flight - ACT_GLIDE, // Fly (don't flap) - ACT_FLY_LEFT, // Turn left in flight - ACT_FLY_RIGHT, // Turn right in flight - ACT_DETECT_SCENT, // this means the monster smells a scent carried by the air - ACT_SNIFF, // this is the act of actually sniffing an item in front of the monster - ACT_BITE, // some large monsters can eat small things in one bite. This plays one time, EAT loops. - ACT_THREAT_DISPLAY, // without attacking, monster demonstrates that it is angry. (Yell, stick out chest, etc ) - ACT_FEAR_DISPLAY, // monster just saw something that it is afraid of - ACT_EXCITED, // for some reason, monster is excited. Sees something he really likes to eat, or whatever. - ACT_SPECIAL_ATTACK1, // very monster specific special attacks. - ACT_SPECIAL_ATTACK2, - ACT_COMBAT_IDLE, // agitated idle. - ACT_WALK_SCARED, - ACT_RUN_SCARED, - ACT_VICTORY_DANCE, // killed a player, do a victory dance. - ACT_DIE_HEADSHOT, // die, hit in head. - ACT_DIE_CHESTSHOT, // die, hit in chest - ACT_DIE_GUTSHOT, // die, hit in gut - ACT_DIE_BACKSHOT, // die, hit in back - ACT_FLINCH_HEAD, - ACT_FLINCH_CHEST, - ACT_FLINCH_STOMACH, - ACT_FLINCH_LEFTARM, - ACT_FLINCH_RIGHTARM, - ACT_FLINCH_LEFTLEG, - ACT_FLINCH_RIGHTLEG, - ACT_VM_NONE, //weapon viewmodel animations - ACT_VM_DEPLOY, //deploy - ACT_VM_DEPLOY_EMPTY, //deploy empty weapon - ACT_VM_HOLSTER, //holster empty weapon - ACT_VM_HOLSTER_EMPTY, - ACT_VM_IDLE1, - ACT_VM_IDLE2, - ACT_VM_IDLE3, - ACT_VM_RANGE_ATTACK1, - ACT_VM_RANGE_ATTACK2, - ACT_VM_RANGE_ATTACK3, - ACT_VM_MELEE_ATTACK1, - ACT_VM_MELEE_ATTACK2, - ACT_VM_MELEE_ATTACK3, - ACT_VM_SHOOT_EMPTY, - ACT_VM_START_RELOAD, - ACT_VM_RELOAD, - ACT_VM_RELOAD_EMPTY, - ACT_VM_TURNON, - ACT_VM_TURNOFF, - ACT_VM_PUMP, //user animations - ACT_VM_PUMP_EMPTY, - ACT_VM_START_CHARGE, - ACT_VM_CHARGE, - ACT_VM_OVERLOAD, - ACT_VM_IDLE_EMPTY, -} Activity; - - -typedef struct { - int type; - char *name; -} activity_map_t; - -extern activity_map_t activity_map[]; - - -#endif //ACTIVITY_H diff --git a/public/activitymap.h b/public/activitymap.h deleted file mode 100644 index 9250acef..00000000 --- a/public/activitymap.h +++ /dev/null @@ -1,127 +0,0 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#ifndef ACTIVITYMAP_H -#define ACTIVITYMAP_H - -#define _A( a ) { a, #a } - -activity_map_t activity_map[] = -{ -_A( ACT_IDLE ), -_A( ACT_GUARD ), -_A( ACT_WALK ), -_A( ACT_RUN ), -_A( ACT_FLY ), -_A( ACT_SWIM ), -_A( ACT_HOP ), -_A( ACT_LEAP ), -_A( ACT_FALL ), -_A( ACT_LAND ), -_A( ACT_STRAFE_LEFT ), -_A( ACT_STRAFE_RIGHT ), -_A( ACT_ROLL_LEFT ), -_A( ACT_ROLL_RIGHT ), -_A( ACT_TURN_LEFT ), -_A( ACT_TURN_RIGHT ), -_A( ACT_CROUCH ), -_A( ACT_CROUCHIDLE ), -_A( ACT_STAND ), -_A( ACT_USE ), -_A( ACT_SIGNAL1 ), -_A( ACT_SIGNAL2 ), -_A( ACT_SIGNAL3 ), -_A( ACT_TWITCH ), -_A( ACT_COWER ), -_A( ACT_SMALL_FLINCH ), -_A( ACT_BIG_FLINCH ), -_A( ACT_RANGE_ATTACK1 ), -_A( ACT_RANGE_ATTACK2 ), -_A( ACT_MELEE_ATTACK1 ), -_A( ACT_MELEE_ATTACK2 ), -_A( ACT_RELOAD ), -_A( ACT_ARM ), -_A( ACT_DISARM ), -_A( ACT_EAT ), -_A( ACT_DIESIMPLE ), -_A( ACT_DIEBACKWARD ), -_A( ACT_DIEFORWARD ), -_A( ACT_DIEVIOLENT ), -_A( ACT_BARNACLE_HIT ), -_A( ACT_BARNACLE_PULL ), -_A( ACT_BARNACLE_CHOMP ), -_A( ACT_BARNACLE_CHEW ), -_A( ACT_SLEEP ), -_A( ACT_INSPECT_FLOOR ), -_A( ACT_INSPECT_WALL ), -_A( ACT_IDLE_ANGRY ), -_A( ACT_WALK_HURT ), -_A( ACT_RUN_HURT ), -_A( ACT_HOVER ), -_A( ACT_GLIDE ), -_A( ACT_FLY_LEFT ), -_A( ACT_FLY_RIGHT ), -_A( ACT_DETECT_SCENT ), -_A( ACT_SNIFF ), -_A( ACT_BITE ), -_A( ACT_THREAT_DISPLAY ), -_A( ACT_FEAR_DISPLAY ), -_A( ACT_EXCITED ), -_A( ACT_SPECIAL_ATTACK1 ), -_A( ACT_SPECIAL_ATTACK2 ), -_A( ACT_COMBAT_IDLE ), -_A( ACT_WALK_SCARED ), -_A( ACT_RUN_SCARED ), -_A( ACT_VICTORY_DANCE ), -_A( ACT_DIE_HEADSHOT ), -_A( ACT_DIE_CHESTSHOT ), -_A( ACT_DIE_GUTSHOT ), -_A( ACT_DIE_BACKSHOT ), -_A( ACT_FLINCH_HEAD ), -_A( ACT_FLINCH_CHEST ), -_A( ACT_FLINCH_STOMACH ), -_A( ACT_FLINCH_LEFTARM ), -_A( ACT_FLINCH_RIGHTARM ), -_A( ACT_FLINCH_LEFTLEG ), -_A( ACT_FLINCH_RIGHTLEG ), -_A( ACT_VM_NONE), //invalid animation -_A( ACT_VM_DEPLOY), //deploy -_A( ACT_VM_DEPLOY_EMPTY), //deploy empty weapon -_A( ACT_VM_HOLSTER), //holster empty weapon -_A( ACT_VM_HOLSTER_EMPTY), -_A( ACT_VM_IDLE1), -_A( ACT_VM_IDLE2), -_A( ACT_VM_IDLE3), -_A( ACT_VM_RANGE_ATTACK1), -_A( ACT_VM_RANGE_ATTACK2), -_A( ACT_VM_RANGE_ATTACK3), -_A( ACT_VM_MELEE_ATTACK1), -_A( ACT_VM_MELEE_ATTACK2), -_A( ACT_VM_MELEE_ATTACK3), -_A( ACT_VM_SHOOT_EMPTY), -_A( ACT_VM_START_RELOAD), -_A( ACT_VM_RELOAD), -_A( ACT_VM_RELOAD_EMPTY), -_A( ACT_VM_TURNON), -_A( ACT_VM_TURNOFF), -_A( ACT_VM_PUMP), //user animations -_A( ACT_VM_PUMP_EMPTY), -_A( ACT_VM_START_CHARGE), -_A( ACT_VM_CHARGE), -_A( ACT_VM_OVERLOAD), -_A( ACT_VM_IDLE_EMPTY), -0, NULL -}; - -#endif//ACTIVITYMAP_H \ No newline at end of file diff --git a/public/basemath.h b/public/basemath.h index 278a62d6..91adf1b4 100644 --- a/public/basemath.h +++ b/public/basemath.h @@ -6,7 +6,7 @@ #define BASEMATH_H #include -#include "bspmodel.h" +#include "ref_format.h" #define SIDE_FRONT 0 #define SIDE_BACK 1 diff --git a/public/basetypes.h b/public/basetypes.h index 334c3e71..c1be4b4e 100644 --- a/public/basetypes.h +++ b/public/basetypes.h @@ -56,12 +56,14 @@ typedef vec_t vec3_t[3]; typedef vec_t vec4_t[4]; typedef long fs_offset_t; typedef vec_t matrix3x4[3][4]; -typedef struct { int fileofs; int filelen; }lump_t; -typedef struct { byte r; byte g; byte b; } color24; +typedef struct { int fileofs; int filelen; } lump_t; +typedef struct { int type; char *name; } activity_map_t; typedef struct { uint b:5; uint g:6; uint r:5; } color16; +typedef struct { byte r:8; byte g:8; byte b:8; } color24; typedef struct { byte r; byte g; byte b; byte a; } color32; typedef struct { const char *name; void **func; } dllfunc_t; + #ifndef NULL #define NULL ((void *)0) #endif diff --git a/public/bspmodel.h b/public/bspmodel.h deleted file mode 100644 index d4083dd7..00000000 --- a/public/bspmodel.h +++ /dev/null @@ -1,228 +0,0 @@ -//======================================================================= -// Copyright XashXT Group 2007 © -// bspmodel.h - world model header -//======================================================================= -#ifndef BSPMODEL_H -#define BSPMODEL_H - -/* -============================================================================== - -BRUSH MODELS -============================================================================== -*/ - -//header -#define BSPMOD_VERSION 38 -#define IDBSPMODHEADER (('P'<<24)+('S'<<16)+('B'<<8)+'I') // little-endian "IBSP" - -// 16 bit short limits -#define MAX_KEY 32 -#define MAX_MAP_AREAS 256 -#define MAX_VALUE 1024 -#define MAX_MAP_MODELS 2048 // mesh models and sprites too -#define MAX_MAP_AREAPORTALS 1024 -#define MAX_MAP_ENTITIES 2048 -#define MAX_MAP_TEXINFO 8192 -#define MAX_MAP_BRUSHES 16384 -#define MAX_MAP_PLANES 65536 -#define MAX_MAP_NODES 65536 -#define MAX_MAP_BRUSHSIDES 65536 -#define MAX_MAP_LEAFS 65536 -#define MAX_MAP_VERTS 65536 -#define MAX_MAP_FACES 65536 -#define MAX_MAP_LEAFFACES 65536 -#define MAX_MAP_LEAFBRUSHES 65536 -#define MAX_MAP_PORTALS 65536 -#define MAX_MAP_EDGES 128000 -#define MAX_MAP_SURFEDGES 256000 -#define MAX_MAP_ENTSTRING 0x40000 -#define MAX_MAP_LIGHTING 0x400000 -#define MAX_MAP_VISIBILITY 0x100000 - -//lump offset -#define LUMP_ENTITIES 0 -#define LUMP_PLANES 1 -#define LUMP_VERTEXES 2 -#define LUMP_VISIBILITY 3 -#define LUMP_NODES 4 -#define LUMP_TEXINFO 5 -#define LUMP_FACES 6 -#define LUMP_LIGHTING 7 -#define LUMP_LEAFS 8 -#define LUMP_LEAFFACES 9 -#define LUMP_LEAFBRUSHES 10 -#define LUMP_EDGES 11 -#define LUMP_SURFEDGES 12 -#define LUMP_MODELS 13 -#define LUMP_BRUSHES 14 -#define LUMP_BRUSHSIDES 15 -#define LUMP_POP 16 -#define LUMP_AREAS 17 -#define LUMP_AREAPORTALS 18 -#define HEADER_LUMPS 19 - - -// the visibility lump consists of a header with a count, then -// byte offsets for the PVS and PHS of each cluster, then the raw -// compressed bit vectors -#define DVIS_PVS 0 -#define DVIS_PHS 1 - -//other limits -#define MAXLIGHTMAPS 4 - -typedef struct -{ - int ident; - int version; - lump_t lumps[HEADER_LUMPS]; -} dheader_t; - -typedef struct -{ - float mins[3], maxs[3]; - float origin[3]; // for sounds or lights - int headnode; - int firstface; // submodels just draw faces - int numfaces; // without walking the bsp tree -} dmodel_t; - -typedef struct -{ - float point[3]; -} dvertex_t; - -typedef struct -{ - float normal[3]; - float dist; - int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate -} dplane_t; - -typedef struct -{ - int planenum; - int children[2]; // negative numbers are -(leafs+1), not nodes - short mins[3]; // for frustom culling - short maxs[3]; - word firstface; - word numfaces; // counting both sides -} dnode_t; - -typedef struct texinfo_s -{ - float vecs[2][4]; // [s/t][xyz offset] - int flags; // miptex flags + overrides - int value; // light emission, etc - char texture[32]; // texture name (textures/*.jpg) - int nexttexinfo; // for animations, -1 = end of chain -} texinfo_t; - -typedef struct -{ - word v[2]; // vertex numbers -} dedge_t; - - -typedef struct -{ - word planenum; - short side; - int firstedge; // we must support > 64k edges - short numedges; - short texinfo; - - // lighting info - byte styles[MAXLIGHTMAPS]; - int lightofs; // start of [numstyles*surfsize] samples -} dface_t; - -typedef struct -{ - int contents; // OR of all brushes (not needed?) - short cluster; - short area; - short mins[3]; // for frustum culling - short maxs[3]; - - word firstleafface; - word numleaffaces; - word firstleafbrush; - word numleafbrushes; -} dleaf_t; - -typedef struct -{ - word planenum; // facing out of the leaf - short texinfo; -} dbrushside_t; - -typedef struct -{ - int firstside; - int numsides; - int contents; -} dbrush_t; - -typedef struct -{ - int numclusters; - int bitofs[8][2]; // bitofs[numclusters][2] -} dvis_t; - -typedef struct -{ - int portalnum; - int otherarea; -} dareaportal_t; - -typedef struct -{ - int numareaportals; - int firstareaportal; -} darea_t; - -/* -============================================================================== - -ENGINE TRACE FORMAT -============================================================================== -*/ -typedef struct cplane_s -{ - vec3_t normal; - float dist; - byte type; // for fast side tests - byte signbits; // signx + (signy<<1) + (signz<<1) - byte pad[2]; -} cplane_t; - - -typedef struct cmodel_s -{ - int modidx; //edict index - char name[64]; //model name - - vec3_t mins, maxs; // boundbox - vec3_t origin; // for sounds or lights - int headnode; // bsp info - - int numframes; //sprite framecount - void *extradata; //for studio models -} cmodel_t; - -typedef struct csurface_s -{ - char name[16]; - int flags; - int value; -} csurface_t; - -typedef struct mapsurface_s -{ - csurface_t c; - char rname[32]; -} mapsurface_t; - -#endif//BSPMODEL_H \ No newline at end of file diff --git a/public/studio.h b/public/ref_format.h similarity index 52% rename from public/studio.h rename to public/ref_format.h index 49784128..20bc69bd 100644 --- a/public/studio.h +++ b/public/ref_format.h @@ -1,9 +1,60 @@ //======================================================================= // Copyright XashXT Group 2007 © -// studio.h - studio model header +// ref_format.h - xash supported formats //======================================================================= -#ifndef STUDIO_H -#define STUDIO_H +#ifndef REF_FORMAT_H +#define REF_FORMAT_H + +/* +============================================================================== + +SPRITE MODELS +============================================================================== +*/ + +// header +#define SPRITE_VERSION_HALF 2 +#define SPRITE_VERSION_XASH 3 +#define IDSPRITEHEADER (('P'<<24)+('S'<<16)+('D'<<8)+'I') // little-endian "IDSP" + +// render format +#define SPR_VP_PARALLEL_UPRIGHT 0 +#define SPR_FACING_UPRIGHT 1 +#define SPR_VP_PARALLEL 2 +#define SPR_ORIENTED 3 +#define SPR_VP_PARALLEL_ORIENTED 4 + +#define SPR_NORMAL 0 // solid sprite +#define SPR_ADDITIVE 1 +#define SPR_INDEXALPHA 2 +#define SPR_ALPHTEST 3 +#define SPR_ADDGLOW 4 // same as additive, but without depthtest + +typedef struct +{ + int ident; + int version; + int type; + int texFormat; + float boundingradius; + int width; + int height; + int numframes; + float framerate; //xash auto-animate + uint rgbacolor; //packed rgba color +} dsprite_t; + +typedef struct +{ + int origin[2]; + int width; + int height; +} dspriteframe_t; + +typedef struct +{ + int type; +} frametype_t; /* ============================================================================== @@ -14,7 +65,7 @@ Studio models are position independent, so the cache manager can move them. ============================================================================== */ -//header +// header #define STUDIO_VERSION 10 #define IDSTUDIOHEADER (('T'<<24)+('S'<<16)+('D'<<8)+'I') // little-endian "IDST" #define IDSEQGRPHEADER (('Q'<<24)+('S'<<16)+('D'<<8)+'I') // little-endian "IDSQ" @@ -38,17 +89,17 @@ Studio models are position independent, so the cache manager can move them. #define MAXSTUDIOATTACHMENTS 32 // max attachments per model // model global flags -#define STUDIO_STATIC 0x0001 //model without anims -#define STUDIO_RAGDOLL 0x0002 //ragdoll animation pose +#define STUDIO_STATIC 0x0001 // model without anims +#define STUDIO_RAGDOLL 0x0002 // ragdoll animation pose // lighting & rendermode options #define STUDIO_NF_FLATSHADE 0x0001 #define STUDIO_NF_CHROME 0x0002 #define STUDIO_NF_FULLBRIGHT 0x0004 -#define STUDIO_NF_RESERVED 0x0008 //reserved -#define STUDIO_NF_BLENDED 0x0010 -#define STUDIO_NF_ADDITIVE 0x0020 -#define STUDIO_NF_TRANSPARENT 0x0040 +#define STUDIO_NF_RESERVED 0x0008 // reserved +#define STUDIO_NF_BLENDED 0x0010 // rendering as semiblended +#define STUDIO_NF_ADDITIVE 0x0020 // rendering with additive mode +#define STUDIO_NF_TRANSPARENT 0x0040 // use texture with alpha channel // motion flags #define STUDIO_X 0x0001 @@ -72,7 +123,7 @@ Studio models are position independent, so the cache manager can move them. // sequence flags #define STUDIO_LOOPING 0x0001 -//render flags +// render flags #define STUDIO_RENDER 0x0001 #define STUDIO_EVENTS 0x0002 @@ -338,4 +389,224 @@ typedef struct int normindex; // normal vec3_t } mstudiomesh_t; -#endif//STUDIO_H \ No newline at end of file +/* +============================================================================== + +BRUSH MODELS +============================================================================== +*/ + +//header +#define BSPMOD_VERSION 38 +#define IDBSPMODHEADER (('P'<<24)+('S'<<16)+('B'<<8)+'I') // little-endian "IBSP" + +// 16 bit short limits +#define MAX_KEY 32 +#define MAX_MAP_AREAS 256 +#define MAX_VALUE 1024 +#define MAX_MAP_MODELS 2048 // mesh models and sprites too +#define MAX_MAP_AREAPORTALS 1024 +#define MAX_MAP_ENTITIES 2048 +#define MAX_MAP_TEXINFO 8192 +#define MAX_MAP_BRUSHES 16384 +#define MAX_MAP_PLANES 65536 +#define MAX_MAP_NODES 65536 +#define MAX_MAP_BRUSHSIDES 65536 +#define MAX_MAP_LEAFS 65536 +#define MAX_MAP_VERTS 65536 +#define MAX_MAP_FACES 65536 +#define MAX_MAP_LEAFFACES 65536 +#define MAX_MAP_LEAFBRUSHES 65536 +#define MAX_MAP_PORTALS 65536 +#define MAX_MAP_EDGES 128000 +#define MAX_MAP_SURFEDGES 256000 +#define MAX_MAP_ENTSTRING 0x40000 +#define MAX_MAP_LIGHTING 0x400000 +#define MAX_MAP_VISIBILITY 0x100000 + +//lump offset +#define LUMP_ENTITIES 0 +#define LUMP_PLANES 1 +#define LUMP_VERTEXES 2 +#define LUMP_VISIBILITY 3 +#define LUMP_NODES 4 +#define LUMP_TEXINFO 5 +#define LUMP_FACES 6 +#define LUMP_LIGHTING 7 +#define LUMP_LEAFS 8 +#define LUMP_LEAFFACES 9 +#define LUMP_LEAFBRUSHES 10 +#define LUMP_EDGES 11 +#define LUMP_SURFEDGES 12 +#define LUMP_MODELS 13 +#define LUMP_BRUSHES 14 +#define LUMP_BRUSHSIDES 15 +#define LUMP_POP 16 // unused +#define LUMP_AREAS 17 +#define LUMP_AREAPORTALS 18 +#define HEADER_LUMPS 19 + + +// the visibility lump consists of a header with a count, then +// byte offsets for the PVS and PHS of each cluster, then the raw +// compressed bit vectors +#define DVIS_PVS 0 +#define DVIS_PHS 1 + +//other limits +#define MAXLIGHTMAPS 4 + +typedef struct +{ + int ident; + int version; + lump_t lumps[HEADER_LUMPS]; +} dheader_t; + +typedef struct +{ + float mins[3], maxs[3]; + float origin[3]; // for sounds or lights + int headnode; + int firstface; // submodels just draw faces + int numfaces; // without walking the bsp tree +} dmodel_t; + +typedef struct +{ + float point[3]; +} dvertex_t; + +typedef struct +{ + float normal[3]; + float dist; + int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate +} dplane_t; + +typedef struct +{ + int planenum; + int children[2]; // negative numbers are -(leafs+1), not nodes + short mins[3]; // for frustom culling + short maxs[3]; + word firstface; + word numfaces; // counting both sides +} dnode_t; + +typedef struct texinfo_s +{ + float vecs[2][4]; // [s/t][xyz offset] + int flags; // miptex flags + overrides + int value; // light emission, etc + char texture[32]; // texture name (textures/*.jpg) + int nexttexinfo; // for animations, -1 = end of chain +} texinfo_t; + +typedef struct +{ + word v[2]; // vertex numbers +} dedge_t; + + +typedef struct +{ + word planenum; + short side; + int firstedge; // we must support > 64k edges + short numedges; + short texinfo; + + // lighting info + byte styles[MAXLIGHTMAPS]; + int lightofs; // start of [numstyles*surfsize] samples +} dface_t; + +typedef struct +{ + int contents; // OR of all brushes (not needed?) + short cluster; + short area; + short mins[3]; // for frustum culling + short maxs[3]; + + word firstleafface; + word numleaffaces; + word firstleafbrush; + word numleafbrushes; +} dleaf_t; + +typedef struct +{ + word planenum; // facing out of the leaf + short texinfo; +} dbrushside_t; + +typedef struct +{ + int firstside; + int numsides; + int contents; +} dbrush_t; + +typedef struct +{ + int numclusters; + int bitofs[8][2]; // bitofs[numclusters][2] +} dvis_t; + +typedef struct +{ + int portalnum; + int otherarea; +} dareaportal_t; + +typedef struct +{ + int numareaportals; + int firstareaportal; +} darea_t; + +/* +============================================================================== + +ENGINE TRACE FORMAT +============================================================================== +*/ +typedef struct cplane_s +{ + vec3_t normal; + float dist; + byte type; // for fast side tests + byte signbits; // signx + (signy<<1) + (signz<<1) + byte pad[2]; +} cplane_t; + + +typedef struct cmodel_s +{ + int modidx; //edict index + char name[64]; //model name + + vec3_t mins, maxs; // boundbox + vec3_t origin; // for sounds or lights + int headnode; // bsp info + + int numframes; //sprite framecount + void *extradata; //for studio models +} cmodel_t; + +typedef struct csurface_s +{ + char name[16]; + int flags; + int value; +} csurface_t; + +typedef struct mapsurface_s +{ + csurface_t c; + char rname[32]; +} mapsurface_t; + +#endif//REF_FORMAT_H \ No newline at end of file diff --git a/public/ref_system.h b/public/ref_system.h index c72daca9..d370dc24 100644 --- a/public/ref_system.h +++ b/public/ref_system.h @@ -5,9 +5,7 @@ #ifndef REF_SYSTEM_H #define REF_SYSTEM_H -#include "studio.h" -#include "sprite.h" -#include "bspmodel.h" +#include "ref_format.h" #include "version.h" @@ -82,10 +80,10 @@ enum comp_format PF_RGBA_32, // already prepared ".bmp", ".tga" or ".jpg" image PF_ARGB_32, // uncompressed dds image PF_RGB_24, // uncompressed dds or another 24-bit image - PF_DXT1, // nvidia DXT5 format - PF_DXT2, // nvidia DXT5 format - PF_DXT3, // nvidia DXT5 format - PF_DXT4, // nvidia DXT5 format + PF_DXT1, // nvidia DXT1 format + PF_DXT2, // nvidia DXT2 format + PF_DXT3, // nvidia DXT3 format + PF_DXT4, // nvidia DXT4 format PF_DXT5, // nvidia DXT5 format PF_ATI1N, // ati 1N texture PF_ATI2N, // ati 2N texture @@ -98,6 +96,113 @@ enum comp_format PF_TOTALCOUNT, // must be last }; +enum ai_activity +{ + ACT_RESET = 0, // Set m_Activity to this invalid value to force a reset to m_IdealActivity + ACT_IDLE = 1, + ACT_GUARD, + ACT_WALK, + ACT_RUN, + ACT_FLY, // Fly (and flap if appropriate) + ACT_SWIM, + ACT_HOP, // vertical jump + ACT_LEAP, // long forward jump + ACT_FALL, + ACT_LAND, + ACT_STRAFE_LEFT, + ACT_STRAFE_RIGHT, + ACT_ROLL_LEFT, // tuck and roll, left + ACT_ROLL_RIGHT, // tuck and roll, right + ACT_TURN_LEFT, // turn quickly left (stationary) + ACT_TURN_RIGHT, // turn quickly right (stationary) + ACT_CROUCH, // the act of crouching down from a standing position + ACT_CROUCHIDLE, // holding body in crouched position (loops) + ACT_STAND, // the act of standing from a crouched position + ACT_USE, + ACT_SIGNAL1, + ACT_SIGNAL2, + ACT_SIGNAL3, + ACT_TWITCH, + ACT_COWER, + ACT_SMALL_FLINCH, + ACT_BIG_FLINCH, + ACT_RANGE_ATTACK1, + ACT_RANGE_ATTACK2, + ACT_MELEE_ATTACK1, + ACT_MELEE_ATTACK2, + ACT_RELOAD, + ACT_ARM, // pull out gun, for instance + ACT_DISARM, // reholster gun + ACT_EAT, // monster chowing on a large food item (loop) + ACT_DIESIMPLE, + ACT_DIEBACKWARD, + ACT_DIEFORWARD, + ACT_DIEVIOLENT, + ACT_BARNACLE_HIT, // barnacle tongue hits a monster + ACT_BARNACLE_PULL, // barnacle is lifting the monster ( loop ) + ACT_BARNACLE_CHOMP, // barnacle latches on to the monster + ACT_BARNACLE_CHEW, // barnacle is holding the monster in its mouth ( loop ) + ACT_SLEEP, + ACT_INSPECT_FLOOR, // for active idles, look at something on or near the floor + ACT_INSPECT_WALL, // for active idles, look at something directly ahead of you + ACT_IDLE_ANGRY, // alternate idle animation in which the monster is clearly agitated. (loop) + ACT_WALK_HURT, // limp (loop) + ACT_RUN_HURT, // limp (loop) + ACT_HOVER, // Idle while in flight + ACT_GLIDE, // Fly (don't flap) + ACT_FLY_LEFT, // Turn left in flight + ACT_FLY_RIGHT, // Turn right in flight + ACT_DETECT_SCENT, // this means the monster smells a scent carried by the air + ACT_SNIFF, // this is the act of actually sniffing an item in front of the monster + ACT_BITE, // some large monsters can eat small things in one bite. This plays one time, EAT loops. + ACT_THREAT_DISPLAY, // without attacking, monster demonstrates that it is angry. (Yell, stick out chest, etc ) + ACT_FEAR_DISPLAY, // monster just saw something that it is afraid of + ACT_EXCITED, // for some reason, monster is excited. Sees something he really likes to eat, or whatever + ACT_SPECIAL_ATTACK1,// very monster specific special attacks. + ACT_SPECIAL_ATTACK2, + ACT_COMBAT_IDLE, // agitated idle. + ACT_WALK_SCARED, + ACT_RUN_SCARED, + ACT_VICTORY_DANCE, // killed a player, do a victory dance. + ACT_DIE_HEADSHOT, // die, hit in head. + ACT_DIE_CHESTSHOT, // die, hit in chest + ACT_DIE_GUTSHOT, // die, hit in gut + ACT_DIE_BACKSHOT, // die, hit in back + ACT_FLINCH_HEAD, + ACT_FLINCH_CHEST, + ACT_FLINCH_STOMACH, + ACT_FLINCH_LEFTARM, + ACT_FLINCH_RIGHTARM, + ACT_FLINCH_LEFTLEG, + ACT_FLINCH_RIGHTLEG, + ACT_VM_NONE, // weapon viewmodel animations + ACT_VM_DEPLOY, // deploy + ACT_VM_DEPLOY_EMPTY,// deploy empty weapon + ACT_VM_HOLSTER, // holster empty weapon + ACT_VM_HOLSTER_EMPTY, + ACT_VM_IDLE1, + ACT_VM_IDLE2, + ACT_VM_IDLE3, + ACT_VM_RANGE_ATTACK1, + ACT_VM_RANGE_ATTACK2, + ACT_VM_RANGE_ATTACK3, + ACT_VM_MELEE_ATTACK1, + ACT_VM_MELEE_ATTACK2, + ACT_VM_MELEE_ATTACK3, + ACT_VM_SHOOT_EMPTY, + ACT_VM_START_RELOAD, + ACT_VM_RELOAD, + ACT_VM_RELOAD_EMPTY, + ACT_VM_TURNON, + ACT_VM_TURNOFF, + ACT_VM_PUMP, // pumping gun + ACT_VM_PUMP_EMPTY, + ACT_VM_START_CHARGE, + ACT_VM_CHARGE, + ACT_VM_OVERLOAD, + ACT_VM_IDLE_EMPTY, +}; + typedef enum { MSG_ONE, @@ -153,6 +258,113 @@ static bpc_desc_t PFDesc[] = {PF_RGBA_GN, "system", GL_RGBA, GL_UNSIGNED_BYTE, 4, 1, -32}, }; +static activity_map_t activity_map[] = +{ +{ACT_IDLE, "ACT_IDLE" }, +{ACT_GUARD, "ACT_GUARD" }, +{ACT_WALK, "ACT_WALK" }, +{ACT_RUN, "ACT_RUN" }, +{ACT_FLY, "ACT_FLY" }, +{ACT_SWIM, "ACT_SWIM", }, +{ACT_HOP, "ACT_HOP", }, +{ACT_LEAP, "ACT_LEAP" }, +{ACT_FALL, "ACT_FALL" }, +{ACT_LAND, "ACT_LAND" }, +{ACT_STRAFE_LEFT, "ACT_STRAFE_LEFT" }, +{ACT_STRAFE_RIGHT, "ACT_STRAFE_RIGHT" }, +{ACT_ROLL_LEFT, "ACT_ROLL_LEFT" }, +{ACT_ROLL_RIGHT, "ACT_ROLL_RIGHT" }, +{ACT_TURN_LEFT, "ACT_TURN_LEFT" }, +{ACT_TURN_RIGHT, "ACT_TURN_RIGHT" }, +{ACT_CROUCH, "ACT_CROUCH" }, +{ACT_CROUCHIDLE, "ACT_CROUCHIDLE" }, +{ACT_STAND, "ACT_STAND" }, +{ACT_USE, "ACT_USE" }, +{ACT_SIGNAL1, "ACT_SIGNAL1" }, +{ACT_SIGNAL2, "ACT_SIGNAL2" }, +{ACT_SIGNAL3, "ACT_SIGNAL3" }, +{ACT_TWITCH, "ACT_TWITCH" }, +{ACT_COWER, "ACT_COWER" }, +{ACT_SMALL_FLINCH, "ACT_SMALL_FLINCH" }, +{ACT_BIG_FLINCH, "ACT_BIG_FLINCH" }, +{ACT_RANGE_ATTACK1, "ACT_RANGE_ATTACK1" }, +{ACT_RANGE_ATTACK2, "ACT_RANGE_ATTACK2" }, +{ACT_MELEE_ATTACK1, "ACT_MELEE_ATTACK1" }, +{ACT_MELEE_ATTACK2, "ACT_MELEE_ATTACK2" }, +{ACT_RELOAD, "ACT_RELOAD" }, +{ACT_ARM, "ACT_ARM" }, +{ACT_DISARM, "ACT_DISARM" }, +{ACT_EAT, "ACT_EAT" }, +{ACT_DIESIMPLE, "ACT_DIESIMPLE" }, +{ACT_DIEBACKWARD, "ACT_DIEBACKWARD" }, +{ACT_DIEFORWARD, "ACT_DIEFORWARD" }, +{ACT_DIEVIOLENT, "ACT_DIEVIOLENT" }, +{ACT_BARNACLE_HIT, "ACT_BARNACLE_HIT" }, +{ACT_BARNACLE_PULL, "ACT_BARNACLE_PULL" }, +{ACT_BARNACLE_CHOMP, "ACT_BARNACLE_CHOMP" }, +{ACT_BARNACLE_CHEW, "ACT_BARNACLE_CHEW" }, +{ACT_SLEEP, "ACT_SLEEP" }, +{ACT_INSPECT_FLOOR, "ACT_INSPECT_FLOOR" }, +{ACT_INSPECT_WALL, "ACT_INSPECT_WALL" }, +{ACT_IDLE_ANGRY, "ACT_IDLE_ANGRY" }, +{ACT_WALK_HURT, "ACT_WALK_HURT" }, +{ACT_RUN_HURT, "ACT_RUN_HURT" }, +{ACT_HOVER, "ACT_HOVER" }, +{ACT_GLIDE, "ACT_GLIDE" }, +{ACT_FLY_LEFT, "ACT_FLY_LEFT" }, +{ACT_FLY_RIGHT, "ACT_FLY_RIGHT" }, +{ACT_DETECT_SCENT, "ACT_DETECT_SCENT" }, +{ACT_SNIFF, "ACT_SNIFF" }, +{ACT_BITE, "ACT_BITE" }, +{ACT_THREAT_DISPLAY, "ACT_THREAT_DISPLAY" }, +{ACT_FEAR_DISPLAY, "ACT_FEAR_DISPLAY" }, +{ACT_EXCITED, "ACT_EXCITED" }, +{ACT_SPECIAL_ATTACK1, "ACT_SPECIAL_ATTACK1" }, +{ACT_SPECIAL_ATTACK2, "ACT_SPECIAL_ATTACK2" }, +{ACT_COMBAT_IDLE, "ACT_COMBAT_IDLE" }, +{ACT_WALK_SCARED, "ACT_WALK_SCARED" }, +{ACT_RUN_SCARED, "ACT_RUN_SCARED" }, +{ACT_VICTORY_DANCE, "ACT_VICTORY_DANCE" }, +{ACT_DIE_HEADSHOT, "ACT_DIE_HEADSHOT" }, +{ACT_DIE_CHESTSHOT, "ACT_DIE_CHESTSHOT" }, +{ACT_DIE_GUTSHOT, "ACT_DIE_GUTSHOT" }, +{ACT_DIE_BACKSHOT, "ACT_DIE_BACKSHOT" }, +{ACT_FLINCH_HEAD, "ACT_FLINCH_HEAD" }, +{ACT_FLINCH_CHEST, "ACT_FLINCH_CHEST" }, +{ACT_FLINCH_STOMACH, "ACT_FLINCH_STOMACH" }, +{ACT_FLINCH_LEFTARM, "ACT_FLINCH_LEFTARM" }, +{ACT_FLINCH_RIGHTARM, "ACT_FLINCH_RIGHTARM" }, +{ACT_FLINCH_LEFTLEG, "ACT_FLINCH_LEFTLEG" }, +{ACT_FLINCH_RIGHTLEG, "ACT_FLINCH_RIGHTLEG" }, +{ACT_VM_NONE, "ACT_VM_NONE" }, // invalid animation +{ACT_VM_DEPLOY, "ACT_VM_DEPLOY" }, // deploy +{ACT_VM_DEPLOY_EMPTY, "ACT_VM_DEPLOY_EMPTY" }, // deploy empty weapon +{ACT_VM_HOLSTER, "ACT_VM_HOLSTER" }, // holster empty weapon +{ACT_VM_HOLSTER_EMPTY, "ACT_VM_HOLSTER_EMPTY" }, +{ACT_VM_IDLE1, "ACT_VM_IDLE1" }, +{ACT_VM_IDLE2, "ACT_VM_IDLE2" }, +{ACT_VM_IDLE3, "ACT_VM_IDLE3" }, +{ACT_VM_RANGE_ATTACK1, "ACT_VM_RANGE_ATTACK1" }, +{ACT_VM_RANGE_ATTACK2, "ACT_VM_RANGE_ATTACK2" }, +{ACT_VM_RANGE_ATTACK3, "ACT_VM_RANGE_ATTACK3" }, +{ACT_VM_MELEE_ATTACK1, "ACT_VM_MELEE_ATTACK1" }, +{ACT_VM_MELEE_ATTACK2, "ACT_VM_MELEE_ATTACK2" }, +{ACT_VM_MELEE_ATTACK3, "ACT_VM_MELEE_ATTACK3" }, +{ACT_VM_SHOOT_EMPTY, "ACT_VM_SHOOT_EMPTY" }, +{ACT_VM_START_RELOAD, "ACT_VM_START_RELOAD" }, +{ACT_VM_RELOAD, "ACT_VM_RELOAD" }, +{ACT_VM_RELOAD_EMPTY, "ACT_VM_RELOAD_EMPTY" }, +{ACT_VM_TURNON, "ACT_VM_TURNON" }, +{ACT_VM_TURNOFF, "ACT_VM_TURNOFF" }, +{ACT_VM_PUMP, "ACT_VM_PUMP" }, // user animations +{ACT_VM_PUMP_EMPTY, "ACT_VM_PUMP_EMPTY" }, +{ACT_VM_START_CHARGE, "ACT_VM_START_CHARGE" }, +{ACT_VM_CHARGE, "ACT_VM_CHARGE" }, +{ACT_VM_OVERLOAD, "ACT_VM_CHARGE" }, +{ACT_VM_IDLE_EMPTY, "ACT_VM_IDLE_EMPTY" }, +{0, NULL }, +}; + #define IMAGE_CUBEMAP 0x00000001 #define IMAGE_HAS_ALPHA 0x00000002 #define IMAGE_PREMULT 0x00000004 // indices who need in additional premultiply diff --git a/public/sprite.h b/public/sprite.h deleted file mode 100644 index 85777617..00000000 --- a/public/sprite.h +++ /dev/null @@ -1,59 +0,0 @@ -//======================================================================= -// Copyright XashXT Group 2007 © -// studio.h - sprite model header -//======================================================================= -#ifndef SPRITE_H -#define SPRITE_H - -/* -============================================================================== - -SPRITE MODELS -============================================================================== -*/ - -//header -#define SPRITE_VERSION_HALF 2 -#define SPRITE_VERSION_XASH 3 -#define IDSPRITEHEADER (('P'<<24)+('S'<<16)+('D'<<8)+'I') // little-endian "IDSP" - -//render format -#define SPR_VP_PARALLEL_UPRIGHT 0 -#define SPR_FACING_UPRIGHT 1 -#define SPR_VP_PARALLEL 2 -#define SPR_ORIENTED 3 -#define SPR_VP_PARALLEL_ORIENTED 4 - -#define SPR_NORMAL 0 //solid sprite -#define SPR_ADDITIVE 1 -#define SPR_INDEXALPHA 2 -#define SPR_ALPHTEST 3 -#define SPR_ADDGLOW 4 //same as additive, but without depthtest - -typedef struct -{ - int ident; - int version; - int type; - int texFormat; - float boundingradius; - int width; - int height; - int numframes; - float framerate; //xash auto-animate - uint rgbacolor; //packed rgba color -} dsprite_t; - -typedef struct -{ - int origin[2]; - int width; - int height; -} dspriteframe_t; - -typedef struct -{ - int type; -} frametype_t; - -#endif//SPRITE_H \ No newline at end of file diff --git a/release.bat b/release.bat index deaf6196..0386dcec 100644 --- a/release.bat +++ b/release.bat @@ -56,6 +56,6 @@ if exist server.dat move server.dat D:\Xash3D\xash\server.dat echo Build succeeded! echo Please wait. Xash is now loading cd D:\Xash3D\ -xash.exe -game valve +map lighttest -debug -log -rem bin\bsplib -game xash +map dm_qstyle -vis -rad -full -log +xash.exe +map qctest -debug -log +rem bin\bsplib -game xash +map qctest -vis -rad -full -log :done \ No newline at end of file diff --git a/render/gl_local.h b/render/gl_local.h index a26f7858..284ab335 100644 --- a/render/gl_local.h +++ b/render/gl_local.h @@ -32,9 +32,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include "ref_system.h" #include "materials.h" -#include "studio.h" -#include "sprite.h" -#include "bspmodel.h" #include "const.h" #ifndef GL_COLOR_INDEX8_EXT diff --git a/render/glw_imp.c b/render/glw_imp.c index 82c030be..2e2e5079 100644 --- a/render/glw_imp.c +++ b/render/glw_imp.c @@ -46,11 +46,14 @@ static bool VerifyDriver( void ) { char buffer[1024]; - strcpy( buffer, qglGetString( GL_RENDERER ) ); + strcpy( buffer, qglGetString( GL_RENDERER )); strlwr( buffer ); - if ( strcmp( buffer, "gdi generic" ) == 0 ) + + if (!strcmp( buffer, "gdi generic" )) + { if ( !glw_state.mcd_accelerated ) return false; + } return true; } @@ -502,7 +505,7 @@ bool GLimp_InitGL (void) goto fail; } - if ( !qwglMakeCurrent( glw_state.hDC, glw_state.hGLRC ) ) + if ( !qwglMakeCurrent( glw_state.hDC, glw_state.hGLRC ) ) { Msg("GLimp_Init() - qwglMakeCurrent failed\n"); goto fail; @@ -607,3 +610,4 @@ void GLimp_AppActivate( bool active ) ShowWindow( glw_state.hWnd, SW_MINIMIZE ); } } + \ No newline at end of file diff --git a/vprogs/PROGS.SRC b/vprogs/PROGS.SRC index de585e1d..99721733 100644 --- a/vprogs/PROGS.SRC +++ b/vprogs/PROGS.SRC @@ -42,6 +42,7 @@ ents/funcs/func_door.c ents/funcs/func_button.c ents/funcs/func_path_corner.c ents/funcs/func_train.c +ents/funcs/func_areaportal.c //ITEMS ents/items/items.c diff --git a/vprogs/client.c b/vprogs/client.c index f2d488c0..f2c29647 100644 --- a/vprogs/client.c +++ b/vprogs/client.c @@ -270,6 +270,7 @@ void() PutClientInServer = pev->origin = spawn_spot.origin + '0 0 1'; // Move to the spawnspot location pev->angles = spawn_spot.angles; // Face the angle the spawnspot indicates pev->fixangle = TRUE; // Turn this way immediately + pev->weaponmodel = "models/weapons/v_eagle.mdl"; // FIXME: rename to viewmodel dprint("PutClientInServer()\n"); @@ -290,7 +291,7 @@ void() PutClientInServer = setstats( pev, STAT_HEALTH_ICON, "i_health"); setstats( pev, STAT_HEALTH, ftos(pev->health)); - //setstats( pev, STAT_HELPICON, "i_help"); + setstats( pev, STAT_HELPICON, "i_help"); GetLevelParms(); }; diff --git a/vprogs/defs.c b/vprogs/defs.c index 66c4e602..33ce551d 100644 --- a/vprogs/defs.c +++ b/vprogs/defs.c @@ -218,6 +218,7 @@ void() traceon = #29; // turns statment trace on void() traceoff = #30; void(entity e) eprint = #31; // prints an entire edict float(float yaw, float dist) walkmove = #32; // returns TRUE or FALSE +void areaportal_state( float num, float state ) = #33; float() droptofloor = #34; // TRUE if landed on floor void(float style, string value) lightstyle = #35; float(float v) rint = #36; // round to nearest int diff --git a/vprogs/ents/funcs/func_areaportal.c b/vprogs/ents/funcs/func_areaportal.c new file mode 100644 index 00000000..211b524a --- /dev/null +++ b/vprogs/ents/funcs/func_areaportal.c @@ -0,0 +1,20 @@ +.float count; +.float style; + +void use_areaportal( void ) +{ + pev->count = 1; // toggle state + areaportal_state( pev->style, pev->count); +} + +/*QUAKED func_areaportal (0 0 0) ? + +This is a non-visible object that divides the world into +areas that are seperated when this portal is not activated. +Usually enclosed in the middle of a door. +*/ +void func_areaportal( void ) +{ + pev->use = use_areaportal; + pev->count = 0; // always start closed; +} \ No newline at end of file diff --git a/vprogs/ents/funcs/func_mover.c b/vprogs/ents/funcs/func_mover.c index e89b4980..f36a99fd 100644 --- a/vprogs/ents/funcs/func_mover.c +++ b/vprogs/ents/funcs/func_mover.c @@ -83,6 +83,17 @@ void() func_mover_stop = void() func_mover_stop_dead = { + entity t; + + // lookup all areaportals + t = find(world, targetname, pev->target); + while(t) + { + if(t->classname == "func_areaportal") + areaportal_state( t->style, FALSE ); + t = find(t, targetname, pev->target); + } + func_mover_stop_general(); }; @@ -160,7 +171,6 @@ void() func_mover_fire = void() func_mover_touch = { - bprint("door touch\n"); if(other.classname != "player") //Are you a player? return; if(other == world) //Are you the world? diff --git a/vprogs/ents/funcs/func_path_corner.c b/vprogs/ents/funcs/func_path_corner.c index 47fce00e..6346072a 100644 --- a/vprogs/ents/funcs/func_path_corner.c +++ b/vprogs/ents/funcs/func_path_corner.c @@ -6,11 +6,11 @@ This is the spawning function to the map entity 'func_path_corner' Currently only trains use this to tell their next stop position; */ -void() func_path_corner = +void() path_corner = { if (!pev->targetname) objerror ("monster_movetarget: no targetname"); - pev->solid = SOLID_TRIGGER; + pev->solid = SOLID_NOT; setsize (pev, '-8 -8 -8', '8 8 8'); }; \ No newline at end of file diff --git a/vprogs/ents/funcs/funcs.c b/vprogs/ents/funcs/funcs.c index 38f8a16a..f7bc0819 100644 --- a/vprogs/ents/funcs/funcs.c +++ b/vprogs/ents/funcs/funcs.c @@ -86,8 +86,4 @@ void() func_place_model = func_setup(); pev->movetype = MOVETYPE_NONE; -}; - -void func_areaportal( void ) -{ -} \ No newline at end of file +}; \ No newline at end of file