diff options
-rw-r--r-- | src/game/g_mover.c | 292 | ||||
-rw-r--r-- | src/game/g_spawn.c | 1 |
2 files changed, 185 insertions, 108 deletions
diff --git a/src/game/g_mover.c b/src/game/g_mover.c index be821c21..f8a3f41c 100644 --- a/src/game/g_mover.c +++ b/src/game/g_mover.c @@ -371,6 +371,12 @@ void G_MoverTeam( gentity_t *ent ) pushed_p = pushed; for( part = ent; part; part = part->teamchain ) { + if( part->s.pos.trType == TR_STATIONARY && + part->s.apos.trType == TR_STATIONARY ) + { + continue; + } + // get current position BG_EvaluateTrajectory( &part->s.pos, level.time, origin ); BG_EvaluateTrajectory( &part->s.apos, level.time, angles ); @@ -385,6 +391,12 @@ void G_MoverTeam( gentity_t *ent ) // go back to the previous position for( part = ent; part; part = part->teamchain ) { + if( part->s.pos.trType == TR_STATIONARY && + part->s.apos.trType == TR_STATIONARY ) + { + continue; + } + part->s.pos.trTime += level.time - level.previousTime; part->s.apos.trTime += level.time - level.previousTime; BG_EvaluateTrajectory( &part->s.pos, level.time, part->r.currentOrigin ); @@ -434,10 +446,7 @@ void G_RunMover( gentity_t *ent ) if( ent->flags & FL_TEAMSLAVE ) return; - // if stationary at one of the positions, don't move anything - if( ( ent->s.pos.trType != TR_STATIONARY || ent->s.apos.trType != TR_STATIONARY ) && - ent->moverState < MODEL_POS1 ) //yuck yuck hack - G_MoverTeam( ent ); + G_MoverTeam( ent ); // check think function G_RunThink( ent ); @@ -546,7 +555,6 @@ void SetMoverState( gentity_t *ent, moverState_t moverState, int time ) MatchTeam All entities in a mover team will move from pos1 to pos2 -in the same amount of time ================ */ void MatchTeam( gentity_t *teamLeader, int moverState, int time ) @@ -558,40 +566,65 @@ void MatchTeam( gentity_t *teamLeader, int moverState, int time ) } +/* +================ +MasterOf +================ +*/ +gentity_t *MasterOf( gentity_t *ent ) +{ + if( ent->teammaster ) + return ent->teammaster; + else + return ent; +} + /* ================ -ReturnToPos1 +GetMoverTeamState + +Returns a MOVER_* value representing the phase (either one + of pos1, 1to2, pos2, or 2to1) of a mover team as a whole. ================ */ -void ReturnToPos1( gentity_t *ent ) +moverState_t GetMoverTeamState( gentity_t *ent ) { - MatchTeam( ent, MOVER_2TO1, level.time ); + qboolean pos1 = qfalse; - // looping sound - ent->s.loopSound = ent->soundLoop; + for( ent = MasterOf( ent ); ent; ent = ent->teamchain ) + { + if( ent->moverState == MOVER_POS1 || ent->moverState == ROTATOR_POS1 ) + pos1 = qtrue; + else if( ent->moverState == MOVER_1TO2 || ent->moverState == ROTATOR_1TO2 ) + return MOVER_1TO2; + else if( ent->moverState == MOVER_2TO1 || ent->moverState == ROTATOR_2TO1 ) + return MOVER_2TO1; + } - // starting sound - if( ent->sound2to1 ) - G_AddEvent( ent, EV_GENERAL_SOUND, ent->sound2to1 ); + if( pos1 ) + return MOVER_POS1; + else + return MOVER_POS2; } /* ================ -ReturnToApos1 +ReturnToPos1orApos1 + +Used only by a master movers. ================ */ -void ReturnToApos1( gentity_t *ent ) -{ - MatchTeam( ent, ROTATOR_2TO1, level.time ); - // looping sound - ent->s.loopSound = ent->soundLoop; +void Use_BinaryMover( gentity_t *ent, gentity_t *other, gentity_t *activator ); - // starting sound - if( ent->sound2to1 ) - G_AddEvent( ent, EV_GENERAL_SOUND, ent->sound2to1 ); +void ReturnToPos1orApos1( gentity_t *ent ) +{ + if( GetMoverTeamState( ent ) != MOVER_POS2 ) + return; // not every mover in the team has reached its endpoint yet + + Use_BinaryMover( ent, ent, ent->activator ); } @@ -682,10 +715,10 @@ void Think_OpenModelDoor( gentity_t *ent ) //set brush non-solid trap_UnlinkEntity( ent->clipBrush ); - // looping sound - ent->s.loopSound = ent->soundLoop; + // stop the looping sound + ent->s.loopSound = 0; - // starting sound + // play sound if( ent->soundPos2 ) G_AddEvent( ent, EV_GENERAL_SOUND, ent->soundPos2 ); @@ -710,8 +743,10 @@ Reached_BinaryMover */ void Reached_BinaryMover( gentity_t *ent ) { + gentity_t *master = MasterOf( ent ); + // stop the looping sound - ent->s.loopSound = ent->soundLoop; + ent->s.loopSound = 0; if( ent->moverState == MOVER_1TO2 ) { @@ -723,8 +758,8 @@ void Reached_BinaryMover( gentity_t *ent ) G_AddEvent( ent, EV_GENERAL_SOUND, ent->soundPos2 ); // return to pos1 after a delay - ent->think = ReturnToPos1; - ent->nextthink = level.time + ent->wait; + master->think = ReturnToPos1orApos1; + master->nextthink = MAX( master->nextthink, level.time + ent->wait ); // fire targets if( !ent->activator ) @@ -755,8 +790,8 @@ void Reached_BinaryMover( gentity_t *ent ) G_AddEvent( ent, EV_GENERAL_SOUND, ent->soundPos2 ); // return to apos1 after a delay - ent->think = ReturnToApos1; - ent->nextthink = level.time + ent->wait; + master->think = ReturnToPos1orApos1; + master->nextthink = MAX( master->nextthink, level.time + ent->wait ); // fire targets if( !ent->activator ) @@ -791,6 +826,8 @@ void Use_BinaryMover( gentity_t *ent, gentity_t *other, gentity_t *activator ) { int total; int partial; + gentity_t *master; + moverState_t teamState; // if this is a non-client-usable door return if( ent->targetname && other && other->client ) @@ -805,11 +842,17 @@ void Use_BinaryMover( gentity_t *ent, gentity_t *other, gentity_t *activator ) ent->activator = activator; + master = MasterOf( ent ); + teamState = GetMoverTeamState( ent ); + + for( ent = master; ent; ent = ent->teamchain ) + { + //ind if( ent->moverState == MOVER_POS1 ) { // start moving 50 msec later, becase if this was player // triggered, level.time hasn't been advanced yet - MatchTeam( ent, MOVER_1TO2, level.time + 50 ); + SetMoverState( ent, MOVER_1TO2, level.time + 50 ); // starting sound if( ent->sound1to2 ) @@ -822,10 +865,30 @@ void Use_BinaryMover( gentity_t *ent, gentity_t *other, gentity_t *activator ) if( ent->teammaster == ent || !ent->teammaster ) trap_AdjustAreaPortalState( ent, qtrue ); } - else if( ent->moverState == MOVER_POS2 ) + else if( ent->moverState == MOVER_POS2 && + !( teamState == MOVER_1TO2 || other == master ) ) { // if all the way up, just delay before coming down - ent->nextthink = level.time + ent->wait; + master->think = ReturnToPos1orApos1; + master->nextthink = MAX( master->nextthink, level.time + ent->wait ); + } + else if( ent->moverState == MOVER_POS2 && + ( teamState == MOVER_1TO2 || other == master ) ) + { + // start moving 50 msec later, becase if this was player + // triggered, level.time hasn't been advanced yet + SetMoverState( ent, MOVER_2TO1, level.time + 50 ); + + // starting sound + if( ent->sound2to1 ) + G_AddEvent( ent, EV_GENERAL_SOUND, ent->sound2to1 ); + + // looping sound + ent->s.loopSound = ent->soundLoop; + + // open areaportal + if( ent->teammaster == ent || !ent->teammaster ) + trap_AdjustAreaPortalState( ent, qtrue ); } else if( ent->moverState == MOVER_2TO1 ) { @@ -836,7 +899,7 @@ void Use_BinaryMover( gentity_t *ent, gentity_t *other, gentity_t *activator ) if( partial > total ) partial = total; - MatchTeam( ent, MOVER_1TO2, level.time - ( total - partial ) ); + SetMoverState( ent, MOVER_1TO2, level.time - ( total - partial ) ); if( ent->sound1to2 ) G_AddEvent( ent, EV_GENERAL_SOUND, ent->sound1to2 ); @@ -850,7 +913,7 @@ void Use_BinaryMover( gentity_t *ent, gentity_t *other, gentity_t *activator ) if( partial > total ) partial = total; - MatchTeam( ent, MOVER_2TO1, level.time - ( total - partial ) ); + SetMoverState( ent, MOVER_2TO1, level.time - ( total - partial ) ); if( ent->sound2to1 ) G_AddEvent( ent, EV_GENERAL_SOUND, ent->sound2to1 ); @@ -859,7 +922,7 @@ void Use_BinaryMover( gentity_t *ent, gentity_t *other, gentity_t *activator ) { // start moving 50 msec later, becase if this was player // triggered, level.time hasn't been advanced yet - MatchTeam( ent, ROTATOR_1TO2, level.time + 50 ); + SetMoverState( ent, ROTATOR_1TO2, level.time + 50 ); // starting sound if( ent->sound1to2 ) @@ -872,10 +935,30 @@ void Use_BinaryMover( gentity_t *ent, gentity_t *other, gentity_t *activator ) if( ent->teammaster == ent || !ent->teammaster ) trap_AdjustAreaPortalState( ent, qtrue ); } - else if( ent->moverState == ROTATOR_POS2 ) + else if( ent->moverState == ROTATOR_POS2 && + !( teamState == MOVER_1TO2 || other == master ) ) { // if all the way up, just delay before coming down - ent->nextthink = level.time + ent->wait; + master->think = ReturnToPos1orApos1; + master->nextthink = MAX( master->nextthink, level.time + ent->wait ); + } + else if( ent->moverState == ROTATOR_POS2 && + ( teamState == MOVER_1TO2 || other == master ) ) + { + // start moving 50 msec later, becase if this was player + // triggered, level.time hasn't been advanced yet + SetMoverState( ent, ROTATOR_2TO1, level.time + 50 ); + + // starting sound + if( ent->sound2to1 ) + G_AddEvent( ent, EV_GENERAL_SOUND, ent->sound2to1 ); + + // looping sound + ent->s.loopSound = ent->soundLoop; + + // open areaportal + if( ent->teammaster == ent || !ent->teammaster ) + trap_AdjustAreaPortalState( ent, qtrue ); } else if( ent->moverState == ROTATOR_2TO1 ) { @@ -886,7 +969,7 @@ void Use_BinaryMover( gentity_t *ent, gentity_t *other, gentity_t *activator ) if( partial > total ) partial = total; - MatchTeam( ent, ROTATOR_1TO2, level.time - ( total - partial ) ); + SetMoverState( ent, ROTATOR_1TO2, level.time - ( total - partial ) ); if( ent->sound1to2 ) G_AddEvent( ent, EV_GENERAL_SOUND, ent->sound1to2 ); @@ -900,7 +983,7 @@ void Use_BinaryMover( gentity_t *ent, gentity_t *other, gentity_t *activator ) if( partial > total ) partial = total; - MatchTeam( ent, ROTATOR_2TO1, level.time - ( total - partial ) ); + SetMoverState( ent, ROTATOR_2TO1, level.time - ( total - partial ) ); if( ent->sound2to1 ) G_AddEvent( ent, EV_GENERAL_SOUND, ent->sound2to1 ); @@ -931,6 +1014,8 @@ void Use_BinaryMover( gentity_t *ent, gentity_t *other, gentity_t *activator ) // if all the way up, just delay before coming down ent->nextthink = level.time + ent->wait; } + //outd + } } @@ -951,15 +1036,16 @@ void InitMover( gentity_t *ent ) vec3_t color; qboolean lightSet, colorSet; char *sound; + char *team; // if the "model2" key is set, use a seperate model // for drawing, but clip against the brushes if( ent->model2 ) ent->s.modelindex2 = G_ModelIndex( ent->model2 ); - // if the "loopsound" key is set, use a constant looping sound when moving - if( G_SpawnString( "noise", "100", &sound ) ) - ent->s.loopSound = G_SoundIndex( sound ); + // if the "noise" key is set, use a constant looping sound when moving + if( G_SpawnString( "noise", "", &sound ) ) + ent->soundLoop = G_SoundIndex( sound ); // if the "color" or "light" keys are set, setup constantLight lightSet = G_SpawnFloat( "light", "100", &light ); @@ -992,8 +1078,10 @@ void InitMover( gentity_t *ent ) ent->use = Use_BinaryMover; ent->reached = Reached_BinaryMover; + if( G_SpawnString( "team", "", &team ) ) + ent->team = G_CopyString( team ); + ent->moverState = MOVER_POS1; - ent->r.svFlags = SVF_USE_CURRENT_ORIGIN; ent->s.eType = ET_MOVER; VectorCopy( ent->pos1, ent->r.currentOrigin ); trap_LinkEntity( ent ); @@ -1031,15 +1119,16 @@ void InitRotator( gentity_t *ent ) vec3_t color; qboolean lightSet, colorSet; char *sound; + char *team; // if the "model2" key is set, use a seperate model // for drawing, but clip against the brushes if( ent->model2 ) ent->s.modelindex2 = G_ModelIndex( ent->model2 ); - // if the "loopsound" key is set, use a constant looping sound when moving - if( G_SpawnString( "noise", "100", &sound ) ) - ent->s.loopSound = G_SoundIndex( sound ); + // if the "noise" key is set, use a constant looping sound when moving + if( G_SpawnString( "noise", "", &sound ) ) + ent->soundLoop = G_SoundIndex( sound ); // if the "color" or "light" keys are set, setup constantLight lightSet = G_SpawnFloat( "light", "100", &light ); @@ -1076,8 +1165,10 @@ void InitRotator( gentity_t *ent ) ent->use = Use_BinaryMover; ent->reached = Reached_BinaryMover; + if( G_SpawnString( "team", "", &team ) ) + ent->team = G_CopyString( team ); + ent->moverState = ROTATOR_POS1; - ent->r.svFlags = SVF_USE_CURRENT_ORIGIN; ent->s.eType = ET_MOVER; VectorCopy( ent->pos1, ent->r.currentAngles ); trap_LinkEntity( ent ); @@ -1291,25 +1382,30 @@ Touch_DoorTrigger */ void Touch_DoorTrigger( gentity_t *ent, gentity_t *other, trace_t *trace ) { + moverState_t teamState; + //buildables don't trigger movers if( other->s.eType == ET_BUILDABLE ) return; + teamState = GetMoverTeamState( ent->parent ); + if( other->client && other->client->sess.spectatorState != SPECTATOR_NOT ) { // if the door is not open and not opening - if( ent->parent->moverState != MOVER_1TO2 && - ent->parent->moverState != MOVER_POS2 && - ent->parent->moverState != ROTATOR_1TO2 && - ent->parent->moverState != ROTATOR_POS2 ) + if( teamState != MOVER_POS2 && teamState != MOVER_1TO2 ) Touch_DoorTriggerSpectator( ent, other, trace ); } - else if( ent->parent->moverState != MOVER_1TO2 && - ent->parent->moverState != ROTATOR_1TO2 && - ent->parent->moverState != ROTATOR_2TO1 ) - { + else if( teamState != MOVER_1TO2 ) Use_BinaryMover( ent->parent, ent, other ); - } +} + + +void Think_MatchTeam( gentity_t *ent ) +{ + if( ent->flags & FL_TEAMSLAVE ) + return; + MatchTeam( ent, ent->moverState, level.time ); } @@ -1361,12 +1457,7 @@ void Think_SpawnNewDoorTrigger( gentity_t *ent ) trap_LinkEntity( other ); if( ent->moverState < MODEL_POS1 ) - MatchTeam( ent, ent->moverState, level.time ); -} - -void Think_MatchTeam( gentity_t *ent ) -{ - MatchTeam( ent, ent->moverState, level.time ); + Think_MatchTeam( ent ); } @@ -1393,6 +1484,7 @@ void SP_func_door( gentity_t *ent ) vec3_t size; float lip; char *s; + int health; G_SpawnString( "sound2to1", "sound/movers/doors/dr1_strt.wav", &s ); ent->sound2to1 = G_SoundIndex( s ); @@ -1449,22 +1541,17 @@ void SP_func_door( gentity_t *ent ) ent->nextthink = level.time + FRAMETIME; - if( !( ent->flags & FL_TEAMSLAVE ) ) - { - int health; - - G_SpawnInt( "health", "0", &health ); - if( health ) - ent->takedamage = qtrue; + G_SpawnInt( "health", "0", &health ); + if( health ) + ent->takedamage = qtrue; - if( ent->targetname || health ) - { - // non touch/shoot doors - ent->think = Think_MatchTeam; - } - else - ent->think = Think_SpawnNewDoorTrigger; + if( ent->targetname || health ) + { + // non touch/shoot doors + ent->think = Think_MatchTeam; } + else + ent->think = Think_SpawnNewDoorTrigger; } /*QUAKED func_door_rotating (0 .5 .8) START_OPEN CRUSHER REVERSE TOGGLE X_AXIS Y_AXIS @@ -1489,6 +1576,7 @@ void SP_func_door( gentity_t *ent ) void SP_func_door_rotating( gentity_t *ent ) { char *s; + int health; G_SpawnString( "sound2to1", "sound/movers/doors/dr1_strt.wav", &s ); ent->sound2to1 = G_SoundIndex( s ); @@ -1567,23 +1655,17 @@ void SP_func_door_rotating( gentity_t *ent ) ent->nextthink = level.time + FRAMETIME; - if( !( ent->flags & FL_TEAMSLAVE ) ) - { - int health; - - G_SpawnInt( "health", "0", &health ); - - if( health ) - ent->takedamage = qtrue; + G_SpawnInt( "health", "0", &health ); + if( health ) + ent->takedamage = qtrue; - if( ent->targetname || health ) - { - // non touch/shoot doors - ent->think = Think_MatchTeam; - } - else - ent->think = Think_SpawnNewDoorTrigger; + if( ent->targetname || health ) + { + // non touch/shoot doors + ent->think = Think_MatchTeam; } + else + ent->think = Think_SpawnNewDoorTrigger; } /*QUAKED func_door_model (0 .5 .8) ? START_OPEN @@ -1607,6 +1689,7 @@ void SP_func_door_model( gentity_t *ent ) qboolean lightSet, colorSet; char *sound; gentity_t *clipBrush; + int health; G_SpawnString( "sound2to1", "sound/movers/doors/dr1_strt.wav", &s ); ent->sound2to1 = G_SoundIndex( s ); @@ -1653,9 +1736,9 @@ void SP_func_door_model( gentity_t *ent ) else ent->s.modelindex = G_ModelIndex( ent->model2 ); - // if the "loopsound" key is set, use a constant looping sound when moving - if( G_SpawnString( "noise", "100", &sound ) ) - ent->s.loopSound = G_SoundIndex( sound ); + // if the "noise" key is set, use a constant looping sound when moving + if( G_SpawnString( "noise", "", &sound ) ) + ent->soundLoop = G_SoundIndex( sound ); // if the "color" or "light" keys are set, setup constantLight lightSet = G_SpawnFloat( "light", "100", &light ); @@ -1710,19 +1793,14 @@ void SP_func_door_model( gentity_t *ent ) trap_LinkEntity( ent ); - if( !( ent->flags & FL_TEAMSLAVE ) ) - { - int health; - - G_SpawnInt( "health", "0", &health ); - if( health ) - ent->takedamage = qtrue; + G_SpawnInt( "health", "0", &health ); + if( health ) + ent->takedamage = qtrue; - if( !( ent->targetname || health ) ) - { - ent->nextthink = level.time + FRAMETIME; - ent->think = Think_SpawnNewDoorTrigger; - } + if( !( ent->targetname || health ) ) + { + ent->nextthink = level.time + FRAMETIME; + ent->think = Think_SpawnNewDoorTrigger; } } diff --git a/src/game/g_spawn.c b/src/game/g_spawn.c index 03c5de03..69dcbabd 100644 --- a/src/game/g_spawn.c +++ b/src/game/g_spawn.c @@ -134,7 +134,6 @@ field_t fields[ ] = {"targetname", FOFS(targetname), F_STRING}, {"targetShaderName", FOFS(targetShaderName), F_STRING}, {"targetShaderNewName", FOFS(targetShaderNewName), F_STRING}, - {"team", FOFS(team), F_STRING}, {"wait", FOFS(wait), F_FLOAT} }; |