summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/game/g_mover.c292
-rw-r--r--src/game/g_spawn.c1
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}
};