Example #1
0
/*
================
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 ) {
	gentity_t		*slave;

	for ( slave = teamLeader ; slave ; slave = slave->teamchain ) {
		SetMoverState( slave, moverState, time );
	}
}
Example #2
0
/*
================
Reached_BinaryMover
================
*/
void Reached_BinaryMover( gentity_t *ent ) {

	// stop the looping sound
	ent->s.loopSound = ent->soundLoop;

	if ( ent->moverState == MOVER_1TO2 ) {
		// reached pos2
		SetMoverState( ent, MOVER_POS2, level.time );

		// play sound
		if ( ent->soundPos2 ) {
			G_AddEvent( ent, EV_GENERAL_SOUND, ent->soundPos2 );
		}

		// return to pos1 after a delay
		ent->think = ReturnToPos1;
		ent->nextthink = level.time + ent->wait;

		// fire targets
		if ( !ent->activator ) {
			ent->activator = ent;
		}
		G_UseTargets( ent, ent->activator );
	} else if ( ent->moverState == MOVER_2TO1 ) {
		// reached pos1
		SetMoverState( ent, MOVER_POS1, level.time );

		// play sound
		if ( ent->soundPos1 ) {
			G_AddEvent( ent, EV_GENERAL_SOUND, ent->soundPos1 );
		}

		// close areaportals
		if ( ent->teammaster == ent || !ent->teammaster ) {
			trap_AdjustAreaPortalState( ent, qfalse );
		}
	} else {
		G_Error( "Reached_BinaryMover: bad moverState" );
	}
}
Example #3
0
/*
===============
Reached_Train
===============
*/
void Reached_Train( gentity_t *ent ) {
	gentity_t		*next;
	float			speed;
	vec3_t			move;
	float			length;

	// copy the apropriate values
	next = ent->nextTrain;
	if ( !next || !next->nextTrain ) {
		return;		// just stop
	}

	// fire all other targets
	G_UseTargets( next, NULL );

	// set the new trajectory
	ent->nextTrain = next->nextTrain;
	VectorCopy( next->s.origin, ent->pos1 );
	VectorCopy( next->nextTrain->s.origin, ent->pos2 );

	// if the path_corner has a speed, use that
	if ( next->speed ) {
		speed = next->speed;
	} else {
		// otherwise use the train's speed
		speed = ent->speed;
	}
	if ( speed < 1 ) {
		speed = 1;
	}

	// calculate duration
	VectorSubtract( ent->pos2, ent->pos1, move );
	length = VectorLength( move );

	ent->s.pos.trDuration = length * 1000 / speed;

	// looping sound
	ent->s.loopSound = next->soundLoop;

	// start it going
	SetMoverState( ent, MOVER_1TO2, level.time );

	// if there is a "wait" value on the target, don't start moving yet
	if ( next->wait ) {
		ent->nextthink = level.time + next->wait * 1000;
		ent->think = Think_BeginMoving;
		ent->s.pos.trType = TR_STATIONARY;
	}
}
Example #4
0
/*
===============
Reached_Train
===============
*/
void Reached_Train( gentity_t *ent ) {
	gentity_t		*next;
	float			speed;
	vec3_t			move;
	float			length;

	// copy the apropriate values
	next = ent->nextTrain;
	if ( !next || !next->nextTrain ) {
		return;		// just stop
	}

	// fire all other targets
	G_UseTargets( next, NULL );

	// set the new trajectory
	ent->nextTrain = next->nextTrain;
	VectorCopy( next->s.origin, ent->pos1 );
	VectorCopy( next->nextTrain->s.origin, ent->pos2 );

	// if the path_corner has a speed, use that
	if ( next->speed ) {
		speed = next->speed;
	} else {
		// otherwise use the train's speed
		speed = ent->speed;
	}
	if ( speed < 1 ) {
		speed = 1;
	}

	// calculate duration
	VectorSubtract( ent->pos2, ent->pos1, move );
	length = VectorLength( move );

	ent->s.pos.trDuration = length * 1000 / speed;

	// Tequila comment: Be sure to send to clients after any fast move case
	ent->r.svFlags &= ~SVF_NOCLIENT;

	// Tequila comment: Fast move case
	if(ent->s.pos.trDuration<1) {
		// Tequila comment: As trDuration is used later in a division, we need to avoid that case now
		// With null trDuration,
		// the calculated rocks bounding box becomes infinite and the engine think for a short time
		// any entity is riding that mover but not the world entity... In rare case, I found it
		// can also stuck every map entities after func_door are used.
		// The desired effect with very very big speed is to have instant move, so any not null duration
		// lower than a frame duration should be sufficient.
		// Afaik, the negative case don't have to be supported.
		ent->s.pos.trDuration=1;

		// Tequila comment: Don't send entity to clients so it becomes really invisible 
		ent->r.svFlags |= SVF_NOCLIENT;
	}

	// looping sound
	ent->s.loopSound = next->soundLoop;

	// start it going
	SetMoverState( ent, MOVER_1TO2, level.time );

	// if there is a "wait" value on the target, don't start moving yet
	if ( next->wait ) {
		ent->nextthink = level.time + next->wait * 1000;
		ent->think = Think_BeginMoving;
		ent->s.pos.trType = TR_STATIONARY;
	}
}
Example #5
0
/*
===========
G_ReachedPath
===========
*/
qboolean G_ReachedPath(gentity_t *ent, qboolean check)
{
	gentity_t	*point;
	qboolean	backward;

	if (!(ent->s.eFlags & EF_PATHMODE)) {
		return qfalse;
	}

	if (ent->player) {
		backward = (ent->player->ps.eFlags & EF_TRAINBACKWARD);
	} else {
		backward = (ent->s.eFlags & EF_TRAINBACKWARD);
	}

	if (backward) {
		point = ent->prevTrain;
	} else {
		point = ent->nextTrain;
	}

	if (!point && ent->player) {
		// Previous point
		if (backward)
			point = ent->nextTrain;
		else
			point = ent->prevTrain;

		// Stop train
		return qfalse;
	} else if (!point && !ent->player) {
		// end of path
		if (!(ent->spawnflags & 1)) {
			// Stop train
			return qfalse;
		}

		// Previous point
		if (backward)
			point = ent->nextTrain;
		else
			point = ent->prevTrain;

		// Go back the way you came
		backward = !backward;
		ent->s.eFlags ^= EF_TRAINBACKWARD;

		// Next point
		if (backward)
			point = ent->prevTrain;
		else
			point = ent->nextTrain;

		if (!point) {
			return qfalse;
		}
	}

	if ((!backward && point == point->nextTrain) || (backward && point == point->prevTrain)) {
		// Entity points to self...
		G_Printf("DEBUG: Entity points to self!\n");
		return qfalse;
	}

	// ZTM: Check if we have made it to the next train
	//               Doesn't work with PATHF_AXIS!
	if (check)
	{
		vec3_t targetPos;
		vec3_t origin;
		vec_t dist;

		VectorCopy(point->s.origin, targetPos);

		if (ent->player)
			VectorCopy(ent->player->ps.origin, origin);
		else
			VectorCopy(ent->s.origin, origin);

		if (ent->player && ent->player->ps.pathMode == PATHMODE_SIDE) {
			// "2D" path
			origin[2] = targetPos[2] = 0; // Don't compare Z
		}

		dist = Distance(origin, targetPos);

		if (dist > 20.0f) {
			return qfalse;
		}
	}

	// fire all other targets
	G_UseTargets( point, ent );

	// Setup next move
	if (backward) {
		ent->prevTrain = point->prevTrain;
		if (ent->prevTrain) {
			ent->nextTrain = point;
		}
	} else {
		ent->nextTrain = point->nextTrain;
		if (ent->nextTrain) {
			ent->prevTrain = point;
		}
	}

	// set the new trajectory
	if (ent->prevTrain) {
		VectorCopy( ent->prevTrain->s.origin, ent->pos1 );
	}
	if (ent->nextTrain) {
		VectorCopy( ent->nextTrain->s.origin, ent->pos2 );
	}

	if (ent->s.eType == ET_MOVER)
	{
		float			speed;
		vec3_t			move;
		float			length;

		// if the path_corner has a speed, use that
		if ( point->speed ) {
			speed = point->speed;
		} else {
			// otherwise use the train's speed
			speed = ent->speed;
		}
		if ( speed < 1 ) {
			speed = 1;
		}

		// calculate duration
		VectorSubtract( ent->pos2, ent->pos1, move );
		length = VectorLength( move );

		ent->s.pos.trDuration = length * 1000 / speed;

		// Tequila comment: Be sure to send to clients after any fast move case
		ent->r.svFlags &= ~SVF_NOCLIENT;

		// Tequila comment: Fast move case
		if(ent->s.pos.trDuration<1) {
			// Tequila comment: As trDuration is used later in a division, we need to avoid that case now
			// With null trDuration,
			// the calculated rocks bounding box becomes infinite and the engine think for a short time
			// any entity is riding that mover but not the world entity... In rare case, I found it
			// can also stuck every map entities after func_door are used.
			// The desired effect with very very big speed is to have instant move, so any not null duration
			// lower than a frame duration should be sufficient.
			// Afaik, the negative case don't have to be supported.
			ent->s.pos.trDuration=1;

			// Tequila comment: Don't send entity to clients so it becomes really invisible 
			ent->r.svFlags |= SVF_NOCLIENT;
		}

		// looping sound
		ent->s.loopSound = point->soundLoop;

		// start it going
		if (backward)
			SetMoverState( ent, MOVER_2TO1, level.time );
		else
			SetMoverState( ent, MOVER_1TO2, level.time );

		// if there is a "wait" value on the target, don't start moving yet
		if ( point->wait ) {
			ent->nextthink = level.time + point->wait * 1000;
			ent->think = Think_BeginMoving;
			ent->s.pos.trType = TR_STATIONARY;
		}
	}
	else if (ent->player)
	{
		vec3_t dir;
		vec3_t viewAngles;
		int mode;

		// Set path movement style
		mode = point->moverState;

		// Unset style means use pervious style.
		if (!mode) {
			mode = ent->player->ps.pathMode;
		}

		VectorCopy( ent->pos1, ent->player->ps.grapplePoint );
		VectorCopy( ent->pos2, ent->player->ps.nextPoint );

		if (backward)
			VectorSubtract( ent->pos1, ent->player->ps.origin, dir );
		else
			VectorSubtract( ent->pos2, ent->player->ps.origin, dir );

		vectoangles( dir, viewAngles );
		viewAngles[ROLL] = ent->player->ps.viewangles[ROLL];
		viewAngles[PITCH] = ent->player->ps.viewangles[PITCH];
		SetPlayerViewAngle(ent, viewAngles);

		if (mode == PATHMODE_SIDE) {
			if (backward) {
				ent->player->ps.stats[STAT_DEAD_YAW] = viewAngles[YAW]-90;
			} else {
				ent->player->ps.stats[STAT_DEAD_YAW] = viewAngles[YAW]+90;
			}
		} else {
			ent->player->ps.stats[STAT_DEAD_YAW] = viewAngles[YAW];
		}

		if (mode != ent->player->ps.pathMode) {
			// ZTM: Do we need to do anything when the mode changes?
			ent->player->ps.pathMode = mode;
		}
	}

	return qtrue;
}
/*
===============
G_ScriptAction_GotoMarker

  syntax: gotomarker <targetname> <speed> [accel/deccel] [turntotarget] [wait]

  NOTE: speed may be modified to round the duration to the next 50ms for smooth
  transitions
===============
*/
qboolean G_ScriptAction_GotoMarker( gentity_t *ent, char *params ) {
    char    *pString, *token;
    gentity_t *target;
    vec3_t vec;
    float speed, dist;
    qboolean wait = qfalse, turntotarget = qfalse;
    int trType;
    int duration, i;
    vec3_t diff;
    vec3_t angles;

    if ( params && ( ent->scriptStatus.scriptFlags & SCFL_GOING_TO_MARKER ) ) {
        // we can't process a new movement until the last one has finished
        return qfalse;
    }

    if ( !params || ent->scriptStatus.scriptStackChangeTime < level.time ) {          // we are waiting for it to reach destination
        if ( ent->s.pos.trTime + ent->s.pos.trDuration <= level.time ) {  // we made it
            ent->scriptStatus.scriptFlags &= ~SCFL_GOING_TO_MARKER;

            // set the angles at the destination
            BG_EvaluateTrajectory( &ent->s.apos, ent->s.apos.trTime + ent->s.apos.trDuration, ent->s.angles );
            VectorCopy( ent->s.angles, ent->s.apos.trBase );
            VectorCopy( ent->s.angles, ent->r.currentAngles );
            ent->s.apos.trTime = level.time;
            ent->s.apos.trDuration = 0;
            ent->s.apos.trType = TR_STATIONARY;
            VectorClear( ent->s.apos.trDelta );

            // stop moving
            BG_EvaluateTrajectory( &ent->s.pos, level.time, ent->s.origin );
            VectorCopy( ent->s.origin, ent->s.pos.trBase );
            VectorCopy( ent->s.origin, ent->r.currentOrigin );
            ent->s.pos.trTime = level.time;
            ent->s.pos.trDuration = 0;
            ent->s.pos.trType = TR_STATIONARY;
            VectorClear( ent->s.pos.trDelta );

            script_linkentity( ent );

            return qtrue;
        }
    } else {    // we have just started this command

        pString = params;
        token = COM_ParseExt( &pString, qfalse );
        if ( !token[0] ) {
            G_Error( "G_Scripting: gotomarker must have an targetname\n" );
        }

        // find the entity with the given "targetname"
        target = G_Find( NULL, FOFS( targetname ), token );

        if ( !target ) {
            G_Error( "G_Scripting: can't find entity with \"targetname\" = \"%s\"\n", token );
        }

        VectorSubtract( target->r.currentOrigin, ent->r.currentOrigin, vec );

        token = COM_ParseExt( &pString, qfalse );
        if ( !token[0] ) {
            G_Error( "G_Scripting: gotomarker must have a speed\n" );
        }

        speed = atof( token );
        trType = TR_LINEAR_STOP;

        while ( token[0] ) {
            token = COM_ParseExt( &pString, qfalse );
            if ( token[0] ) {
                if ( !Q_stricmp( token, "accel" ) ) {
                    trType = TR_ACCELERATE;
                } else if ( !Q_stricmp( token, "deccel" ) )      {
                    trType = TR_DECCELERATE;
                } else if ( !Q_stricmp( token, "wait" ) )      {
                    wait = qtrue;
                } else if ( !Q_stricmp( token, "turntotarget" ) )      {
                    turntotarget = qtrue;
                }
            }
        }

        // start the movement
        if ( ent->s.eType == ET_MOVER ) {

            VectorCopy( vec, ent->movedir );
            VectorCopy( ent->r.currentOrigin, ent->pos1 );
            VectorCopy( target->r.currentOrigin, ent->pos2 );
            ent->speed = speed;
            dist = VectorDistance( ent->pos1, ent->pos2 );
            // setup the movement with the new parameters
            InitMover( ent );

            // start the movement

            SetMoverState( ent, MOVER_1TO2, level.time );
            if ( trType != TR_LINEAR_STOP ) { // allow for acceleration/decceleration
                ent->s.pos.trDuration = 1000.0 * dist / ( speed / 2.0 );
                ent->s.pos.trType = trType;
            }
            ent->reached = NULL;

            if ( turntotarget ) {
                duration = ent->s.pos.trDuration;
                VectorCopy( target->s.angles, angles );

                for ( i = 0; i < 3; i++ ) {
                    diff[i] = AngleDifference( angles[i], ent->s.angles[i] );
                    while ( diff[i] > 180 )
                        diff[i] -= 360;
                    while ( diff[i] < -180 )
                        diff[i] += 360;
                }
                VectorCopy( ent->s.angles, ent->s.apos.trBase );
                if ( duration ) {
                    VectorScale( diff, 1000.0 / (float)duration, ent->s.apos.trDelta );
                } else {
                    VectorClear( ent->s.apos.trDelta );
                }
                ent->s.apos.trDuration = duration;
                ent->s.apos.trTime = level.time;
                ent->s.apos.trType = TR_LINEAR_STOP;
                if ( trType != TR_LINEAR_STOP ) { // allow for acceleration/decceleration
                    ent->s.pos.trDuration = 1000.0 * dist / ( speed / 2.0 );
                    ent->s.pos.trType = trType;
                }
            }

        } else {
            // calculate the trajectory
            ent->s.pos.trType = TR_LINEAR_STOP;
            ent->s.pos.trTime = level.time;
            VectorCopy( ent->r.currentOrigin, ent->s.pos.trBase );
            dist = VectorNormalize( vec );
            VectorScale( vec, speed, ent->s.pos.trDelta );
            ent->s.pos.trDuration = 1000 * ( dist / speed );

            if ( turntotarget ) {
                duration = ent->s.pos.trDuration;
                VectorCopy( target->s.angles, angles );

                for ( i = 0; i < 3; i++ ) {
                    diff[i] = AngleDifference( angles[i], ent->s.angles[i] );
                    while ( diff[i] > 180 )
                        diff[i] -= 360;
                    while ( diff[i] < -180 )
                        diff[i] += 360;
                }
                VectorCopy( ent->s.angles, ent->s.apos.trBase );
                if ( duration ) {
                    VectorScale( diff, 1000.0 / (float)duration, ent->s.apos.trDelta );
                } else {
                    VectorClear( ent->s.apos.trDelta );
                }
                ent->s.apos.trDuration = duration;
                ent->s.apos.trTime = level.time;
                ent->s.apos.trType = TR_LINEAR_STOP;
            }

        }

        if ( !wait ) {
            // round the duration to the next 50ms
            if ( ent->s.pos.trDuration % 50 ) {
                float frac;

                frac = (float)( ( ( ent->s.pos.trDuration / 50 ) * 50 + 50 ) - ent->s.pos.trDuration ) / (float)( ent->s.pos.trDuration );
                if ( frac < 1 ) {
                    VectorScale( ent->s.pos.trDelta, 1.0 / ( 1.0 + frac ), ent->s.pos.trDelta );
                    ent->s.pos.trDuration = ( ent->s.pos.trDuration / 50 ) * 50 + 50;
                }
            }

            // set the goto flag, so we can keep processing the move until we reach the destination
            ent->scriptStatus.scriptFlags |= SCFL_GOING_TO_MARKER;
            return qtrue;   // continue to next command
        }

    }

    BG_EvaluateTrajectory( &ent->s.pos, level.time, ent->r.currentOrigin );
    BG_EvaluateTrajectory( &ent->s.apos, level.time, ent->r.currentAngles );
    script_linkentity( ent );

    return qfalse;
}
Example #7
0
void Reached_Tramcar( gentity_t *ent ) {
	gentity_t       *next;
	float speed;
	vec3_t move;
	float length;

	// copy the apropriate values
	next = ent->nextTrain;
	if ( !next || !next->nextTrain ) {
		return;     // just stop
	}

	// Rafael
	if ( next->wait == -1 && next->count ) {
		// G_Printf ("stoped wait = -1 count %i\n",next->count);
		return;
	}

	if ( !Q_stricmp( ent->classname, "props_me109" ) ) {
		vec3_t vec, angles;
		float diff;

		if ( next->spawnflags & 8 ) { // laps
			next->count--;

			if ( !next->count ) {
				next->count = next->count2;

				GetNextTrack( ent );
				Think_SetupAirplaneWaypoints( ent );

				next = ent->nextTrain;

				G_Printf( "changed track to %s\n", next->targetname );
			} else {
				G_Printf( "%s lap %i\n", next->targetname, next->count );
			}
		} else if ( ( next->spawnflags & 1 ) && !( next->count ) && ent->health > 0 )         { // SCRIPT flag
			GetNextTrack( ent );
			Think_SetupAirplaneWaypoints( ent );
		} else if ( ( next->spawnflags & 2 ) && ( ent->spawnflags & 8 ) && ent->health <= 0 && ent->takedamage )         { // death path
			ent->takedamage = qfalse;

			GetNextTrack( ent );
			Think_SetupAirplaneWaypoints( ent );
		} else if ( ( next->spawnflags & 4 ) )       { // explode the plane
			ExplodePlaneSndFx( ent );

			ent->s.modelindex = crash_part;
			// spawn the wing at the player effect

			ent->nextTrain = NULL;
			G_UseTargets( next, NULL );

			return;
		}

		VectorSubtract( ent->nextTrain->nextTrain->s.origin, ent->r.currentOrigin, vec );
		vectoangles( vec, angles );


		diff = AngleSubtract( ent->r.currentAngles [YAW], angles[YAW] );
		// diff = AngleSubtract (ent->TargetAngles [YAW], angles[YAW]);

		ent->rotate[1] = 1;
		ent->angle = -diff;

		//if (angles[YAW] == 0)
		//	ent->s.apos.trDuration = ent->s.pos.trDuration;
		//else
		//	ent->s.apos.trDuration = 1000;

		{
			VectorCopy( next->s.origin, ent->pos1 );
			VectorCopy( next->nextTrain->s.origin, ent->pos2 );

			// if the path_corner has a speed, use that
			if ( next->speed ) {
				speed = next->speed;
			} else {
				// otherwise use the train's speed
				speed = ent->speed;
			}
			if ( speed < 1 ) {
				speed = 1;
			}

			// calculate duration
			VectorSubtract( ent->pos2, ent->pos1, move );
			length = VectorLength( move );

			ent->s.apos.trDuration = length * 1000 / speed;

//testing
// ent->gDuration = ent->s.apos.trDuration;
			ent->gDurationBack = ent->gDuration = ent->s.apos.trDuration;
// ent->gDeltaBack = ent->gDelta =

		}

		VectorClear( ent->s.apos.trDelta );

		SetMoverState( ent, MOVER_1TO2ROTATE, level.time );
		VectorCopy( ent->r.currentAngles, ent->s.apos.trBase );

		trap_LinkEntity( ent );

		ent->think = props_me109_think;
		ent->nextthink = level.time + 50;
	} else if ( !Q_stricmp( ent->classname, "truck_cam" ) )       {
		G_Printf( "target: %s\n", next->targetname );

		if ( next->spawnflags & 2 ) { // END
			ent->s.loopSound = 0; // stop sound
			ent->nextTrain = NULL;
			return;
		} else
		{
			vec3_t vec, angles;
			float diff;

			if ( next->spawnflags & 4 ) { // reverse
				ent->props_frame_state = truck_reverse;
				VectorSubtract( ent->r.currentOrigin, ent->nextTrain->nextTrain->s.origin, vec );
			} else
			{
				ent->props_frame_state = truck_moving;
				VectorSubtract( ent->nextTrain->nextTrain->s.origin, ent->r.currentOrigin, vec );
			}

			vectoangles( vec, angles );

			diff = AngleSubtract( ent->r.currentAngles [YAW], angles[YAW] );

			ent->rotate[1] = 1;
			ent->angle = -diff;

			if ( angles[YAW] == 0 ) {
				ent->s.apos.trDuration = ent->s.pos.trDuration;
			} else {
				ent->s.apos.trDuration = 1000;
			}

//testing
			ent->gDuration = ent->s.pos.trDuration;

			VectorClear( ent->s.apos.trDelta );

			SetMoverState( ent, MOVER_1TO2ROTATE, level.time );
			VectorCopy( ent->r.currentAngles, ent->s.apos.trBase );

			trap_LinkEntity( ent );
		}

		if ( next->wait == -1 ) {
			ent->props_frame_state = truck_idle;
		}

		if ( next->count2 == 1 ) {
			ent->props_frame_state = truck_gear1;
		} else if ( next->count2 == 2 ) {
			ent->props_frame_state = truck_gear2;
		} else if ( next->count2 == 3 ) {
			ent->props_frame_state = truck_gear3;
		}

		switch ( ent->props_frame_state )
		{
		case truck_idle: ent->s.loopSound = truck_idle_snd; break;
		case truck_gear1: ent->s.loopSound = truck_gear1_snd; break;
		case truck_gear2: ent->s.loopSound = truck_gear2_snd; break;
		case truck_gear3: ent->s.loopSound = truck_gear3_snd; break;
		case truck_reverse: ent->s.loopSound = truck_reverse_snd; break;
		case truck_moving: ent->s.loopSound = truck_moving_snd; break;
		case truck_breaking: ent->s.loopSound = truck_breaking_snd; break;
		case truck_bouncy1: ent->s.loopSound = truck_bouncy1_snd; break;
		case truck_bouncy2: ent->s.loopSound = truck_bouncy2_snd; break;
		case truck_bouncy3: ent->s.loopSound = truck_bouncy3_snd; break;
		}

//testing
		ent->s.loopSound = truck_sound;
		ent->think = truck_cam_think;
		ent->nextthink = level.time + ( FRAMETIME / 2 );

	} else if ( !Q_stricmp( ent->classname, "camera_cam" ) )       {

	}

	// fire all other targets
	G_UseTargets( next, NULL );

	// set the new trajectory
	ent->nextTrain = next->nextTrain;

	if ( next->wait == -1 ) {
		next->count = 1;
	}

	VectorCopy( next->s.origin, ent->pos1 );
	VectorCopy( next->nextTrain->s.origin, ent->pos2 );

	// if the path_corner has a speed, use that
	if ( next->speed ) {
		speed = next->speed;
	} else {
		// otherwise use the train's speed
		speed = ent->speed;
	}
	if ( speed < 1 ) {
		speed = 1;
	}

	// calculate duration
	VectorSubtract( ent->pos2, ent->pos1, move );
	length = VectorLength( move );

	ent->s.pos.trDuration = length * 1000 / speed;

//testing
// ent->gDuration = ent->s.pos.trDuration;
	ent->gDurationBack = ent->gDuration = ent->s.pos.trDuration;
// ent->gDeltaBack = ent->gDelta = ;

	// looping sound
	if ( next->soundLoop ) {
		ent->s.loopSound = next->soundLoop;
	}

	// start it going
	SetMoverState( ent, MOVER_1TO2, level.time );

	// if there is a "wait" value on the target, don't start moving yet
	// if ( next->wait )
	if ( next->wait && next->wait != -1 ) {
		ent->nextthink = level.time + next->wait * 1000;
		ent->think = Think_BeginMoving;
		ent->s.pos.trType = TR_STATIONARY;
	}
}
Example #8
0
/***
Moves an entity like a func_train entity. Targets have to be path_corner entities.
@function AsTrain
@param mover Entity to move.
@param target path_corner entity to move to.
@param speed Speed to move with to the first path_corner.
@return Success or failure.
 */
