From 784c7b351d013e77d5aeaca6fdf98341fb75b284 Mon Sep 17 00:00:00 2001 From: Christopher Schwarz Date: Sat, 3 Apr 2010 20:47:11 +0000 Subject: * 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 --- src/game/bg_public.h | 1 + src/game/g_buildable.c | 108 +++++++++++++++++++++++-------------------------- src/game/g_cmds.c | 3 +- src/game/g_combat.c | 50 ++++++++++++++--------- src/game/g_local.h | 1 - 5 files changed, 84 insertions(+), 79 deletions(-) (limited to 'src/game') 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 -- cgit