summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author/dev/humancontroller <devhc@example.com>2014-07-13 17:15:05 +0200
committer/dev/humancontroller <devhc@example.com>2017-03-09 13:51:11 +0100
commit59875f1378dca6605cd0426eff89f850d8743c92 (patch)
tree386f33324df8e2c528b3237d86d4fb0c20a37aba
parent7224c7bf34cf7548f86a3af2247240705c0f4b4b (diff)
fix noclipping players affecting other players
notably, other players were able to stand on the "center" of a noclipped player set an r.contents value of 0 for noclipping clients, backing up the r.contents value in the new ent->client->cliprcontents field
-rw-r--r--src/game/g_client.c9
-rw-r--r--src/game/g_cmds.c10
-rw-r--r--src/game/g_combat.c5
-rw-r--r--src/game/g_local.h1
-rw-r--r--src/game/g_team.c6
5 files changed, 27 insertions, 4 deletions
diff --git a/src/game/g_client.c b/src/game/g_client.c
index 76078040..548ec963 100644
--- a/src/game/g_client.c
+++ b/src/game/g_client.c
@@ -1199,7 +1199,7 @@ void ClientSpawn( gentity_t *ent, gentity_t *spawn, vec3_t origin, vec3_t angles
int i;
clientPersistant_t saved;
clientSession_t savedSess;
- qboolean savedNoclip;
+ qboolean savedNoclip, savedCliprcontents;
int persistant[ MAX_PERSISTANT ];
gentity_t *spawnPoint = NULL;
int flags;
@@ -1283,6 +1283,7 @@ void ClientSpawn( gentity_t *ent, gentity_t *spawn, vec3_t origin, vec3_t angles
savedSess = client->sess;
savedPing = client->ps.ping;
savedNoclip = client->noclip;
+ savedCliprcontents = client->cliprcontents;
for( i = 0; i < MAX_PERSISTANT; i++ )
persistant[ i ] = client->ps.persistant[ i ];
@@ -1294,6 +1295,7 @@ void ClientSpawn( gentity_t *ent, gentity_t *spawn, vec3_t origin, vec3_t angles
client->sess = savedSess;
client->ps.ping = savedPing;
client->noclip = savedNoclip;
+ client->cliprcontents = savedCliprcontents;
client->lastkilled_client = -1;
for( i = 0; i < MAX_PERSISTANT; i++ )
@@ -1316,7 +1318,10 @@ void ClientSpawn( gentity_t *ent, gentity_t *spawn, vec3_t origin, vec3_t angles
ent->client = &level.clients[ index ];
ent->takedamage = qtrue;
ent->classname = "player";
- ent->r.contents = CONTENTS_BODY;
+ if( client->noclip )
+ client->cliprcontents = CONTENTS_BODY;
+ else
+ ent->r.contents = CONTENTS_BODY;
ent->clipmask = MASK_PLAYERSOLID;
ent->die = player_die;
ent->waterlevel = 0;
diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c
index 8ad781ab..caa5f990 100644
--- a/src/game/g_cmds.c
+++ b/src/game/g_cmds.c
@@ -544,12 +544,22 @@ void Cmd_Noclip_f( gentity_t *ent )
char *msg;
if( ent->client->noclip )
+ {
msg = "noclip OFF\n";
+ ent->r.contents = ent->client->cliprcontents;
+ }
else
+ {
msg = "noclip ON\n";
+ ent->client->cliprcontents = ent->r.contents;
+ ent->r.contents = 0;
+ }
ent->client->noclip = !ent->client->noclip;
+ if( ent->r.linked )
+ trap_LinkEntity( ent );
+
trap_SendServerCommand( ent - g_entities, va( "print \"%s\"", msg ) );
}
diff --git a/src/game/g_combat.c b/src/game/g_combat.c
index 527e3068..0b61ce59 100644
--- a/src/game/g_combat.c
+++ b/src/game/g_combat.c
@@ -344,7 +344,10 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
self->takedamage = qfalse; // can still be gibbed
self->s.weapon = WP_NONE;
- self->r.contents = CONTENTS_CORPSE;
+ if( self->client->noclip )
+ self->client->cliprcontents = CONTENTS_CORPSE;
+ else
+ self->r.contents = CONTENTS_CORPSE;
self->s.angles[ PITCH ] = 0;
self->s.angles[ ROLL ] = 0;
diff --git a/src/game/g_local.h b/src/game/g_local.h
index d319a5c2..081c47b8 100644
--- a/src/game/g_local.h
+++ b/src/game/g_local.h
@@ -362,6 +362,7 @@ struct gclient_s
qboolean readyToExit; // wishes to leave the intermission
qboolean noclip;
+ int cliprcontents; // the backup layer of ent->r.contents for when noclipping
int lastCmdTime; // level.time of last usercmd_t, for EF_CONNECTION
// we can't just use pers.lastCommand.time, because
diff --git a/src/game/g_team.c b/src/game/g_team.c
index f3ca0f84..ad29beaf 100644
--- a/src/game/g_team.c
+++ b/src/game/g_team.c
@@ -222,7 +222,11 @@ void G_ChangeTeam( gentity_t *ent, team_t newTeam )
if( !g_cheats.integer )
{
- ent->client->noclip = qfalse;
+ if( ent->client->noclip )
+ {
+ ent->client->noclip = qfalse;
+ ent->r.contents = ent->client->cliprcontents;
+ }
ent->flags &= ~( FL_GODMODE | FL_NOTARGET );
}