summaryrefslogtreecommitdiff
path: root/src/game/g_buildable.c
diff options
context:
space:
mode:
author/dev/humancontroller <devhc@example.com>2014-07-13 18:12:01 +0200
committer/dev/humancontroller <devhc@example.com>2017-03-09 13:51:11 +0100
commit10121326fbf07b701038893ecdb19f672c29c11e (patch)
treef14b006721b4835f7dc04a3ef3ed75b73556d621 /src/game/g_buildable.c
parent8391e8997fad1bdbd6b9d189c6afca22d3e4324c (diff)
implement the range marker functionality, use it to create buildable range markers
use the entity 64-bit client-masking extension when available
Diffstat (limited to 'src/game/g_buildable.c')
-rw-r--r--src/game/g_buildable.c144
1 files changed, 144 insertions, 0 deletions
diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c
index 3b237379..34136909 100644
--- a/src/game/g_buildable.c
+++ b/src/game/g_buildable.c
@@ -789,6 +789,7 @@ void AGeneric_Die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, i
else
self->nextthink = level.time; //blast immediately
+ G_RemoveRangeMarkerFrom( self );
G_LogDestruction( self, attacker, mod );
}
@@ -1661,6 +1662,7 @@ void HSpawn_Die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
self->nextthink = level.time; //blast immediately
}
+ G_RemoveRangeMarkerFrom( self );
G_LogDestruction( self, attacker, mod );
}
@@ -1747,6 +1749,7 @@ static void HRepeater_Die( gentity_t *self, gentity_t *inflictor, gentity_t *att
self->nextthink = level.time; //blast immediately
}
+ G_RemoveRangeMarkerFrom( self );
G_LogDestruction( self, attacker, mod );
if( self->usesBuildPointZone )
@@ -3020,6 +3023,7 @@ void G_FreeMarkedBuildables( gentity_t *deconner, char *readable, int rsize,
if( nums )
Q_strcat( nums, nsize, va( " %d", (int)( ent - g_entities ) ) );
+ G_RemoveRangeMarkerFrom( ent );
G_FreeEntity( ent );
}
@@ -3491,6 +3495,55 @@ itemBuildError_t G_CanBuild( gentity_t *ent, buildable_t buildable, int distance
/*
================
+G_AddRangeMarkerForBuildable
+================
+*/
+static void G_AddRangeMarkerForBuildable( gentity_t *self )
+{
+ gentity_t *rm;
+
+ switch( self->s.modelindex )
+ {
+ case BA_A_SPAWN:
+ case BA_A_OVERMIND:
+ case BA_A_ACIDTUBE:
+ case BA_A_TRAPPER:
+ case BA_A_HIVE:
+ case BA_H_MGTURRET:
+ case BA_H_TESLAGEN:
+ case BA_H_DCC:
+ case BA_H_REACTOR:
+ case BA_H_REPEATER:
+ break;
+ default:
+ return;
+ }
+
+ rm = G_Spawn();
+ rm->classname = "buildablerangemarker";
+ rm->r.svFlags = SVF_BROADCAST | SVF_CLIENTMASK;
+ rm->s.eType = ET_RANGE_MARKER;
+ rm->s.modelindex = self->s.modelindex;
+
+ self->rangeMarker = rm;
+}
+
+/*
+================
+G_RemoveRangeMarkerFrom
+================
+*/
+void G_RemoveRangeMarkerFrom( gentity_t *self )
+{
+ if( self->rangeMarker )
+ {
+ G_FreeEntity( self->rangeMarker );
+ self->rangeMarker = NULL;
+ }
+}
+
+/*
+================
G_Build
Spawns a buildable
@@ -3719,6 +3772,8 @@ static gentity_t *G_Build( gentity_t *builder, buildable_t buildable,
if( log )
G_BuildLogSet( log, built );
+ G_AddRangeMarkerForBuildable( built );
+
return built;
}
@@ -3840,6 +3895,7 @@ static gentity_t *G_FinishSpawningBuildable( gentity_t *ent, qboolean force )
{
G_Printf( S_COLOR_YELLOW "G_FinishSpawningBuildable: %s startsolid at %s\n",
built->classname, vtos( built->s.origin ) );
+ G_RemoveRangeMarkerFrom( built );
G_FreeEntity( built );
return NULL;
}
@@ -4309,6 +4365,7 @@ void G_BuildLogRevert( int id )
if( ent->s.eType == ET_BUILDABLE )
G_LogPrintf( "revert: remove %d %s\n",
(int)( ent - g_entities ), BG_Buildable( ent->s.modelindex )->name );
+ G_RemoveRangeMarkerFrom( ent );
G_FreeEntity( ent );
break;
}
@@ -4370,3 +4427,90 @@ void G_BuildLogRevert( int id )
}
}
+/*
+================
+G_UpdateBuildableRangeMarkers
+================
+*/
+void G_UpdateBuildableRangeMarkers( void )
+{
+ // is the entity 64-bit client-masking extension available?
+ qboolean maskingExtension = ( trap_Cvar_VariableIntegerValue( "sv_gppExtension" ) >= 1 );
+
+ gentity_t *e;
+ for( e = &g_entities[ MAX_CLIENTS ]; e < &g_entities[ level.num_entities ]; ++e )
+ {
+ buildable_t bType;
+ team_t bTeam;
+ int i;
+
+ if( e->s.eType != ET_BUILDABLE || !e->rangeMarker )
+ continue;
+
+ bType = e->s.modelindex;
+ bTeam = BG_Buildable( bType )->team;
+
+ e->rangeMarker->s.pos = e->s.pos;
+ if( bType == BA_A_HIVE || bType == BA_H_TESLAGEN )
+ VectorMA( e->s.pos.trBase, e->r.maxs[ 2 ], e->s.origin2, e->rangeMarker->s.pos.trBase );
+ else if( bType == BA_A_TRAPPER || bType == BA_H_MGTURRET )
+ vectoangles( e->s.origin2, e->rangeMarker->s.apos.trBase );
+
+ e->rangeMarker->r.singleClient = 0;
+ e->rangeMarker->r.hack.generic1 = 0;
+
+ // remove any previously added NOCLIENT flags from the hack below
+ e->rangeMarker->r.svFlags &= ~SVF_NOCLIENT;
+
+ for( i = 0; i < level.maxclients; ++i )
+ {
+ gclient_t *client;
+ team_t team;
+ qboolean weaponDisplays, wantsToSee;
+
+ client = &level.clients[ i ];
+ if( client->pers.connected != CON_CONNECTED )
+ continue;
+
+ if( i >= 32 && !maskingExtension )
+ {
+ // resort to not sending range markers at all
+ if( !trap_Cvar_VariableIntegerValue( "g_rangeMarkerWarningGiven" ) )
+ {
+ trap_SendServerCommand( -1, "print \"" S_COLOR_YELLOW "WARNING: There is no "
+ "support for entity 64-bit client-masking on this server. Please update "
+ "your server executable. Until then, range markers will not be displayed "
+ "while there are clients with client numbers above 31 in the game.\n\"" );
+ trap_Cvar_Set( "g_rangeMarkerWarningGiven", "1" );
+ }
+
+ for( e = &g_entities[ MAX_CLIENTS ]; e < &g_entities[ level.num_entities ]; ++e )
+ {
+ if( e->s.eType == ET_BUILDABLE && e->rangeMarker )
+ e->rangeMarker->r.svFlags |= SVF_NOCLIENT;
+ }
+
+ return;
+ }
+
+ team = client->pers.teamSelection;
+ if( team != TEAM_NONE )
+ {
+ weaponDisplays = ( BG_InventoryContainsWeapon( WP_HBUILD, client->ps.stats ) ||
+ client->ps.weapon == WP_ABUILD || client->ps.weapon == WP_ABUILD2 );
+ }
+ wantsToSee = !!( client->pers.buildableRangeMarkerMask & ( 1 << bType ) );
+
+ if( ( team == TEAM_NONE || ( team == bTeam && weaponDisplays ) ) && wantsToSee )
+ {
+ if( i >= 32 )
+ e->rangeMarker->r.hack.generic1 |= 1 << ( i - 32 );
+ else
+ e->rangeMarker->r.singleClient |= 1 << i;
+ }
+ }
+
+ trap_LinkEntity( e->rangeMarker );
+ }
+}
+