summaryrefslogtreecommitdiff
path: root/src/game
diff options
context:
space:
mode:
Diffstat (limited to 'src/game')
-rw-r--r--src/game/bg_pmove.c3
-rw-r--r--src/game/g_buildable.c130
-rw-r--r--src/game/g_client.c2
-rw-r--r--src/game/g_local.h3
-rw-r--r--src/game/g_main.c32
-rw-r--r--src/game/g_physics.c21
-rw-r--r--src/game/tremulous.h41
7 files changed, 164 insertions, 68 deletions
diff --git a/src/game/bg_pmove.c b/src/game/bg_pmove.c
index 26a95255..77692398 100644
--- a/src/game/bg_pmove.c
+++ b/src/game/bg_pmove.c
@@ -1926,7 +1926,7 @@ static void PM_GroundClimbTrace( void )
vectoangles( trace.plane.normal, toAngles );
vectoangles( pm->ps->grapplePoint, surfAngles );
- pm->ps->delta_angles[ 1 ] -= ANGLE2SHORT( ( ( surfAngles[ 1 ] - toAngles[ 1 ] ) * 2 ) - 180 );
+ pm->ps->delta_angles[ 1 ] -= ANGLE2SHORT( ( ( surfAngles[ 1 ] - toAngles[ 1 ] ) * 2 ) - 180.0f );
}
}
@@ -1949,7 +1949,6 @@ static void PM_GroundClimbTrace( void )
else if( trace.allsolid )
{
// do something corrective if the trace starts in a solid...
- //TA: fuck knows what this does with all my new stuff :(
if( !PM_CorrectAllSolid( &trace ) )
return;
}
diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c
index a525ae9c..7035ec18 100644
--- a/src/game/g_buildable.c
+++ b/src/game/g_buildable.c
@@ -268,6 +268,62 @@ static qboolean isDCC( )
/*
================
+findOvermind
+
+Attempt to find an overmind for self
+================
+*/
+static qboolean findOvermind( gentity_t *self )
+{
+ int i;
+ gentity_t *ent;
+ gentity_t *closestOvermind;
+ int distance = 0;
+ int minDistance = 10000;
+ vec3_t temp_v;
+ qboolean foundOvermind = qfalse;
+
+ if( self->biteam != BIT_ALIENS )
+ return qfalse;
+
+ //if this already has dcc then stop now
+ if( self->overmindNode )
+ return qtrue;
+
+ //reset parent
+ self->overmindNode = NULL;
+
+ //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 entity is a dcc calculate the distance to it
+ if( ent->s.modelindex == BA_A_OVERMIND && ent->spawned )
+ {
+ VectorSubtract( self->s.origin, ent->s.origin, temp_v );
+ distance = VectorLength( temp_v );
+ if( distance < minDistance && ent->powered )
+ {
+ closestOvermind = ent;
+ minDistance = distance;
+ foundOvermind = qtrue;
+ }
+ }
+ }
+
+ //if there were no power items nearby give up
+ if( !foundOvermind )
+ return qfalse;
+
+ self->overmindNode = closestOvermind;
+
+ return qtrue;
+}
+
+/*
+================
findCreep
attempt to find creep for self, return qtrue if successful
@@ -413,7 +469,14 @@ void A_CreepRecede( gentity_t *self )
{
self->s.eFlags |= EF_DEAD;
G_AddEvent( self, EV_BUILD_DESTROY, 0 );
- self->s.time = -level.time;
+
+ if( self->spawned )
+ self->s.time = -level.time;
+ else
+ self->s.time = -( level.time -
+ (int)( (float)CREEP_SCALEDOWN_TIME *
+ ( 1.0f - ( (float)( level.time - self->buildTime ) /
+ (float)BG_FindBuildTimeForBuildable( self->s.modelindex ) ) ) ) );
}
//creep is still receeding
@@ -448,7 +511,14 @@ void ASpawn_Melt( gentity_t *self )
{
self->s.eFlags |= EF_DEAD;
G_AddEvent( self, EV_BUILD_DESTROY, 0 );
- self->s.time = -level.time;
+
+ if( self->spawned )
+ self->s.time = -level.time;
+ else
+ self->s.time = -( level.time -
+ (int)( (float)CREEP_SCALEDOWN_TIME *
+ ( 1.0f - ( (float)( level.time - self->buildTime ) /
+ (float)BG_FindBuildTimeForBuildable( self->s.modelindex ) ) ) ) );
}
//not dead yet
@@ -500,7 +570,12 @@ void ASpawn_Die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
self->die = nullDieFunction;
self->think = ASpawn_Blast;
- self->nextthink = level.time + 5000; //wait .5 seconds before damaging others
+
+ if( self->spawned )
+ self->nextthink = level.time + 5000;
+ else
+ self->nextthink = level.time; //blast immediately
+
self->s.eFlags &= ~EF_FIRING; //prevent any firing effects
if( attacker && attacker->client && attacker->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
@@ -523,7 +598,7 @@ void ASpawn_Think( gentity_t *self )
{
gentity_t *ent;
- if( self->spawned )
+ if( self->spawned )
{
//only suicide if at rest
if( self->s.groundEntityNum )
@@ -706,7 +781,11 @@ void ABarricade_Die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker,
self->die = nullDieFunction;
self->think = ABarricade_Blast;
self->s.eFlags &= ~EF_FIRING; //prevent any firing effects
- self->nextthink = level.time + 5000;
+
+ if( self->spawned )
+ self->nextthink = level.time + 5000;
+ else
+ self->nextthink = level.time; //blast immediately
}
/*
@@ -800,7 +879,7 @@ void AAcidTube_Think( gentity_t *self )
return;
}
- if( self->spawned )
+ if( self->spawned && findOvermind( self ) )
{
//do some damage
num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
@@ -866,7 +945,7 @@ void AHive_Think( gentity_t *self )
if( self->timestamp < level.time )
self->active = qfalse; //nothing has returned in HIVE_REPEAT seconds, forget about it
- if( self->spawned && !self->active )
+ if( self->spawned && !self->active && findOvermind( self ) )
{
//do some damage
num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
@@ -999,7 +1078,7 @@ void AHovel_Use( gentity_t *self, gentity_t *other, gentity_t *activator )
{
vec3_t hovelOrigin, hovelAngles, inverseNormal;
- if( self->spawned )
+ if( self->spawned && findOvermind( self ) )
{
if( self->active )
{
@@ -1142,6 +1221,9 @@ void ABooster_Touch( gentity_t *self, gentity_t *other, trace_t *trace )
if( !self->spawned )
return;
+
+ if( !findOvermind( self ) )
+ return;
if( !client )
return;
@@ -1307,7 +1389,7 @@ void ATrapper_Think( gentity_t *self )
return;
}
- if( self->spawned )
+ if( self->spawned && findOvermind( self ) )
{
//if the current target is not valid find a new one
if( !ADef_CheckTarget( self, self->enemy, range ) )
@@ -1932,9 +2014,13 @@ void HSpawn_Die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
self->die = nullDieFunction;
self->think = HSpawn_Blast;
- self->nextthink = level.time + HUMAN_DETONATION_DELAY;
self->powered = qfalse; //free up power
self->s.eFlags &= ~EF_FIRING; //prevent any firing effects
+
+ if( self->spawned )
+ self->nextthink = level.time + HUMAN_DETONATION_DELAY;
+ else
+ self->nextthink = level.time; //blast immediately
if( attacker && attacker->client && attacker->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS )
{
@@ -1999,17 +2085,15 @@ void G_BuildableThink( gentity_t *ent, int msec )
{
int bHealth = BG_FindHealthForBuildable( ent->s.modelindex );
int bRegen = BG_FindRegenRateForBuildable( ent->s.modelindex );
+ int bTime = BG_FindBuildTimeForBuildable( ent->s.modelindex );
//pack health, power and dcc
//toggle spawned flag for buildables
if( !ent->spawned )
{
- if( ent->buildTime + BG_FindBuildTimeForBuildable( ent->s.modelindex ) < level.time )
- {
- ent->takedamage = qtrue;
+ if( ent->buildTime + bTime < level.time )
ent->spawned = qtrue;
- }
}
ent->s.generic1 = (int)( ( (float)ent->health / (float)bHealth ) * B_HEALTH_SCALE );
@@ -2032,14 +2116,13 @@ void G_BuildableThink( gentity_t *ent, int msec )
{
ent->time1000 -= 1000;
- //regenerate health
- if( ent->health > 0 && ent->health < bHealth && bRegen )
- {
+ if( !ent->spawned )
+ ent->health += (int)( ceil( (float)bHealth / (float)( bTime * 0.001 ) ) );
+ else if( ent->health > 0 && ent->health < bHealth && bRegen )
ent->health += bRegen;
-
- if( ent->health > bHealth )
- ent->health = bHealth;
- }
+
+ if( ent->health > bHealth )
+ ent->health = bHealth;
}
//fall back on normal physics routines
@@ -2306,7 +2389,7 @@ gentity_t *G_buildItem( gentity_t *builder, buildable_t buildable, vec3_t origin
built->biteam = built->s.modelindex2 = BG_FindTeamForBuildable( buildable );
BG_FindBBoxForBuildable( buildable, built->r.mins, built->r.maxs );
- built->health = BG_FindHealthForBuildable( buildable );
+ built->health = 1;
built->splashDamage = BG_FindSplashDamageForBuildable( buildable );
built->splashRadius = BG_FindSplashRadiusForBuildable( buildable );
@@ -2314,7 +2397,7 @@ gentity_t *G_buildItem( gentity_t *builder, buildable_t buildable, vec3_t origin
built->nextthink = BG_FindNextThinkForBuildable( buildable );
- built->takedamage = qfalse;
+ built->takedamage = qtrue;
built->spawned = qfalse;
built->buildTime = built->s.time = level.time;
@@ -2595,6 +2678,7 @@ void FinishSpawningBuildable( gentity_t *ent )
built->takedamage = qtrue;
built->spawned = qtrue; //map entities are already spawned
+ built->health = BG_FindHealthForBuildable( buildable );
built->s.generic1 |= B_SPAWNED_TOGGLEBIT;
// drop to floor
diff --git a/src/game/g_client.c b/src/game/g_client.c
index da1fb811..dc1d37bf 100644
--- a/src/game/g_client.c
+++ b/src/game/g_client.c
@@ -1381,7 +1381,6 @@ void ClientSpawn( gentity_t *ent, gentity_t *spawn, vec3_t origin, vec3_t angles
VectorNormalize( dir );
VectorScale( dir, UP_VEL, client->ps.velocity );
-
}
G_AddPredictableEvent( ent, EV_PLAYER_RESPAWN, 0 );
@@ -1402,7 +1401,6 @@ void ClientSpawn( gentity_t *ent, gentity_t *spawn, vec3_t origin, vec3_t angles
// force the base weapon up
client->ps.weapon = WP_NONE;
client->ps.weaponstate = WEAPON_READY;
-
}
// don't allow full run speed for a bit
diff --git a/src/game/g_local.h b/src/game/g_local.h
index 2cdddf2e..9f267c51 100644
--- a/src/game/g_local.h
+++ b/src/game/g_local.h
@@ -189,6 +189,7 @@ struct gentity_s
qboolean powered; //TA: for human buildables
int builtBy; //TA: clientNum of person that built this
gentity_t *dccNode; //TA: controlling dcc
+ gentity_t *overmindNode;//TA: controlling overmind
qboolean dcced; //TA: controlled by a dcc or not?
qboolean spawned; //TA: whether or not this buildable has finished spawning
int buildTime; //TA: when this buildable was built
@@ -196,6 +197,8 @@ struct gentity_s
int overmindAttackTimer;
int overmindDyingTimer;
int overmindSpawnsTimer;
+ int nextPhysicsTime; //TA: buildables don't need to check what they're sitting on
+ // every single frame.. so only do it periodically
int credits[ MAX_CLIENTS ]; //TA: human credits for each client
qboolean creditsHash[ MAX_CLIENTS ]; //TA: track who has claimed credit
diff --git a/src/game/g_main.c b/src/game/g_main.c
index 0ad46bb9..8656f0f5 100644
--- a/src/game/g_main.c
+++ b/src/game/g_main.c
@@ -680,7 +680,7 @@ void countSpawns( void )
level.numAlienSpawns = 0;
level.numHumanSpawns = 0;
- for ( i = 1, ent = g_entities + i ; i < level.num_entities ; i++, ent++ )
+ for( i = 1, ent = g_entities + i ; i < level.num_entities ; i++, ent++ )
{
if( !ent->inuse )
continue;
@@ -703,34 +703,38 @@ Recalculate the quantity of building points available to the teams
*/
void calculateBuildPoints( void )
{
- int i;
- int bclass;
- gentity_t *ent;
- int localHTP = g_humanBuildPoints.integer,
- localATP = g_alienBuildPoints.integer;
+ int i;
+ int bclass;
+ buildable_t buildable;
+ gentity_t *ent;
+ int localHTP = g_humanBuildPoints.integer,
+ localATP = g_alienBuildPoints.integer;
level.humanBuildPoints = level.humanBuildPointsPowered = localHTP;
level.alienBuildPoints = localATP;
- for ( i = 1, ent = g_entities + i ; i < level.num_entities ; i++, ent++ )
+ for( i = 1, ent = g_entities + i ; i < level.num_entities ; i++, ent++ )
{
- if (!ent->inuse)
+ if( !ent->inuse )
+ continue;
+
+ if( ent->s.eType != ET_BUILDABLE )
continue;
- bclass = BG_FindBuildNumForEntityName( ent->classname );
+ buildable = ent->s.modelindex;
- if( bclass != BA_NONE )
+ if( buildable != BA_NONE )
{
- if( BG_FindTeamForBuildable( bclass ) == BIT_HUMANS )
+ if( BG_FindTeamForBuildable( buildable ) == BIT_HUMANS )
{
- level.humanBuildPoints -= BG_FindBuildPointsForBuildable( bclass );
+ level.humanBuildPoints -= BG_FindBuildPointsForBuildable( buildable );
if( ent->powered )
- level.humanBuildPointsPowered -= BG_FindBuildPointsForBuildable( bclass );
+ level.humanBuildPointsPowered -= BG_FindBuildPointsForBuildable( buildable );
}
else
{
- level.alienBuildPoints -= BG_FindBuildPointsForBuildable( bclass );
+ level.alienBuildPoints -= BG_FindBuildPointsForBuildable( buildable );
}
}
}
diff --git a/src/game/g_physics.c b/src/game/g_physics.c
index a1183ad4..856fcadb 100644
--- a/src/game/g_physics.c
+++ b/src/game/g_physics.c
@@ -68,6 +68,7 @@ static void G_Bounce( gentity_t *ent, trace_t *trace )
ent->s.pos.trTime = level.time;
}
+#define PHYSICS_TIME 200
/*
================
@@ -111,14 +112,20 @@ void G_Physics( gentity_t *ent, int msec )
// check think function
G_RunThink( ent );
- VectorCopy( ent->r.currentOrigin, origin );
+ //check floor infrequently
+ if( ent->nextPhysicsTime < level.time )
+ {
+ VectorCopy( ent->r.currentOrigin, origin );
+
+ VectorMA( origin, -2.0f, ent->s.origin2, origin );
- VectorMA( origin, -2.0f, ent->s.origin2, origin );
+ trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, origin, ent->s.number, mask );
+
+ if( tr.fraction == 1.0f )
+ ent->s.groundEntityNum = -1;
- trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, origin, ent->s.number, mask );
-
- if( tr.fraction == 1.0 )
- ent->s.groundEntityNum = -1;
+ ent->nextPhysicsTime = level.time + PHYSICS_TIME;
+ }
return;
}
@@ -138,7 +145,7 @@ void G_Physics( gentity_t *ent, int msec )
// check think function
G_RunThink( ent );
- if( tr.fraction == 1 )
+ if( tr.fraction == 1.0f )
return;
// if it is in a nodrop volume, remove it
diff --git a/src/game/tremulous.h b/src/game/tremulous.h
index a8960a0e..ccca7044 100644
--- a/src/game/tremulous.h
+++ b/src/game/tremulous.h
@@ -38,7 +38,7 @@
#define ABUILDER_BLOB_TIME 5000
#define SOLDIER_BITE_DMG ADM(60)
-#define SOLDIER_BITE_RANGE 80.0f
+#define SOLDIER_BITE_RANGE 64.0f
#define SOLDIER_BITE_REPEAT 500
#define HYDRA_CLAW_DMG ADM(40)
@@ -189,37 +189,38 @@
#define CREEP_TIMEOUT 1000
#define CREEP_MODIFIER 0.5f
#define CREEP_ARMOUR_MODIFIER 0.75f
+#define CREEP_SCALEDOWN_TIME 3000
#define ASPAWN_BP 100
-#define ASPAWN_BT 10000
+#define ASPAWN_BT 15000
#define ASPAWN_HEALTH ABHM(500)
-#define ASPAWN_REGEN 10
+#define ASPAWN_REGEN 8
#define ASPAWN_SPLASHDAMAGE 50
#define ASPAWN_SPLASHRADIUS 50
#define ASPAWN_CREEPSIZE 120
#define ASPAWN_VALUE 150
#define BARRICADE_BP 80
-#define BARRICADE_BT 10000
+#define BARRICADE_BT 20000
#define BARRICADE_HEALTH ABHM(350)
-#define BARRICADE_REGEN 15
+#define BARRICADE_REGEN 12
#define BARRICADE_SPLASHDAMAGE 50
#define BARRICADE_SPLASHRADIUS 50
#define BARRICADE_CREEPSIZE 120
#define BOOSTER_BP 120
-#define BOOSTER_BT 10000
+#define BOOSTER_BT 15000
#define BOOSTER_HEALTH ABHM(300)
-#define BOOSTER_REGEN 10
+#define BOOSTER_REGEN 8
#define BOOSTER_SPLASHDAMAGE 50
#define BOOSTER_SPLASHRADIUS 50
#define BOOSTER_CREEPSIZE 120
#define BOOSTER_INTERVAL 30000 //time in msec between uses (per player)
#define ACIDTUBE_BP 50
-#define ACIDTUBE_BT 10000
+#define ACIDTUBE_BT 15000
#define ACIDTUBE_HEALTH ABHM(200)
-#define ACIDTUBE_REGEN 10
+#define ACIDTUBE_REGEN 8
#define ACIDTUBE_SPLASHDAMAGE 40
#define ACIDTUBE_SPLASHRADIUS 300
#define ACIDTUBE_CREEPSIZE 120
@@ -227,9 +228,9 @@
#define ACIDTUBE_REPEAT 3000
#define HIVE_BP 50
-#define HIVE_BT 10000
+#define HIVE_BT 20000
#define HIVE_HEALTH ABHM(200)
-#define HIVE_REGEN 10
+#define HIVE_REGEN 8
#define HIVE_SPLASHDAMAGE 30
#define HIVE_SPLASHRADIUS 200
#define HIVE_CREEPSIZE 120
@@ -240,9 +241,9 @@
#define HIVE_DIR_CHANGE_PERIOD 500
#define TRAPPER_BP 150
-#define TRAPPER_BT 5000
+#define TRAPPER_BT 12000
#define TRAPPER_HEALTH ABHM(80)
-#define TRAPPER_REGEN 8
+#define TRAPPER_REGEN 6
#define TRAPPER_SPLASHDAMAGE 15
#define TRAPPER_SPLASHRADIUS 100
#define TRAPPER_CREEPSIZE 30
@@ -252,9 +253,9 @@
#define LOCKBLOB_DOT 0.85f // max angle = acos( LOCKBLOB_DOT )
#define OVERMIND_BP 0
-#define OVERMIND_BT 20000
+#define OVERMIND_BT 30000
#define OVERMIND_HEALTH ABHM(1000)
-#define OVERMIND_REGEN 15
+#define OVERMIND_REGEN 10
#define OVERMIND_SPLASHDAMAGE 100
#define OVERMIND_SPLASHRADIUS 300
#define OVERMIND_CREEPSIZE 120
@@ -263,7 +264,7 @@
#define OVERMIND_VALUE 300
#define HOVEL_BP 80
-#define HOVEL_BT 10000
+#define HOVEL_BT 15000
#define HOVEL_HEALTH ABHM(750)
#define HOVEL_REGEN 20
#define HOVEL_SPLASHDAMAGE 20
@@ -372,8 +373,8 @@
#define LCANNON_REPEAT 500
#define LCANNON_CHARGEREPEAT 1000
#define LCANNON_RELOAD 2000
-#define LCANNON_DAMAGE HDM(400)
-#define LCANNON_RADIUS 200
+#define LCANNON_DAMAGE HDM(300)
+#define LCANNON_RADIUS 150
#define LCANNON_SECONDARY_DAMAGE HDM(30)
#define LCANNON_SECONDARY_RADIUS 75
#define LCANNON_SPEED 250
@@ -457,7 +458,7 @@
#define MGTURRET_BP 80
#define MGTURRET_BT 10000
-#define MGTURRET_HEALTH HBHM(250)
+#define MGTURRET_HEALTH HBHM(500)
#define MGTURRET_SPLASHDAMAGE 50
#define MGTURRET_SPLASHRADIUS 100
#define MGTURRET_ANGULARSPEED 5 //degrees/think ~= 200deg/sec
@@ -466,7 +467,7 @@
#define MGTURRET_REPEAT 100
#define MGTURRET_RANGE 250
#define MGTURRET_SPREAD 200
-#define MGTURRET_DMG HDM(5)
+#define MGTURRET_DMG HDM(6)
#define MGTURRET_DCC_ANGULARSPEED 7
#define MGTURRET_DCC_ACCURACYTOLERANCE MGTURRET_DCC_ANGULARSPEED / 1.5f