summaryrefslogtreecommitdiff
path: root/src/game
diff options
context:
space:
mode:
authorPetr Pudlak <petr.mvd@gmail.com>2014-08-16 14:26:16 +0200
committerPetr Pudlak <petr.mvd@gmail.com>2014-08-16 14:26:16 +0200
commit8816244ec329acdd5eb64e0518e69ae77df1cd75 (patch)
treec7a7614c537a79b29452695c94ee7597b69e7993 /src/game
parentfc765f5f146627d282b4374dd0c575895d64a900 (diff)
Add the ability for humans to heal their team members
The medkit handling is moved to a new function G_UseMedkit. If there is a human within a given range that is either more wounded than the player, or poisoned, the medkit is applied to him (see G_NeedsMedkit). The range and the breadth of the action is configurable by cvars. The original patch was used on a server, but this port wasn't tested (only that it compiles).
Diffstat (limited to 'src/game')
-rw-r--r--src/game/g_active.c101
-rw-r--r--src/game/g_local.h3
-rw-r--r--src/game/g_main.c4
-rw-r--r--src/game/g_weapon.c31
4 files changed, 107 insertions, 32 deletions
diff --git a/src/game/g_active.c b/src/game/g_active.c
index fc32ed6..2f7f906 100644
--- a/src/game/g_active.c
+++ b/src/game/g_active.c
@@ -426,6 +426,74 @@ void G_TouchTriggers( gentity_t *ent )
static qboolean ClientInactivityTimer( gentity_t *ent, qboolean active );
/*
+============
+G_NeedsMedkit
+
+============
+*/
+qboolean G_NeedsMedkit( gclient_t *client )
+{
+ //not if currently using a medkit or have no need for a medkit now
+ return !( client->ps.stats[ STAT_STATE ] & SS_HEALING_2X ) &&
+ ( client->ps.stats[ STAT_HEALTH ] < client->ps.stats[ STAT_MAX_HEALTH ] ||
+ ( client->ps.stats[ STAT_STATE ] & SS_POISONED ) );
+}
+/*
+============
+G_UseMedkit
+
+============
+*/
+void G_UseMedkit( gentity_t *ent )
+{
+ gclient_t *client = ent->client;
+ gentity_t *targetEnt = NULL;
+ gclient_t *tclient = NULL;
+ qboolean clientNeedsMedkit;
+
+ if( client->ps.stats[ STAT_HEALTH ] <= 0 )
+ return;
+
+ clientNeedsMedkit = G_NeedsMedkit( client );
+ //look for a teammate that would need healing
+ targetEnt = G_MedkitTarget( ent );
+ if( ( targetEnt != NULL ) &&
+ ( ( tclient = targetEnt->client ) != NULL ) &&
+ ( tclient->ps.stats[ STAT_HEALTH ] > 0 ) &&
+ ( tclient->ps.stats[ STAT_TEAM ] == TEAM_HUMANS ) &&
+ ( G_NeedsMedkit( tclient ) ) &&
+ ( ( client->ps.stats[ STAT_HEALTH ] >= tclient->ps.stats[ STAT_HEALTH ] ) ||
+ !clientNeedsMedkit )
+ )
+ ;
+ else if( clientNeedsMedkit )
+ {
+ targetEnt = ent;
+ tclient = client;
+ } else {
+ BG_DeactivateUpgrade( UP_MEDKIT, client->ps.stats );
+ return;
+ }
+
+ //remove anti toxin
+ BG_DeactivateUpgrade( UP_MEDKIT, client->ps.stats );
+ BG_RemoveUpgradeFromInventory( UP_MEDKIT, client->ps.stats );
+
+ // don't poison and/or infect the client anymore
+ tclient->ps.stats[ STAT_STATE ] &= ~( SS_POISONED | SS_INFECTED );
+ tclient->poisonImmunityTime = level.time + MEDKIT_POISON_IMMUNITY_TIME;
+
+ tclient->ps.stats[ STAT_STATE ] |= SS_HEALING_2X;
+ tclient->lastMedKitTime = level.time;
+ tclient->medKitHealthToRestore =
+ tclient->ps.stats[ STAT_MAX_HEALTH ] - tclient->ps.stats[ STAT_HEALTH ];
+ tclient->medKitIncrementTime = level.time +
+ ( MEDKIT_STARTUP_TIME / MEDKIT_STARTUP_SPEED );
+
+ G_AddEvent( targetEnt, EV_MEDKIT_USED, ent->s.number );
+}
+
+/*
=================
SpectatorThink
=================
@@ -1685,38 +1753,7 @@ void ClientThink_real( gentity_t *ent )
if( BG_InventoryContainsUpgrade( UP_MEDKIT, client->ps.stats ) &&
BG_UpgradeIsActive( UP_MEDKIT, client->ps.stats ) )
- {
- //if currently using a medkit or have no need for a medkit now
- if( client->ps.stats[ STAT_STATE ] & SS_HEALING_2X ||
- ( client->ps.stats[ STAT_HEALTH ] == client->ps.stats[ STAT_MAX_HEALTH ] &&
- !( client->ps.stats[ STAT_STATE ] & SS_POISONED ) ) )
- {
- BG_DeactivateUpgrade( UP_MEDKIT, client->ps.stats );
- }
- else if( client->ps.stats[ STAT_HEALTH ] > 0 )
- {
- //remove anti toxin
- BG_DeactivateUpgrade( UP_MEDKIT, client->ps.stats );
- BG_RemoveUpgradeFromInventory( UP_MEDKIT, client->ps.stats );
-
- // don't poison and/or infect the client anymore
- client->ps.stats[ STAT_STATE ] &= ~SS_POISONED;
-
- if( client->ps.stats[ STAT_STATE ] & SS_INFECTED )
- client->ps.stats[ STAT_STATE ] &= ~SS_INFECTED;
-
- client->poisonImmunityTime = level.time + MEDKIT_POISON_IMMUNITY_TIME;
-
- client->ps.stats[ STAT_STATE ] |= SS_HEALING_2X;
- client->lastMedKitTime = level.time;
- client->medKitHealthToRestore =
- client->ps.stats[ STAT_MAX_HEALTH ] - client->ps.stats[ STAT_HEALTH ];
- client->medKitIncrementTime = level.time +
- ( MEDKIT_STARTUP_TIME / MEDKIT_STARTUP_SPEED );
-
- G_AddEvent( ent, EV_MEDKIT_USED, 0 );
- }
- }
+ G_UseMedkit( ent );
if( BG_InventoryContainsUpgrade( UP_CLOAK, client->ps.stats ) &&
BG_UpgradeIsActive( UP_CLOAK, client->ps.stats ) )
diff --git a/src/game/g_local.h b/src/game/g_local.h
index e437349..37971ed 100644
--- a/src/game/g_local.h
+++ b/src/game/g_local.h
@@ -1042,6 +1042,7 @@ void G_UnregisterCommands( void );
void FireWeapon( gentity_t *ent );
void FireWeapon2( gentity_t *ent );
void FireWeapon3( gentity_t *ent );
+gentity_t *G_MedkitTarget( gentity_t *ent );
//
// g_main.c
@@ -1179,6 +1180,8 @@ extern vmCvar_t g_suddenDeathVoteDelay;
extern vmCvar_t g_readyPercent;
extern vmCvar_t g_armageddonVotePercent;
extern vmCvar_t g_armageddonPercent;
+extern vmCvar_t g_humanMedkitRange;
+extern vmCvar_t g_humanMedkitWidth;
extern vmCvar_t g_teamForceBalance;
extern vmCvar_t g_smoothClients;
extern vmCvar_t pmove_fixed;
diff --git a/src/game/g_main.c b/src/game/g_main.c
index 45f7b03..c644bdd 100644
--- a/src/game/g_main.c
+++ b/src/game/g_main.c
@@ -86,6 +86,8 @@ vmCvar_t g_suddenDeathVotePercent;
vmCvar_t g_suddenDeathVoteDelay;
vmCvar_t g_armageddonVotePercent;
vmCvar_t g_armageddonPercent;
+vmCvar_t g_humanMedkitRange;
+vmCvar_t g_humanMedkitWidth;
vmCvar_t g_readyPercent;
vmCvar_t g_teamForceBalance;
vmCvar_t g_smoothClients;
@@ -217,6 +219,8 @@ static cvarTable_t gameCvarTable[ ] =
{ &g_maxclients, "sv_maxclients", "8", CVAR_SERVERINFO | CVAR_LATCH | CVAR_ARCHIVE, 0, qfalse },
{ &g_maxGameClients, "g_maxGameClients", "0", CVAR_SERVERINFO | CVAR_ARCHIVE, 0, qfalse },
{ &g_timelimit, "timelimit", "0", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
+ { &g_humanMedkitRange, "g_humanMedkitRange", "200", CVAR_ARCHIVE, 0, qfalse },
+ { &g_humanMedkitWidth, "g_humanMedkitWidth", "20", CVAR_ARCHIVE, 0, qfalse },
{ &g_suddenDeathTime, "g_suddenDeathTime", "40", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
{ &g_armageddonTimeStep, "g_armageddonTimeStep", "5", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
{ &g_armageddonInitialTimeStep, "g_armageddonInitialTimeStep", "10", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue },
diff --git a/src/game/g_weapon.c b/src/game/g_weapon.c
index a64f0f8..feee414 100644
--- a/src/game/g_weapon.c
+++ b/src/game/g_weapon.c
@@ -1454,6 +1454,37 @@ void G_ClearPlayerZapEffects( gentity_t *player )
}
}
+
+/*
+===============
+G_MedkitTarget
+
+Look for a possible healing target (a client) in the front.
+===============
+*/
+gentity_t *G_MedkitTarget( gentity_t *ent )
+{
+ trace_t tr;
+ gentity_t *targetEnt = NULL;
+
+ if( g_humanMedkitRange.value <= 0 ||
+ g_humanMedkitWidth.value <= 0 )
+ return NULL;
+
+ // Calculate muzzle point
+ AngleVectors( ent->client->ps.viewangles, forward, right, up );
+ CalcMuzzlePoint( ent, forward, right, up, muzzle );
+
+ G_WideTrace( &tr, ent, g_humanMedkitRange.value,
+ g_humanMedkitWidth.value, g_humanMedkitWidth.value, &targetEnt );
+
+ if( ( targetEnt != NULL ) &&
+ ( targetEnt->client != NULL ) )
+ return targetEnt;
+ else
+ return NULL;
+}
+
/*
===============
areaZapFire