summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/game/bg_misc.c68
-rw-r--r--src/game/bg_public.h3
-rw-r--r--src/game/g_buildable.c194
-rw-r--r--src/game/g_local.h4
4 files changed, 195 insertions, 74 deletions
diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c
index f688d858..1a94a8c2 100644
--- a/src/game/bg_misc.c
+++ b/src/game/bg_misc.c
@@ -962,6 +962,22 @@ TA: human defense item
"" //sounds
},
+/*QUAKED team_human_dcc (0 0 1) (-16 -16 -16) (16 16 16)
+TA: human defense item
+*/
+ {
+ "team_human_dcc",
+ "sound/items/holdable.wav",
+ { "models/buildables/dcc/dcc.md3", 0, 0, 0 },
+ "icons/teleporter", //icon
+ "Human DCC", //pickup
+ 0,
+ IT_BUILDABLE,
+ BA_H_DCC,
+ "", //precache
+ "" //sounds
+ },
+
/*QUAKED team_human_reactor (0 0 1) (-16 -16 -16) (16 16 16)
TA: human power item
*/
@@ -1160,7 +1176,7 @@ buildableAttributes_t bg_buildableList[ ] =
MOD_DSPAWN, //int meansOfDeath;
BIT_DROIDS, //int team;
( 1 << WP_DBUILD )|( 1 << WP_DBUILD2 ), //weapon_t buildWeapon;
- BANIM_IDLE1, //int constructAnim;
+ BANIM_IDLE1, //int idleAnim;
100, //int nextthink;
0, //int turretFireSpeed;
0, //int turretRange;
@@ -1186,7 +1202,7 @@ buildableAttributes_t bg_buildableList[ ] =
MOD_DSPAWN, //int meansOfDeath;
BIT_DROIDS, //int team;
( 1 << WP_DBUILD )|( 1 << WP_DBUILD2 ), //weapon_t buildWeapon;
- BANIM_IDLE1, //int constructAnim;
+ BANIM_IDLE1, //int idleAnim;
100, //int nextthink;
0, //int turretFireSpeed;
0, //int turretRange;
@@ -1212,7 +1228,7 @@ buildableAttributes_t bg_buildableList[ ] =
MOD_DSPAWN, //int meansOfDeath;
BIT_DROIDS, //int team;
( 1 << WP_DBUILD )|( 1 << WP_DBUILD2 ), //weapon_t buildWeapon;
- BANIM_IDLE1, //int constructAnim;
+ BANIM_IDLE1, //int idleAnim;
500, //int nextthink;
0, //int turretFireSpeed;
0, //int turretRange;
@@ -1238,7 +1254,7 @@ buildableAttributes_t bg_buildableList[ ] =
MOD_DSPAWN, //int meansOfDeath;
BIT_DROIDS, //int team;
( 1 << WP_DBUILD )|( 1 << WP_DBUILD2 ), //weapon_t buildWeapon;
- BANIM_IDLE1, //int constructAnim;
+ BANIM_IDLE1, //int idleAnim;
-1, //int nextthink;
0, //int turretFireSpeed;
0, //int turretRange;
@@ -1264,7 +1280,7 @@ buildableAttributes_t bg_buildableList[ ] =
MOD_HSPAWN, //int meansOfDeath;
BIT_HUMANS, //int team;
( 1 << WP_HBUILD )|( 1 << WP_HBUILD2 ), //weapon_t buildWeapon;
- BANIM_IDLE1, //int constructAnim;
+ BANIM_IDLE1, //int idleAnim;
100, //int nextthink;
0, //int turretFireSpeed;
0, //int turretRange;
@@ -1290,7 +1306,7 @@ buildableAttributes_t bg_buildableList[ ] =
MOD_HSPAWN, //int meansOfDeath;
BIT_HUMANS, //int team;
( 1 << WP_HBUILD )|( 1 << WP_HBUILD2 ), //weapon_t buildWeapon;
- BANIM_IDLE1, //int constructAnim;
+ BANIM_IDLE1, //int idleAnim;
50, //int nextthink;
500, //int turretFireSpeed;
500, //int turretRange;
@@ -1316,7 +1332,7 @@ buildableAttributes_t bg_buildableList[ ] =
MOD_HSPAWN, //int meansOfDeath;
BIT_HUMANS, //int team;
( 1 << WP_HBUILD )|( 1 << WP_HBUILD2 ), //weapon_t buildWeapon;
- BANIM_IDLE1, //int constructAnim;
+ BANIM_IDLE1, //int idleAnim;
50, //int nextthink;
50, //int turretFireSpeed;
300, //int turretRange;
@@ -1342,7 +1358,7 @@ buildableAttributes_t bg_buildableList[ ] =
MOD_HSPAWN, //int meansOfDeath;
BIT_HUMANS, //int team;
( 1 << WP_HBUILD )|( 1 << WP_HBUILD2 ), //weapon_t buildWeapon;
- BANIM_IDLE1, //int constructAnim;
+ BANIM_IDLE1, //int idleAnim;
150, //int nextthink;
4000, //int turretFireSpeed;
1500, //int turretRange;
@@ -1353,6 +1369,32 @@ buildableAttributes_t bg_buildableList[ ] =
qfalse //qboolean reactorTest;
},
{
+ BA_H_DCC, //int buildNum;
+ "dcc", //char *buildName;
+ "team_human_dcc", //char *entityName;
+ { -15, -15, -15 }, //vec3_t mins;
+ { 15, 15, 15 }, //vec3_t maxs;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ 200, //int buildPoints;
+ 1000, //int health;
+ 50, //int damage;
+ 50, //int splashDamage;
+ 150, //int splashRadius;
+ MOD_HSPAWN, //int meansOfDeath;
+ BIT_HUMANS, //int team;
+ ( 1 << WP_HBUILD )|( 1 << WP_HBUILD2 ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 100, //int nextthink;
+ 0, //int turretFireSpeed;
+ 0, //int turretRange;
+ WP_NONE, //weapon_t turretProjType;
+ 0.707f, //float minNormal;
+ qfalse, //qboolean invertNormal;
+ qfalse, //qboolean creepTest;
+ qfalse //qboolean reactorTest;
+ },
+ {
BA_H_MCU, //int buildNum;
"mcu", //char *buildName;
"team_human_mcu", //char *entityName;
@@ -1368,7 +1410,7 @@ buildableAttributes_t bg_buildableList[ ] =
MOD_HSPAWN, //int meansOfDeath;
BIT_HUMANS, //int team;
( 1 << WP_HBUILD )|( 1 << WP_HBUILD2 ), //weapon_t buildWeapon;
- BANIM_IDLE1, //int constructAnim;
+ BANIM_IDLE1, //int idleAnim;
100, //int nextthink;
0, //int turretFireSpeed;
0, //int turretRange;
@@ -1394,7 +1436,7 @@ buildableAttributes_t bg_buildableList[ ] =
MOD_HSPAWN, //int meansOfDeath;
BIT_HUMANS, //int team;
( 1 << WP_HBUILD )|( 1 << WP_HBUILD2 ), //weapon_t buildWeapon;
- BANIM_IDLE1, //int constructAnim;
+ BANIM_IDLE1, //int idleAnim;
-1, //int nextthink;
0, //int turretFireSpeed;
0, //int turretRange;
@@ -1420,7 +1462,7 @@ buildableAttributes_t bg_buildableList[ ] =
MOD_HSPAWN, //int meansOfDeath;
BIT_HUMANS, //int team;
( 1 << WP_HBUILD )|( 1 << WP_HBUILD2 ), //weapon_t buildWeapon;
- BANIM_IDLE1, //int constructAnim;
+ BANIM_IDLE1, //int idleAnim;
100, //int nextthink;
0, //int turretFireSpeed;
0, //int turretRange;
@@ -1446,7 +1488,7 @@ buildableAttributes_t bg_buildableList[ ] =
MOD_HSPAWN, //int meansOfDeath;
BIT_HUMANS, //int team;
( 1 << WP_HBUILD )|( 1 << WP_HBUILD2 ), //weapon_t buildWeapon;
- BANIM_IDLE1, //int constructAnim;
+ BANIM_IDLE1, //int idleAnim;
100, //int nextthink;
0, //int turretFireSpeed;
0, //int turretRange;
@@ -1779,7 +1821,7 @@ int BG_FindAnimForBuildable( int bclass )
{
if( bg_buildableList[ i ].buildNum == bclass )
{
- return bg_buildableList[ i ].constructAnim;
+ return bg_buildableList[ i ].idleAnim;
}
}
diff --git a/src/game/bg_public.h b/src/game/bg_public.h
index b6e1e6fa..c40ed9d7 100644
--- a/src/game/bg_public.h
+++ b/src/game/bg_public.h
@@ -402,6 +402,7 @@ typedef enum {
BA_H_DEF3,
BA_H_MCU,
+ BA_H_DCC,
BA_H_REACTOR,
BA_H_REPEATER,
@@ -860,7 +861,7 @@ typedef struct
int team;
weapon_t buildWeapon;
- int constructAnim;
+ int idleAnim;
int nextthink;
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;
diff --git a/src/game/g_local.h b/src/game/g_local.h
index 633c29e9..634f956c 100644
--- a/src/game/g_local.h
+++ b/src/game/g_local.h
@@ -185,11 +185,15 @@ struct gentity_s {
qboolean active; //TA: for power repeater, but could be useful elsewhere
qboolean powered; //TA: for human buildables
int builtBy; //TA: clientNum of person that built this
+ gentity_t *dccNode; //TA: controlling dcc
+ qboolean dcced; //TA: controlled by a dcc or not?
int credits[ MAX_CLIENTS ]; //TA: human credits for each client
qboolean creditsHash[ MAX_CLIENTS ]; //TA: track who has claimed credit
int killedBy; //TA: clientNum of killer
+ gentity_t *targeted; //TA: true if the player is currently a valid target of a turret
+
vec4_t animation; //TA: animated map objects
};