commit 0db45650c79ddfa0b85a1fe97c24ec8a6eb98ab7 Author: devhc Date: Sat Jul 16 22:47:05 2011 +0200 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 diff --git a/src/game/g_client.c b/src/game/g_client.c index d33e453..4355fed 100644 --- a/src/game/g_client.c +++ b/src/game/g_client.c @@ -1201,7 +1201,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; @@ -1285,6 +1285,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 ]; @@ -1296,6 +1297,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++ ) @@ -1319,7 +1321,10 @@ void ClientSpawn( gentity_t *ent, gentity_t *spawn, vec3_t origin, vec3_t angles ent->takedamage = qtrue; ent->inuse = 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 6004c8a..c92ffb1 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 32c5c4b..738f183 100644 --- a/src/game/g_combat.c +++ b/src/game/g_combat.c @@ -345,7 +345,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 d5af8e2..49c2be9 100644 --- a/src/game/g_local.h +++ b/src/game/g_local.h @@ -361,6 +361,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 73d8d69..06d83dd 100644 --- a/src/game/g_team.c +++ b/src/game/g_team.c @@ -240,7 +240,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 ); }