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.c194
1 files changed, 134 insertions, 60 deletions
diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c
index a7661ed8..5eb95341 100644
--- a/src/game/g_buildable.c
+++ b/src/game/g_buildable.c
@@ -86,12 +86,11 @@ qboolean findPower( gentity_t *self )
continue;
//if entity is a power item calculate the distance to it
- if( !Q_stricmp( ent->classname, "team_human_reactor" ) ||
- !Q_stricmp( ent->classname, "team_human_repeater" ) )
+ if( ent->s.clientNum == BA_H_REACTOR || ent->s.clientNum == BA_H_REPEATER )
{
VectorSubtract( self->s.origin, ent->s.origin, temp_v );
distance = VectorLength( temp_v );
- if( distance < minDistance && ( ent->active || !Q_stricmp( self->classname, "team_human_spawn" ) ) )
+ if( distance < minDistance && ( ent->active || self->s.clientNum == BA_H_SPAWN ) )
{
closestPower = ent;
minDistance = distance;
@@ -105,22 +104,11 @@ qboolean findPower( gentity_t *self )
return qfalse;
//bleh
- if( (
- !Q_stricmp( closestPower->classname, "team_human_reactor" ) &&
- ( minDistance <= REACTOR_BASESIZE )
- ) ||
- (
- !Q_stricmp( closestPower->classname, "team_human_repeater" ) &&
- !Q_stricmp( self->classname, "team_human_spawn" ) &&
- ( minDistance <= REPEATER_BASESIZE ) &&
- closestPower->powered
- ) ||
- (
- !Q_stricmp( closestPower->classname, "team_human_repeater" ) &&
- ( minDistance <= REPEATER_BASESIZE ) &&
- closestPower->active &&
- closestPower->powered
- )
+ if( ( closestPower->s.clientNum == BA_H_REACTOR && ( minDistance <= REACTOR_BASESIZE ) ) ||
+ ( closestPower->s.clientNum == BA_H_REPEATER && self->s.clientNum == BA_H_SPAWN &&
+ ( minDistance <= REPEATER_BASESIZE ) && closestPower->powered ) ||
+ ( closestPower->s.clientNum == BA_H_REPEATER && ( minDistance <= REPEATER_BASESIZE ) &&
+ closestPower->active && closestPower->powered )
)
{
self->parentNode = closestPower;
@@ -133,6 +121,59 @@ qboolean findPower( gentity_t *self )
/*
================
+findDCC
+
+attempt to find a controlling DCC for self, return qtrue if successful
+================
+*/
+qboolean findDCC( gentity_t *self )
+{
+ int i;
+ gentity_t *ent;
+ gentity_t *closestDCC;
+ int distance = 0;
+ int minDistance = 10000;
+ vec3_t temp_v;
+ qboolean foundDCC = qfalse;
+
+ //if this already has dcc then stop now
+ if( self->dccNode && self->dccNode->powered )
+ return qtrue;
+
+ //reset parent
+ self->dccNode = NULL;
+
+ //iterate through entities
+ for( i = 1, ent = g_entities + i; i < level.num_entities; i++, ent++ )
+ {
+ if( !ent->classname )
+ continue;
+
+ //if entity is a power item calculate the distance to it
+ if( ent->s.clientNum == BA_H_DCC )
+ {
+ VectorSubtract( self->s.origin, ent->s.origin, temp_v );
+ distance = VectorLength( temp_v );
+ if( distance < minDistance && ent->powered )
+ {
+ closestDCC = ent;
+ minDistance = distance;
+ foundDCC = qtrue;
+ }
+ }
+ }
+
+ //if there were no power items nearby give up
+ if( !foundDCC )
+ return qfalse;
+
+ self->dccNode = closestDCC;
+
+ return qtrue;
+}
+
+/*
+================
findCreep
attempt to find creep for self, return qtrue if successful
@@ -152,8 +193,7 @@ qboolean findCreep( gentity_t *self )
{
for ( i = 1, ent = g_entities + i; i < level.num_entities; i++, ent++ )
{
- if( !Q_stricmp( ent->classname, "team_droid_spawn" ) ||
- !Q_stricmp( ent->classname, "team_droid_hivemind" ) )
+ if( ent->s.clientNum == BA_D_SPAWN || ent->s.clientNum == BA_D_HIVEMIND )
{
VectorSubtract( self->s.origin, ent->s.origin, temp_v );
distance = VectorLength( temp_v );
@@ -312,7 +352,7 @@ void DSpawn_Die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
self->die = nullDieFunction;
self->think = DSpawn_Blast;
- self->nextthink = level.time + 1500; //wait .5 seconds before damaging others
+ self->nextthink = level.time + 15000; //wait .5 seconds before damaging others
trap_LinkEntity( self );
}
@@ -405,7 +445,7 @@ void DBarricade_Die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker,
self->die = nullDieFunction;
self->think = DBarricade_Blast;
- self->nextthink = level.time + 1500;
+ self->nextthink = level.time + 15000;
trap_LinkEntity( self );
}
@@ -664,10 +704,10 @@ void HRpt_Think( gentity_t *self )
//iterate through entities
for ( i = 1, ent = g_entities + i; i < level.num_entities; i++, ent++ )
{
- if( !Q_stricmp( ent->classname, "team_human_spawn" ) && ent->parentNode == self )
+ if( ent->s.clientNum == BA_H_SPAWN && ent->parentNode == self )
count++;
- if( !Q_stricmp( ent->classname, "team_human_reactor" ) )
+ if( ent->s.clientNum == BA_H_REACTOR )
reactor = qtrue;
}
@@ -730,6 +770,29 @@ void HMCU_Think( gentity_t *self )
+
+/*
+================
+HDCC_Think
+
+Think for dcc
+================
+*/
+void HDCC_Think( gentity_t *self )
+{
+ //make sure we have power
+ self->nextthink = level.time + REFRESH_TIME;
+
+ self->powered = findPower( self );
+}
+
+
+
+
+//==================================================================================
+
+
+
/*
================
HFM_Touch
@@ -840,25 +903,26 @@ qboolean hdef1_trackenemy( gentity_t *self )
VectorSubtract( dirToTarget, self->s.pos.trBase, dirToTarget );
#endif
-//better, but more expensive method
-#if 0
- VectorScale( self->enemy->acceleration, 1.0f / 2.0f, halfAcceleration );
- VectorScale( self->enemy->jerk, 1.0f / 3.0f, thirdJerk );
-
- //O( time ) - worst case O( time ) = 250 iterations
- for( i = 0; ( i * HDEF1_PROJSPEED ) / 1000.0f < distanceToTarget; i++ )
+ //better, but more expensive method
+ if( self->dcced )
{
- float time = (float)i / 1000.0f;
+ VectorScale( self->enemy->acceleration, 1.0f / 2.0f, halfAcceleration );
+ VectorScale( self->enemy->jerk, 1.0f / 3.0f, thirdJerk );
+
+ //O( time ) - worst case O( time ) = 250 iterations
+ for( i = 0; ( i * HDEF1_PROJSPEED ) / 1000.0f < distanceToTarget; i++ )
+ {
+ float time = (float)i / 1000.0f;
- VectorMA( self->enemy->s.pos.trBase, time, self->enemy->s.pos.trDelta, dirToTarget );
- VectorMA( dirToTarget, time * time, halfAcceleration, dirToTarget );
- VectorMA( dirToTarget, time * time * time, thirdJerk, dirToTarget );
- VectorSubtract( dirToTarget, self->s.pos.trBase, dirToTarget );
- distanceToTarget = VectorLength( dirToTarget );
+ VectorMA( self->enemy->s.pos.trBase, time, self->enemy->s.pos.trDelta, dirToTarget );
+ VectorMA( dirToTarget, time * time, halfAcceleration, dirToTarget );
+ VectorMA( dirToTarget, time * time * time, thirdJerk, dirToTarget );
+ VectorSubtract( dirToTarget, self->s.pos.trBase, dirToTarget );
+ distanceToTarget = VectorLength( dirToTarget );
- distanceToTarget -= self->enemy->r.maxs[ 0 ];
+ distanceToTarget -= self->enemy->r.maxs[ 0 ];
+ }
}
-#endif
VectorNormalize( dirToTarget );
@@ -1066,13 +1130,15 @@ qboolean hdef_checktarget( gentity_t *self, gentity_t *target, int range )
return qfalse;
if( target->health <= 0 ) // is the target still alive?
return qfalse;
+ if( self->dcced && target->targeted && target->targeted->powered ) //some turret has already selected this target
+ return qfalse;
VectorSubtract( target->r.currentOrigin, self->r.currentOrigin, distance );
if( VectorLength( distance ) > range ) // is the target within range?
return qfalse;
- trap_Trace( &trace, self->s.pos.trBase, NULL, NULL, target->s.pos.trBase, self->s.number, MASK_SHOT );
- if ( trace.contents & CONTENTS_SOLID ) // can we see the target?
+ trap_Trace( &trace, self->s.pos.trBase, NULL, NULL, target->s.pos.trBase, self->s.number, MASK_OPAQUE );
+ if( trace.fraction < 1.0 ) // can we see the target?
return qfalse;
return qtrue;
@@ -1090,10 +1156,8 @@ void hdef_findenemy( gentity_t *ent, int range )
{
gentity_t *target;
- target = g_entities;
-
//iterate through entities
- for (; target < &g_entities[ level.num_entities ]; target++)
+ for( target = g_entities; target < &g_entities[ level.num_entities ]; target++ )
{
//if target is not valid keep searching
if( !hdef_checktarget( ent, target, range ) )
@@ -1133,14 +1197,24 @@ 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->enemy )
+ self->enemy->targeted = NULL;
+
hdef_findenemy( self, range );
+ }
//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.clientNum )
{
@@ -1218,7 +1292,8 @@ void HSpawn_Die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
self->die = nullDieFunction;
self->think = HSpawn_Blast;
- self->nextthink = level.time + 1500; //wait 1.5 seconds before damaging others
+ self->nextthink = level.time + 15000; //wait 1.5 seconds before damaging others
+ self->powered = qfalse; //free up power
trap_LinkEntity( self );
}
@@ -1292,8 +1367,7 @@ itemBuildError_t G_itemFits( gentity_t *ent, buildable_t buildable, int distance
{
for ( i = 1, tempent = g_entities + i; i < level.num_entities; i++, tempent++ )
{
- if( !Q_stricmp( tempent->classname, "team_droid_spawn" ) ||
- !Q_stricmp( tempent->classname, "team_droid_hivemind" ) )
+ if( tempent->s.clientNum == BA_D_SPAWN || tempent->s.clientNum == BA_D_HIVEMIND )
{
VectorSubtract( entity_origin, tempent->s.origin, temp_v );
if( VectorLength( temp_v ) <= ( CREEP_BASESIZE * 3 ) )
@@ -1308,7 +1382,7 @@ itemBuildError_t G_itemFits( gentity_t *ent, buildable_t buildable, int distance
//look for a hivemind
for ( i = 1, tempent = g_entities + i; i < level.num_entities; i++, tempent++ )
{
- if( !Q_stricmp( tempent->classname, "team_droid_hivemind" ) )
+ if( tempent->s.clientNum == BA_D_HIVEMIND )
break;
}
@@ -1326,7 +1400,7 @@ itemBuildError_t G_itemFits( gentity_t *ent, buildable_t buildable, int distance
{
for ( i = 1, tempent = g_entities + i; i < level.num_entities; i++, tempent++ )
{
- if( !Q_stricmp( tempent->classname, "team_droid_hivemind" ) )
+ if( tempent->s.clientNum == BA_D_HIVEMIND )
{
reason = IBE_HIVEMIND;
break;
@@ -1346,8 +1420,7 @@ itemBuildError_t G_itemFits( gentity_t *ent, buildable_t buildable, int distance
//find the nearest power entity
for ( i = 1, tempent = g_entities + i; i < level.num_entities; i++, tempent++ )
{
- if( !Q_stricmp( tempent->classname, "team_human_reactor" ) ||
- !Q_stricmp( tempent->classname, "team_human_repeater" ) )
+ if( tempent->s.clientNum == BA_H_REACTOR || tempent->s.clientNum == BA_H_REPEATER )
{
VectorSubtract( entity_origin, tempent->s.origin, temp_v );
templength = VectorLength( temp_v );
@@ -1361,13 +1434,9 @@ itemBuildError_t G_itemFits( gentity_t *ent, buildable_t buildable, int distance
//if this power entity satisfies expression
if( !(
+ ( closestPower->s.clientNum == BA_H_REACTOR && minDistance <= REACTOR_BASESIZE ) ||
(
- !Q_stricmp( closestPower->classname, "team_human_reactor" ) &&
- minDistance <= REACTOR_BASESIZE
- ) ||
- (
- !Q_stricmp( closestPower->classname, "team_human_repeater" ) &&
- minDistance <= REPEATER_BASESIZE &&
+ closestPower->s.clientNum == BA_H_REPEATER && minDistance <= REPEATER_BASESIZE &&
(
( buildable == BA_H_SPAWN && closestPower->powered ) ||
( closestPower->powered && closestPower->active )
@@ -1390,7 +1459,7 @@ itemBuildError_t G_itemFits( gentity_t *ent, buildable_t buildable, int distance
{
for ( i = 1, tempent = g_entities + i; i < level.num_entities; i++, tempent++ )
{
- if( !Q_stricmp( tempent->classname, "team_human_reactor" ) )
+ if( tempent->s.clientNum == BA_H_REACTOR )
break;
}
@@ -1403,7 +1472,7 @@ itemBuildError_t G_itemFits( gentity_t *ent, buildable_t buildable, int distance
{
for ( i = 1, tempent = g_entities + i; i < level.num_entities; i++, tempent++ )
{
- if( !Q_stricmp( tempent->classname, "team_human_reactor" ) )
+ if( tempent->s.clientNum == BA_H_REACTOR )
{
reason = IBE_REACTOR;
break;
@@ -1518,6 +1587,11 @@ gentity_t *G_buildItem( gentity_t *ent, buildable_t buildable, int distance, flo
built->use = HMCU_Activate;
break;
+ case BA_H_DCC:
+ built->think = HDCC_Think;
+ built->die = HSpawn_Die;
+ break;
+
case BA_H_REACTOR:
built->die = HSpawn_Die;
built->powered = built->active = qtrue;