From 5c87db6e886c5d79f9e91dd022c6f19bbefb8a54 Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Sun, 22 Oct 2023 12:39:37 +0300 Subject: [PATCH] game: sync rogue player code --- Makefile | 6 +- src/ctf/g_spawn.c | 151 +++- src/game/player/hud.c | 56 ++ src/game/player/view.c | 182 ++++- src/rogue/player/hud.c | 677 ----------------- src/rogue/player/trail.c | 176 ----- src/rogue/player/view.c | 1502 -------------------------------------- 7 files changed, 338 insertions(+), 2412 deletions(-) delete mode 100644 src/rogue/player/hud.c delete mode 100644 src/rogue/player/trail.c delete mode 100644 src/rogue/player/view.c diff --git a/Makefile b/Makefile index 893f5cc2..2daf6d00 100644 --- a/Makefile +++ b/Makefile @@ -1523,9 +1523,9 @@ ROGUE_OBJS_ = \ src/game/monster/widow/widow.o \ src/game/monster/widow/widow2.o \ src/game/player/client.o \ - src/rogue/player/hud.o \ - src/rogue/player/trail.o \ - src/rogue/player/view.o \ + src/game/player/hud.o \ + src/game/player/trail.o \ + src/game/player/view.o \ src/game/player/weapon.o \ src/rogue/savegame/savegame.o diff --git a/src/ctf/g_spawn.c b/src/ctf/g_spawn.c index a8409634..3b031bae 100644 --- a/src/ctf/g_spawn.c +++ b/src/ctf/g_spawn.c @@ -1,5 +1,6 @@ /* * Copyright (C) 1997-2001 Id Software, Inc. + * Copyright (c) ZeniMax Media Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -292,11 +293,16 @@ ED_CallSpawn(edict_t *ent) } char * -ED_NewString(char *string) +ED_NewString(const char *string) { char *newb, *new_p; int i, l; + if (!string) + { + return NULL; + } + l = strlen(string) + 1; newb = gi.TagMalloc(l, TAG_LEVEL); @@ -332,16 +338,21 @@ ED_NewString(char *string) * the binary values in an edict */ void -ED_ParseField(char *key, char *value, edict_t *ent) +ED_ParseField(const char *key, const char *value, edict_t *ent) { field_t *f; byte *b; float v; vec3_t vec; + if (!ent || !value || !key) + { + return; + } + for (f = fields; f->name; f++) { - if (!Q_stricmp(f->name, key)) + if (!(f->flags & FFL_NOSPAWN) && !Q_strcasecmp(f->name, (char *)key)) { /* found it */ if (f->flags & FFL_SPAWNTEMP) @@ -365,13 +376,13 @@ ED_ParseField(char *key, char *value, edict_t *ent) ((float *)(b + f->ofs))[2] = vec[2]; break; case F_INT: - *(int *)(b + f->ofs) = atoi(value); + *(int *)(b + f->ofs) = (int)strtol(value, (char **)NULL, 10); break; case F_FLOAT: - *(float *)(b + f->ofs) = atof(value); + *(float *)(b + f->ofs) = (float)strtod(value, (char **)NULL); break; case F_ANGLEHACK: - v = atof(value); + v = (float)strtod(value, (char **)NULL); ((float *)(b + f->ofs))[0] = 0; ((float *)(b + f->ofs))[1] = v; ((float *)(b + f->ofs))[2] = 0; @@ -391,7 +402,7 @@ ED_ParseField(char *key, char *value, edict_t *ent) /* * Parses an edict out of the given string, - * returning the new position ed should be + * returning the new position. ed should be * a properly initialized empty edict. */ char * @@ -399,10 +410,16 @@ ED_ParseEdict(char *data, edict_t *ent) { qboolean init; char keyname[256]; - char *com_token; + const char *com_token; + + if (!ent) + { + return NULL; + } init = false; memset(&st, 0, sizeof(st)); + st.skyautorotate = 1; /* go through all the dictionary pairs */ while (1) @@ -420,7 +437,7 @@ ED_ParseEdict(char *data, edict_t *ent) gi.error("ED_ParseEntity: EOF without closing brace"); } - strncpy(keyname, com_token, sizeof(keyname) - 1); + Q_strlcpy(keyname, com_token, sizeof(keyname)); /* parse value */ com_token = COM_Parse(&data); @@ -437,9 +454,9 @@ ED_ParseEdict(char *data, edict_t *ent) init = true; - /* keynames with a leading underscore are used - for utility comments, and are immediately - discarded by quake */ + /* keynames with a leading underscore are + used for utility comments, and are + immediately discarded by quake */ if (keyname[0] == '_') { continue; @@ -462,6 +479,77 @@ ED_ParseEdict(char *data, edict_t *ent) * All but the first will have the FL_TEAMSLAVE flag set. * All but the last will have the teamchain field set to the next one */ +static void +G_FixTeams(void) +{ + edict_t *e, *e2, *chain; + int i, j; + int c, c2; + + c = 0; + c2 = 0; + + for (i = 1, e = g_edicts + i; i < globals.num_edicts; i++, e++) + { + if (!e->inuse) + { + continue; + } + + if (!e->team) + { + continue; + } + + if (!strcmp(e->classname, "func_train")) + { + if (e->flags & FL_TEAMSLAVE) + { + chain = e; + e->teammaster = e; + e->teamchain = NULL; + e->flags &= ~FL_TEAMSLAVE; + c++; + c2++; + + for (j = 1, e2 = g_edicts + j; + j < globals.num_edicts; + j++, e2++) + { + if (e2 == e) + { + continue; + } + + if (!e2->inuse) + { + continue; + } + + if (!e2->team) + { + continue; + } + + if (!strcmp(e->team, e2->team)) + { + c2++; + chain->teamchain = e2; + e2->teammaster = e; + e2->teamchain = NULL; + chain = e2; + e2->flags |= FL_TEAMSLAVE; + e2->movetype = MOVETYPE_PUSH; + e2->speed = e->speed; + } + } + } + } + } + + gi.dprintf("%i teams repaired\n", c); +} + void G_FindTeams(void) { @@ -522,6 +610,8 @@ G_FindTeams(void) } } + G_FixTeams(); + gi.dprintf("%i teams with %i entities.\n", c, c2); } @@ -534,10 +624,15 @@ SpawnEntities(const char *mapname, char *entities, const char *spawnpoint) { edict_t *ent; int inhibit; - char *com_token; + const char *com_token; int i; float skill_level; + if (!mapname || !entities || !spawnpoint) + { + return; + } + skill_level = floor(skill->value); if (skill_level < 0) @@ -562,8 +657,8 @@ SpawnEntities(const char *mapname, char *entities, const char *spawnpoint) memset(&level, 0, sizeof(level)); memset(g_edicts, 0, game.maxentities * sizeof(g_edicts[0])); - strncpy(level.mapname, mapname, sizeof(level.mapname) - 1); - strncpy(game.spawnpoint, spawnpoint, sizeof(game.spawnpoint) - 1); + Q_strlcpy(level.mapname, mapname, sizeof(level.mapname)); + Q_strlcpy(game.spawnpoint, spawnpoint, sizeof(game.spawnpoint)); /* set client fields on player ents */ for (i = 0; i < game.maxclients; i++) @@ -603,12 +698,34 @@ SpawnEntities(const char *mapname, char *entities, const char *spawnpoint) /* yet another map hack */ if (!Q_stricmp(level.mapname, "command") && - !Q_stricmp(ent->classname, - "trigger_once") && !Q_stricmp(ent->model, "*27")) + !Q_stricmp(ent->classname, "trigger_once") && + !Q_stricmp(ent->model, "*27")) { ent->spawnflags &= ~SPAWNFLAG_NOT_HARD; } + /* ahh, the joys of map hacks .. */ + if (!Q_stricmp(level.mapname, "rhangar2") && + !Q_stricmp(ent->classname, "func_door_rotating") && + ent->targetname && !Q_stricmp(ent->targetname, "t265")) + { + ent->spawnflags &= ~SPAWNFLAG_NOT_COOP; + } + + if (!Q_stricmp(level.mapname, "rhangar2") && + !Q_stricmp(ent->classname, "trigger_always") && + ent->target && !Q_stricmp(ent->target, "t265")) + { + ent->spawnflags |= SPAWNFLAG_NOT_COOP; + } + + if (!Q_stricmp(level.mapname, "rhangar2") && + !Q_stricmp(ent->classname, "func_wall") && + !Q_stricmp(ent->model, "*15")) + { + ent->spawnflags |= SPAWNFLAG_NOT_COOP; + } + /* remove things (except the world) from different skill levels or deathmatch */ if (ent != g_edicts) diff --git a/src/game/player/hud.c b/src/game/player/hud.c index 8e649e53..dda9433b 100644 --- a/src/game/player/hud.c +++ b/src/game/player/hud.c @@ -60,6 +60,12 @@ MoveClientToIntermission(edict_t *ent) ent->client->quadfire_framenum = 0; ent->client->trap_blew_up = false; ent->client->trap_time = 0; + ent->client->ir_framenum = 0; + ent->client->nuke_framenum = 0; + ent->client->double_framenum = 0; + + ent->client->ps.rdflags &= ~RDF_IRGOGGLES; + ent->viewheight = 0; ent->s.modelindex = 0; @@ -307,6 +313,15 @@ DeathmatchScoreboardMessage(edict_t *ent, edict_t *killer) tag = NULL; } + /* allow new DM games to override the tag picture */ + if (gamerules && gamerules->value) + { + if (DMGame.DogTag) + { + DMGame.DogTag(cl_ent, killer, &tag); + } + } + if (tag) { Com_sprintf(entry, sizeof(entry), @@ -342,6 +357,9 @@ DeathmatchScoreboardMessage(edict_t *ent, edict_t *killer) gi.WriteString(string); } +/* + * Draw help computer. + */ void HelpComputerMessage(edict_t *ent) { @@ -391,6 +409,9 @@ HelpComputerMessage(edict_t *ent) gi.WriteString(string); } +/* + * Display the current help message + */ void InventoryMessage(edict_t *ent) { @@ -494,6 +515,12 @@ G_SetStats(edict_t *ent) ent->client->ps.stats[STAT_TIMER] = (ent->client->quad_framenum - level.framenum) / 10; } + else if (ent->client->double_framenum > level.framenum) + { + ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("p_double"); + ent->client->ps.stats[STAT_TIMER] = + (ent->client->double_framenum - level.framenum) / 10; + } else if (ent->client->quadfire_framenum > level.framenum) { ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("p_quadfire"); @@ -519,6 +546,35 @@ G_SetStats(edict_t *ent) ent->client->ps.stats[STAT_TIMER] = (ent->client->breather_framenum - level.framenum) / 10; } + else if (ent->client->owned_sphere) + { + if (ent->client->owned_sphere->spawnflags == 1) /* defender */ + { + ent->client->ps.stats[STAT_TIMER_ICON] = + gi.imageindex("p_defender"); + } + else if (ent->client->owned_sphere->spawnflags == 2) /* hunter */ + { + ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("p_hunter"); + } + else if (ent->client->owned_sphere->spawnflags == 4) /* vengeance */ + { + ent->client->ps.stats[STAT_TIMER_ICON] = + gi.imageindex("p_vengeance"); + } + else /* error case */ + { + ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("i_fixme"); + } + + ent->client->ps.stats[STAT_TIMER] = + (int)(ent->client->owned_sphere->wait - level.time); + } + else if (ent->client->ir_framenum > level.framenum) + { + ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("p_ir"); + ent->client->ps.stats[STAT_TIMER] = + (ent->client->ir_framenum - level.framenum) / 10; } else { ent->client->ps.stats[STAT_TIMER_ICON] = 0; diff --git a/src/game/player/view.c b/src/game/player/view.c index 5c1d1399..345865ea 100644 --- a/src/game/player/view.c +++ b/src/game/player/view.c @@ -281,6 +281,12 @@ SV_CalcViewOffset(edict_t *ent) float delta; vec3_t v; + if (!ent) + { + return; + } + + /* base angles */ angles = ent->client->ps.kick_angles; @@ -289,8 +295,17 @@ SV_CalcViewOffset(edict_t *ent) { VectorClear(angles); - ent->client->ps.viewangles[ROLL] = 40; - ent->client->ps.viewangles[PITCH] = -15; + if (ent->flags & FL_SAM_RAIMI) + { + ent->client->ps.viewangles[ROLL] = 0; + ent->client->ps.viewangles[PITCH] = 0; + } + else + { + ent->client->ps.viewangles[ROLL] = 40; + ent->client->ps.viewangles[PITCH] = -15; + } + ent->client->ps.viewangles[YAW] = ent->client->killer_yaw; } else @@ -352,6 +367,8 @@ SV_CalcViewOffset(edict_t *ent) angles[ROLL] += delta; } + /* =================================== */ + /* base origin */ VectorClear(v); @@ -419,55 +436,73 @@ SV_CalcGunOffset(edict_t *ent) { int i; float delta; + static gitem_t *heatbeam; if (!ent) { return; } - /* gun angles from bobbing */ - ent->client->ps.gunangles[ROLL] = xyspeed * bobfracsin * 0.005; - ent->client->ps.gunangles[YAW] = xyspeed * bobfracsin * 0.01; - - if (bobcycle & 1) + if (!heatbeam) { - ent->client->ps.gunangles[ROLL] = -ent->client->ps.gunangles[ROLL]; - ent->client->ps.gunangles[YAW] = -ent->client->ps.gunangles[YAW]; + heatbeam = FindItemByClassname("weapon_plasmabeam"); } - ent->client->ps.gunangles[PITCH] = xyspeed * bobfracsin * 0.005; - - /* gun angles from delta movement */ - for (i = 0; i < 3; i++) + /* heatbeam shouldn't bob so the beam looks right */ + if (ent->client->pers.weapon != heatbeam) { - delta = ent->client->oldviewangles[i] - ent->client->ps.viewangles[i]; + /* gun angles from bobbing */ + ent->client->ps.gunangles[ROLL] = xyspeed * bobfracsin * 0.005; + ent->client->ps.gunangles[YAW] = xyspeed * bobfracsin * 0.01; - if (delta > 180) + if (bobcycle & 1) { - delta -= 360; + ent->client->ps.gunangles[ROLL] = -ent->client->ps.gunangles[ROLL]; + ent->client->ps.gunangles[YAW] = -ent->client->ps.gunangles[YAW]; } - if (delta < -180) - { - delta += 360; - } + ent->client->ps.gunangles[PITCH] = xyspeed * bobfracsin * 0.005; - if (delta > 45) + /* gun angles from delta movement */ + for (i = 0; i < 3; i++) { - delta = 45; - } + delta = ent->client->oldviewangles[i] - + ent->client->ps.viewangles[i]; - if (delta < -45) + if (delta > 180) + { + delta -= 360; + } + + if (delta < -180) + { + delta += 360; + } + + if (delta > 45) + { + delta = 45; + } + + if (delta < -45) + { + delta = -45; + } + + if (i == YAW) + { + ent->client->ps.gunangles[ROLL] += 0.1 * delta; + } + + ent->client->ps.gunangles[i] += 0.2 * delta; + } + } + else + { + for (i = 0; i < 3; i++) { - delta = -45; + ent->client->ps.gunangles[i] = 0; } - - if (i == YAW) - { - ent->client->ps.gunangles[ROLL] += 0.1 * delta; - } - - ent->client->ps.gunangles[i] += 0.2 * delta; } /* gun height */ @@ -563,6 +598,21 @@ SV_CalcBlend(edict_t *ent) SV_AddBlend(0, 0, 1, 0.08, ent->client->ps.blend); } } + else if (ent->client->double_framenum > level.framenum) + { + remaining = ent->client->double_framenum - level.framenum; + + if (remaining == 30) /* beginning to fade */ + { + gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/ddamage2.wav"), + 1, ATTN_NORM, 0); + } + + if ((remaining > 30) || (remaining & 4)) + { + SV_AddBlend(0.9, 0.7, 0, 0.08, ent->client->ps.blend); + } + } else if (ent->client->quadfire_framenum > level.framenum) { remaining = ent->client->quadfire_framenum - level.framenum; @@ -570,7 +620,7 @@ SV_CalcBlend(edict_t *ent) if (remaining == 30) /* beginning to fade */ { gi.sound(ent, CHAN_ITEM, gi.soundindex("items/quadfire2.wav"), - 1, ATTN_NORM, 0); + 1, ATTN_NORM, 0); } if ((remaining > 30) || (remaining & 4)) @@ -624,6 +674,32 @@ SV_CalcBlend(edict_t *ent) } } + if (ent->client->nuke_framenum > level.framenum) + { + float brightness; + brightness = (ent->client->nuke_framenum - level.framenum) / 20.0; + SV_AddBlend(1, 1, 1, brightness, ent->client->ps.blend); + } + + if (ent->client->ir_framenum > level.framenum) + { + remaining = ent->client->ir_framenum - level.framenum; + + if ((remaining > 30) || (remaining & 4)) + { + ent->client->ps.rdflags |= RDF_IRGOGGLES; + SV_AddBlend(1, 0, 0, 0.2, ent->client->ps.blend); + } + else + { + ent->client->ps.rdflags &= ~RDF_IRGOGGLES; + } + } + else + { + ent->client->ps.rdflags &= ~RDF_IRGOGGLES; + } + /* add for damage */ if (ent->client->damage_alpha > 0) { @@ -991,6 +1067,8 @@ G_SetClientEffects(edict_t *ent) } ent->s.effects = 0; + + /* player is always ir visible, even dead. */ ent->s.renderfx = RF_IR_VISIBLE; if ((ent->health <= 0) || level.intermissiontime) @@ -998,6 +1076,19 @@ G_SetClientEffects(edict_t *ent) return; } + if (ent->flags & FL_DISGUISED) + { + ent->s.renderfx |= RF_USE_DISGUISE; + } + + if (gamerules && gamerules->value) + { + if (DMGame.PlayerEffects) + { + DMGame.PlayerEffects(ent); + } + } + if (ent->powerarmor_time > level.time) { pa_type = PowerArmorType(ent); @@ -1023,6 +1114,16 @@ G_SetClientEffects(edict_t *ent) } } + if (ent->client->double_framenum > level.framenum) + { + remaining = ent->client->double_framenum - level.framenum; + + if ((remaining > 30) || (remaining & 4)) + { + ent->s.effects |= EF_DOUBLE; + } + } + if (ent->client->quadfire_framenum > level.framenum) { remaining = ent->client->quadfire_framenum - level.framenum; @@ -1033,6 +1134,17 @@ G_SetClientEffects(edict_t *ent) } } + if ((ent->client->owned_sphere) && + (ent->client->owned_sphere->spawnflags == 1)) + { + ent->s.effects |= EF_HALF_DAMAGE; + } + + if (ent->client->tracker_pain_framenum > level.framenum) + { + ent->s.effects |= EF_TRACKERTRAIL; + } + if (ent->client->invincible_framenum > level.framenum) { remaining = ent->client->invincible_framenum - level.framenum; @@ -1416,13 +1528,9 @@ ClientEndServerFrame(edict_t *ent) } G_CheckChaseStats(ent); - G_SetClientEvent(ent); - G_SetClientEffects(ent); - G_SetClientSound(ent); - G_SetClientFrame(ent); VectorCopy(ent->velocity, ent->client->oldvelocity); diff --git a/src/rogue/player/hud.c b/src/rogue/player/hud.c deleted file mode 100644 index 46f36fa4..00000000 --- a/src/rogue/player/hud.c +++ /dev/null @@ -1,677 +0,0 @@ -/* - * Copyright (C) 1997-2001 Id Software, Inc. - * Copyright (c) ZeniMax Media Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * ======================================================================= - * - * HUD, deathmatch scoreboard, help computer and intermission stuff. - * - * ======================================================================= - */ - -#include "../header/local.h" - -void -MoveClientToIntermission(edict_t *ent) -{ - if (!ent) - { - return; - } - - if (deathmatch->value || coop->value) - { - ent->client->showscores = true; - } - - VectorCopy(level.intermission_origin, ent->s.origin); - ent->client->ps.pmove.origin[0] = level.intermission_origin[0] * 8; - ent->client->ps.pmove.origin[1] = level.intermission_origin[1] * 8; - ent->client->ps.pmove.origin[2] = level.intermission_origin[2] * 8; - VectorCopy(level.intermission_angle, ent->client->ps.viewangles); - ent->client->ps.pmove.pm_type = PM_FREEZE; - ent->client->ps.gunindex = 0; - ent->client->ps.blend[3] = 0; - ent->client->ps.rdflags &= ~RDF_UNDERWATER; - - /* clean up powerup info */ - ent->client->quad_framenum = 0; - ent->client->invincible_framenum = 0; - ent->client->breather_framenum = 0; - ent->client->enviro_framenum = 0; - ent->client->grenade_blew_up = false; - ent->client->grenade_time = 0; - - ent->client->ps.rdflags &= ~RDF_IRGOGGLES; - ent->client->ir_framenum = 0; - ent->client->nuke_framenum = 0; - ent->client->double_framenum = 0; - - ent->viewheight = 0; - ent->s.modelindex = 0; - ent->s.modelindex2 = 0; - ent->s.modelindex3 = 0; - ent->s.modelindex = 0; - ent->s.effects = 0; - ent->s.sound = 0; - ent->solid = SOLID_NOT; - - gi.linkentity(ent); - - /* add the layout */ - if (deathmatch->value || coop->value) - { - DeathmatchScoreboardMessage(ent, NULL); - gi.unicast(ent, true); - } -} - -void -BeginIntermission(edict_t *targ) -{ - int i, n; - edict_t *ent, *client; - - if (!targ) - { - return; - } - - if (level.intermissiontime) - { - return; /* already activated */ - } - - game.autosaved = false; - - /* respawn any dead clients */ - for (i = 0; i < maxclients->value; i++) - { - client = g_edicts + 1 + i; - - if (!client->inuse) - { - continue; - } - - if (client->health <= 0) - { - respawn(client); - } - } - - level.intermissiontime = level.time; - level.changemap = targ->map; - - if (strstr(level.changemap, "*")) - { - if (coop->value) - { - for (i = 0; i < maxclients->value; i++) - { - client = g_edicts + 1 + i; - - if (!client->inuse) - { - continue; - } - - /* strip players of all keys between units */ - for (n = 0; n < game.num_items; n++) - { - if (itemlist[n].flags & IT_KEY) - { - client->client->pers.inventory[n] = 0; - } - } - - client->client->pers.power_cubes = 0; - } - } - } - else - { - if (!deathmatch->value) - { - level.exitintermission = 1; /* go immediately to the next level */ - return; - } - } - - level.exitintermission = 0; - - /* find an intermission spot */ - ent = G_Find(NULL, FOFS(classname), "info_player_intermission"); - - if (!ent) - { - /* the map creator forgot to put in an intermission point... */ - ent = G_Find(NULL, FOFS(classname), "info_player_start"); - - if (!ent) - { - ent = G_Find(NULL, FOFS(classname), "info_player_deathmatch"); - } - } - else - { - /* chose one of four spots */ - i = rand() & 3; - - while (i--) - { - ent = G_Find(ent, FOFS(classname), "info_player_intermission"); - - if (!ent) /* wrap around the list */ - { - ent = G_Find(ent, FOFS(classname), "info_player_intermission"); - } - } - } - - VectorCopy(ent->s.origin, level.intermission_origin); - VectorCopy(ent->s.angles, level.intermission_angle); - - /* move all clients to the intermission point */ - for (i = 0; i < maxclients->value; i++) - { - client = g_edicts + 1 + i; - - if (!client->inuse) - { - continue; - } - - MoveClientToIntermission(client); - } -} - -void -DeathmatchScoreboardMessage(edict_t *ent, edict_t *killer /* can be NULL */) -{ - char entry[1024]; - char string[1400]; - int stringlength; - int i, j, k; - int sorted[MAX_CLIENTS]; - int sortedscores[MAX_CLIENTS]; - int score, total; - int x, y; - gclient_t *cl; - edict_t *cl_ent; - char *tag; - - if (!ent) - { - return; - } - - /* sort the clients by score */ - total = 0; - - for (i = 0; i < game.maxclients; i++) - { - cl_ent = g_edicts + 1 + i; - - if (!cl_ent->inuse || game.clients[i].resp.spectator) - { - continue; - } - - score = game.clients[i].resp.score; - - for (j = 0; j < total; j++) - { - if (score > sortedscores[j]) - { - break; - } - } - - for (k = total; k > j; k--) - { - sorted[k] = sorted[k - 1]; - sortedscores[k] = sortedscores[k - 1]; - } - - sorted[j] = i; - sortedscores[j] = score; - total++; - } - - /* print level name and exit rules */ - string[0] = 0; - - stringlength = strlen(string); - - /* add the clients in sorted order */ - if (total > 12) - { - total = 12; - } - - for (i = 0; i < total; i++) - { - cl = &game.clients[sorted[i]]; - cl_ent = g_edicts + 1 + sorted[i]; - - x = (i >= 6) ? 160 : 0; - y = 32 + 32 * (i % 6); - - /* add a dogtag */ - if (cl_ent == ent) - { - tag = "tag1"; - } - else if (cl_ent == killer) - { - tag = "tag2"; - } - else - { - tag = NULL; - } - - /* allow new DM games to override the tag picture */ - if (gamerules && gamerules->value) - { - if (DMGame.DogTag) - { - DMGame.DogTag(cl_ent, killer, &tag); - } - } - - if (tag) - { - Com_sprintf(entry, sizeof(entry), "xv %i yv %i picn %s ", x + 32, y, tag); - j = strlen(entry); - - if (stringlength + j > 1024) - { - break; - } - - strcpy(string + stringlength, entry); - stringlength += j; - } - - /* send the layout */ - Com_sprintf(entry, sizeof(entry), "client %i %i %i %i %i %i ", - x, y, sorted[i], cl->resp.score, cl->ping, - (level.framenum - cl->resp.enterframe) / 600); - j = strlen(entry); - - if (stringlength + j > 1024) - { - break; - } - - strcpy(string + stringlength, entry); - stringlength += j; - } - - gi.WriteByte(svc_layout); - gi.WriteString(string); -} - -/* - * Draw help computer. - */ -void -HelpComputerMessage(edict_t *ent) -{ - char string[1024]; - char *sk; - - if (!ent) - { - return; - } - - if (skill->value == SKILL_EASY) - { - sk = "easy"; - } - else if (skill->value == SKILL_MEDIUM) - { - sk = "medium"; - } - else if (skill->value == SKILL_HARD) - { - sk = "hard"; - } - else - { - sk = "hard+"; - } - - /* send the layout */ - Com_sprintf(string, sizeof(string), - "xv 32 yv 8 picn help " /* background */ - "xv 202 yv 12 string2 \"%s\" " /* skill */ - "xv 0 yv 24 cstring2 \"%s\" " /* level name */ - "xv 0 yv 54 cstring2 \"%s\" " /* help 1 */ - "xv 0 yv 110 cstring2 \"%s\" " /* help 2 */ - "xv 50 yv 164 string2 \" kills goals secrets\" " - "xv 50 yv 172 string2 \"%3i/%3i %i/%i %i/%i\" ", - sk, level.level_name, - game.helpmessage1, - game.helpmessage2, - level.killed_monsters, level.total_monsters, - level.found_goals, level.total_goals, - level.found_secrets, level.total_secrets); - - gi.WriteByte(svc_layout); - gi.WriteString(string); -} - -/* - * Display the current help message - */ -void -InventoryMessage(edict_t *ent) -{ - int i; - - if (!ent) - { - return; - } - - gi.WriteByte(svc_inventory); - - for (i = 0; i < MAX_ITEMS; i++) - { - gi.WriteShort(ent->client->pers.inventory[i]); - } -} - -/* ======================================================================= */ - -void -G_SetStats(edict_t *ent) -{ - gitem_t *item; - int index, cells; - int power_armor_type; - - if (!ent) - { - return; - } - - /* health */ - ent->client->ps.stats[STAT_HEALTH_ICON] = level.pic_health; - ent->client->ps.stats[STAT_HEALTH] = (ent->health < -99) ? -99 : ent->health; - - /* ammo */ - if (!ent->client->ammo_index) - { - ent->client->ps.stats[STAT_AMMO_ICON] = 0; - ent->client->ps.stats[STAT_AMMO] = 0; - } - else - { - item = &itemlist[ent->client->ammo_index]; - ent->client->ps.stats[STAT_AMMO_ICON] = gi.imageindex(item->icon); - ent->client->ps.stats[STAT_AMMO] = - ent->client->pers.inventory[ent->client->ammo_index]; - } - - /* armor */ - power_armor_type = PowerArmorType(ent); - - if (power_armor_type) - { - cells = ent->client->pers.inventory[ITEM_INDEX(FindItem("cells"))]; - - if (cells == 0) - { - /* ran out of cells for power armor */ - ent->flags &= ~FL_POWER_ARMOR; - gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/power2.wav"), 1, ATTN_NORM, 0); - power_armor_type = 0; - } - } - - index = ArmorIndex(ent); - - if (power_armor_type && (!index || (level.framenum & 8))) - { - /* flash between power armor and other armor icon */ - ent->client->ps.stats[STAT_ARMOR_ICON] = gi.imageindex("i_powershield"); - ent->client->ps.stats[STAT_ARMOR] = cells; - } - else if (index) - { - item = GetItemByIndex(index); - ent->client->ps.stats[STAT_ARMOR_ICON] = gi.imageindex(item->icon); - ent->client->ps.stats[STAT_ARMOR] = ent->client->pers.inventory[index]; - } - else - { - ent->client->ps.stats[STAT_ARMOR_ICON] = 0; - ent->client->ps.stats[STAT_ARMOR] = 0; - } - - /* pickup message */ - if (level.time > ent->client->pickup_msg_time) - { - ent->client->ps.stats[STAT_PICKUP_ICON] = 0; - ent->client->ps.stats[STAT_PICKUP_STRING] = 0; - } - - /* timers */ - if (ent->client->quad_framenum > level.framenum) - { - ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("p_quad"); - ent->client->ps.stats[STAT_TIMER] = (ent->client->quad_framenum - level.framenum) / 10; - } - else if (ent->client->double_framenum > level.framenum) - { - ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("p_double"); - ent->client->ps.stats[STAT_TIMER] = - (ent->client->double_framenum - level.framenum) / 10; - } - else if (ent->client->invincible_framenum > level.framenum) - { - ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex( "p_invulnerability"); - ent->client->ps.stats[STAT_TIMER] = (ent->client->invincible_framenum - level.framenum) / 10; - } - else if (ent->client->enviro_framenum > level.framenum) - { - ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("p_envirosuit"); - ent->client->ps.stats[STAT_TIMER] = (ent->client->enviro_framenum - level.framenum) / 10; - } - else if (ent->client->breather_framenum > level.framenum) - { - ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("p_rebreather"); - ent->client->ps.stats[STAT_TIMER] = (ent->client->breather_framenum - level.framenum) / 10; - } - else if (ent->client->owned_sphere) - { - if (ent->client->owned_sphere->spawnflags == 1) /* defender */ - { - ent->client->ps.stats[STAT_TIMER_ICON] = - gi.imageindex("p_defender"); - } - else if (ent->client->owned_sphere->spawnflags == 2) /* hunter */ - { - ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("p_hunter"); - } - else if (ent->client->owned_sphere->spawnflags == 4) /* vengeance */ - { - ent->client->ps.stats[STAT_TIMER_ICON] = - gi.imageindex("p_vengeance"); - } - else /* error case */ - { - ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("i_fixme"); - } - - ent->client->ps.stats[STAT_TIMER] = - (int)(ent->client->owned_sphere->wait - level.time); - } - else if (ent->client->ir_framenum > level.framenum) - { - ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex("p_ir"); - ent->client->ps.stats[STAT_TIMER] = - (ent->client->ir_framenum - level.framenum) / 10; } - else - { - ent->client->ps.stats[STAT_TIMER_ICON] = 0; - ent->client->ps.stats[STAT_TIMER] = 0; - } - - /* selected item */ - if (ent->client->pers.selected_item == -1) - { - ent->client->ps.stats[STAT_SELECTED_ICON] = 0; - } - else - { - ent->client->ps.stats[STAT_SELECTED_ICON] = gi.imageindex(itemlist[ent->client->pers.selected_item].icon); - } - - ent->client->ps.stats[STAT_SELECTED_ITEM] = ent->client->pers.selected_item; - - /* layouts */ - ent->client->ps.stats[STAT_LAYOUTS] = 0; - - if (deathmatch->value) - { - if ((ent->client->pers.health <= 0) || level.intermissiontime || ent->client->showscores) - { - ent->client->ps.stats[STAT_LAYOUTS] |= 1; - } - - if (ent->client->showinventory && (ent->client->pers.health > 0)) - { - ent->client->ps.stats[STAT_LAYOUTS] |= 2; - } - } - else - { - if (ent->client->showscores || ent->client->showhelp) - { - ent->client->ps.stats[STAT_LAYOUTS] |= 1; - } - - if (ent->client->showinventory && (ent->client->pers.health > 0)) - { - ent->client->ps.stats[STAT_LAYOUTS] |= 2; - } - } - - /* frags */ - ent->client->ps.stats[STAT_FRAGS] = ent->client->resp.score; - - /* help icon / current weapon if not shown */ - if (ent->client->pers.helpchanged && (level.framenum & 8)) - { - ent->client->ps.stats[STAT_HELPICON] = gi.imageindex("i_help"); - } - else if (((ent->client->pers.hand == CENTER_HANDED) || - (ent->client->ps.fov > 91)) && ent->client->pers.weapon) - { - cvar_t *gun; - gun = gi.cvar("cl_gun", "2", 0); - - if (gun->value != 2) - { - ent->client->ps.stats[STAT_HELPICON] = gi.imageindex(ent->client->pers.weapon->icon); - } - else - { - ent->client->ps.stats[STAT_HELPICON] = 0; - } - } - else - { - ent->client->ps.stats[STAT_HELPICON] = 0; - } - - ent->client->ps.stats[STAT_SPECTATOR] = 0; -} - -void -G_CheckChaseStats(edict_t *ent) -{ - int i; - gclient_t *cl; - - if (!ent) - { - return; - } - - for (i = 1; i <= maxclients->value; i++) - { - cl = g_edicts[i].client; - - if (!g_edicts[i].inuse || (cl->chase_target != ent)) - { - continue; - } - - memcpy(cl->ps.stats, ent->client->ps.stats, sizeof(cl->ps.stats)); - G_SetSpectatorStats(g_edicts + i); - } -} - -void -G_SetSpectatorStats(edict_t *ent) -{ - if (!ent) - { - return; - } - - gclient_t *cl = ent->client; - - if (!cl->chase_target) - { - G_SetStats(ent); - } - - cl->ps.stats[STAT_SPECTATOR] = 1; - - /* layouts are independant in spectator */ - cl->ps.stats[STAT_LAYOUTS] = 0; - - if ((cl->pers.health <= 0) || level.intermissiontime || cl->showscores) - { - cl->ps.stats[STAT_LAYOUTS] |= 1; - } - - if (cl->showinventory && (cl->pers.health > 0)) - { - cl->ps.stats[STAT_LAYOUTS] |= 2; - } - - if (cl->chase_target && cl->chase_target->inuse) - { - cl->ps.stats[STAT_CHASE] = CS_PLAYERSKINS + - (cl->chase_target - g_edicts) - 1; - } - else - { - cl->ps.stats[STAT_CHASE] = 0; - } -} diff --git a/src/rogue/player/trail.c b/src/rogue/player/trail.c deleted file mode 100644 index 00dc1dfd..00000000 --- a/src/rogue/player/trail.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 1997-2001 Id Software, Inc. - * Copyright (c) ZeniMax Media Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * ======================================================================= - * - * The player trail, used by monsters to locate the player. - * - * ======================================================================= - */ - -#include "../header/local.h" - -/* - * This is a circular list containing the a list of points of where - * the player has been recently. It is used by monsters for pursuit. - * - * .origin the spot - * .owner forward link - * .aiment backward link - */ - -#define NEXT(n) (((n) + 1) & (TRAIL_LENGTH - 1)) -#define PREV(n) (((n) - 1) & (TRAIL_LENGTH - 1)) - -#define TRAIL_LENGTH 8 - -edict_t *trail[TRAIL_LENGTH]; -int trail_head; -qboolean trail_active = false; - -void -PlayerTrail_Init(void) -{ - int n; - - if (deathmatch->value) - { - return; - } - - for (n = 0; n < TRAIL_LENGTH; n++) - { - trail[n] = G_Spawn(); - trail[n]->classname = "player_trail"; - } - - trail_head = 0; - trail_active = true; -} - -void -PlayerTrail_Add(vec3_t spot) -{ - vec3_t temp; - - if (!trail_active) - { - return; - } - - VectorCopy(spot, trail[trail_head]->s.origin); - - trail[trail_head]->timestamp = level.time; - - VectorSubtract(spot, trail[PREV(trail_head)]->s.origin, temp); - trail[trail_head]->s.angles[1] = vectoyaw(temp); - - trail_head = NEXT(trail_head); -} - -void -PlayerTrail_New(vec3_t spot) -{ - if (!trail_active) - { - return; - } - - PlayerTrail_Init(); - PlayerTrail_Add(spot); -} - -edict_t * -PlayerTrail_PickFirst(edict_t *self) -{ - int marker; - int n; - - if (!self) - { - return NULL; - } - - if (!trail_active) - { - return NULL; - } - - for (marker = trail_head, n = TRAIL_LENGTH; n; n--) - { - if (trail[marker]->timestamp <= self->monsterinfo.trail_time) - { - marker = NEXT(marker); - } - else - { - break; - } - } - - if (visible(self, trail[marker])) - { - return trail[marker]; - } - - if (visible(self, trail[PREV(marker)])) - { - return trail[PREV(marker)]; - } - - return trail[marker]; -} - -edict_t * -PlayerTrail_PickNext(edict_t *self) -{ - int marker; - int n; - - if (!self) - { - return NULL; - } - - if (!trail_active) - { - return NULL; - } - - for (marker = trail_head, n = TRAIL_LENGTH; n; n--) - { - if (trail[marker]->timestamp <= self->monsterinfo.trail_time) - { - marker = NEXT(marker); - } - else - { - break; - } - } - - return trail[marker]; -} - -edict_t * -PlayerTrail_LastSpot(void) -{ - return trail[PREV(trail_head)]; -} diff --git a/src/rogue/player/view.c b/src/rogue/player/view.c deleted file mode 100644 index fe4347c4..00000000 --- a/src/rogue/player/view.c +++ /dev/null @@ -1,1502 +0,0 @@ -/* - * Copyright (C) 1997-2001 Id Software, Inc. - * Copyright (c) ZeniMax Media Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * ======================================================================= - * - * The "camera" through that the player looks into the game. - * - * ======================================================================= - */ - -#include "../header/local.h" -#include "../monster/misc/player.h" - -static edict_t *current_player; -static gclient_t *current_client; - -static vec3_t forward, right, up; -float xyspeed; - -float bobmove; -int bobcycle; -float bobfracsin; - -float -SV_CalcRoll(vec3_t angles, vec3_t velocity) -{ - float sign; - float side; - float value; - - side = DotProduct(velocity, right); - sign = side < 0 ? -1 : 1; - side = fabs(side); - - value = sv_rollangle->value; - - if (side < sv_rollspeed->value) - { - side = side * value / sv_rollspeed->value; - } - else - { - side = value; - } - - return side * sign; -} - -/* - * Handles color blends and view kicks - */ -void -P_DamageFeedback(edict_t *player) -{ - gclient_t *client; - float side; - float realcount, count, kick; - vec3_t v; - int r, l; - static vec3_t power_color = {0.0, 1.0, 0.0}; - static vec3_t acolor = {1.0, 1.0, 1.0}; - static vec3_t bcolor = {1.0, 0.0, 0.0}; - - if (!player) - { - return; - } - - /* death/gib sound is now aggregated and played here */ - if (player->sounds) - { - gi.sound (player, CHAN_VOICE, player->sounds, 1, ATTN_NORM, 0); - player->sounds = 0; - } - - client = player->client; - - /* flash the backgrounds behind the status numbers */ - client->ps.stats[STAT_FLASHES] = 0; - - if (client->damage_blood) - { - client->ps.stats[STAT_FLASHES] |= 1; - } - - if (client->damage_armor && !(player->flags & FL_GODMODE) && - (client->invincible_framenum <= level.framenum)) - { - client->ps.stats[STAT_FLASHES] |= 2; - } - - /* total points of damage shot at the player this frame */ - count = (client->damage_blood + client->damage_armor + client->damage_parmor); - - if (count == 0) - { - return; /* didn't take any damage */ - } - - /* start a pain animation if still in the player model */ - if ((client->anim_priority < ANIM_PAIN) && (player->s.modelindex == 255)) - { - static int i; - - client->anim_priority = ANIM_PAIN; - - if (client->ps.pmove.pm_flags & PMF_DUCKED) - { - player->s.frame = FRAME_crpain1 - 1; - client->anim_end = FRAME_crpain4; - } - else - { - i = (i + 1) % 3; - - switch (i) - { - case 0: - player->s.frame = FRAME_pain101 - 1; - client->anim_end = FRAME_pain104; - break; - case 1: - player->s.frame = FRAME_pain201 - 1; - client->anim_end = FRAME_pain204; - break; - case 2: - player->s.frame = FRAME_pain301 - 1; - client->anim_end = FRAME_pain304; - break; - } - } - } - - realcount = count; - - if (count < 10) - { - count = 10; /* always make a visible effect */ - } - - /* play an apropriate pain sound */ - if ((level.time > player->pain_debounce_time) && - !(player->flags & FL_GODMODE) && - (client->invincible_framenum <= level.framenum) && - player->health > 0) - { - r = 1 + (rand() & 1); - player->pain_debounce_time = level.time + 0.7; - - if (player->health < 25) - { - l = 25; - } - else if (player->health < 50) - { - l = 50; - } - else if (player->health < 75) - { - l = 75; - } - else - { - l = 100; - } - - gi.sound(player, CHAN_VOICE, gi.soundindex(va("*pain%i_%i.wav", l, r)), 1, ATTN_NORM, 0); - } - - /* the total alpha of the blend is always proportional to count */ - if (client->damage_alpha < 0) - { - client->damage_alpha = 0; - } - - client->damage_alpha += count * 0.01; - - if (client->damage_alpha < 0.2) - { - client->damage_alpha = 0.2; - } - - if (client->damage_alpha > 0.6) - { - client->damage_alpha = 0.6; /* don't go too saturated */ - } - - /* the color of the blend will vary based on how - much was absorbed by different armors */ - VectorClear(v); - - if (client->damage_parmor) - { - VectorMA(v, (float)client->damage_parmor / realcount, power_color, v); - } - - if (client->damage_armor) - { - VectorMA(v, (float)client->damage_armor / realcount, acolor, v); - } - - if (client->damage_blood) - { - VectorMA(v, (float)client->damage_blood / realcount, bcolor, v); - } - - VectorCopy(v, client->damage_blend); - - /* calculate view angle kicks */ - kick = abs(client->damage_knockback); - - if (kick && (player->health > 0)) /* kick of 0 means no view adjust at all */ - { - kick = kick * 100 / player->health; - - if (kick < count * 0.5) - { - kick = count * 0.5; - } - - if (kick > 50) - { - kick = 50; - } - - VectorSubtract(client->damage_from, player->s.origin, v); - VectorNormalize(v); - - side = DotProduct(v, right); - client->v_dmg_roll = kick * side * 0.3; - - side = -DotProduct(v, forward); - client->v_dmg_pitch = kick * side * 0.3; - - client->v_dmg_time = level.time + DAMAGE_TIME; - } - - /* clear totals */ - client->damage_blood = 0; - client->damage_armor = 0; - client->damage_parmor = 0; - client->damage_knockback = 0; -} - -/* - * Auto pitching on slopes? - * - * fall from 128: 400 = 160000 - * fall from 256: 580 = 336400 - * fall from 384: 720 = 518400 - * fall from 512: 800 = 640000 - * fall from 640: 960 = - * - * damage = deltavelocity*deltavelocity * 0.0001 - */ -void -SV_CalcViewOffset(edict_t *ent) -{ - float *angles; - float bob; - float ratio; - float delta; - vec3_t v; - - if (!ent) - { - return; - } - - - /* base angles */ - angles = ent->client->ps.kick_angles; - - /* if dead, fix the angle and don't add any kick */ - if (ent->deadflag) - { - VectorClear(angles); - - if (ent->flags & FL_SAM_RAIMI) - { - ent->client->ps.viewangles[ROLL] = 0; - ent->client->ps.viewangles[PITCH] = 0; - } - else - { - ent->client->ps.viewangles[ROLL] = 40; - ent->client->ps.viewangles[PITCH] = -15; - } - - ent->client->ps.viewangles[YAW] = ent->client->killer_yaw; - } - else - { - /* add angles based on weapon kick */ - VectorCopy(ent->client->kick_angles, angles); - - /* add angles based on damage kick */ - ratio = (ent->client->v_dmg_time - level.time) / DAMAGE_TIME; - - if (ratio < 0) - { - ratio = 0; - ent->client->v_dmg_pitch = 0; - ent->client->v_dmg_roll = 0; - } - - angles[PITCH] += ratio * ent->client->v_dmg_pitch; - angles[ROLL] += ratio * ent->client->v_dmg_roll; - - /* add pitch based on fall kick */ - ratio = (ent->client->fall_time - level.time) / FALL_TIME; - - if (ratio < 0) - { - ratio = 0; - } - - angles[PITCH] += ratio * ent->client->fall_value; - - /* add angles based on velocity */ - delta = DotProduct(ent->velocity, forward); - angles[PITCH] += delta * run_pitch->value; - - delta = DotProduct(ent->velocity, right); - angles[ROLL] += delta * run_roll->value; - - /* add angles based on bob */ - delta = bobfracsin * bob_pitch->value * xyspeed; - - if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) - { - delta *= 6; /* crouching */ - } - - angles[PITCH] += delta; - delta = bobfracsin * bob_roll->value * xyspeed; - - if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) - { - delta *= 6; /* crouching */ - } - - if (bobcycle & 1) - { - delta = -delta; - } - - angles[ROLL] += delta; - } - - /* =================================== */ - - /* base origin */ - VectorClear(v); - - /* add view height */ - v[2] += ent->viewheight; - - /* add fall height */ - ratio = (ent->client->fall_time - level.time) / FALL_TIME; - - if (ratio < 0) - { - ratio = 0; - } - - v[2] -= ratio * ent->client->fall_value * 0.4; - - /* add bob height */ - bob = bobfracsin * xyspeed * bob_up->value; - - if (bob > 6) - { - bob = 6; - } - - v[2] += bob; - - /* add kick offset */ - VectorAdd(v, ent->client->kick_origin, v); - - /* absolutely bound offsets so the view can - never be outside the player box */ - - if (v[0] < -14) - { - v[0] = -14; - } - else if (v[0] > 14) - { - v[0] = 14; - } - - if (v[1] < -14) - { - v[1] = -14; - } - else if (v[1] > 14) - { - v[1] = 14; - } - - if (v[2] < -22) - { - v[2] = -22; - } - else if (v[2] > 30) - { - v[2] = 30; - } - - VectorCopy(v, ent->client->ps.viewoffset); -} - -void -SV_CalcGunOffset(edict_t *ent) -{ - int i; - float delta; - static gitem_t *heatbeam; - - if (!ent) - { - return; - } - - if (!heatbeam) - { - heatbeam = FindItemByClassname("weapon_plasmabeam"); - } - - /* heatbeam shouldn't bob so the beam looks right */ - if (ent->client->pers.weapon != heatbeam) - { - /* gun angles from bobbing */ - ent->client->ps.gunangles[ROLL] = xyspeed * bobfracsin * 0.005; - ent->client->ps.gunangles[YAW] = xyspeed * bobfracsin * 0.01; - - if (bobcycle & 1) - { - ent->client->ps.gunangles[ROLL] = -ent->client->ps.gunangles[ROLL]; - ent->client->ps.gunangles[YAW] = -ent->client->ps.gunangles[YAW]; - } - - ent->client->ps.gunangles[PITCH] = xyspeed * bobfracsin * 0.005; - - /* gun angles from delta movement */ - for (i = 0; i < 3; i++) - { - delta = ent->client->oldviewangles[i] - - ent->client->ps.viewangles[i]; - - if (delta > 180) - { - delta -= 360; - } - - if (delta < -180) - { - delta += 360; - } - - if (delta > 45) - { - delta = 45; - } - - if (delta < -45) - { - delta = -45; - } - - if (i == YAW) - { - ent->client->ps.gunangles[ROLL] += 0.1 * delta; - } - - ent->client->ps.gunangles[i] += 0.2 * delta; - } - } - else - { - for (i = 0; i < 3; i++) - { - ent->client->ps.gunangles[i] = 0; - } - } - - /* gun height */ - VectorClear(ent->client->ps.gunoffset); - - /* gun_x / gun_y / gun_z are development tools */ - for (i = 0; i < 3; i++) - { - ent->client->ps.gunoffset[i] += forward[i] * (gun_y->value); - ent->client->ps.gunoffset[i] += right[i] * gun_x->value; - ent->client->ps.gunoffset[i] += up[i] * (-gun_z->value); - } -} - -void -SV_AddBlend(float r, float g, float b, float a, float *v_blend) -{ - float a2, a3; - - if (!v_blend) - { - return; - } - - if (a <= 0) - { - return; - } - - a2 = v_blend[3] + (1 - v_blend[3]) * a; /* new total alpha */ - a3 = v_blend[3] / a2; /* fraction of color from old */ - - v_blend[0] = v_blend[0] * a3 + r * (1 - a3); - v_blend[1] = v_blend[1] * a3 + g * (1 - a3); - v_blend[2] = v_blend[2] * a3 + b * (1 - a3); - v_blend[3] = a2; -} - -void -SV_CalcBlend(edict_t *ent) -{ - int contents; - vec3_t vieworg; - int remaining; - - if (!ent) - { - return; - } - - ent->client->ps.blend[0] = ent->client->ps.blend[1] = ent->client->ps.blend[2] = ent->client->ps.blend[3] = 0; - - /* add for contents */ - VectorAdd(ent->s.origin, ent->client->ps.viewoffset, vieworg); - contents = gi.pointcontents(vieworg); - - if (contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) - { - ent->client->ps.rdflags |= RDF_UNDERWATER; - } - else - { - ent->client->ps.rdflags &= ~RDF_UNDERWATER; - } - - if (contents & (CONTENTS_SOLID | CONTENTS_LAVA)) - { - SV_AddBlend(1.0, 0.3, 0.0, 0.6, ent->client->ps.blend); - } - else if (contents & CONTENTS_SLIME) - { - SV_AddBlend(0.0, 0.1, 0.05, 0.6, ent->client->ps.blend); - } - else if (contents & CONTENTS_WATER) - { - SV_AddBlend(0.5, 0.3, 0.2, 0.4, ent->client->ps.blend); - } - - /* add for powerups */ - if (ent->client->quad_framenum > level.framenum) - { - remaining = ent->client->quad_framenum - level.framenum; - - if (remaining == 30) /* beginning to fade */ - { - gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage2.wav"), 1, ATTN_NORM, 0); - } - - if ((remaining > 30) || (remaining & 4)) - { - SV_AddBlend(0, 0, 1, 0.08, ent->client->ps.blend); - } - } - else if (ent->client->double_framenum > level.framenum) - { - remaining = ent->client->double_framenum - level.framenum; - - if (remaining == 30) /* beginning to fade */ - { - gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/ddamage2.wav"), 1, ATTN_NORM, 0); - } - - if ((remaining > 30) || (remaining & 4)) - { - SV_AddBlend(0.9, 0.7, 0, 0.08, ent->client->ps.blend); - } - } - else if (ent->client->invincible_framenum > level.framenum) - { - remaining = ent->client->invincible_framenum - level.framenum; - - if (remaining == 30) /* beginning to fade */ - { - gi.sound(ent, CHAN_ITEM, gi.soundindex("items/protect2.wav"), 1, ATTN_NORM, 0); - } - - if ((remaining > 30) || (remaining & 4)) - { - SV_AddBlend(1, 1, 0, 0.08, ent->client->ps.blend); - } - } - else if (ent->client->enviro_framenum > level.framenum) - { - remaining = ent->client->enviro_framenum - level.framenum; - - if (remaining == 30) /* beginning to fade */ - { - gi.sound(ent, CHAN_ITEM, gi.soundindex("items/airout.wav"), 1, ATTN_NORM, 0); - } - - if ((remaining > 30) || (remaining & 4)) - { - SV_AddBlend(0, 1, 0, 0.08, ent->client->ps.blend); - } - } - else if (ent->client->breather_framenum > level.framenum) - { - remaining = ent->client->breather_framenum - level.framenum; - - if (remaining == 30) /* beginning to fade */ - { - gi.sound(ent, CHAN_ITEM, gi.soundindex("items/airout.wav"), 1, ATTN_NORM, 0); - } - - if ((remaining > 30) || (remaining & 4)) - { - SV_AddBlend(0.4, 1, 0.4, 0.04, ent->client->ps.blend); - } - } - - if (ent->client->nuke_framenum > level.framenum) - { - float brightness; - brightness = (ent->client->nuke_framenum - level.framenum) / 20.0; - SV_AddBlend(1, 1, 1, brightness, ent->client->ps.blend); - } - - if (ent->client->ir_framenum > level.framenum) - { - remaining = ent->client->ir_framenum - level.framenum; - - if ((remaining > 30) || (remaining & 4)) - { - ent->client->ps.rdflags |= RDF_IRGOGGLES; - SV_AddBlend(1, 0, 0, 0.2, ent->client->ps.blend); - } - else - { - ent->client->ps.rdflags &= ~RDF_IRGOGGLES; - } - } - else - { - ent->client->ps.rdflags &= ~RDF_IRGOGGLES; - } - - /* add for damage */ - if (ent->client->damage_alpha > 0) - { - SV_AddBlend(ent->client->damage_blend[0], ent->client->damage_blend[1], - ent->client->damage_blend[2], ent->client->damage_alpha, ent->client->ps.blend); - } - - if (ent->client->bonus_alpha > 0) - { - SV_AddBlend(0.85, 0.7, 0.3, ent->client->bonus_alpha, ent->client->ps.blend); - } - - /* drop the damage value */ - ent->client->damage_alpha -= 0.06; - - if (ent->client->damage_alpha < 0) - { - ent->client->damage_alpha = 0; - } - - /* drop the bonus value */ - ent->client->bonus_alpha -= 0.1; - - if (ent->client->bonus_alpha < 0) - { - ent->client->bonus_alpha = 0; - } -} - -void -P_FallingDamage(edict_t *ent) -{ - float delta; - int damage; - vec3_t dir; - - if (!ent) - { - return; - } - - if (ent->s.modelindex != 255) - { - return; /* not in the player model */ - } - - if (ent->movetype == MOVETYPE_NOCLIP) - { - return; - } - - if ((ent->client->oldvelocity[2] < 0) && - (ent->velocity[2] > ent->client->oldvelocity[2]) && - (!ent->groundentity)) - { - delta = ent->client->oldvelocity[2]; - } - else - { - if (!ent->groundentity) - { - return; - } - - delta = ent->velocity[2] - ent->client->oldvelocity[2]; - } - - delta = delta * delta * 0.0001; - - /* never take falling damage if completely underwater */ - if (ent->waterlevel == 3) - { - return; - } - - if (ent->waterlevel == 2) - { - delta *= 0.25; - } - - if (ent->waterlevel == 1) - { - delta *= 0.5; - } - - if (delta < 1) - { - return; - } - - if (delta < 15) - { - ent->s.event = EV_FOOTSTEP; - return; - } - - ent->client->fall_value = delta * 0.5; - - if (ent->client->fall_value > 40) - { - ent->client->fall_value = 40; - } - - ent->client->fall_time = level.time + FALL_TIME; - - if (delta > 30) - { - if (ent->health > 0) - { - if (delta >= 55) - { - ent->s.event = EV_FALLFAR; - } - else - { - ent->s.event = EV_FALL; - } - } - - ent->pain_debounce_time = level.time; /* no normal pain sound */ - damage = (delta - 30) / 2; - - if (damage < 1) - { - damage = 1; - } - - VectorSet(dir, 0, 0, 1); - - if (!deathmatch->value || !((int)dmflags->value & DF_NO_FALLING)) - { - T_Damage(ent, world, world, dir, ent->s.origin, vec3_origin, - damage, 0, 0, MOD_FALLING); - } - } - else - { - ent->s.event = EV_FALLSHORT; - return; - } -} - -void -P_WorldEffects(void) -{ - qboolean breather; - qboolean envirosuit; - int waterlevel, old_waterlevel; - - if (current_player->movetype == MOVETYPE_NOCLIP) - { - current_player->air_finished = level.time + 12; /* don't need air */ - return; - } - - waterlevel = current_player->waterlevel; - old_waterlevel = current_client->old_waterlevel; - current_client->old_waterlevel = waterlevel; - - breather = current_client->breather_framenum > level.framenum; - envirosuit = current_client->enviro_framenum > level.framenum; - - /* if just entered a water volume, play a sound */ - if (!old_waterlevel && waterlevel) - { - PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF); - - if (current_player->watertype & CONTENTS_LAVA) - { - gi.sound(current_player, CHAN_BODY, gi.soundindex("player/lava_in.wav"), 1, ATTN_NORM, 0); - } - else if (current_player->watertype & CONTENTS_SLIME) - { - gi.sound(current_player, CHAN_BODY, gi.soundindex("player/watr_in.wav"), 1, ATTN_NORM, 0); - } - else if (current_player->watertype & CONTENTS_WATER) - { - gi.sound(current_player, CHAN_BODY, gi.soundindex("player/watr_in.wav"), 1, ATTN_NORM, 0); - } - - current_player->flags |= FL_INWATER; - - /* clear damage_debounce, so the pain sound will play immediately */ - current_player->damage_debounce_time = level.time - 1; - } - - /* if just completely exited a water volume, play a sound */ - if (old_waterlevel && !waterlevel) - { - PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF); - gi.sound(current_player, CHAN_BODY, gi.soundindex("player/watr_out.wav"), 1, ATTN_NORM, 0); - current_player->flags &= ~FL_INWATER; - } - - /* check for head just going under water */ - if ((old_waterlevel != 3) && (waterlevel == 3)) - { - gi.sound(current_player, CHAN_BODY, gi.soundindex("player/watr_un.wav"), 1, ATTN_NORM, 0); - } - - /* check for head just coming out of water */ - if ((old_waterlevel == 3) && (waterlevel != 3)) - { - if (current_player->air_finished < level.time) - { - /* gasp for air */ - gi.sound(current_player, CHAN_VOICE, gi.soundindex("player/gasp1.wav"), 1, ATTN_NORM, 0); - PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF); - } - else if (current_player->air_finished < level.time + 11) - { - /* just break surface */ - gi.sound(current_player, CHAN_VOICE, gi.soundindex("player/gasp2.wav"), 1, ATTN_NORM, 0); - } - } - - /* check for drowning */ - if (waterlevel == 3) - { - /* breather or envirosuit give air */ - if (breather || envirosuit) - { - current_player->air_finished = level.time + 10; - - if (((int)(current_client->breather_framenum - level.framenum) % 25) == 0) - { - if (!current_client->breather_sound) - { - gi.sound(current_player, CHAN_AUTO, gi.soundindex("player/u_breath1.wav"), 1, ATTN_NORM, 0); - } - else - { - gi.sound(current_player, CHAN_AUTO, gi.soundindex("player/u_breath2.wav"), 1, ATTN_NORM, 0); - } - - current_client->breather_sound ^= 1; - PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF); - } - } - - /* if out of air, start drowning */ - if (current_player->air_finished < level.time) - { - /* drown! */ - if ((current_player->client->next_drown_time < level.time) && - (current_player->health > 0)) - { - current_player->client->next_drown_time = level.time + 1; - - /* take more damage the longer underwater */ - current_player->dmg += 2; - - if (current_player->dmg > 15) - { - current_player->dmg = 15; - } - - /* play a gurp sound instead of a normal pain sound */ - if (current_player->health <= current_player->dmg) - { - gi.sound(current_player, CHAN_VOICE, gi.soundindex("player/drown1.wav"), 1, ATTN_NORM, 0); - } - else if (rand() & 1) - { - gi.sound(current_player, CHAN_VOICE, gi.soundindex("*gurp1.wav"), 1, ATTN_NORM, 0); - } - else - { - gi.sound(current_player, CHAN_VOICE, gi.soundindex("*gurp2.wav"), 1, ATTN_NORM, 0); - } - - current_player->pain_debounce_time = level.time; - - T_Damage(current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, - current_player->dmg, 0, DAMAGE_NO_ARMOR, MOD_WATER); - } - } - } - else - { - current_player->air_finished = level.time + 12; - current_player->dmg = 2; - } - - /* check for sizzle damage */ - if (waterlevel && (current_player->watertype & (CONTENTS_LAVA | CONTENTS_SLIME))) - { - if (current_player->watertype & CONTENTS_LAVA) - { - if ((current_player->health > 0) && - (current_player->pain_debounce_time <= level.time) && - (current_client->invincible_framenum < level.framenum) && - !(current_player->flags & FL_GODMODE)) - { - if (rand() & 1) - { - gi.sound(current_player, CHAN_VOICE, gi.soundindex("player/burn1.wav"), 1, ATTN_NORM, 0); - } - else - { - gi.sound(current_player, CHAN_VOICE, gi.soundindex("player/burn2.wav"), 1, ATTN_NORM, 0); - } - - current_player->pain_debounce_time = level.time + 1; - } - - if (envirosuit) /* take 1/3 damage with envirosuit */ - { - T_Damage(current_player, world, world, vec3_origin, current_player->s.origin, - vec3_origin, 1 * waterlevel, 0, 0, MOD_LAVA); - } - else - { - T_Damage(current_player, world, world, vec3_origin, current_player->s.origin, - vec3_origin, 3 * waterlevel, 0, 0, MOD_LAVA); - } - } - - if (current_player->watertype & CONTENTS_SLIME) - { - if (!envirosuit) - { - /* no damage from slime with envirosuit */ - T_Damage(current_player, world, world, vec3_origin, current_player->s.origin, - vec3_origin, 1 * waterlevel, 0, 0, MOD_SLIME); - } - } - } -} - -void -G_SetClientEffects(edict_t *ent) -{ - int pa_type; - int remaining; - - if (!ent) - { - return; - } - - ent->s.effects = 0; - - /* player is always ir visible, even dead. */ - ent->s.renderfx = RF_IR_VISIBLE; - - if ((ent->health <= 0) || level.intermissiontime) - { - return; - } - - if (ent->flags & FL_DISGUISED) - { - ent->s.renderfx |= RF_USE_DISGUISE; - } - - if (gamerules && gamerules->value) - { - if (DMGame.PlayerEffects) - { - DMGame.PlayerEffects(ent); - } - } - - if (ent->powerarmor_time > level.time) - { - pa_type = PowerArmorType(ent); - - if (pa_type == POWER_ARMOR_SCREEN) - { - ent->s.effects |= EF_POWERSCREEN; - } - else if (pa_type == POWER_ARMOR_SHIELD) - { - ent->s.effects |= EF_COLOR_SHELL; - ent->s.renderfx |= RF_SHELL_GREEN; - } - } - - if (ent->client->quad_framenum > level.framenum) - { - remaining = ent->client->quad_framenum - level.framenum; - - if ((remaining > 30) || (remaining & 4)) - { - ent->s.effects |= EF_QUAD; - } - } - - if (ent->client->double_framenum > level.framenum) - { - remaining = ent->client->double_framenum - level.framenum; - - if ((remaining > 30) || (remaining & 4)) - { - ent->s.effects |= EF_DOUBLE; - } - } - - if ((ent->client->owned_sphere) && - (ent->client->owned_sphere->spawnflags == 1)) - { - ent->s.effects |= EF_HALF_DAMAGE; - } - - if (ent->client->tracker_pain_framenum > level.framenum) - { - ent->s.effects |= EF_TRACKERTRAIL; - } - - if (ent->client->invincible_framenum > level.framenum) - { - remaining = ent->client->invincible_framenum - level.framenum; - - if ((remaining > 30) || (remaining & 4)) - { - ent->s.effects |= EF_PENT; - } - } - - /* show cheaters!!! */ - if (ent->flags & FL_GODMODE) - { - ent->s.effects |= EF_COLOR_SHELL; - ent->s.renderfx |= (RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE); - } -} - -void -G_SetClientEvent(edict_t *ent) -{ - if (!ent) - { - return; - } - - if (ent->s.event) - { - return; - } - - if (ent->health <= 0) - { - return; - } - - if (g_footsteps->value == 1) - { - if (ent->groundentity && (xyspeed > 225)) - { - if ((int)(current_client->bobtime + bobmove) != bobcycle) - { - ent->s.event = EV_FOOTSTEP; - } - } - } - else if (g_footsteps->value == 2) - { - if (ent->groundentity) - { - if ((int)(current_client->bobtime + bobmove) != bobcycle) - { - ent->s.event = EV_FOOTSTEP; - } - } - } - else if (g_footsteps->value >= 3) - { - if ((int)(current_client->bobtime + bobmove) != bobcycle) - { - ent->s.event = EV_FOOTSTEP; - } - } -} - -void -G_SetClientSound(edict_t *ent) -{ - char *weap; - - if (!ent) - { - return; - } - - if (ent->client->pers.game_helpchanged != game.helpchanged) - { - ent->client->pers.game_helpchanged = game.helpchanged; - ent->client->pers.helpchanged = 1; - } - - /* help beep (no more than three times) */ - if (ent->client->pers.helpchanged && (ent->client->pers.helpchanged <= 3) && !(level.framenum & 63)) - { - ent->client->pers.helpchanged++; - gi.sound(ent, CHAN_VOICE, gi.soundindex("misc/pc_up.wav"), 1, ATTN_STATIC, 0); - } - - if (ent->client->pers.weapon) - { - weap = ent->client->pers.weapon->classname; - } - else - { - weap = ""; - } - - if (ent->waterlevel && (ent->watertype & (CONTENTS_LAVA | CONTENTS_SLIME))) - { - ent->s.sound = snd_fry; - } - else if (strcmp(weap, "weapon_railgun") == 0) - { - ent->s.sound = gi.soundindex("weapons/rg_hum.wav"); - } - else if (strcmp(weap, "weapon_bfg") == 0) - { - ent->s.sound = gi.soundindex("weapons/bfg_hum.wav"); - } - else if (ent->client->weapon_sound) - { - ent->s.sound = ent->client->weapon_sound; - } - else - { - ent->s.sound = 0; - } -} - -void -G_SetClientFrame(edict_t *ent) -{ - gclient_t *client; - qboolean duck, run; - - if (!ent) - { - return; - } - - if (ent->s.modelindex != 255) - { - return; /* not in the player model */ - } - - client = ent->client; - - if (client->ps.pmove.pm_flags & PMF_DUCKED) - { - duck = true; - } - else - { - duck = false; - } - - if (xyspeed) - { - run = true; - } - else - { - run = false; - } - - /* check for stand/duck and stop/go transitions */ - if ((duck != client->anim_duck) && (client->anim_priority < ANIM_DEATH)) - { - goto newanim; - } - - if ((run != client->anim_run) && (client->anim_priority == ANIM_BASIC)) - { - goto newanim; - } - - if (!ent->groundentity && (client->anim_priority <= ANIM_WAVE)) - { - goto newanim; - } - - if (client->anim_priority == ANIM_REVERSE) - { - if (ent->s.frame > client->anim_end) - { - ent->s.frame--; - return; - } - } - else if (ent->s.frame < client->anim_end) - { - /* continue an animation */ - ent->s.frame++; - return; - } - - if (client->anim_priority == ANIM_DEATH) - { - return; /* stay there */ - } - - if (client->anim_priority == ANIM_JUMP) - { - if (!ent->groundentity) - { - return; /* stay there */ - } - - ent->client->anim_priority = ANIM_WAVE; - ent->s.frame = FRAME_jump3; - ent->client->anim_end = FRAME_jump6; - return; - } - -newanim: - - /* return to either a running or standing frame */ - client->anim_priority = ANIM_BASIC; - client->anim_duck = duck; - client->anim_run = run; - - if (!ent->groundentity) - { - client->anim_priority = ANIM_JUMP; - - if (ent->s.frame != FRAME_jump2) - { - ent->s.frame = FRAME_jump1; - } - - client->anim_end = FRAME_jump2; - } - else if (run) - { - /* running */ - if (duck) - { - ent->s.frame = FRAME_crwalk1; - client->anim_end = FRAME_crwalk6; - } - else - { - ent->s.frame = FRAME_run1; - client->anim_end = FRAME_run6; - } - } - else - { - /* standing */ - if (duck) - { - ent->s.frame = FRAME_crstnd01; - client->anim_end = FRAME_crstnd19; - } - else - { - ent->s.frame = FRAME_stand01; - client->anim_end = FRAME_stand40; - } - } -} - -/* - * Called for each player at the end of - * the server frame and right after spawning - */ -void -ClientEndServerFrame(edict_t *ent) -{ - float bobtime; - int i; - - if (!ent) - { - return; - } - - current_player = ent; - current_client = ent->client; - - /* If the origin or velocity have changed since ClientThink(), - update the pmove values. This will happen when the client - is pushed by a bmodel or kicked by an explosion. - If it wasn't updated here, the view position would lag a frame - behind the body position when pushed -- "sinking into plats" */ - for (i = 0; i < 3; i++) - { - current_client->ps.pmove.origin[i] = ent->s.origin[i] * 8.0; - current_client->ps.pmove.velocity[i] = ent->velocity[i] * 8.0; - } - - /* If the end of unit layout is displayed, don't give - the player any normal movement attributes */ - if (level.intermissiontime) - { - current_client->ps.blend[3] = 0; - current_client->ps.fov = 90; - G_SetStats(ent); - return; - } - - AngleVectors(ent->client->v_angle, forward, right, up); - - /* burn from lava, etc */ - P_WorldEffects(); - - /* set model angles from view angles so other things in - the world can tell which direction you are looking */ - if (ent->client->v_angle[PITCH] > 180) - { - ent->s.angles[PITCH] = (-360 + ent->client->v_angle[PITCH]) / 3; - } - else - { - ent->s.angles[PITCH] = ent->client->v_angle[PITCH] / 3; - } - - ent->s.angles[YAW] = ent->client->v_angle[YAW]; - ent->s.angles[ROLL] = 0; - ent->s.angles[ROLL] = SV_CalcRoll(ent->s.angles, ent->velocity) * 4; - - /* calculate speed and cycle to be - used for all cyclic walking effects */ - xyspeed = sqrt( - ent->velocity[0] * ent->velocity[0] + ent->velocity[1] * - ent->velocity[1]); - - if (xyspeed < 5) - { - bobmove = 0; - current_client->bobtime = 0; /* start at beginning of cycle again */ - } - else if (ent->groundentity) - { - /* so bobbing only cycles when on ground */ - if (xyspeed > 210) - { - bobmove = 0.25; - } - else if (xyspeed > 100) - { - bobmove = 0.125; - } - else - { - bobmove = 0.0625; - } - } - - bobtime = (current_client->bobtime += bobmove); - - if (current_client->ps.pmove.pm_flags & PMF_DUCKED) - { - bobtime *= 4; - } - - bobcycle = (int)bobtime; - bobfracsin = fabs(sin(bobtime * M_PI)); - - /* detect hitting the floor */ - P_FallingDamage(ent); - - /* apply all the damage taken this frame */ - P_DamageFeedback(ent); - - /* determine the view offsets */ - SV_CalcViewOffset(ent); - - /* determine the gun offsets */ - SV_CalcGunOffset(ent); - - /* determine the full screen color blend must be after viewoffset, - so eye contents can be accurately determined */ - SV_CalcBlend(ent); - - /* chase cam stuff */ - if (ent->client->resp.spectator) - { - G_SetSpectatorStats(ent); - } - else - { - G_SetStats(ent); - } - - G_CheckChaseStats(ent); - G_SetClientEvent(ent); - G_SetClientEffects(ent); - G_SetClientSound(ent); - G_SetClientFrame(ent); - - VectorCopy(ent->velocity, ent->client->oldvelocity); - VectorCopy(ent->client->ps.viewangles, ent->client->oldviewangles); - - /* clear weapon kicks */ - VectorClear(ent->client->kick_origin); - VectorClear(ent->client->kick_angles); - - if (!(level.framenum & 31)) - { - /* if the scoreboard is up, update it */ - if (ent->client->showscores) - { - DeathmatchScoreboardMessage(ent, ent->enemy); - gi.unicast(ent, false); - } - - /* if the help computer is up, update it */ - if (ent->client->showhelp) - { - ent->client->pers.helpchanged = 0; - HelpComputerMessage(ent); - gi.unicast(ent, false); - } - } - - /* if the inventory is up, update it */ - if (ent->client->showinventory) - { - InventoryMessage(ent); - gi.unicast(ent, false); - } -}