From 7b6cf403eaf1f6fce9c77be172498a8b17463ad5 Mon Sep 17 00:00:00 2001 From: Christopher Schwarz Date: Fri, 23 Oct 2009 08:21:00 +0000 Subject: * (bug 4006) Prevent human buildables from playing idle sounds while unpowered and give them new slightly-different animations so they also look different. In the case of turrets, 'droop' a bit when unpowered. (Rezyn) --- assets/models/buildables/medistat/animation.cfg | 18 +++++ assets/models/buildables/mgturret/animation.cfg | 15 ++++ assets/models/buildables/repeater/animation.cfg | 15 ++++ assets/models/buildables/tesla/animation.cfg | 15 ++++ src/cgame/cg_buildable.c | 17 ++++ src/cgame/cg_local.h | 1 + src/game/g_buildable.c | 101 ++++++++++++++++++++++-- 7 files changed, 177 insertions(+), 5 deletions(-) create mode 100644 assets/models/buildables/medistat/animation.cfg create mode 100644 assets/models/buildables/mgturret/animation.cfg create mode 100644 assets/models/buildables/repeater/animation.cfg create mode 100644 assets/models/buildables/tesla/animation.cfg diff --git a/assets/models/buildables/medistat/animation.cfg b/assets/models/buildables/medistat/animation.cfg new file mode 100644 index 00000000..5a5ab0f7 --- /dev/null +++ b/assets/models/buildables/medistat/animation.cfg @@ -0,0 +1,18 @@ +//medistation +0 8 0 24 // CONSTRUCT +0 8 0 24 // CONSTRUCT +8 19 19 12 // IDLE +32 1 1 1 // IDLE2-HEAL +0 1 1 1 // IDLE3-NOPOWER +27 6 0 24 // ATTACK1-HEAL +0 0 0 0 // ATTACK2 +0 0 0 0 // SPAWN1 +0 0 0 0 // SPAWN2 +0 0 0 0 // PAIN1 +0 0 0 0 // PAIN2 +33 1 0 5 // DESTROY +0 0 0 0 // DESTROY2 +33 1 1 1 // DEAD + +//attack is the heal activate +//idle2 is the heal idle diff --git a/assets/models/buildables/mgturret/animation.cfg b/assets/models/buildables/mgturret/animation.cfg new file mode 100644 index 00000000..7b80fb71 --- /dev/null +++ b/assets/models/buildables/mgturret/animation.cfg @@ -0,0 +1,15 @@ +//mgturret +0 1 0 1 // CONSTRUCT1 +0 1 0 1 // CONSTRUCT1 +0 1 1 1 // IDLE1 +0 1 1 1 // IDLE2 +0 1 1 1 // IDLE3-NOPOWER +1 1 0 10 // ATTACK1 +0 1 0 0 // ATTACK2 +0 1 0 0 // SPAWN1 +0 1 0 0 // SPAWN2 +0 1 0 0 // PAIN1 +0 1 0 0 // PAIN2 +0 1 0 1 // DESTROY1 +0 1 0 0 // DESTROY2 +0 1 1 1 // DEAD diff --git a/assets/models/buildables/repeater/animation.cfg b/assets/models/buildables/repeater/animation.cfg new file mode 100644 index 00000000..fdfdb655 --- /dev/null +++ b/assets/models/buildables/repeater/animation.cfg @@ -0,0 +1,15 @@ +//repeater +0 12 0 24 // CONSTRUCT1 +0 12 0 24 // CONSTRUCT1 +12 24 24 36 // IDLE1 +0 0 0 0 // IDLE2 +12 24 24 6 // IDLE3-NOPOWER +0 0 0 0 // ATTACK1 +0 0 0 0 // ATTACK2 +0 0 0 0 // SPAWN1 +0 0 0 0 // SPAWN2 +0 0 0 0 // PAIN1 +0 0 0 0 // PAIN2 +37 1 0 5 // DESTROY +0 0 0 0 // DESTROY2 +37 1 1 1 // DEAD diff --git a/assets/models/buildables/tesla/animation.cfg b/assets/models/buildables/tesla/animation.cfg new file mode 100644 index 00000000..2c3f1d96 --- /dev/null +++ b/assets/models/buildables/tesla/animation.cfg @@ -0,0 +1,15 @@ +// tesla +0 8 0 12 // CONSTRUCT1 +0 8 0 12 // CONSTRUCT1 +8 24 24 24 // IDLE1 +0 0 0 0 // IDLE2 +32 1 1 1 // IDLE3-NOPOWER +0 0 0 0 // ATTACK1 +0 0 0 0 // ATTACK2 +0 0 0 0 // SPAWN1 +0 0 0 0 // SPAWN2 +0 0 0 0 // PAIN1 +0 0 0 0 // PAIN2 +32 2 0 12 // DESTROY1 +0 0 0 0 // DESTROY2 +34 1 1 1 // DESTROYED diff --git a/src/cgame/cg_buildable.c b/src/cgame/cg_buildable.c index 8a5bb858..b457808b 100644 --- a/src/cgame/cg_buildable.c +++ b/src/cgame/cg_buildable.c @@ -464,7 +464,10 @@ static void CG_RunBuildableLerpFrame( centity_t *cent ) // animation ended if( lf->frameTime == cg.time ) + { cent->buildableAnim = cent->currentState.torsoAnim; + cent->buildableIdleAnim = qtrue; + } } /* @@ -478,7 +481,10 @@ static void CG_BuildableAnimation( centity_t *cent, int *old, int *now, float *b //if no animation is set default to idle anim if( cent->buildableAnim == BANIM_NONE ) + { cent->buildableAnim = es->torsoAnim; + cent->buildableIdleAnim = qtrue; + } //display the first frame of the construction anim if not yet spawned if( !( es->eFlags & EF_B_SPAWNED ) ) @@ -509,9 +515,20 @@ static void CG_BuildableAnimation( centity_t *cent, int *old, int *now, float *b BG_Buildable( es->modelindex )->humanName, es->number ); if( cent->buildableAnim == es->torsoAnim || es->legsAnim & ANIM_FORCEBIT ) + { cent->buildableAnim = cent->oldBuildableAnim = es->legsAnim; + cent->buildableIdleAnim = qfalse; + } else + { cent->buildableAnim = cent->oldBuildableAnim = es->torsoAnim; + cent->buildableIdleAnim = qtrue; + } + } + else if( cent->buildableIdleAnim == qtrue && + cent->buildableAnim != es->torsoAnim ) + { + cent->buildableAnim = es->torsoAnim; } CG_RunBuildableLerpFrame( cent ); diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h index 90e88648..477bd384 100644 --- a/src/cgame/cg_local.h +++ b/src/cgame/cg_local.h @@ -647,6 +647,7 @@ typedef struct centity_s buildableAnimNumber_t buildableAnim; //persistant anim number buildableAnimNumber_t oldBuildableAnim; //to detect when new anims are set + qboolean buildableIdleAnim; //to check if new idle anim particleSystem_t *buildablePS; buildableStatus_t buildableStatus; buildableCache_t buildableCache; // so we don't recalculate things diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c index ee3a02a2..1c3c0a22 100644 --- a/src/game/g_buildable.c +++ b/src/game/g_buildable.c @@ -1734,6 +1734,27 @@ static void G_SuicideIfNoPower( gentity_t *self ) } } +/* +================ +G_IdlePowerState + +Set buildable idle animation to match power state +================ +*/ +static void G_IdlePowerState( gentity_t *self ) +{ + if( self->powered ) + { + if( self->s.torsoAnim == BANIM_IDLE3 ) + G_SetIdleBuildableAnim( self, BG_Buildable( self->s.modelindex )->idleAnim ); + } + else + { + if( self->s.torsoAnim != BANIM_IDLE3 ) + G_SetIdleBuildableAnim( self, BANIM_IDLE3 ); + } +} + @@ -1950,6 +1971,8 @@ void HRepeater_Think( gentity_t *self ) self->powered = reactor; + G_IdlePowerState( self ); + // Initialise the zone once the repeater has spawned if( self->spawned && ( !self->usesBuildPointZone || !level.buildPointZones[ self->buildPointZone ].active ) ) { @@ -2178,19 +2201,19 @@ void HMedistat_Think( gentity_t *self ) self->nextthink = level.time + BG_Buildable( self->s.modelindex )->nextthink; + self->powered = G_FindPower( self ); G_SuicideIfNoPower( self ); + G_IdlePowerState( self ); //clear target's healing flag if( self->enemy && self->enemy->client ) self->enemy->client->ps.stats[ STAT_STATE ] &= ~SS_HEALING_ACTIVE; //make sure we have power - if( !( self->powered = G_FindPower( self ) ) ) + if( !self->powered ) { if( self->active ) { - G_SetBuildableAnim( self, BANIM_CONSTRUCT2, qtrue ); - G_SetIdleBuildableAnim( self, BANIM_IDLE1 ); self->active = qfalse; self->enemy = NULL; } @@ -2429,6 +2452,62 @@ void HMGTurret_FindEnemy( gentity_t *self ) } } +/* +================ +HMGTurret_State + +Raise or lower MG turret towards desired state +================ +*/ +enum { + MGT_STATE_INACTIVE, + MGT_STATE_DROP, + MGT_STATE_RISE, + MGT_STATE_ACTIVE +}; + +static qboolean HMGTurret_State( gentity_t *self, int state ) +{ + float angle; + + if( self->waterlevel == state ) + return qfalse; + + angle = AngleNormalize180( self->s.angles2[ PITCH ] ); + + if( state == MGT_STATE_INACTIVE ) + { + if( angle < MGTURRET_VERTICALCAP ) + { + if( self->waterlevel != MGT_STATE_DROP ) + { + self->speed = 0.25f; + self->waterlevel = MGT_STATE_DROP; + } + else + self->speed *= 1.25f; + + self->s.angles2[ PITCH ] = + MIN( MGTURRET_VERTICALCAP, angle + self->speed ); + return qtrue; + } + else + self->waterlevel = MGT_STATE_INACTIVE; + } + else if( state == MGT_STATE_ACTIVE ) + { + if( !self->enemy && angle > 0.0f ) + { + self->waterlevel = MGT_STATE_RISE; + self->s.angles2[ PITCH ] = + MAX( 0.0f, angle - MGTURRET_ANGULARSPEED * 0.5f ); + } + else + self->waterlevel = MGT_STATE_ACTIVE; + } + + return qfalse; +} /* ================ @@ -2445,11 +2524,18 @@ void HMGTurret_Think( gentity_t *self ) // Turn off client side muzzle flashes self->s.eFlags &= ~EF_FIRING; + self->powered = G_FindPower( self ); G_SuicideIfNoPower( self ); + G_IdlePowerState( self ); // If not powered or spawned don't do anything - if( !( self->powered = G_FindPower( self ) ) ) + if( !self->powered ) { + // if power loss drop turret + if( self->spawned && + HMGTurret_State( self, MGT_STATE_INACTIVE ) ); + return; + self->nextthink = level.time + POWER_REFRESH_TIME; return; } @@ -2463,6 +2549,8 @@ void HMGTurret_Think( gentity_t *self ) self->turretSpinupTime = -1; HMGTurret_FindEnemy( self ); } + // if newly powered raise turret + HMGTurret_State( self, MGT_STATE_ACTIVE ); if( !self->enemy ) return; @@ -2517,10 +2605,12 @@ void HTeslaGen_Think( gentity_t *self ) { self->nextthink = level.time + BG_Buildable( self->s.modelindex )->nextthink; + self->powered = G_FindPower( self ); G_SuicideIfNoPower( self ); + G_IdlePowerState( self ); //if not powered don't do anything and check again for power next think - if( !( self->powered = G_FindPower( self ) ) ) + if( !self->powered ) { self->s.eFlags &= ~EF_FIRING; self->nextthink = level.time + POWER_REFRESH_TIME; @@ -3691,6 +3781,7 @@ static gentity_t *G_Build( gentity_t *builder, buildable_t buildable, vec3_t ori VectorCopy( angles, built->s.angles ); built->s.angles[ PITCH ] = 0.0f; built->s.angles2[ YAW ] = angles[ YAW ]; + built->s.angles2[ PITCH ] = MGTURRET_VERTICALCAP; built->s.pos.trType = BG_Buildable( buildable )->traj; built->s.pos.trTime = level.time; built->physicsBounce = BG_Buildable( buildable )->bounce; -- cgit