static int Mover_AsTrain(lua_State * L)
{
	lent_t			*lent, *tlent;
	gentity_t      *ent = NULL;
	gentity_t      *targ = NULL;
	vec3_t          move;
	float           length;
	int				id = 0, tid = 0;

	float           speed = (float)luaL_checknumber(L, 3);

	if(lua_isnumber(L, 1)) {
		id = luaL_checkint(L, 1);
		if(id < 0 || id > MAX_GENTITIES - 1) {
			lua_pushboolean(L, qfalse);
			return 1;
		}
		ent = &g_entities[id];
		if(ent == NULL) {
			lua_pushboolean(L, qfalse);
			return 1;
		}
	} else {
		lent = Lua_GetEntity(L, 1);
		if(lent == NULL || lent->e == NULL) {
			lua_pushboolean(L, qfalse);
			return 1;
		}
		ent = lent->e;
	}
	if(luaL_checkint(L, 2)) {
		tid = luaL_checkint(L, 2);
		if(tid < 0 || tid > MAX_GENTITIES - 1) {
			lua_pushboolean(L, qfalse);
			return 1;
		}
		targ = &g_entities[tid];
		if(targ == NULL) {
			lua_pushboolean(L, qfalse);
			return 1;
		}
	} else {
		tlent = Lua_GetEntity(L, 2);
		if(!tlent || tlent->e == NULL) {
			lua_pushboolean(L, qfalse);
			return 1;
		}
		targ = tlent->e;
	}

	LUA_DEBUG("Mover_AsTrain - start: ent=%d target=%d speed=%f", ent->s.number, targ->s.number, speed);

	if(ent == NULL || targ == NULL)
	{
		LUA_DEBUG("Mover_AsTrain - return: ent or/and target missing");
		lua_pushboolean(L, qfalse);
		return 1;
	}
	if(speed < 1)
	{
		LUA_DEBUG("Mover_AsTrain - moving: speed less than 1 fixed");
		speed = 1;
	}

	if(ent->nextTrain)
	{
		LUA_DEBUG("Mover_AsTrain - pathing: NextTrain=%d ", ent->nextTrain->s.number);
	}

	ent->speed = speed;
	ent->nextTrain = targ;
	ent->reached = Reached_Train;
	ent->target = G_NewString(targ->targetname);

	Think_SetupTrainTargets(ent);

	BG_EvaluateTrajectory(&ent->s.pos, level.time, ent->r.currentOrigin);
	VectorCopy(ent->r.currentOrigin, ent->s.origin);

	VectorCopy(ent->s.origin, ent->pos1);
	VectorCopy(ent->nextTrain->s.origin, ent->pos2);

	VectorSubtract(ent->pos2, ent->pos1, move);
	length = VectorLength(move);

	if(length <= 0.05)
	{
		G_SetOrigin(ent, ent->pos2);
		LUA_DEBUG("Mover_AsTrain - return: snapped to target, length too small length=%f", length);
		lua_pushboolean(L, qtrue);
		return 1;
	}

	ent->s.pos.trDuration = length * 1000 / speed;

	ent->s.loopSound = ent->nextTrain->soundLoop;

	SetMoverState(ent, MOVER_1TO2, level.time);

	LUA_DEBUG("Mover_AsTrain - return: moving to target, length=%f duration=%d", length, ent->s.pos.trDuration);
	lua_pushboolean(L, qtrue);
	return 1;
}