summaryrefslogtreecommitdiff
path: root/src/game
diff options
context:
space:
mode:
authorTim Angus <tim@ngus.net>2003-09-12 04:36:26 +0000
committerTim Angus <tim@ngus.net>2003-09-12 04:36:26 +0000
commit84e75ec07a5027e76726bc28073438d8c9a8d04a (patch)
treee989a56316db265b02a99840cf478f1e982ec4b4 /src/game
parentd8ed915000aef140bbe4bd22020acced5eae654f (diff)
* Removed the func_door_model auto scaling and positioning code - it didn't work
* Added the server side stuff for the hive
Diffstat (limited to 'src/game')
-rw-r--r--src/game/bg_misc.c55
-rw-r--r--src/game/bg_public.h31
-rw-r--r--src/game/g_buildable.c83
-rw-r--r--src/game/g_local.h1
-rw-r--r--src/game/g_missile.c225
-rw-r--r--src/game/g_mover.c28
-rw-r--r--src/game/g_weapon.c20
-rw-r--r--src/game/tremulous.h20
8 files changed, 385 insertions, 78 deletions
diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c
index 01033261..eca4e53d 100644
--- a/src/game/bg_misc.c
+++ b/src/game/bg_misc.c
@@ -153,6 +153,39 @@ buildableAttributes_t bg_buildableList[ ] =
qfalse //qboolean reactorTest;
},
{
+ BA_A_HIVE, //int buildNum;
+ "hive", //char *buildName;
+ "Hive", //char *humanName;
+ "team_alien_hive", //char *entityName;
+ { "models/buildables/acid_tube/acid_tube.md3", 0, 0, 0 },
+ { -35, -35, -11 }, //vec3_t mins;
+ { 35, 35, 40 }, //vec3_t maxs;
+ TR_GRAVITY, //trType_t traj;
+ 0.0, //float bounce;
+ HIVE_BP, //int buildPoints;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ HIVE_HEALTH, //int health;
+ HIVE_REGEN, //int regenRate;
+ HIVE_SPLASHDAMAGE, //int splashDamage;
+ HIVE_SPLASHRADIUS, //int splashRadius;
+ MOD_ASPAWN, //int meansOfDeath;
+ BIT_ALIENS, //int team;
+ ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ), //weapon_t buildWeapon;
+ BANIM_IDLE1, //int idleAnim;
+ 500, //int nextthink;
+ 10000, //int buildTime;
+ qfalse, //qboolean usable;
+ 0, //int turretRange;
+ 0, //int turretFireSpeed;
+ WP_HIVE, //weapon_t turretProjType;
+ 0.707f, //float minNormal;
+ qtrue, //qboolean invertNormal;
+ qtrue, //qboolean creepTest;
+ HIVE_CREEPSIZE, //int creepSize;
+ qfalse, //qboolean dccTest;
+ qfalse //qboolean reactorTest;
+ },
+ {
BA_A_TRAPPER, //int buildNum;
"trapper", //char *buildName;
"Trapper", //char *humanName;
@@ -2622,6 +2655,28 @@ weaponAttributes_t bg_weapons[ ] =
WUT_ALIENS //WUTeam_t team;
},
{
+ WP_HIVE, //int weaponNum;
+ 0, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "hive", //char *weaponName;
+ "Hive", //char *weaponHumanName;
+ 0, //int quan;
+ 0, //int clips;
+ 0, //int maxClips;
+ qtrue, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ 500, //int repeatRate1;
+ 500, //int repeatRate2;
+ 500, //int repeatRate3;
+ 0, //int reloadTime;
+ qfalse, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qfalse, //qboolean purchasable;
+ 0, //int buildDelay;
+ WUT_ALIENS //WUTeam_t team;
+ },
+ {
WP_MGTURRET, //int weaponNum;
0, //int price;
( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
diff --git a/src/game/bg_public.h b/src/game/bg_public.h
index a519595f..494c3cf7 100644
--- a/src/game/bg_public.h
+++ b/src/game/bg_public.h
@@ -268,20 +268,20 @@ typedef enum
#define EF_PLAYER_EVENT 0x00000004
#define EF_BOUNCE 0x00000008 // for missiles
#define EF_BOUNCE_HALF 0x00000010 // for missiles
-#define EF_WALLCLIMB 0x00000020 // TA: wall walking
-#define EF_WALLCLIMBCEILING 0x00000040 // TA: wall walking ceiling hack
-#define EF_NODRAW 0x00000080 // may have an event, but no model (unspawned items)
-#define EF_FIRING 0x00000100 // for lightning gun
-#define EF_FIRING2 0x00000200 // alt fire
-#define EF_FIRING3 0x00000400 // third fire
-#define EF_MOVER_STOP 0x00000800 // will push otherwise
-#define EF_TALK 0x00001000 // draw a talk balloon
-#define EF_CONNECTION 0x00002000 // draw a connection trouble sprite
-#define EF_VOTED 0x00004000 // already cast a vote
-#define EF_TEAMVOTED 0x00008000 // already cast a vote
-#define EF_OVERDRAW_OFF 0x00010000 // TA: disable overdraw protection on sprites
-#define EF_REAL_LIGHT 0x00020000 // TA: light sprites according to ambient light
-#define EF_NO_AUTO_SCALE 0x00040000 // TA: don't auto scale model doors
+#define EF_NO_BOUNCE_SOUND 0x00000020 // for missiles
+#define EF_WALLCLIMB 0x00000040 // TA: wall walking
+#define EF_WALLCLIMBCEILING 0x00000080 // TA: wall walking ceiling hack
+#define EF_NODRAW 0x00000100 // may have an event, but no model (unspawned items)
+#define EF_FIRING 0x00000200 // for lightning gun
+#define EF_FIRING2 0x00000400 // alt fire
+#define EF_FIRING3 0x00000800 // third fire
+#define EF_MOVER_STOP 0x00001000 // will push otherwise
+#define EF_TALK 0x00002000 // draw a talk balloon
+#define EF_CONNECTION 0x00004000 // draw a connection trouble sprite
+#define EF_VOTED 0x00008000 // already cast a vote
+#define EF_TEAMVOTED 0x00010000 // already cast a vote
+#define EF_OVERDRAW_OFF 0x00020000 // TA: disable overdraw protection on sprites
+#define EF_REAL_LIGHT 0x00040000 // TA: light sprites according to ambient light
typedef enum
{
@@ -335,6 +335,7 @@ typedef enum
WP_PAIN_SAW,
WP_LOCKBLOB_LAUNCHER,
+ WP_HIVE,
WP_TESLAGEN,
WP_MGTURRET,
@@ -397,6 +398,7 @@ typedef enum
BA_A_ACIDTUBE,
BA_A_TRAPPER,
BA_A_BOOSTER,
+ BA_A_HIVE,
BA_A_HOVEL,
@@ -825,6 +827,7 @@ typedef enum
MOD_SLOWBLOB,
MOD_POISON,
+ MOD_SWARM,
MOD_HSPAWN,
MOD_TESLAGEN,
diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c
index 6ff424f0..50b64f1c 100644
--- a/src/game/g_buildable.c
+++ b/src/game/g_buildable.c
@@ -663,7 +663,7 @@ void ABarricade_Die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker,
================
ABarricade_Think
-think function for Alien Barricade
+Think function for Alien Barricade
================
*/
void ABarricade_Think( gentity_t *self )
@@ -694,7 +694,7 @@ void AAcidTube_Think( gentity_t *self );
================
AAcidTube_Damage
-damage function for Alien Acid Tube
+Damage function for Alien Acid Tube
================
*/
void AAcidTube_Damage( gentity_t *self )
@@ -729,7 +729,7 @@ void AAcidTube_Damage( gentity_t *self )
================
AAcidTube_Think
-think function for Alien Acid Tube
+Think function for Alien Acid Tube
================
*/
void AAcidTube_Think( gentity_t *self )
@@ -782,6 +782,77 @@ void AAcidTube_Think( gentity_t *self )
+/*
+================
+AHive_Think
+
+Think function for Alien Hive
+================
+*/
+void AHive_Think( gentity_t *self )
+{
+ int entityList[ MAX_GENTITIES ];
+ vec3_t range = { ACIDTUBE_RANGE, ACIDTUBE_RANGE, ACIDTUBE_RANGE };
+ vec3_t mins, maxs;
+ int i, num;
+ gentity_t *enemy;
+ vec3_t dirToTarget;
+
+ self->nextthink = level.time + BG_FindNextThinkForBuildable( self->s.modelindex );
+
+ VectorAdd( self->s.origin, range, maxs );
+ VectorSubtract( self->s.origin, range, mins );
+
+ //if there is no creep nearby die
+ if( !findCreep( self ) )
+ {
+ G_Damage( self, NULL, NULL, NULL, NULL, 10000, 0, MOD_SUICIDE );
+ return;
+ }
+
+ if( self->timestamp < level.time )
+ self->active = qfalse; //nothing has returned in HIVE_REPEAT seconds, forget about it
+
+ if( self->spawned && !self->active )
+ {
+ //do some damage
+ num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
+ for( i = 0; i < num; i++ )
+ {
+ enemy = &g_entities[ entityList[ i ] ];
+
+ if( enemy->health <= 0 )
+ continue;
+
+ if( enemy->client && enemy->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
+ {
+ self->active = qtrue;
+ self->target_ent = enemy;
+ self->timestamp = level.time + HIVE_REPEAT;
+
+ VectorSubtract( enemy->s.pos.trBase, self->s.pos.trBase, dirToTarget );
+ VectorNormalize( dirToTarget );
+ vectoangles( dirToTarget, self->turretAim );
+
+ //fire at target
+ FireWeapon( self );
+ G_setBuildableAnim( self, BANIM_ATTACK1, qfalse );
+ return;
+ }
+ }
+ }
+
+ creepSlow( self->s.modelindex, self->s.origin );
+}
+
+
+
+
+//==================================================================================
+
+
+
+
#define HOVEL_TRACE_DEPTH 16.0f
/*
@@ -2091,6 +2162,12 @@ gentity_t *G_buildItem( gentity_t *builder, buildable_t buildable, vec3_t origin
built->pain = ASpawn_Pain;
break;
+ case BA_A_HIVE:
+ built->die = ABarricade_Die;
+ built->think = AHive_Think;
+ built->pain = ASpawn_Pain;
+ break;
+
case BA_A_TRAPPER:
built->die = ABarricade_Die;
built->think = ATrapper_Think;
diff --git a/src/game/g_local.h b/src/game/g_local.h
index e65d1e69..9d78b932 100644
--- a/src/game/g_local.h
+++ b/src/game/g_local.h
@@ -656,6 +656,7 @@ gentity_t *fire_luciferCannon( gentity_t *self, vec3_t start, vec3_t dir, int da
gentity_t *fire_lockblob( gentity_t *self, vec3_t start, vec3_t dir );
gentity_t *fire_paraLockBlob( gentity_t *self, vec3_t start, vec3_t dir );
gentity_t *fire_slowBlob( gentity_t *self, vec3_t start, vec3_t dir );
+gentity_t *fire_hive( gentity_t *self, vec3_t start, vec3_t dir );
//
diff --git a/src/game/g_missile.c b/src/game/g_missile.c
index 76f3cd10..8eb4169f 100644
--- a/src/game/g_missile.c
+++ b/src/game/g_missile.c
@@ -89,6 +89,7 @@ void G_ExplodeMissile( gentity_t *ent )
trap_LinkEntity( ent );
}
+void AHive_ReturnToHive( gentity_t *self );
/*
================
@@ -98,38 +99,25 @@ G_MissileImpact
*/
void G_MissileImpact( gentity_t *ent, trace_t *trace )
{
- gentity_t *other;
- qboolean hitClient = qfalse;
+ gentity_t *other, *attacker;
+ qboolean returnAfterDamage = qfalse;
other = &g_entities[ trace->entityNum ];
+ attacker = &g_entities[ ent->r.ownerNum ];
// check for bounce
if( !other->takedamage &&
( ent->s.eFlags & ( EF_BOUNCE | EF_BOUNCE_HALF ) ) )
{
G_BounceMissile( ent, trace );
- G_AddEvent( ent, EV_GRENADE_BOUNCE, 0 );
- return;
- }
+
+ //only play a sound if requested
+ if( !( ent->s.eFlags & EF_NO_BOUNCE_SOUND ) )
+ G_AddEvent( ent, EV_GRENADE_BOUNCE, 0 );
- // impact damage
- if( other->takedamage )
- {
- // FIXME: wrong damage direction?
- if( ent->damage )
- {
- vec3_t velocity;
-
- BG_EvaluateTrajectoryDelta( &ent->s.pos, level.time, velocity );
- if( VectorLength( velocity ) == 0 )
- velocity[ 2 ] = 1; // stepped on a grenade
-
- G_Damage( other, ent, &g_entities[ ent->r.ownerNum ], velocity,
- ent->s.origin, ent->damage,
- 0, ent->methodOfDeath );
- }
+ return;
}
-
+
if( !strcmp( ent->classname, "lockblob" ) )
{
if( other->client && other->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
@@ -148,7 +136,54 @@ void G_MissileImpact( gentity_t *ent, trace_t *trace )
VectorCopy( other->client->ps.viewangles, other->client->ps.grapplePoint );
}
}
+ else if( !strcmp( ent->classname, "hive" ) )
+ {
+ if( other->s.eType == ET_BUILDABLE && other->s.modelindex == BA_A_HIVE )
+ {
+ if( !ent->parent )
+ G_Printf( S_COLOR_YELLOW "WARNING: hive entity has no parent in G_MissileImpact\n" );
+ else
+ ent->parent->active = qfalse;
+
+ G_FreeEntity( ent );
+ return;
+ }
+ else
+ {
+ //prevent collision with the client when returning
+ ent->r.ownerNum = other->s.number;
+
+ ent->think = AHive_ReturnToHive;
+ ent->nextthink = level.time + FRAMETIME;
+
+ //only damage humans
+ if( other->client && other->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
+ returnAfterDamage = qtrue;
+ else
+ return;
+ }
+ }
+ // impact damage
+ if( other->takedamage )
+ {
+ // FIXME: wrong damage direction?
+ if( ent->damage )
+ {
+ vec3_t velocity;
+
+ BG_EvaluateTrajectoryDelta( &ent->s.pos, level.time, velocity );
+ if( VectorLength( velocity ) == 0 )
+ velocity[ 2 ] = 1; // stepped on a grenade
+
+ G_Damage( other, ent, attacker, velocity, ent->s.origin, ent->damage,
+ 0, ent->methodOfDeath );
+ }
+ }
+
+ if( returnAfterDamage )
+ return;
+
// is it cheaper in bandwidth to just remove this ent and create a new
// one, rather than changing the missile into the explosion?
@@ -195,16 +230,9 @@ void G_RunMissile( gentity_t *ent )
// get current position
BG_EvaluateTrajectory( &ent->s.pos, level.time, origin );
- // if this missile bounced off an invulnerability sphere
- if ( ent->target_ent )
- {
- passent = ent->target_ent->s.number;
- }
- else
- {
- // ignore interactions with the missile owner
- passent = ent->r.ownerNum;
- }
+ // ignore interactions with the missile owner
+ passent = ent->r.ownerNum;
+
// trace a line from the previous position to the current position
trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, origin, passent, ent->clipmask );
@@ -233,7 +261,7 @@ void G_RunMissile( gentity_t *ent )
}
G_MissileImpact( ent, &tr );
- if ( ent->s.eType != ET_MISSILE )
+ if( ent->s.eType != ET_MISSILE )
return; // exploded
}
@@ -418,6 +446,136 @@ gentity_t *fire_luciferCannon( gentity_t *self, vec3_t start, vec3_t dir, int da
//=============================================================================
/*
+================
+AHive_ReturnToHive
+
+Adjust the trajectory to point towards the hive
+================
+*/
+void AHive_ReturnToHive( gentity_t *self )
+{
+ vec3_t dir;
+ trace_t tr;
+
+ if( !self->parent )
+ {
+ G_Printf( S_COLOR_YELLOW "WARNING: AHive_ReturnToHive called with no self->parent\n" );
+ return;
+ }
+
+ trap_UnlinkEntity( self->parent );
+ trap_Trace( &tr, self->r.currentOrigin, self->r.mins, self->r.maxs,
+ self->parent->r.currentOrigin, self->r.ownerNum, self->clipmask );
+ trap_LinkEntity( self->parent );
+
+ if( tr.fraction < 1.0f )
+ {
+ //if can't see hive then disperse
+ VectorCopy( self->r.currentOrigin, self->s.pos.trBase );
+ self->s.pos.trType = TR_STATIONARY;
+ self->s.pos.trTime = level.time;
+
+ self->think = G_ExplodeMissile;
+ self->nextthink = level.time + 2000;
+ self->parent->active = qfalse; //allow the parent to start again
+ }
+ else
+ {
+ VectorSubtract( self->parent->r.currentOrigin, self->r.currentOrigin, dir );
+ VectorNormalize( dir );
+
+ //change direction towards the hive
+ VectorScale( dir, HIVE_SPEED, self->s.pos.trDelta );
+ SnapVector( self->s.pos.trDelta ); // save net bandwidth
+ VectorCopy( self->r.currentOrigin, self->s.pos.trBase );
+ self->s.pos.trTime = level.time;
+
+ self->think = G_ExplodeMissile;
+ self->nextthink = level.time + 15000;
+ }
+}
+
+/*
+================
+AHive_SearchAndDestroy
+
+Adjust the trajectory to point towards the target
+================
+*/
+void AHive_SearchAndDestroy( gentity_t *self )
+{
+ vec3_t dir;
+ trace_t tr;
+
+ trap_Trace( &tr, self->r.currentOrigin, self->r.mins, self->r.maxs,
+ self->target_ent->r.currentOrigin, self->r.ownerNum, self->clipmask );
+
+ //if there is no LOS or the parent hive is too far away or the target is dead, return
+ if( tr.entityNum == ENTITYNUM_WORLD ||
+ Distance( self->r.currentOrigin, self->parent->r.currentOrigin ) > ( HIVE_RANGE * 5 ) ||
+ self->target_ent->health <= 0 )
+ {
+ self->r.ownerNum = ENTITYNUM_WORLD;
+
+ self->think = AHive_ReturnToHive;
+ self->nextthink = level.time + FRAMETIME;
+ }
+ else
+ {
+ VectorSubtract( self->target_ent->r.currentOrigin, self->r.currentOrigin, dir );
+ VectorNormalize( dir );
+
+ //change direction towards the player
+ VectorScale( dir, HIVE_SPEED, self->s.pos.trDelta );
+ SnapVector( self->s.pos.trDelta ); // save net bandwidth
+ VectorCopy( self->r.currentOrigin, self->s.pos.trBase );
+ self->s.pos.trTime = level.time;
+
+ self->nextthink = level.time + HIVE_DIR_CHANGE_PERIOD;
+ }
+}
+
+/*
+=================
+fire_hive
+=================
+*/
+gentity_t *fire_hive( gentity_t *self, vec3_t start, vec3_t dir )
+{
+ gentity_t *bolt;
+
+ VectorNormalize ( dir );
+
+ bolt = G_Spawn( );
+ bolt->classname = "hive";
+ bolt->nextthink = level.time + HIVE_DIR_CHANGE_PERIOD;
+ bolt->think = AHive_SearchAndDestroy;
+ bolt->s.eType = ET_MISSILE;
+ bolt->s.eFlags |= EF_BOUNCE|EF_NO_BOUNCE_SOUND;
+ bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN;
+ bolt->s.weapon = WP_HIVE;
+ bolt->r.ownerNum = self->s.number;
+ bolt->parent = self;
+ bolt->damage = HIVE_DMG;
+ bolt->splashDamage = 0;
+ bolt->splashRadius = 0;
+ bolt->methodOfDeath = MOD_SWARM;
+ bolt->clipmask = MASK_SHOT;
+ bolt->target_ent = self->target_ent;
+
+ bolt->s.pos.trType = TR_LINEAR;
+ bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME; // move a bit on the very first frame
+ VectorCopy( start, bolt->s.pos.trBase );
+ VectorScale( dir, HIVE_SPEED, bolt->s.pos.trDelta );
+ SnapVector( bolt->s.pos.trDelta ); // save net bandwidth
+ VectorCopy( start, bolt->r.currentOrigin );
+
+ return bolt;
+}
+
+//=============================================================================
+
+/*
=================
fire_lockblob
=================
@@ -440,6 +598,7 @@ gentity_t *fire_lockblob( gentity_t *self, vec3_t start, vec3_t dir )
bolt->damage = 0;
bolt->splashDamage = 0;
bolt->splashRadius = 0;
+ bolt->methodOfDeath = MOD_UNKNOWN; //doesn't do damage so will never kill
bolt->clipmask = MASK_SHOT;
bolt->target_ent = NULL;
diff --git a/src/game/g_mover.c b/src/game/g_mover.c
index ea7f40be..3d171343 100644
--- a/src/game/g_mover.c
+++ b/src/game/g_mover.c
@@ -1601,8 +1601,6 @@ void SP_func_door_model( gentity_t *ent )
char *sound;
gentity_t *door;
gentity_t *clipBrush;
- vec3_t scale;
- qboolean dontAutoScale = qfalse;
G_SpawnString( "sound2to1", "sound/movers/doors/dr1_strt.wav", &s );
ent->sound2to1 = G_SoundIndex( s );
@@ -1638,27 +1636,9 @@ void SP_func_door_model( gentity_t *ent )
VectorCopy( clipBrush->r.mins, ent->r.mins );
VectorCopy( clipBrush->r.maxs, ent->r.maxs );
- if( !VectorLength( ent->s.origin ) )
- {
- //calculate the centre of the brush
- VectorSubtract( ent->r.maxs, ent->r.mins, size );
- VectorScale( size, 0.5f, size );
- VectorAdd( size, ent->r.mins, ent->s.origin );
- }
- else
- dontAutoScale = qtrue;
-
- if( G_SpawnVector( "scale", "1 1 1", scale ) )
- dontAutoScale = qtrue;
-
- //let the client know the scaling of the model
- VectorCopy( scale, ent->s.origin2 );
-
- //let the client know the bounds of the brush
- VectorCopy( size, ent->s.angles2 );
+ G_SpawnVector( "modelOrigin", "0 0 0", ent->s.origin );
- if( dontAutoScale )
- ent->s.eFlags |= EF_NO_AUTO_SCALE;
+ G_SpawnVector( "scale", "1 1 1", ent->s.origin2 );
// if the "model2" key is set, use a seperate model
// for drawing, but clip against the brushes
@@ -1703,10 +1683,12 @@ void SP_func_door_model( gentity_t *ent )
ent->moverState = MODEL_POS1;
ent->s.eType = ET_MODELDOOR;
VectorCopy( ent->s.origin, ent->s.pos.trBase );
+ ent->s.pos.trType = TR_STATIONARY;
ent->s.pos.trTime = 0;
ent->s.pos.trDuration = 0;
VectorClear( ent->s.pos.trDelta );
VectorCopy( ent->s.angles, ent->s.apos.trBase );
+ ent->s.apos.trType = TR_STATIONARY;
ent->s.apos.trTime = 0;
ent->s.apos.trDuration = 0;
VectorClear( ent->s.apos.trDelta );
@@ -1722,8 +1704,6 @@ void SP_func_door_model( gentity_t *ent )
trap_LinkEntity( ent );
- ent->s.pos.trType = TR_STATIONARY;
-
if( !( ent->flags & FL_TEAMSLAVE ) )
{
int health;
diff --git a/src/game/g_weapon.c b/src/game/g_weapon.c
index 2590503e..fd44840c 100644
--- a/src/game/g_weapon.c
+++ b/src/game/g_weapon.c
@@ -212,6 +212,23 @@ void lockBlobLauncherFire( gentity_t *ent )
/*
======================================================================
+HIVE
+
+======================================================================
+*/
+
+void hiveFire( gentity_t *ent )
+{
+ gentity_t *m;
+
+ m = fire_hive( ent, muzzle, forward );
+
+// VectorAdd( m->s.pos.trDelta, ent->client->ps.velocity, m->s.pos.trDelta ); // "real" physics
+}
+
+/*
+======================================================================
+
BLASTER PISTOL
======================================================================
@@ -1101,6 +1118,9 @@ void FireWeapon( gentity_t *ent )
case WP_LOCKBLOB_LAUNCHER:
lockBlobLauncherFire( ent );
break;
+ case WP_HIVE:
+ hiveFire( ent );
+ break;
case WP_TESLAGEN:
teslaFire( ent );
break;
diff --git a/src/game/tremulous.h b/src/game/tremulous.h
index b50be9d9..3ee4bbd7 100644
--- a/src/game/tremulous.h
+++ b/src/game/tremulous.h
@@ -215,6 +215,18 @@
#define ACIDTUBE_RANGE 200.0f
#define ACIDTUBE_REPEAT 10000
+#define HIVE_BP 50
+#define HIVE_HEALTH ABHM(100)
+#define HIVE_REGEN 10
+#define HIVE_SPLASHDAMAGE 30
+#define HIVE_SPLASHRADIUS 200
+#define HIVE_CREEPSIZE 120
+#define HIVE_RANGE 400.0f
+#define HIVE_REPEAT 10000
+#define HIVE_DMG 40
+#define HIVE_SPEED 230.0f
+#define HIVE_DIR_CHANGE_PERIOD 500
+
#define TRAPPER_BP 150
#define TRAPPER_HEALTH ABHM(80)
#define TRAPPER_REGEN 8
@@ -467,10 +479,10 @@
#define HUMAN_BACK_MODIFIER 0.7f
#define HUMAN_SIDE_MODIFIER 0.8f
-#define STAMINA_STOP_RESTORE 10
-#define STAMINA_WALK_RESTORE 5
-#define STAMINA_SPRINT_TAKE 10
-#define STAMINA_LARMOUR_TAKE 5
+#define STAMINA_STOP_RESTORE 20
+#define STAMINA_WALK_RESTORE 10
+#define STAMINA_SPRINT_TAKE 6
+#define STAMINA_LARMOUR_TAKE 3
/*
* Misc