Moderators: sparcdr, torhu, Tequila
Index: code/game/g_local.h
===================================================================
--- code/game/g_local.h (revision 247)
+++ code/game/g_local.h (working copy)
-343,6 +343,9 @@
int savedMoney; // copy of ps.stats[STAT_MONEY]
int savedWins; // copy of ps.stats[STAT_WINS]
int savedScore; // copy of ps.persistant[PERS_SCORE]
+// Tequila: TeamKill management inspired by Conq patch
+ int lastTeamKillTime;
+ int TeamKillsCount;
#endif
} clientPersistant_t;
-1016,6 +1019,10 @@
extern vmCvar_t g_scorelimit;
#endif
extern vmCvar_t g_friendlyFire;
+#ifdef SMOKINGUNS
+extern vmCvar_t g_maxteamkills;
+extern vmCvar_t g_teamkillsforgettime;
+#endif
extern vmCvar_t g_password;
extern vmCvar_t g_needpass;
extern vmCvar_t g_gravity;
Index: code/game/g_main.c
===================================================================
--- code/game/g_main.c (revision 247)
+++ code/game/g_main.c (working copy)
-104,6 +104,10 @@
vmCvar_t g_scorelimit;
#endif
vmCvar_t g_friendlyFire;
+#ifdef SMOKINGUNS
+vmCvar_t g_maxteamkills;
+vmCvar_t g_teamkillsforgettime;
+#endif
vmCvar_t g_password;
vmCvar_t g_needpass;
vmCvar_t g_maxclients;
-232,6 +236,8 @@
{ &g_friendlyFire, "g_friendlyFire", "0", CVAR_ARCHIVE, 0, qtrue },
#else
{ &g_friendlyFire, "g_friendlyFire", "1", CVAR_ARCHIVE, 0, qtrue },
+ { &g_maxteamkills, "g_maxteamkills", "3", CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
+ { &g_teamkillsforgettime, "g_teamkillsforgettime", "30", CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
#endif
{ &g_teamAutoJoin, "g_teamAutoJoin", "0", CVAR_ARCHIVE },
Index: code/game/g_combat.c
===================================================================
--- code/game/g_combat.c (revision 247)
+++ code/game/g_combat.c (working copy)
-1612,6 +1612,21 @@
if ( !g_friendlyFire.integer ) {
return;
}
+
+#ifdef SMOKINGUNS
+// Tequila: TeamKill management inspired by Conq patch
+ // Check if we should reset TK count before
+ if ( level.time > attacker->client->pers.lastTeamKillTime + g_teamkillsforgettime.integer * 1000 )
+ attacker->client->pers.TeamKillsCount=0;
+ attacker->client->pers.TeamKillsCount ++;
+ attacker->client->pers.lastTeamKillTime = level.time;
+ // Kick the attacker if TK limit is hit but keep the victim alive
+ if ( attacker->client->pers.TeamKillsCount >= g_maxteamkills.integer )
+ {
+ trap_DropClient( attacker-g_entities, "You reached the limit of supported teammate kills." );
+ return;
+ }
+#endif
}
#ifndef SMOKINGUNS
if (mod == MOD_PROXIMITY_MINE) {
Index: code/game/g_combat.c
===================================================================
--- code/game/g_combat.c (revision 248)
+++ code/game/g_combat.c (working copy)
@@ -1430,8 +1430,56 @@
return take;
}
+
+/*
+============
+CheckTeamKills
+By Tequila, TeamKill management inspired by Conq patch
+Return false when TK supported limit is not hit
+============
+*/
+static qboolean CheckTeamKills( gentity_t *attacker, gentity_t *targ ) {
+
+ if ( !attacker || !targ )
+ return qfalse;
+
+ if ( !attacker->client )
+ return qfalse;
+
+ if ( attacker == targ || !OnSameTeam (targ,attacker) )
+ return qfalse;
+
+ // Check if we should reset TK count before
+ if ( attacker->client->pers.lastTeamKillTime && level.time > attacker->client->pers.lastTeamKillTime + g_teamkillsforgettime.integer * 1000 ) {
+#ifndef NDEBUG
+ G_Printf(S_COLOR_MAGENTA "CheckTeamKills: Forget TeamKillsCount (%i) from %s\n", attacker->client->pers.TeamKillsCount, attacker->client->pers.netname);
#endif
+ attacker->client->pers.TeamKillsCount=0;
+ }
+ attacker->client->pers.TeamKillsCount ++;
+#ifndef NDEBUG
+ if (attacker->client->pers.lastTeamKillTime)
+ G_Printf(S_COLOR_MAGENTA "CheckTeamKills: Last TeamKills for %s was %.2f seconds ago\n", attacker->client->pers.netname,(float)(level.time-attacker->client->pers.lastTeamKillTime)/1000.0f);
+#endif
+ attacker->client->pers.lastTeamKillTime = level.time;
+
+ // Kick the attacker if TK limit is hit and return true
+ if ( attacker->client->pers.TeamKillsCount >= g_maxteamkills.integer )
+ {
+ trap_DropClient( attacker-g_entities, "Reached the limit of supported teammate kills." );
+ return qtrue;
+ } else if ( attacker->client->pers.TeamKillsCount == g_maxteamkills.integer -1 )
+ trap_SendServerCommand( attacker-g_entities,
+ va("print \"%s" S_COLOR_YELLOW "... Be careful teammate !!! Next teammate kill could kick you from that server.\n\"",
+ attacker->client->pers.netname));
+#ifndef NDEBUG
+ G_Printf(S_COLOR_MAGENTA "CheckTeamKills: TeamKillsCount is %i for %s\n", attacker->client->pers.TeamKillsCount, attacker->client->pers.netname);
+#endif
+ return qfalse;
+}
+#endif
+
/*
============
G_Damage
@@ -1469,6 +1517,7 @@
int asave;
#else
float take;
+ int hsave=0;
#endif
int knockback;
@@ -1612,6 +1661,10 @@
if ( !g_friendlyFire.integer ) {
return;
}
+#ifdef SMOKINGUNS
+ // Can be used later in case of TK limit reached to protect the last victim
+ hsave = targ->health;
+#endif
}
#ifndef SMOKINGUNS
if (mod == MOD_PROXIMITY_MINE) {
@@ -1835,8 +1888,17 @@
targ->enemy = attacker;
+#ifdef SMOKINGUNS
+ // Target is not killed if TK limit is hit
+ if ( g_friendlyFire.integer && CheckTeamKills(attacker,targ) ) {
+ targ->client->ps.stats[STAT_HEALTH] = targ->health = hsave;
+ if ( g_debugDamage.integer )
+ G_LogPrintf( "%i: client:%i health:%i saved from TK by:%i\n", level.time,
+ targ->s.number, targ->health, attacker->s.number );
+ return;
+ }
+
// do the hit-message before the death-message
-#ifdef SMOKINGUNS
if(attacker->s.angles2[0] != -1 &&
(attacker->s.eFlags & EF_HIT_MESSAGE)){
gentity_t *tent;
Tequila wrote::oops:
Then I updated the code/game/g_combat.c patch by:
- Code: Select all
Index: code/game/g_combat.c
===================================================================
--- code/game/g_combat.c (revision 248)
+++ code/game/g_combat.c (working copy)
@@ -1430,8 +1430,56 @@
return take;
}
+
+/*
+============
+CheckTeamKills
+By Tequila, TeamKill management inspired by Conq patch
+Return false when TK supported limit is not hit
+============
+*/
+static qboolean CheckTeamKills( gentity_t *attacker, gentity_t *targ ) {
+
+ if ( !attacker || !targ )
+ return qfalse;
+
+ if ( !attacker->client )
+ return qfalse;
+
+ if ( attacker == targ || !OnSameTeam (targ,attacker) )
+ return qfalse;
+
+ // Check if we should reset TK count before
+ if ( attacker->client->pers.lastTeamKillTime && level.time > attacker->client->pers.lastTeamKillTime + g_teamkillsforgettime.integer * 1000 ) {
+#ifndef NDEBUG
+ G_Printf(S_COLOR_MAGENTA "CheckTeamKills: Forget TeamKillsCount (%i) from %s\n", attacker->client->pers.TeamKillsCount, attacker->client->pers.netname);
#endif
+ attacker->client->pers.TeamKillsCount=0;
+ }
+ attacker->client->pers.TeamKillsCount ++;
+#ifndef NDEBUG
+ if (attacker->client->pers.lastTeamKillTime)
+ G_Printf(S_COLOR_MAGENTA "CheckTeamKills: Last TeamKills for %s was %.2f seconds ago\n", attacker->client->pers.netname,(float)(level.time-attacker->client->pers.lastTeamKillTime)/1000.0f);
+#endif
+ attacker->client->pers.lastTeamKillTime = level.time;
+
+ // Kick the attacker if TK limit is hit and return true
+ if ( attacker->client->pers.TeamKillsCount >= g_maxteamkills.integer )
+ {
+ trap_DropClient( attacker-g_entities, "Reached the limit of supported teammate kills." );
+ return qtrue;
+ } else if ( attacker->client->pers.TeamKillsCount == g_maxteamkills.integer -1 )
+ trap_SendServerCommand( attacker-g_entities,
+ va("print "%s" S_COLOR_YELLOW "... Be careful teammate !!! Next teammate kill could kick you from that server.\n"",
+ attacker->client->pers.netname));
+#ifndef NDEBUG
+ G_Printf(S_COLOR_MAGENTA "CheckTeamKills: TeamKillsCount is %i for %s\n", attacker->client->pers.TeamKillsCount, attacker->client->pers.netname);
+#endif
+ return qfalse;
+}
+#endif
+
/*
============
G_Damage
@@ -1469,6 +1517,7 @@
int asave;
#else
float take;
+ int hsave=0;
#endif
int knockback;
@@ -1612,6 +1661,10 @@
if ( !g_friendlyFire.integer ) {
return;
}
+#ifdef SMOKINGUNS
+ // Can be used later in case of TK limit reached to protect the last victim
+ hsave = targ->health;
+#endif
}
#ifndef SMOKINGUNS
if (mod == MOD_PROXIMITY_MINE) {
@@ -1835,8 +1888,17 @@
targ->enemy = attacker;
+#ifdef SMOKINGUNS
+ // Target is not killed if TK limit is hit
+ if ( g_friendlyFire.integer && CheckTeamKills(attacker,targ) ) {
+ targ->client->ps.stats[STAT_HEALTH] = targ->health = hsave;
+ if ( g_debugDamage.integer )
+ G_LogPrintf( "%i: client:%i health:%i saved from TK by:%i\n", level.time,
+ targ->s.number, targ->health, attacker->s.number );
+ return;
+ }
+
// do the hit-message before the death-message
-#ifdef SMOKINGUNS
if(attacker->s.angles2[0] != -1 &&
(attacker->s.eFlags & EF_HIT_MESSAGE)){
gentity_t *tent;
I tested it and it seems to work like expected.
I also added a warning when max TeamKills is about to be reached...
Patch code wrote:// Check if we should reset TK count before
if ( attacker->client->pers.lastTeamKillTime && level.time > attacker->client->pers.lastTeamKillTime + g_teamkillsforgettime.integer * 1000 ) {...
Lucky Bro wrote:Good job Conq & his inspired follower Tequila!
I've got only two questions - how do I disable this feature? Usualy I would do it by setting g_maxteamkills to 0, but seems here it won't work. This is helpfull for non-public servers where this feature is not required at all.
And the second - why does teamkill check begin with lastTeamKillTime comparision even if it is the first player's teamkill? What value will have the lastTeamKillTime in that case in that check?:Patch code wrote:// Check if we should reset TK count before
if ( attacker->client->pers.lastTeamKillTime && level.time > attacker->client->pers.lastTeamKillTime + g_teamkillsforgettime.integer * 1000 ) {...
P.S. This is not the first time when troubles come from messed configuration file(s) which is(are) going with the game. Previous time it was case with enemyModel variable. Seems 1.1 is the point when the file(s) should be cleaned from all unused values.
if ( g_friendlyFire.integer && CheckTeamKills(attacker,targ) ) {
if ( g_maxteamkills.integer && g_friendlyFire.integer && CheckTeamKills(attacker,targ) ) {
Tequila wrote:Replacing the line:
...
should authorize to disable the feature by setting the g_maxteamkills cvar to 0.
Tequila wrote:About the check toward lastTeamKillTime, this is simpler to reset the counter here than elsewhere. You should know "pers" and its members are set to zero at the beginning of the map, so I know it is not set at the first interesting call.
My mind wrote:if ( attacker->client->pers.lastTeamKillTime && level.time > attacker->client->pers.lastTeamKillTime + g_teamkillsforgettime.integer * 1000 ) {...
->
if ( attacker->client->pers.TeamKillsCount && level.time > attacker->client->pers.lastTeamKillTime + g_teamkillsforgettime.integer * 1000 ) {...
Tequila wrote:About cleaning config, yes, I agree we should clean default.cfg with 1.1 engine... but that won't clean your own q3config.cfg. But I don't think that can involve big problems. Next beta should help us.
ReD NeCKersoN wrote:If you guys want to show us your "cleaned up" cfg it would certainly save the devs some trime.
moRtem wrote:hope to see you back in the arena asap !!!