From 7224c7bf34cf7548f86a3af2247240705c0f4b4b Mon Sep 17 00:00:00 2001 From: /dev/humancontroller Date: Sun, 13 Jul 2014 17:14:58 +0200 Subject: improve the usability of noclip, notarget, give and godmode: - 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 --- src/game/g_active.c | 8 +++++--- src/game/g_client.c | 5 ++++- src/game/g_cmds.c | 28 +++++++++++++++++++--------- src/game/g_combat.c | 10 +++++----- src/game/g_local.h | 2 +- src/game/g_team.c | 6 ++++++ 6 files changed, 40 insertions(+), 19 deletions(-) diff --git a/src/game/g_active.c b/src/game/g_active.c index d2abf65d..f99e7661 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; @@ -1550,8 +1554,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 ); @@ -1730,7 +1733,6 @@ void ClientThink_real( gentity_t *ent ) if( ent->suicideTime > 0 && ent->suicideTime < level.time ) { - ent->flags &= ~FL_GODMODE; ent->client->ps.stats[ STAT_HEALTH ] = ent->health = 0; player_die( ent, ent, ent, 100000, MOD_SUICIDE ); diff --git a/src/game/g_client.c b/src/game/g_client.c index 01986061..76078040 100644 --- a/src/game/g_client.c +++ b/src/game/g_client.c @@ -1199,6 +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; int persistant[ MAX_PERSISTANT ]; gentity_t *spawnPoint = NULL; int flags; @@ -1281,6 +1282,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 ]; @@ -1291,6 +1293,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++ ) @@ -1318,7 +1321,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 6ab2ae15..8ad781ab 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,7 +563,6 @@ void Cmd_Kill_f( gentity_t *ent ) { if( g_cheats.integer ) { - ent->flags &= ~FL_GODMODE; ent->client->ps.stats[ STAT_HEALTH ] = ent->health = 0; player_die( ent, ent, ent, 100000, MOD_SUICIDE ); } @@ -1634,6 +1641,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; @@ -3098,8 +3108,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 93237e96..527e3068 100644 --- a/src/game/g_combat.c +++ b/src/game/g_combat.c @@ -894,7 +894,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_local.h b/src/game/g_local.h index 047aa4c1..d319a5c2 100644 --- a/src/game/g_local.h +++ b/src/game/g_local.h @@ -876,7 +876,7 @@ void G_InitDamageLocations( void ); #define DAMAGE_RADIUS 0x00000001 // damage was indirect #define DAMAGE_NO_ARMOR 0x00000002 // armour does not protect from this damage #define DAMAGE_NO_KNOCKBACK 0x00000004 // do not affect velocity, just view angles -#define DAMAGE_NO_PROTECTION 0x00000008 // armor, shields, invulnerability, and godmode have no effect +#define DAMAGE_NO_PROTECTION 0x00000008 // kills everything except godmode #define DAMAGE_NO_LOCDAMAGE 0x00000010 // do not apply locational damage // diff --git a/src/game/g_team.c b/src/game/g_team.c index dded18ee..f3ca0f84 100644 --- a/src/game/g_team.c +++ b/src/game/g_team.c @@ -220,6 +220,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; -- cgit