summaryrefslogtreecommitdiff
path: root/src/game/g_buildable.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/g_buildable.c')
-rw-r--r--src/game/g_buildable.c415
1 files changed, 234 insertions, 181 deletions
diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c
index 640fa752..224efc72 100644
--- a/src/game/g_buildable.c
+++ b/src/game/g_buildable.c
@@ -82,7 +82,8 @@ static qboolean findPower( gentity_t *self )
continue;
//if entity is a power item calculate the distance to it
- if( ent->s.modelindex == BA_H_REACTOR || ent->s.modelindex == BA_H_REPEATER )
+ if( ( ent->s.modelindex == BA_H_REACTOR || ent->s.modelindex == BA_H_REPEATER ) &&
+ ent->spawned )
{
VectorSubtract( self->s.origin, ent->s.origin, temp_v );
distance = VectorLength( temp_v );
@@ -163,8 +164,8 @@ static qboolean findDCC( gentity_t *self )
if( !ent->classname || ent->s.eType != ET_BUILDABLE )
continue;
- //if entity is a power item calculate the distance to it
- if( ent->s.modelindex == BA_H_DCC )
+ //if entity is a dcc calculate the distance to it
+ if( ent->s.modelindex == BA_H_DCC && ent->spawned )
{
VectorSubtract( self->s.origin, ent->s.origin, temp_v );
distance = VectorLength( temp_v );
@@ -231,7 +232,8 @@ static qboolean findCreep( gentity_t *self )
if( !ent->classname || ent->s.eType != ET_BUILDABLE )
continue;
- if( ent->s.modelindex == BA_A_SPAWN || ent->s.modelindex == BA_A_OVERMIND )
+ if( ( ent->s.modelindex == BA_A_SPAWN || ent->s.modelindex == BA_A_OVERMIND ) &&
+ ent->spawned )
{
VectorSubtract( self->s.origin, ent->s.origin, temp_v );
distance = VectorLength( temp_v );
@@ -470,27 +472,30 @@ void ASpawn_Think( gentity_t *self )
trace_t tr;
float displacement;
- VectorSet( mins, -MAX_ALIEN_BBOX, -MAX_ALIEN_BBOX, -MAX_ALIEN_BBOX );
- VectorSet( maxs, MAX_ALIEN_BBOX, MAX_ALIEN_BBOX, MAX_ALIEN_BBOX );
-
- VectorCopy( self->s.origin, origin );
- displacement = ( self->r.maxs[ 2 ] + MAX_ALIEN_BBOX ) * M_ROOT3 + 1.0f;
- VectorMA( origin, displacement, self->s.origin2, origin );
-
- //only suicide if at rest
- if( self->s.groundEntityNum )
+ if( self->spawned )
{
- trap_Trace( &tr, origin, mins, maxs, origin, self->s.number, MASK_SHOT );
- ent = &g_entities[ tr.entityNum ];
+ VectorSet( mins, -MAX_ALIEN_BBOX, -MAX_ALIEN_BBOX, -MAX_ALIEN_BBOX );
+ VectorSet( maxs, MAX_ALIEN_BBOX, MAX_ALIEN_BBOX, MAX_ALIEN_BBOX );
- if( ent->s.eType == ET_BUILDABLE || ent->s.number == ENTITYNUM_WORLD )
+ VectorCopy( self->s.origin, origin );
+ displacement = ( self->r.maxs[ 2 ] + MAX_ALIEN_BBOX ) * M_ROOT3 + 1.0f;
+ VectorMA( origin, displacement, self->s.origin2, origin );
+
+ //only suicide if at rest
+ if( self->s.groundEntityNum )
{
- G_Damage( self, NULL, NULL, NULL, NULL, 10000, 0, MOD_SUICIDE );
- return;
- }
+ trap_Trace( &tr, origin, mins, maxs, origin, self->s.number, MASK_SHOT );
+ ent = &g_entities[ tr.entityNum ];
+
+ if( ent->s.eType == ET_BUILDABLE || ent->s.number == ENTITYNUM_WORLD )
+ {
+ G_Damage( self, NULL, NULL, NULL, NULL, 10000, 0, MOD_SUICIDE );
+ return;
+ }
- if( ent->s.eType == ET_CORPSE )
- G_FreeEntity( ent ); //quietly remove
+ if( ent->s.eType == ET_CORPSE )
+ G_FreeEntity( ent ); //quietly remove
+ }
}
creepSlow( self->s.modelindex, self->s.origin );
@@ -538,7 +543,7 @@ void AOvermind_Think( gentity_t *self )
VectorAdd( self->s.origin, range, maxs );
VectorSubtract( self->s.origin, range, mins );
- if( self->health > 0 )
+ if( self->spawned && ( self->health > 0 ) )
{
//do some damage
num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
@@ -676,23 +681,26 @@ damage function for Alien Acid Tube
*/
void AAcidTube_Damage( gentity_t *self )
{
- if( !( self->s.eFlags & EF_FIRING ) )
+ if( self->spawned )
{
- self->s.eFlags |= EF_FIRING;
- G_AddEvent( self, EV_GIB_ALIEN, DirToByte( self->s.origin2 ) );
- }
-
- if( ( self->timestamp + ACIDTUBE_REPEAT ) > level.time )
- self->think = AAcidTube_Damage;
- else
- {
- self->think = AAcidTube_Think;
- self->s.eFlags &= ~EF_FIRING;
- }
+ if( !( self->s.eFlags & EF_FIRING ) )
+ {
+ self->s.eFlags |= EF_FIRING;
+ G_AddEvent( self, EV_GIB_ALIEN, DirToByte( self->s.origin2 ) );
+ }
+
+ if( ( self->timestamp + ACIDTUBE_REPEAT ) > level.time )
+ self->think = AAcidTube_Damage;
+ else
+ {
+ self->think = AAcidTube_Think;
+ self->s.eFlags &= ~EF_FIRING;
+ }
- //do some damage
- G_SelectiveRadiusDamage( self->s.pos.trBase, self->parent, self->splashDamage,
- self->splashRadius, self, self->splashMethodOfDeath, PTE_ALIENS );
+ //do some damage
+ G_SelectiveRadiusDamage( self->s.pos.trBase, self->parent, self->splashDamage,
+ self->splashRadius, self, self->splashMethodOfDeath, PTE_ALIENS );
+ }
creepSlow( self->s.modelindex, self->s.origin );
@@ -724,19 +732,22 @@ void AAcidTube_Think( gentity_t *self )
return;
}
- //do some damage
- num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
- for( i = 0; i < num; i++ )
+ if( self->spawned )
{
- enemy = &g_entities[ entityList[ i ] ];
-
- if( enemy->client && enemy->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
+ //do some damage
+ num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
+ for( i = 0; i < num; i++ )
{
- self->timestamp = level.time;
- self->think = AAcidTube_Damage;
- self->nextthink = level.time + 100;
- G_setBuildableAnim( self, BANIM_ATTACK1, qfalse );
- return;
+ enemy = &g_entities[ entityList[ i ] ];
+
+ if( enemy->client && enemy->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
+ {
+ self->timestamp = level.time;
+ self->think = AAcidTube_Damage;
+ self->nextthink = level.time + 100;
+ G_setBuildableAnim( self, BANIM_ATTACK1, qfalse );
+ return;
+ }
}
}
@@ -763,37 +774,40 @@ void AHovel_Use( gentity_t *self, gentity_t *other, gentity_t *activator )
{
vec3_t hovelOrigin, hovelAngles, inverseNormal;
- if( self->active )
- {
- //this hovel is in use
- G_TriggerMenu( activator->client->ps.clientNum, MN_A_HOVEL_OCCUPIED );
- }
- else if( ( activator->client->ps.stats[ STAT_PCLASS ] == PCL_A_B_BASE ) ||
- ( activator->client->ps.stats[ STAT_PCLASS ] == PCL_A_B_LEV1 ) )
+ if( self->spawned )
{
- self->active = qtrue;
- G_setBuildableAnim( self, BANIM_ATTACK1, qfalse );
+ if( self->active )
+ {
+ //this hovel is in use
+ G_TriggerMenu( activator->client->ps.clientNum, MN_A_HOVEL_OCCUPIED );
+ }
+ else if( ( activator->client->ps.stats[ STAT_PCLASS ] == PCL_A_B_BASE ) ||
+ ( activator->client->ps.stats[ STAT_PCLASS ] == PCL_A_B_LEV1 ) )
+ {
+ self->active = qtrue;
+ G_setBuildableAnim( self, BANIM_ATTACK1, qfalse );
- //prevent lerping
- activator->client->ps.eFlags ^= EF_TELEPORT_BIT;
-
- activator->client->sess.sessionTeam = TEAM_FREE;
- activator->client->ps.stats[ STAT_STATE ] |= SS_HOVELING;
- activator->client->infestBody = self;
- self->builder = activator;
+ //prevent lerping
+ activator->client->ps.eFlags ^= EF_TELEPORT_BIT;
+
+ activator->client->sess.sessionTeam = TEAM_FREE;
+ activator->client->ps.stats[ STAT_STATE ] |= SS_HOVELING;
+ activator->client->infestBody = self;
+ self->builder = activator;
- VectorCopy( self->s.pos.trBase, hovelOrigin );
- VectorMA( hovelOrigin, 128.0f, self->s.origin2, hovelOrigin );
+ VectorCopy( self->s.pos.trBase, hovelOrigin );
+ VectorMA( hovelOrigin, 128.0f, self->s.origin2, hovelOrigin );
- VectorCopy( self->s.origin2, inverseNormal );
- VectorInverse( inverseNormal );
- vectoangles( inverseNormal, hovelAngles );
+ VectorCopy( self->s.origin2, inverseNormal );
+ VectorInverse( inverseNormal );
+ vectoangles( inverseNormal, hovelAngles );
- VectorCopy( activator->s.pos.trBase, activator->client->hovelOrigin );
+ VectorCopy( activator->s.pos.trBase, activator->client->hovelOrigin );
- G_SetOrigin( activator, hovelOrigin );
- VectorCopy( hovelOrigin, activator->client->ps.origin );
- SetClientViewAngle( activator, hovelAngles );
+ G_SetOrigin( activator, hovelOrigin );
+ VectorCopy( hovelOrigin, activator->client->ps.origin );
+ SetClientViewAngle( activator, hovelAngles );
+ }
}
}
@@ -807,10 +821,13 @@ Think for alien hovel
*/
void AHovel_Think( gentity_t *self )
{
- if( self->active )
- G_setIdleBuildableAnim( self, BANIM_IDLE2 );
- else
- G_setIdleBuildableAnim( self, BANIM_IDLE1 );
+ if( self->spawned )
+ {
+ if( self->active )
+ G_setIdleBuildableAnim( self, BANIM_IDLE2 );
+ else
+ G_setIdleBuildableAnim( self, BANIM_IDLE1 );
+ }
creepSlow( self->s.modelindex, self->s.origin );
@@ -892,6 +909,9 @@ void ABooster_Touch( gentity_t *self, gentity_t *other, trace_t *trace )
int ammo, clips, maxClips;
gclient_t *client = other->client;
+ if( !self->spawned )
+ return;
+
if( !client )
return;
@@ -1056,17 +1076,20 @@ void ATrapper_Think( gentity_t *self )
return;
}
- //if the current target is not valid find a new one
- if( !adef_checktarget( self, self->enemy, range ) )
- adef_findenemy( self, range );
+ if( self->spawned )
+ {
+ //if the current target is not valid find a new one
+ if( !adef_checktarget( self, self->enemy, range ) )
+ adef_findenemy( self, range );
- //if a new target cannot be found don't do anything
- if( !self->enemy )
- return;
-
- //if we are pointing at our target and we can fire shoot it
- if( self->count < level.time )
- adef_fireonenemy( self, firespeed );
+ //if a new target cannot be found don't do anything
+ if( !self->enemy )
+ return;
+
+ //if we are pointing at our target and we can fire shoot it
+ if( self->count < level.time )
+ adef_fireonenemy( self, firespeed );
+ }
}
@@ -1087,15 +1110,18 @@ void HRpt_Think( gentity_t *self )
int i;
qboolean reactor = qfalse;
gentity_t *ent;
-
- //iterate through entities
- for ( i = 1, ent = g_entities + i; i < level.num_entities; i++, ent++ )
+
+ if( self->spawned )
{
- if( !ent->classname || ent->s.eType != ET_BUILDABLE )
- continue;
+ //iterate through entities
+ for ( i = 1, ent = g_entities + i; i < level.num_entities; i++, ent++ )
+ {
+ if( !ent->classname || ent->s.eType != ET_BUILDABLE )
+ continue;
- if( ent->s.modelindex == BA_H_REACTOR )
- reactor = qtrue;
+ if( ent->s.modelindex == BA_H_REACTOR )
+ reactor = qtrue;
+ }
}
self->powered = reactor;
@@ -1117,6 +1143,9 @@ void HRpt_Use( gentity_t *self, gentity_t *other, gentity_t *activator )
playerState_t *ps = &activator->client->ps;
+ if( !self->spawned )
+ return;
+
if( activator->client->lastRefilTime + ENERGY_REFIL_TIME > level.time )
return;
@@ -1162,14 +1191,18 @@ Called when a human activates an Armoury
*/
void HArmoury_Activate( gentity_t *self, gentity_t *other, gentity_t *activator )
{
- //only humans can activate this
- if( activator->client->ps.stats[ STAT_PTEAM ] != PTE_HUMANS ) return;
-
- //if this is powered then call the armoury menu
- if( self->powered )
- G_TriggerMenu( activator->client->ps.clientNum, MN_H_ARMOURY );
- else
- G_TriggerMenu( activator->client->ps.clientNum, MN_H_NOPOWER );
+ if( self->spawned )
+ {
+ //only humans can activate this
+ if( activator->client->ps.stats[ STAT_PTEAM ] != PTE_HUMANS )
+ return;
+
+ //if this is powered then call the armoury menu
+ if( self->powered )
+ G_TriggerMenu( activator->client->ps.clientNum, MN_H_ARMOURY );
+ else
+ G_TriggerMenu( activator->client->ps.clientNum, MN_H_NOPOWER );
+ }
}
/*
@@ -1203,14 +1236,18 @@ Called when a human activates a Bank
*/
void HBank_Activate( gentity_t *self, gentity_t *other, gentity_t *activator )
{
- //only humans can activate this
- if( activator->client->ps.stats[ STAT_PTEAM ] != PTE_HUMANS ) return;
-
- //if this is powered then call the bank menu
- if( self->powered )
- G_TriggerMenu( activator->client->ps.clientNum, MN_H_BANK );
- else
- G_TriggerMenu( activator->client->ps.clientNum, MN_H_NOPOWER );
+ if( self->spawned )
+ {
+ //only humans can activate this
+ if( activator->client->ps.stats[ STAT_PTEAM ] != PTE_HUMANS )
+ return;
+
+ //if this is powered then call the bank menu
+ if( self->powered )
+ G_TriggerMenu( activator->client->ps.clientNum, MN_H_BANK );
+ else
+ G_TriggerMenu( activator->client->ps.clientNum, MN_H_NOPOWER );
+ }
}
/*
@@ -1272,6 +1309,8 @@ void HMedistat_Think( gentity_t *self )
int healCount = 0;
int maxclients;
+ self->nextthink = level.time + BG_FindNextThinkForBuildable( self->s.modelindex );
+
//make sure we have power
if( !( self->powered = findPower( self ) ) )
{
@@ -1279,53 +1318,54 @@ void HMedistat_Think( gentity_t *self )
return;
}
- maxclients = MAX_MEDISTAT_CLIENTS;
-
- VectorAdd( self->s.origin, self->r.maxs, maxs );
- VectorAdd( self->s.origin, self->r.mins, mins );
-
- mins[ 2 ] += fabs( self->r.mins[ 2 ] ) + self->r.maxs[ 2 ];
- maxs[ 2 ] += 60; //player height
-
- //if active use the healing idle
- if( self->active )
- G_setIdleBuildableAnim( self, BANIM_IDLE2 );
-
- //do some healage
- num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
- for( i = 0; i < num; i++ )
+ if( self->spawned )
{
- player = &g_entities[ entityList[ i ] ];
+ maxclients = MAX_MEDISTAT_CLIENTS;
- if( player->client && player->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
+ VectorAdd( self->s.origin, self->r.maxs, maxs );
+ VectorAdd( self->s.origin, self->r.mins, mins );
+
+ mins[ 2 ] += fabs( self->r.mins[ 2 ] ) + self->r.maxs[ 2 ];
+ maxs[ 2 ] += 60; //player height
+
+ //if active use the healing idle
+ if( self->active )
+ G_setIdleBuildableAnim( self, BANIM_IDLE2 );
+
+ //do some healage
+ num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
+ for( i = 0; i < num; i++ )
{
- if( player->health < player->client->ps.stats[ STAT_MAX_HEALTH ] &&
- player->client->ps.pm_type != PM_DEAD &&
- healCount < maxclients )
+ player = &g_entities[ entityList[ i ] ];
+
+ if( player->client && player->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
{
- healCount++;
- player->health++;
-
- //start the heal anim
- if( !self->active )
+ if( player->health < player->client->ps.stats[ STAT_MAX_HEALTH ] &&
+ player->client->ps.pm_type != PM_DEAD &&
+ healCount < maxclients )
{
- G_setBuildableAnim( self, BANIM_ATTACK1, qfalse );
- self->active = qtrue;
+ healCount++;
+ player->health++;
+
+ //start the heal anim
+ if( !self->active )
+ {
+ G_setBuildableAnim( self, BANIM_ATTACK1, qfalse );
+ self->active = qtrue;
+ }
}
}
}
- }
- //nothing left to heal so go back to idling
- if( healCount == 0 && self->active )
- {
- G_setBuildableAnim( self, BANIM_CONSTRUCT2, qtrue );
- G_setIdleBuildableAnim( self, BANIM_IDLE1 );
-
- self->active = qfalse;
+ //nothing left to heal so go back to idling
+ if( healCount == 0 && self->active )
+ {
+ G_setBuildableAnim( self, BANIM_CONSTRUCT2, qtrue );
+ G_setIdleBuildableAnim( self, BANIM_IDLE1 );
+
+ self->active = qfalse;
+ }
}
-
- self->nextthink = level.time + BG_FindNextThinkForBuildable( self->s.modelindex );
}
@@ -1607,40 +1647,43 @@ void HDef_Think( gentity_t *self )
return;
}
- //find a dcc for self
- self->dcced = findDCC( self );
-
- //if the current target is not valid find a new one
- if( !HDef_CheckTarget( self, self->enemy, range ) )
+ if( self->spawned )
{
- if( self->enemy )
- self->enemy->targeted = NULL;
+ //find a dcc for self
+ self->dcced = findDCC( self );
+
+ //if the current target is not valid find a new one
+ if( !HDef_CheckTarget( self, self->enemy, range ) )
+ {
+ if( self->enemy )
+ self->enemy->targeted = NULL;
- HDef_FindEnemy( self, range );
- }
+ HDef_FindEnemy( self, range );
+ }
- //if a new target cannot be found don't do anything
- if( !self->enemy )
- return;
-
- self->enemy->targeted = self;
+ //if a new target cannot be found don't do anything
+ if( !self->enemy )
+ return;
+
+ self->enemy->targeted = self;
- //if we are pointing at our target and we can fire shoot it
- switch( self->s.modelindex )
- {
- case BA_H_MGTURRET:
- if( HMGTurret_TrackEnemy( self ) && ( self->count < level.time ) )
- HMGTurret_FireOnEnemy( self, firespeed );
- break;
-
- case BA_H_TESLAGEN:
- if( self->count < level.time )
- HTeslaGen_FireOnEnemy( self, firespeed );
- break;
+ //if we are pointing at our target and we can fire shoot it
+ switch( self->s.modelindex )
+ {
+ case BA_H_MGTURRET:
+ if( HMGTurret_TrackEnemy( self ) && ( self->count < level.time ) )
+ HMGTurret_FireOnEnemy( self, firespeed );
+ break;
+
+ case BA_H_TESLAGEN:
+ if( self->count < level.time )
+ HTeslaGen_FireOnEnemy( self, firespeed );
+ break;
- default:
- Com_Printf( S_COLOR_YELLOW "WARNING: Unknown turret type in think\n" );
- break;
+ default:
+ Com_Printf( S_COLOR_YELLOW "WARNING: Unknown turret type in think\n" );
+ break;
+ }
}
}
@@ -1970,6 +2013,10 @@ gentity_t *G_buildItem( gentity_t *builder, buildable_t buildable, vec3_t origin
G_setIdleBuildableAnim( built, BG_FindAnimForBuildable( buildable ) );
built->nextthink = BG_FindNextThinkForBuildable( buildable );
+
+ built->takedamage = qfalse;
+ built->spawned = qfalse;
+ built->buildTime = level.time;
//things that vary for each buildable that aren't in the dbase
switch( buildable )
@@ -2074,7 +2121,6 @@ gentity_t *G_buildItem( gentity_t *builder, buildable_t buildable, vec3_t origin
break;
}
- built->takedamage = qtrue;
built->s.number = built - g_entities;
built->r.contents = CONTENTS_BODY;
built->clipmask = MASK_PLAYERSOLID;
@@ -2109,7 +2155,7 @@ gentity_t *G_buildItem( gentity_t *builder, buildable_t buildable, vec3_t origin
VectorSet( normal, 0.0f, 0.0f, 1.0f );
built->s.generic1 = (int)( ( (float)built->health /
- (float)BG_FindHealthForBuildable( buildable ) ) * 63.0f );
+ (float)BG_FindHealthForBuildable( buildable ) ) * B_HEALTH_SCALE );
if( built->s.generic1 < 0 )
built->s.generic1 = 0;
@@ -2120,6 +2166,8 @@ gentity_t *G_buildItem( gentity_t *builder, buildable_t buildable, vec3_t origin
if( built->dcced = findDCC( built ) )
built->s.generic1 |= B_DCCED_TOGGLEBIT;
+ built->s.generic1 &= ~B_SPAWNED_TOGGLEBIT;
+
VectorCopy( normal, built->s.origin2 );
G_AddEvent( built, EV_BUILD_CONSTRUCT, BANIM_CONSTRUCT1 );
@@ -2224,16 +2272,21 @@ void FinishSpawningBuildable( gentity_t *ent )
built = G_buildItem( ent, buildable, ent->s.pos.trBase, ent->s.angles );
G_FreeEntity( ent );
+ built->takedamage = qtrue;
+ built->spawned = qtrue; //map entities are already spawned
+ built->s.generic1 |= B_SPAWNED_TOGGLEBIT;
+
// drop to floor
if( buildable != BA_NONE && BG_FindTrajectoryForBuildable( buildable ) == TR_BUOYANCY )
- VectorSet( dest, built->s.origin[0], built->s.origin[1], built->s.origin[2] + 4096 );
+ VectorSet( dest, built->s.origin[ 0 ], built->s.origin[ 1 ], built->s.origin[ 2 ] + 4096 );
else
- VectorSet( dest, built->s.origin[0], built->s.origin[1], built->s.origin[2] - 4096 );
+ VectorSet( dest, built->s.origin[ 0 ], built->s.origin[ 1 ], built->s.origin[ 2 ] - 4096 );
trap_Trace( &tr, built->s.origin, built->r.mins, built->r.maxs, dest, built->s.number, built->clipmask );
+
if( tr.startsolid )
{
- G_Printf ("FinishSpawningBuildable: %s startsolid at %s\n", built->classname, vtos(built->s.origin));
+ G_Printf( "FinishSpawningBuildable: %s startsolid at %s\n", built->classname, vtos( built->s.origin ) );
G_FreeEntity( built );
return;
}