summaryrefslogtreecommitdiff
path: root/src/game
diff options
context:
space:
mode:
authorChristopher Schwarz <lakitu7@gmail.com>2010-04-03 20:47:11 +0000
committerTim Angus <tim@ngus.net>2013-01-03 00:17:33 +0000
commit784c7b351d013e77d5aeaca6fdf98341fb75b284 (patch)
treecac2dbb07bf5ea1f337c7bdcc30ebf0d39f551ce /src/game
parent3ffe579310f49043d7350adc7b5a2f3d23b48c85 (diff)
* Queue BP according to the proportion of damage that came from not-friendly-fire (e.g. things killed entirely by FF have their BP returned instantly, and those killed by enemies/other have their BP queued, and others split accordingly)
* Human buildings dying from no power now uses MOD_NOCREEP instead of MOD_SUICIDE * Attribute deaths caused by nopower, nocreep, and human buildable blowup-chain-reactions to the person that killed the egg/power/original building that started the chain * Minor cleanups of unused functions/variables
Diffstat (limited to 'src/game')
-rw-r--r--src/game/bg_public.h1
-rw-r--r--src/game/g_buildable.c108
-rw-r--r--src/game/g_cmds.c3
-rw-r--r--src/game/g_combat.c50
-rw-r--r--src/game/g_local.h1
5 files changed, 84 insertions, 79 deletions
diff --git a/src/game/bg_public.h b/src/game/bg_public.h
index d5a143a6..62c981d2 100644
--- a/src/game/bg_public.h
+++ b/src/game/bg_public.h
@@ -901,6 +901,7 @@ typedef enum
MOD_ATUBE,
MOD_OVERMIND,
MOD_DECONSTRUCT,
+ MOD_REPLACE,
MOD_NOCREEP
} meansOfDeath_t;
diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c
index 3e13ea6f..a64772b5 100644
--- a/src/game/g_buildable.c
+++ b/src/game/g_buildable.c
@@ -148,9 +148,6 @@ qboolean G_FindPower( gentity_t *self, qboolean searchUnspawned )
return self->parentNode != NULL;
}
- // Reset parent
- self->parentNode = NULL;
-
// Iterate through entities
for( i = MAX_CLIENTS, ent = g_entities + i; i < level.num_entities; i++, ent++ )
{
@@ -685,6 +682,9 @@ void AGeneric_CreepRecede( gentity_t *self )
{
self->s.eFlags |= EF_DEAD;
G_QueueBuildPoints( self );
+
+ G_RewardAttackers( self );
+
G_AddEvent( self, EV_BUILD_DESTROY, 0 );
if( self->spawned )
@@ -717,7 +717,7 @@ void AGeneric_Blast( gentity_t *self )
VectorCopy( self->s.origin2, dir );
//do a bit of radius damage
- G_SelectiveRadiusDamage( self->s.pos.trBase, self, self->splashDamage,
+ G_SelectiveRadiusDamage( self->s.pos.trBase, g_entities + self->killedBy, self->splashDamage,
self->splashRadius, self, self->splashMethodOfDeath,
TEAM_ALIENS );
@@ -742,11 +742,11 @@ exploding.
*/
void AGeneric_Die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int mod )
{
- G_RewardAttackers( self );
G_SetBuildableAnim( self, BANIM_DESTROY1, qtrue );
G_SetIdleBuildableAnim( self, BANIM_DESTROYED );
self->die = nullDieFunction;
+ self->killedBy = attacker - g_entities;
self->think = AGeneric_Blast;
self->s.eFlags &= ~EF_FIRING; //prevent any firing effects
self->powered = qfalse;
@@ -773,8 +773,8 @@ void AGeneric_CreepCheck( gentity_t *self )
spawn = self->parentNode;
if( !G_FindCreep( self ) )
{
- if( spawn && self->killedBy != ENTITYNUM_NONE )
- G_Damage( self, NULL, g_entities + self->killedBy, NULL, NULL,
+ if( spawn )
+ G_Damage( self, NULL, g_entities + spawn->killedBy, NULL, NULL,
self->health, 0, MOD_NOCREEP );
else
G_Damage( self, NULL, NULL, NULL, NULL, self->health, 0, MOD_NOCREEP );
@@ -818,35 +818,6 @@ void AGeneric_Pain( gentity_t *self, gentity_t *attacker, int damage )
//==================================================================================
-
-
-
-/*
-================
-ASpawn_Die
-
-Called when an alien spawn dies
-================
-*/
-void ASpawn_Die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int mod )
-{
- int i;
-
- AGeneric_Die( self, inflictor, attacker, damage, mod );
-
- // All supported structures that no longer have creep will have been killed
- // by whoever killed this structure
- for( i = MAX_CLIENTS; i < level.num_entities; i++ )
- {
- gentity_t *ent = g_entities + i;
-
- if( !ent->inuse || ent->health <= 0 || ent->s.eType != ET_BUILDABLE ||
- ent->parentNode != self )
- continue;
- ent->killedBy = attacker - g_entities;
- }
-}
-
/*
================
ASpawn_Think
@@ -1527,13 +1498,19 @@ static void G_SuicideIfNoPower( gentity_t *self )
if( self->buildableTeam != TEAM_HUMANS )
return;
- if( G_Reactor( ) && !self->parentNode )
+ if( G_Reactor( ) && !self->powered )
{
// If no parent for x seconds then disappear
if( self->count < 0 )
self->count = level.time;
else if( self->count > 0 && ( ( level.time - self->count ) > HUMAN_BUILDABLE_INACTIVE_TIME ) )
- G_Damage( self, NULL, NULL, NULL, NULL, self->health, 0, MOD_SUICIDE );
+ {
+ if( self->parentNode )
+ G_Damage( self, NULL, g_entities + self->parentNode->killedBy,
+ NULL, NULL, self->health, 0, MOD_NOCREEP );
+ else
+ G_Damage( self, NULL, NULL, NULL, NULL, self->health, 0, MOD_NOCREEP );
+ }
}
else
{
@@ -1583,6 +1560,7 @@ void HSpawn_Disappear( gentity_t *self )
self->s.eFlags |= EF_NODRAW; //don't draw the model once its destroyed
self->timestamp = level.time;
G_QueueBuildPoints( self );
+ G_RewardAttackers( self );
G_FreeEntity( self );
}
@@ -1607,11 +1585,12 @@ void HSpawn_Blast( gentity_t *self )
self->timestamp = level.time;
//do some radius damage
- G_RadiusDamage( self->s.pos.trBase, self, self->splashDamage,
+ G_RadiusDamage( self->s.pos.trBase, g_entities + self->killedBy, self->splashDamage,
self->splashRadius, self, self->splashMethodOfDeath );
// begin freeing build points
G_QueueBuildPoints( self );
+ G_RewardAttackers( self );
// turn into an explosion
self->s.eType = ET_EVENTS + EV_HUMAN_BUILDABLE_EXPLOSION;
self->freeAfterEvent = qtrue;
@@ -1628,11 +1607,11 @@ Called when a human spawn dies
*/
void HSpawn_Die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int mod )
{
- G_RewardAttackers( self );
G_SetBuildableAnim( self, BANIM_DESTROY1, qtrue );
G_SetIdleBuildableAnim( self, BANIM_DESTROYED );
self->die = nullDieFunction;
+ self->killedBy = attacker - g_entities;
self->powered = qfalse; //free up power
self->s.eFlags &= ~EF_FIRING; //prevent any firing effects
@@ -1718,6 +1697,7 @@ static void HRepeater_Die( gentity_t *self, gentity_t *inflictor, gentity_t *att
G_SetIdleBuildableAnim( self, BANIM_DESTROYED );
self->die = nullDieFunction;
+ self->killedBy = attacker - g_entities;
self->powered = qfalse; //free up power
self->s.eFlags &= ~EF_FIRING; //prevent any firing effects
@@ -2496,19 +2476,34 @@ G_QueueBuildPoints
*/
void G_QueueBuildPoints( gentity_t *self )
{
- gentity_t *killer = NULL;
gentity_t *powerEntity;
+ int i;
+ int damageTotal = 0;
+ int queuePoints = 0;
+ double queueFraction = 0;
- if( self->killedBy != ENTITYNUM_NONE )
- killer = &g_entities[ self->killedBy ];
-
- if( killer && killer->client &&
- killer->client->ps.stats[ STAT_TEAM ] == self->buildableTeam )
+ for( i = 0; i < MAX_CLIENTS; i++ )
{
- // Don't take away build points if killed by a teammate
- // deconstructing an egg/overmind (MOD_NOCREEP)
- return;
+ gentity_t *player = g_entities + i;
+
+ if( !player->client )
+ continue;
+
+ damageTotal += self->credits[ i ];
+
+ if( self->buildableTeam != player->client->pers.teamSelection )
+ queueFraction += (double) self->credits[ i ];
}
+
+ if( damageTotal > 0 )
+ queueFraction = queueFraction / (double) damageTotal;
+ else // all damage was done by nonclients, so queue everything
+ queueFraction = 1.0;
+
+ queuePoints = (int) ( queueFraction * (double) BG_Buildable( self->s.modelindex )->buildPoints );
+
+ if( !queuePoints )
+ return;
switch( self->buildableTeam )
{
@@ -2520,8 +2515,7 @@ void G_QueueBuildPoints( gentity_t *self )
if( !level.alienBuildPointQueue )
level.alienNextQueueTime = level.time + g_alienBuildQueueTime.integer;
- level.alienBuildPointQueue +=
- BG_Buildable( self->s.modelindex )->buildPoints;
+ level.alienBuildPointQueue += queuePoints;
break;
case TEAM_HUMANS:
@@ -2540,8 +2534,7 @@ void G_QueueBuildPoints( gentity_t *self )
level.time + nqt < level.humanNextQueueTime )
level.humanNextQueueTime = level.time + nqt;
- level.humanBuildPointQueue +=
- BG_Buildable( self->s.modelindex )->buildPoints;
+ level.humanBuildPointQueue += queuePoints;
break;
case BA_H_REPEATER:
@@ -2558,8 +2551,7 @@ void G_QueueBuildPoints( gentity_t *self )
level.time + nqt < zone->nextQueueTime )
zone->nextQueueTime = level.time + nqt;
- zone->queuedBuildPoints +=
- BG_Buildable( self->s.modelindex )->buildPoints;
+ zone->queuedBuildPoints += queuePoints;
}
break;
@@ -2970,7 +2962,7 @@ void G_FreeMarkedBuildables( gentity_t *deconner, char *readable, int rsize,
if( removalCounts[ bNum ] == 0 )
totalListItems++;
- G_Damage( ent, NULL, NULL, NULL, NULL, ent->health, 0, MOD_DECONSTRUCT );
+ G_Damage( ent, NULL, NULL, NULL, NULL, ent->health, 0, MOD_REPLACE );
removalCounts[ bNum ]++;
@@ -3496,7 +3488,7 @@ static gentity_t *G_Build( gentity_t *builder, buildable_t buildable, vec3_t ori
switch( buildable )
{
case BA_A_SPAWN:
- built->die = ASpawn_Die;
+ built->die = AGeneric_Die;
built->think = ASpawn_Think;
built->pain = AGeneric_Pain;
break;
@@ -3536,7 +3528,7 @@ static gentity_t *G_Build( gentity_t *builder, buildable_t buildable, vec3_t ori
break;
case BA_A_OVERMIND:
- built->die = ASpawn_Die;
+ built->die = AGeneric_Die;
built->think = AOvermind_Think;
built->pain = AGeneric_Pain;
break;
diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c
index 65f34ef6..d194c142 100644
--- a/src/game/g_cmds.c
+++ b/src/game/g_cmds.c
@@ -1700,7 +1700,8 @@ void Cmd_Destroy_f( gentity_t *ent )
ent->client->ps.stats[ STAT_MISC ] +=
BG_Buildable( traceEnt->s.modelindex )->buildTime / 4;
}
- G_LogDestruction( traceEnt, ent, MOD_DECONSTRUCT );
+ G_Damage( traceEnt, ent, ent, forward, tr.endpos,
+ traceEnt->health, 0, MOD_DECONSTRUCT );
G_FreeEntity( traceEnt );
}
}
diff --git a/src/game/g_combat.c b/src/game/g_combat.c
index 66a092ef..64d047f8 100644
--- a/src/game/g_combat.c
+++ b/src/game/g_combat.c
@@ -123,6 +123,7 @@ char *modNames[ ] =
"MOD_ATUBE",
"MOD_OVERMIND",
"MOD_DECONSTRUCT",
+ "MOD_REPLACE",
"MOD_NOCREEP"
};
@@ -139,9 +140,15 @@ float G_RewardAttackers( gentity_t *self )
float value, totalDamage = 0;
int team, i, maxHealth = 0;
- // Total up all the damage done by every client
+ // Total up all the damage done by non-teammates
for( i = 0; i < MAX_CLIENTS; i++ )
- totalDamage += (float)self->credits[ i ];
+ {
+ gentity_t *player = g_entities + i;
+
+ if( !OnSameTeam( self, player ) ||
+ self->buildableTeam != player->client->pers.teamSelection )
+ totalDamage += (float)self->credits[ i ];
+ }
if( totalDamage <= 0.0f )
return 0.0f;
@@ -176,27 +183,32 @@ float G_RewardAttackers( gentity_t *self )
gentity_t *player = g_entities + i;
short num = value * self->credits[ i ] / totalDamage;
int stageValue = num;
- if( totalDamage < maxHealth )
+
+ if( !OnSameTeam( self, player ) ||
+ self->buildableTeam != player->client->pers.teamSelection )
+ {
+
+ if( totalDamage < maxHealth )
stageValue *= totalDamage / maxHealth;
- if( !player->client || !self->credits[ i ] ||
- player->client->ps.stats[ STAT_TEAM ] == team )
- continue;
+ if( !player->client || !self->credits[ i ] ||
+ player->client->ps.stats[ STAT_TEAM ] == team )
+ continue;
- AddScore( player, num );
+ AddScore( player, num );
- // killing buildables earns score, but not credits
- if( self->s.eType != ET_BUILDABLE )
- {
- G_AddCreditToClient( player->client, num, qtrue );
+ // killing buildables earns score, but not credits
+ if( self->s.eType != ET_BUILDABLE )
+ {
+ G_AddCreditToClient( player->client, num, qtrue );
- // add to stage counters
- if( player->client->ps.stats[ STAT_TEAM ] == TEAM_ALIENS )
- trap_Cvar_Set( "g_alienCredits", va( "%d", g_alienCredits.integer + stageValue ) );
- else if( player->client->ps.stats[ STAT_TEAM ] == TEAM_HUMANS )
- trap_Cvar_Set( "g_humanCredits", va( "%d", g_humanCredits.integer + stageValue ) );
+ // add to stage counters
+ if( player->client->ps.stats[ STAT_TEAM ] == TEAM_ALIENS )
+ trap_Cvar_Set( "g_alienCredits", va( "%d", g_alienCredits.integer + stageValue ) );
+ else if( player->client->ps.stats[ STAT_TEAM ] == TEAM_HUMANS )
+ trap_Cvar_Set( "g_humanCredits", va( "%d", g_humanCredits.integer + stageValue ) );
+ }
}
-
self->credits[ i ] = 0;
}
@@ -1126,7 +1138,7 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
targ->nextRegenTime = level.time + ALIEN_REGEN_DAMAGE_TIME;
// add to the attackers "account" on the target
- if( attacker->client && attacker != targ && !OnSameTeam( targ, attacker ) )
+ if( attacker->client && attacker != targ )
targ->credits[ attacker->client->ps.clientNum ] += take;
if( targ->health <= 0 )
@@ -1364,7 +1376,7 @@ void G_LogDestruction( gentity_t *self, gentity_t *actor, int mod )
return;
// don't log when marked structures are removed
- if( mod == MOD_DECONSTRUCT && !actor->client )
+ if( mod == MOD_REPLACE )
return;
if( actor->client && actor->client->pers.teamSelection ==
diff --git a/src/game/g_local.h b/src/game/g_local.h
index 51cf3ac0..78981667 100644
--- a/src/game/g_local.h
+++ b/src/game/g_local.h
@@ -215,7 +215,6 @@ struct gentity_s
int clientSpawnTime; // the time until this spawn can spawn a client
int credits[ MAX_CLIENTS ]; // human credits for each client
- qboolean creditsHash[ MAX_CLIENTS ]; // track who has claimed credit
int killedBy; // clientNum of killer
gentity_t *targeted; // true if the player is currently a valid target of a turret