commit 5df6d58db623b97208d94080fc1e16778597ce37 Author: devhc Date: Sun Jul 17 06:16:01 2011 +0200 noclip, notarget, give, and godmode usability improvements - godmode protects against everything (except suicides via the kill command) - godmode can also be toggled when dead or spectating - noclip, notarget, and godmode retain their status until explicitly toggled (except when outside of devmode, or when reconnecting), notably, they are not turned off when switching teams or suiciding - funds can be given also when dead - noclipping players do not activate any triggers - map geometry does not interfere with noclipping players when it comes to changing classes diff --git a/src/game/g_active.c b/src/game/g_active.c index 2b03f6d..21bc826 100644 --- a/src/game/g_active.c +++ b/src/game/g_active.c @@ -324,6 +324,10 @@ void G_TouchTriggers( gentity_t *ent ) if( !ent->client ) return; + // noclipping clients don't activate triggers! + if( ent->client->noclip ) + return; + // dead clients don't activate triggers! if( ent->client->ps.stats[ STAT_HEALTH ] <= 0 ) return; @@ -1558,8 +1562,7 @@ void ClientThink_real( gentity_t *ent ) // moved from after Pmove -- potentially the cause of // future triggering bugs - if( !ent->client->noclip ) - G_TouchTriggers( ent ); + G_TouchTriggers( ent ); Pmove( &pm ); diff --git a/src/game/g_client.c b/src/game/g_client.c index f25a6a2..d33e453 100644 --- a/src/game/g_client.c +++ b/src/game/g_client.c @@ -1201,6 +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; int persistant[ MAX_PERSISTANT ]; gentity_t *spawnPoint = NULL; int flags; @@ -1283,6 +1284,7 @@ void ClientSpawn( gentity_t *ent, gentity_t *spawn, vec3_t origin, vec3_t angles saved = client->pers; savedSess = client->sess; savedPing = client->ps.ping; + savedNoclip = client->noclip; for( i = 0; i < MAX_PERSISTANT; i++ ) persistant[ i ] = client->ps.persistant[ i ]; @@ -1293,6 +1295,7 @@ void ClientSpawn( gentity_t *ent, gentity_t *spawn, vec3_t origin, vec3_t angles client->pers = saved; client->sess = savedSess; client->ps.ping = savedPing; + client->noclip = savedNoclip; client->lastkilled_client = -1; for( i = 0; i < MAX_PERSISTANT; i++ ) @@ -1321,7 +1324,7 @@ void ClientSpawn( gentity_t *ent, gentity_t *spawn, vec3_t origin, vec3_t angles ent->die = player_die; ent->waterlevel = 0; ent->watertype = 0; - ent->flags = 0; + ent->flags &= FL_GODMODE | FL_NOTARGET; // calculate each client's acceleration ent->evaluateAcceleration = qtrue; diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c index be2d173..2303227 100644 --- a/src/game/g_cmds.c +++ b/src/game/g_cmds.c @@ -404,12 +404,6 @@ void Cmd_Give_f( gentity_t *ent ) if( Q_stricmp( name, "all" ) == 0 ) give_all = qtrue; - if( give_all || Q_stricmp( name, "health" ) == 0 ) - { - ent->health = ent->client->ps.stats[ STAT_MAX_HEALTH ]; - BG_AddUpgradeToInventory( UP_MEDKIT, ent->client->ps.stats ); - } - if( give_all || Q_stricmpn( name, "funds", 5 ) == 0 ) { float credits; @@ -432,6 +426,20 @@ void Cmd_Give_f( gentity_t *ent ) G_AddCreditToClient( ent->client, (short)credits, qtrue ); } + if( ent->client->ps.stats[ STAT_HEALTH ] <= 0 || + ent->client->sess.spectatorState != SPECTATOR_NOT ) + { + if( !( give_all || Q_stricmpn( name, "funds", 5 ) == 0 ) ) + G_TriggerMenu( ent-g_entities, MN_CMD_ALIVE ); + return; + } + + if( give_all || Q_stricmp( name, "health" ) == 0 ) + { + ent->health = ent->client->ps.stats[ STAT_MAX_HEALTH ]; + BG_AddUpgradeToInventory( UP_MEDKIT, ent->client->ps.stats ); + } + if( give_all || Q_stricmp( name, "stamina" ) == 0 ) ent->client->ps.stats[ STAT_STAMINA ] = STAMINA_MAX; @@ -555,9 +563,11 @@ void Cmd_Kill_f( gentity_t *ent ) { if( g_cheats.integer ) { + int godmode = ent->flags & FL_GODMODE; ent->flags &= ~FL_GODMODE; ent->client->ps.stats[ STAT_HEALTH ] = ent->health = 0; player_die( ent, ent, ent, 100000, MOD_SUICIDE ); + ent->flags |= godmode; } else { @@ -1630,6 +1640,9 @@ static qboolean G_RoomForClassChange( gentity_t *ent, class_t class, // find what the new origin would be on a level surface newOrigin[ 2 ] -= toMins[ 2 ] - fromMins[ 2 ]; + if( ent->client->noclip ) + return qtrue; + //compute a place up in the air to start the real trace VectorCopy( newOrigin, temp ); temp[ 2 ] += nudgeHeight; @@ -3106,8 +3119,8 @@ commands_t cmds[ ] = { { "follow", CMD_SPEC, Cmd_Follow_f }, { "follownext", CMD_SPEC, Cmd_FollowCycle_f }, { "followprev", CMD_SPEC, Cmd_FollowCycle_f }, - { "give", CMD_CHEAT|CMD_TEAM|CMD_ALIVE, Cmd_Give_f }, - { "god", CMD_CHEAT|CMD_TEAM|CMD_ALIVE, Cmd_God_f }, + { "give", CMD_CHEAT|CMD_TEAM, Cmd_Give_f }, + { "god", CMD_CHEAT, Cmd_God_f }, { "ignore", 0, Cmd_Ignore_f }, { "itemact", CMD_HUMAN|CMD_ALIVE, Cmd_ActivateItem_f }, { "itemdeact", CMD_HUMAN|CMD_ALIVE, Cmd_DeActivateItem_f }, diff --git a/src/game/g_combat.c b/src/game/g_combat.c index 287c7ad..32c5c4b 100644 --- a/src/game/g_combat.c +++ b/src/game/g_combat.c @@ -893,7 +893,7 @@ dflags these flags are used to control how T_Damage works DAMAGE_RADIUS damage was indirect (from a nearby explosion) DAMAGE_NO_ARMOR armor does not protect from this damage DAMAGE_NO_KNOCKBACK do not affect velocity, just view angles - DAMAGE_NO_PROTECTION kills godmode, armor, everything + DAMAGE_NO_PROTECTION kills everything except godmode ============ */ @@ -1000,6 +1000,10 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, } } + // check for godmode + if( targ->flags & FL_GODMODE ) + return; + // don't do friendly fire on movement attacks if( ( mod == MOD_LEVEL4_TRAMPLE || mod == MOD_LEVEL3_POUNCE || mod == MOD_LEVEL4_CRUSH ) && @@ -1060,10 +1064,6 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, G_BroadcastEvent( EV_DCC_ATTACK, 0 ); } } - - // check for godmode - if ( targ->flags & FL_GODMODE ) - return; } // add to the attacker's hit counter diff --git a/src/game/g_team.c b/src/game/g_team.c index 6f407a3..73d8d69 100644 --- a/src/game/g_team.c +++ b/src/game/g_team.c @@ -238,6 +238,12 @@ void G_ChangeTeam( gentity_t *ent, team_t newTeam ) HUMAN_MAX_CREDITS / ALIEN_MAX_CREDITS + 0.5f ); } + if( !g_cheats.integer ) + { + ent->client->noclip = qfalse; + ent->flags &= ~( FL_GODMODE | FL_NOTARGET ); + } + // Copy credits to ps for the client ent->client->ps.persistant[ PERS_CREDIT ] = ent->client->pers.credit;