From ab3753cd67f614786efc5bf89db6e317b83a197b Mon Sep 17 00:00:00 2001 From: IronClawTrem Date: Sat, 14 Mar 2020 19:15:57 +0000 Subject: add barricade shrink mechanic --- src/cgame/cg_buildable.c | 7 ++++ src/game/g_buildable.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++ src/game/g_local.h | 1 + src/game/tremulous.h | 2 + 4 files changed, 117 insertions(+) diff --git a/src/cgame/cg_buildable.c b/src/cgame/cg_buildable.c index e678ebd..40736e6 100644 --- a/src/cgame/cg_buildable.c +++ b/src/cgame/cg_buildable.c @@ -899,6 +899,7 @@ static void CG_BuildableStatusDisplay( centity_t *cent ) qboolean visible = qfalse; vec3_t mins, maxs; entityState_t *hit; + int anim; if( BG_FindTeamForBuildable( es->modelindex ) == BIT_ALIENS ) bs = &cgs.alienBuildStat; @@ -917,6 +918,12 @@ static void CG_BuildableStatusDisplay( centity_t *cent ) // trace for center point BG_FindBBoxForBuildable( es->modelindex, mins, maxs ); + // hack for shrunken barricades + anim = es->torsoAnim & ~( ANIM_FORCEBIT | ANIM_TOGGLEBIT ); + if( es->modelindex == BA_A_BARRICADE && + ( anim == BANIM_DESTROYED || !( es->generic1 & B_SPAWNED_TOGGLEBIT ) ) ) + maxs[ 2 ] = (int)( maxs[ 2 ] * BARRICADE_SHRINKPROP ); + VectorCopy( cent->lerpOrigin, origin ); // center point diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c index 722bbb5..62d757d 100644 --- a/src/game/g_buildable.c +++ b/src/game/g_buildable.c @@ -942,6 +942,81 @@ void ABarricade_Blast( gentity_t *self ) trap_LinkEntity( self ); //...requires a relink } +/* +================ +ABarricade_Shrink + +Set shrink state for a barricade. When unshrinking, checks to make sure there +is enough room. +================ +*/ +void ABarricade_Shrink( gentity_t *self, qboolean shrink ) +{ + if ( !self->spawned || self->health <= 0 ) + shrink = qtrue; + if ( shrink && self->shrunkTime ) + { + int anim; + + // We need to make sure that the animation has been set to shrunk mode + // because we start out shrunk but with the construct animation when built + self->shrunkTime = level.time; + anim = self->s.torsoAnim & ~( ANIM_FORCEBIT | ANIM_TOGGLEBIT ); + if ( self->spawned && self->health > 0 && anim != BANIM_DESTROYED ) + { + G_SetIdleBuildableAnim( self, BANIM_DESTROYED ); + G_SetBuildableAnim( self, BANIM_ATTACK1, qtrue ); + } + return; + } + + if ( !shrink && ( !self->shrunkTime || + level.time < self->shrunkTime + BARRICADE_SHRINKTIMEOUT ) ) + return; + + BG_FindBBoxForBuildable( BA_A_BARRICADE, self->r.mins, self->r.maxs ); + + if ( shrink ) + { + self->r.maxs[ 2 ] = (int)( self->r.maxs[ 2 ] * BARRICADE_SHRINKPROP ); + self->shrunkTime = level.time; + + // shrink animation, the destroy animation is used + if ( self->spawned && self->health > 0 ) + { + G_SetBuildableAnim( self, BANIM_ATTACK1, qtrue ); + G_SetIdleBuildableAnim( self, BANIM_DESTROYED ); + } + } + else + { + trace_t tr; + int anim; + + trap_Trace( &tr, self->r.currentOrigin, self->r.mins, self->r.maxs, + self->r.currentOrigin, self->s.number, MASK_PLAYERSOLID ); + if ( tr.startsolid || tr.fraction < 1.0f ) + { + self->r.maxs[ 2 ] = (int)( self->r.maxs[ 2 ] * BARRICADE_SHRINKPROP ); + return; + } + self->shrunkTime = 0; + + // unshrink animation, IDLE2 has been hijacked for this + anim = self->s.legsAnim & ~( ANIM_FORCEBIT | ANIM_TOGGLEBIT ); + if ( self->spawned && self->health > 0 && + anim != BANIM_CONSTRUCT1 && anim != BANIM_CONSTRUCT2 ) + { + G_SetIdleBuildableAnim( self, BG_FindAnimForBuildable( BA_A_BARRICADE ) ); + G_SetBuildableAnim( self, BANIM_ATTACK2, qtrue ); + } + } + + // a change in size requires a relink + if ( self->spawned ) + trap_LinkEntity( self ); +} + /* ================ ABarricade_Die @@ -977,6 +1052,8 @@ void ABarricade_Die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, self->think = ABarricade_Blast; self->s.eFlags &= ~EF_FIRING; //prevent any firing effects + ABarricade_Shrink( self, qtrue ); + if( self->spawned ) self->nextthink = level.time + 5000; else @@ -1024,10 +1101,37 @@ void ABarricade_Think( gentity_t *self ) G_CreepSlow( self ); self->nextthink = level.time + BG_FindNextThinkForBuildable( self->s.modelindex ); + + // Shrink if unpowered + ABarricade_Shrink( self, !self->powered ); } +/* +================ +ABarricade_Touch +Barricades shrink when they are come into contact with an Alien that can +pass through +================ +*/ +void ABarricade_Touch( gentity_t *self, gentity_t *other, trace_t *trace ) +{ + gclient_t *client = other->client; + int client_z, min_z; + + if( !client || client->pers.teamSelection != PTE_ALIENS ) + return; + + // Client must be high enough to pass over. Note that STEPSIZE (18) is + // hardcoded here because we don't include bg_local.h! + client_z = other->r.currentOrigin[ 2 ] + other->r.mins[ 2 ]; + min_z = self->r.currentOrigin[ 2 ] - 18 + + (int)( self->r.maxs[ 2 ] * BARRICADE_SHRINKPROP ); + if( client_z < min_z ) + return; + ABarricade_Shrink( self, qtrue ); +} //================================================================================== @@ -3599,6 +3703,9 @@ static gentity_t *G_Build( gentity_t *builder, buildable_t buildable, vec3_t ori built->die = ABarricade_Die; built->think = ABarricade_Think; built->pain = ABarricade_Pain; + built->touch = ABarricade_Touch; + built->shrunkTime = 0; + ABarricade_Shrink( built, qtrue ); break; case BA_A_BOOSTER: diff --git a/src/game/g_local.h b/src/game/g_local.h index a77a5d6..b5e6e8c 100644 --- a/src/game/g_local.h +++ b/src/game/g_local.h @@ -217,6 +217,7 @@ struct gentity_s gentity_t *overmindNode; // controlling overmind qboolean dcced; // controlled by a dcc or not? qboolean spawned; // whether or not this buildable has finished spawning + int shrunkTime; // time when a barricade shrunk or zero int buildTime; // when this buildable was built int animTime; // last animation change int time1000; // timer evaluated every second diff --git a/src/game/tremulous.h b/src/game/tremulous.h index 65bd3ca..97738f2 100644 --- a/src/game/tremulous.h +++ b/src/game/tremulous.h @@ -239,6 +239,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define BARRICADE_SPLASHDAMAGE 50 #define BARRICADE_SPLASHRADIUS 50 #define BARRICADE_CREEPSIZE 120 +#define BARRICADE_SHRINKPROP 0.25f +#define BARRICADE_SHRINKTIMEOUT 500 #define BOOSTER_BP 12 #define BOOSTER_BT 15000 -- cgit