示例#1
0
void TeleportPlayer( gentity_t *player, vec3_t origin, vec3_t angles )
{
  // unlink to make sure it can't possibly interfere with G_KillBox
  trap_UnlinkEntity( player );

  VectorCopy( origin, player->client->ps.origin );
  player->client->ps.origin[ 2 ] += 1;

  // spit the player out
  AngleVectors( angles, player->client->ps.velocity, NULL, NULL );
  VectorScale( player->client->ps.velocity, 400, player->client->ps.velocity );
  player->client->ps.pm_time = 160;   // hold time
  player->client->ps.pm_flags |= PMF_TIME_KNOCKBACK;

  // toggle the teleport bit so the client knows to not lerp
  player->client->ps.eFlags ^= EF_TELEPORT_BIT;
  G_UnlaggedClear( player );

  // set angles
  G_SetClientViewAngle( player, angles );

  // kill anything at the destination
  if( player->client->sess.spectatorState == SPECTATOR_NOT )
    G_KillBox( player );

  // save results of pmove
  BG_PlayerStateToEntityState( &player->client->ps, &player->s, qtrue );

  // use the precise origin for linking
  VectorCopy( player->client->ps.origin, player->r.currentOrigin );

  if( player->client->sess.spectatorState == SPECTATOR_NOT )
    trap_LinkEntity (player);
}
示例#2
0
void TeleportPlayerSeamless( gentity_t *player, vector3 *origin, vector3 *angles ) {
	gentity_t	*tent;

	// use temp events at source and destination to prevent the effect
	// from getting dropped by a second player event
	if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) {
		tent = G_TempEntity( &player->client->ps.origin, EV_PLAYER_TELEPORT_OUT );
		tent->s.clientNum = player->s.clientNum;

		tent = G_TempEntity( origin, EV_PLAYER_TELEPORT_IN );
		tent->s.clientNum = player->s.clientNum;
	}

	// unlink to make sure it can't possibly interfere with G_KillBox
	trap->SV_UnlinkEntity ((sharedEntity_t *)player);

	VectorCopy ( origin, &player->client->ps.origin );
	player->client->ps.origin.z += 1;
	// toggle the teleport bit so the client knows to not lerp
	player->client->ps.eFlags ^= EF_TELEPORT_BIT;
	// kill anything at the destination
	if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) {
		G_KillBox (player);
	}

	// save results of pmove
	BG_PlayerStateToEntityState( &player->client->ps, &player->s, !pm_float->boolean );

	// use the precise origin for linking
	VectorCopy( &player->client->ps.origin, &player->r.currentOrigin );

	if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) {
		trap->SV_LinkEntity ((sharedEntity_t *)player);
	}
}
示例#3
0
void TeleportPlayer( gentity_t *player, vec3_t origin, vec3_t angles ) {
	gentity_t	*tent;
	qboolean noAngles;

	noAngles = (angles[0] > 999999.0);
	// use temp events at source and destination to prevent the effect
	// from getting dropped by a second player event
	if ( player->client->sess.sessionTeam != TEAM_SPECTATOR && player->client->ps.pm_type != PM_SPECTATOR) {
		tent = G_TempEntity( player->client->ps.origin, EV_PLAYER_TELEPORT_OUT );
		tent->s.clientNum = player->s.clientNum;

		tent = G_TempEntity( origin, EV_PLAYER_TELEPORT_IN );
		tent->s.clientNum = player->s.clientNum;
	}

	// unlink to make sure it can't possibly interfere with G_KillBox
	trap_UnlinkEntity (player);

	VectorCopy ( origin, player->client->ps.origin );
	player->client->ps.origin[2] += 1;

	if (!noAngles) {
		// spit the player out
		AngleVectors( angles, player->client->ps.velocity, NULL, NULL );
		VectorScale( player->client->ps.velocity, 400, player->client->ps.velocity );
		player->client->ps.pm_time = 160;		// hold time
		player->client->ps.pm_flags |= PMF_TIME_KNOCKBACK;

		// set angles
		SetClientViewAngle(player, angles);
	}

	// toggle the teleport bit so the client knows to not lerp
	player->client->ps.eFlags ^= EF_TELEPORT_BIT;

//unlagged - backward reconciliation #3
	// we don't want players being backward-reconciled back through teleporters
	G_ResetHistory( player );
//unlagged - backward reconciliation #3

	// kill anything at the destination
	if ( player->client->sess.sessionTeam != TEAM_SPECTATOR && player->client->ps.pm_type != PM_SPECTATOR ) {
		G_KillBox (player);
	}

	// save results of pmove
	BG_PlayerStateToEntityState( &player->client->ps, &player->s, qtrue );

	// use the precise origin for linking
	VectorCopy( player->client->ps.origin, player->r.currentOrigin );

	if ( player->client->sess.sessionTeam != TEAM_SPECTATOR && player->client->ps.pm_type != PM_SPECTATOR ) {
		trap_LinkEntity (player);
	}
}
示例#4
0
/*
 * G_misc_teleporter_touch
 */
static void G_misc_teleporter_touch(g_edict_t *self, g_edict_t *other,
		c_bsp_plane_t *plane, c_bsp_surface_t *surf) {
	g_edict_t *dest;
	float speed;
	vec3_t forward;
	int i;

	if (!other->client)
		return;

	dest = G_Find(NULL, FOFS(target_name), self->target);

	if (!dest) {
		gi.Debug("G_teleporter_touch: Couldn't find destination.\n");
		return;
	}

	// unlink to make sure it can't possibly interfere with G_KillBox
	gi.UnlinkEntity(other);

	VectorCopy(dest->s.origin, other->s.origin);
	VectorCopy(dest->s.origin, other->s.old_origin);
	other->s.origin[2] += 10.0;

	// clear the velocity and hold them in place briefly
	other->velocity[2] = 0.0;
	speed = VectorLength(other->velocity);
	VectorClear(other->velocity);

	other->client->ps.pmove.pm_time = 20; // hold time
	other->client->ps.pmove.pm_flags |= PMF_TIME_TELEPORT;

	// draw the teleport splash at source and on the player
	self->s.event = EV_TELEPORT;
	other->s.event = EV_TELEPORT;

	// set angles
	for (i = 0; i < 3; i++) {
		other->client->ps.pmove.delta_angles[i]
				= ANGLE2SHORT(dest->s.angles[i] - other->client->cmd_angles[i]);
	}

	AngleVectors(dest->s.angles, forward, NULL, NULL);
	VectorScale(forward, speed, other->velocity);
	other->velocity[2] = 150.0;

	VectorClear(other->client->cmd_angles);
	VectorClear(other->client->angles);
	VectorClear(other->s.angles);

	G_KillBox(other); // telefrag anyone in our spot

	gi.LinkEntity(other);
}
示例#5
0
void TeleportPlayer( gentity_t *player, vector3 *origin, vector3 *angles ) {
	gentity_t	*tent;
	qboolean noAngles;

	noAngles = (angles->x > 999999.0);
	// use temp events at source and destination to prevent the effect
	// from getting dropped by a second player event
	if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) {
		tent = G_TempEntity( &player->client->ps.origin, EV_PLAYER_TELEPORT_OUT );
		tent->s.clientNum = player->s.clientNum;

		tent = G_TempEntity( origin, EV_PLAYER_TELEPORT_IN );
		tent->s.clientNum = player->s.clientNum;
	}

	// unlink to make sure it can't possibly interfere with G_KillBox
	trap->SV_UnlinkEntity ((sharedEntity_t *)player);

	VectorCopy ( origin, &player->client->ps.origin );
	player->client->ps.origin.z += 1;
	if (!noAngles) {
		float xyspeed = sqrtf( player->client->ps.velocity.x*player->client->ps.velocity.x + player->client->ps.velocity.y*player->client->ps.velocity.y );
		float zspeed = player->client->ps.velocity.z;
		// spit the player out
		AngleVectors( angles, &player->client->ps.velocity, NULL, NULL );
		VectorScale( &player->client->ps.velocity, xyspeed, &player->client->ps.velocity );
		// can't just fall through a tele
		if ( zspeed > 0 )
			player->client->ps.velocity.z = zspeed;
		player->client->ps.pm_time = 160;		// hold time
		player->client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
		// set angles
		SetClientViewAngle(player, angles);
	}
	// toggle the teleport bit so the client knows to not lerp
	player->client->ps.eFlags ^= EF_TELEPORT_BIT;
	// kill anything at the destination
	if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) {
		G_KillBox (player);
	}

	// save results of pmove
	BG_PlayerStateToEntityState( &player->client->ps, &player->s, !pm_float->boolean );

	// use the precise origin for linking
	VectorCopy( &player->client->ps.origin, &player->r.currentOrigin );

	if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) {
		trap->SV_LinkEntity ((sharedEntity_t *)player);
	}
}
示例#6
0
void TeleportPlayer(gentity_t *player, vec3_t origin, vec3_t angles, float speed)
{
    // unlink to make sure it can't possibly interfere with G_KillBox
    G_UnlinkEntity(player);

    VectorCopy(origin, player->client->ps.origin);
    player->client->ps.groundEntityNum = ENTITYNUM_NONE;
    player->client->ps.stats[STAT_STATE] &= ~SS_GRABBED;

    AngleVectors(angles, player->client->ps.velocity, NULL, NULL);
    VectorScale(player->client->ps.velocity, speed, player->client->ps.velocity);
    player->client->ps.pm_time = 0.4f * fabs(speed);  // duration of loss of control
    if (player->client->ps.pm_time > 160)
        player->client->ps.pm_time = 160;
    if (player->client->ps.pm_time != 0)
        player->client->ps.pm_flags |= PMF_TIME_KNOCKBACK;

    // toggle the teleport bit so the client knows to not lerp
    player->client->ps.eFlags ^= EF_TELEPORT_BIT;
    G_UnlaggedClear(player);

    // cut all relevant zap beams
    G_ClearPlayerZapEffects(player);

    // set angles
    G_SetClientViewAngle(player, angles);

    // save results of pmove
    BG_PlayerStateToEntityState(&player->client->ps, &player->s, true);

    // use the precise origin for linking
    VectorCopy(player->client->ps.origin, player->r.currentOrigin);
    VectorCopy(player->client->ps.viewangles, player->r.currentAngles);

    if (player->client->sess.spectatorState == SPECTATOR_NOT)
    {
        // kill anything at the destination
        G_KillBox(player);

        G_LinkEntity(player);
    }
}
示例#7
0
/*
===========
ClientSpawn

Called every time a client is placed fresh in the world:
after the first ClientBegin, and after each respawn
Initializes all non-persistant parts of playerState
============
*/
void ClientSpawn(gentity_t *ent) {
	int		index;
	vec3_t	spawn_origin, spawn_angles;
	gclient_t	*client;
	int		i;
	clientPersistant_t	saved;
	clientSession_t		savedSess;
	int		persistant[MAX_PERSISTANT];
	gentity_t	*spawnPoint;
	int		flags;
	int		savedPing;
//	char	*savedAreaBits;
	int		accuracy_hits, accuracy_shots;
	int		eventSequence;
	char	userinfo[MAX_INFO_STRING];
	int		weapon;

	index = ent - g_entities;
	client = ent->client;

	// find a spawn point
	// do it before setting health back up, so farthest
	// ranging doesn't count this client
	if ( client->sess.sessionTeam == TEAM_SPECTATOR ) {
		spawnPoint = SelectSpectatorSpawnPoint ( 
						spawn_origin, spawn_angles);
	} else if (g_gametype.integer >= GT_CTF ) {
		// all base oriented team games use the CTF spawn points
		spawnPoint = SelectCTFSpawnPoint ( 
						client->sess.sessionTeam, 
						client->pers.teamState.state, 
						spawn_origin, spawn_angles);
	} else {
		do {
			// the first spawn should be at a good looking spot
			if ( !client->pers.initialSpawn && client->pers.localClient ) {
				client->pers.initialSpawn = qtrue;
				spawnPoint = SelectInitialSpawnPoint( spawn_origin, spawn_angles );
			} else {
				// don't spawn near existing origin if possible
				spawnPoint = SelectSpawnPoint ( 
					client->ps.origin, 
					spawn_origin, spawn_angles);
			}

			// Tim needs to prevent bots from spawning at the initial point
			// on q3dm0...
			if ( ( spawnPoint->flags & FL_NO_BOTS ) && ( ent->r.svFlags & SVF_BOT ) ) {
				continue;	// try again
			}
			// just to be symetric, we have a nohumans option...
			if ( ( spawnPoint->flags & FL_NO_HUMANS ) && !( ent->r.svFlags & SVF_BOT ) ) {
				continue;	// try again
			}

			break;

		} while ( 1 );
	}
	client->pers.teamState.state = TEAM_ACTIVE;

	// always clear the kamikaze flag
	ent->s.eFlags &= ~EF_KAMIKAZE;

	// toggle the teleport bit so the client knows to not lerp
	// and never clear the voted flag
	flags = ent->client->ps.eFlags & (EF_TELEPORT_BIT | EF_VOTED | EF_TEAMVOTED);
	flags ^= EF_TELEPORT_BIT;

	// clear everything but the persistant data

	saved = client->pers;
	savedSess = client->sess;
	savedPing = client->ps.ping;
//	savedAreaBits = client->areabits;
	accuracy_hits = client->accuracy_hits;
	accuracy_shots = client->accuracy_shots;
	for ( i = 0 ; i < MAX_PERSISTANT ; i++ ) {
		persistant[i] = client->ps.persistant[i];
	}
	eventSequence = client->ps.eventSequence;

	memset (client, 0, sizeof(*client)); // bk FIXME: Com_Memset?

	client->pers = saved;
	client->sess = savedSess;
	client->ps.ping = savedPing;
//	client->areabits = savedAreaBits;
	client->accuracy_hits = accuracy_hits;
	client->accuracy_shots = accuracy_shots;
	client->lastkilled_client = -1;

	for ( i = 0 ; i < MAX_PERSISTANT ; i++ ) {
		client->ps.persistant[i] = persistant[i];
	}
	client->ps.eventSequence = eventSequence;
	// increment the spawncount so the client will detect the respawn
	client->ps.persistant[PERS_SPAWN_COUNT]++;
	client->ps.persistant[PERS_TEAM] = client->sess.sessionTeam;

	client->airOutTime = level.time + 12000;

	trap_GetUserinfo( index, userinfo, sizeof(userinfo) );
	// set max health
	client->pers.maxHealth = atoi( Info_ValueForKey( userinfo, "handicap" ) );
	if ( client->pers.maxHealth < 1 || client->pers.maxHealth > 100 ) {
		client->pers.maxHealth = 100;
	}
	// clear entity values
	client->ps.stats[STAT_MAX_HEALTH] = client->pers.maxHealth;
	client->ps.eFlags = flags;

	ent->s.groundEntityNum = ENTITYNUM_NONE;
	ent->client = &level.clients[index];
	ent->takedamage = qtrue;
	ent->inuse = qtrue;
	ent->classname = "player";
	ent->r.contents = CONTENTS_BODY;
	ent->clipmask = MASK_PLAYERSOLID;
	ent->die = player_die;
	ent->waterlevel = 0;
	ent->watertype = 0;
	ent->flags = 0;
	
	VectorCopy (playerMins, ent->r.mins);
	VectorCopy (playerMaxs, ent->r.maxs);

	client->ps.clientNum = index;


	if (IsBot(client->ps.clientNum)) {
		weapon = WP_LIGHTNING;
		client->ps.stats[STAT_WEAPONS] = ( 1 << weapon );
		client->ps.ammo[weapon] = -1;
	} else {
		weapon = WP_MACHINEGUN;
		client->ps.stats[STAT_WEAPONS] = ( 1 << weapon );
		client->ps.ammo[weapon] = 100;

		client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_GAUNTLET );
		client->ps.ammo[WP_GAUNTLET] = -1;
		client->ps.ammo[WP_GRAPPLING_HOOK] = -1;
	}

	// health will count down towards max_health
	ent->health = client->ps.stats[STAT_HEALTH] = client->ps.stats[STAT_MAX_HEALTH] + 25;

	G_SetOrigin( ent, spawn_origin );
	VectorCopy( spawn_origin, client->ps.origin );

	// the respawned flag will be cleared after the attack and jump keys come up
	client->ps.pm_flags |= PMF_RESPAWNED;

	trap_GetUsercmd( client - level.clients, &ent->client->pers.cmd );
	SetClientViewAngle( ent, spawn_angles );

	if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) {

	} else {
		G_KillBox( ent );
		trap_LinkEntity (ent);

		// force the base weapon up
		client->ps.weapon = weapon;
		client->ps.weaponstate = WEAPON_READY;

	}

	// don't allow full run speed for a bit
	client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
	client->ps.pm_time = 100;

	client->respawnTime = level.time;
	client->inactivityTime = level.time + g_inactivity.integer * 1000;
	client->latched_buttons = 0;

	// set default animations
	client->ps.torsoAnim = TORSO_STAND;
	client->ps.legsAnim = LEGS_IDLE;

	if ( level.intermissiontime ) {
		MoveClientToIntermission( ent );
	} else {
		// fire the targets of the spawn point
		G_UseTargets( spawnPoint, ent );

		// select the highest weapon number available, after any
		// spawn given items have fired
		client->ps.weapon = weapon;
		for ( i = WP_NUM_WEAPONS - 1 ; i > 0 ; i-- ) {
			if ( client->ps.stats[STAT_WEAPONS] & ( 1 << i ) ) {
				client->ps.weapon = i;
				break;
			}
		}
	}

	// run a client frame to drop exactly to the floor,
	// initialize animations and other things
	client->ps.commandTime = level.time - 100;
	ent->client->pers.cmd.serverTime = level.time;
	ClientThink( ent-g_entities );

	// positively link the client, even if the command times are weird
	if ( ent->client->sess.sessionTeam != TEAM_SPECTATOR ) {
		BG_PlayerStateToEntityState( &client->ps, &ent->s, qtrue );
		VectorCopy( ent->client->ps.origin, ent->r.currentOrigin );
		trap_LinkEntity( ent );
	}

	// run the presend to set anything else
	ClientEndFrame( ent );

	// clear entity state values
	BG_PlayerStateToEntityState( &client->ps, &ent->s, qtrue );
}
示例#8
0
/*
 * G_ClientRespawn_
 *
 * The grunt work of putting the client into the server on [re]spawn.
 */
static void G_ClientRespawn_(g_edict_t *ent) {
	vec3_t spawn_origin, spawn_angles, old_angles;
	float height;
	g_client_t *cl;
	g_client_persistent_t locals;
	int i;

	// find a spawn point
	G_SelectSpawnPoint(ent, spawn_origin, spawn_angles);

	cl = ent->client;

	// retain last angles for delta
	VectorCopy(ent->client->cmd_angles, old_angles);

	// reset inventory, health, etc
	G_InitClientLocals(cl);

	// clear everything but locals
	locals = cl->persistent;
	memset(cl, 0, sizeof(*cl));
	cl->persistent = locals;

	// clear entity values
	VectorScale(PM_MINS, PM_SCALE, ent->mins);
	VectorScale(PM_MAXS, PM_SCALE, ent->maxs);
	height = ent->maxs[2] - ent->mins[2];

	ent->ground_entity = NULL;
	ent->take_damage = true;
	ent->move_type = MOVE_TYPE_WALK;
	ent->view_height = ent->mins[2] + (height * 0.75);
	ent->class_name = "player";
	ent->mass = 200.0;
	ent->solid = SOLID_BOX;
	ent->dead = false;
	ent->clip_mask = MASK_PLAYER_SOLID;
	ent->pain = G_ClientPain;
	ent->die = G_ClientDie;
	ent->water_level = 0;
	ent->water_type = 0;
	ent->sv_flags = 0;

	// copy these back once they have been set in locals
	ent->health = ent->client->persistent.health;
	ent->max_health = ent->client->persistent.max_health;

	VectorClear(ent->velocity);
	ent->velocity[2] = 150.0;

	// clear player state values
	memset(&ent->client->ps, 0, sizeof(cl->ps));

	cl->ps.pmove.origin[0] = spawn_origin[0] * 8.0;
	cl->ps.pmove.origin[1] = spawn_origin[1] * 8.0;
	cl->ps.pmove.origin[2] = spawn_origin[2] * 8.0;

	// clear entity state values
	ent->s.effects = 0;
	ent->s.model1 = 0xff; // use the client info model
	ent->s.model2 = 0;
	ent->s.model3 = 0;
	ent->s.model4 = 0;
	ent->s.client = ent - g_game.edicts - 1;

	G_SetAnimation(ent, ANIM_TORSO_STAND1, true);
	G_SetAnimation(ent, ANIM_LEGS_JUMP1, true);

	VectorCopy(spawn_origin, ent->s.origin);
	VectorCopy(ent->s.origin, ent->s.old_origin);

	// set the delta angle of the spawn point
	for (i = 0; i < 3; i++) {
		cl->ps.pmove.delta_angles[i]
				= ANGLE2SHORT(spawn_angles[i] - old_angles[i]);
	}

	VectorClear(cl->cmd_angles);
	VectorClear(cl->angles);
	VectorClear(ent->s.angles);

	// spawn a spectator
	if (cl->persistent.spectator) {
		cl->chase_target = NULL;

		cl->persistent.weapon = NULL;
		cl->persistent.team = NULL;
		cl->persistent.ready = false;

		ent->move_type = MOVE_TYPE_NO_CLIP;
		ent->solid = SOLID_NOT;
		ent->sv_flags |= SVF_NO_CLIENT;
		ent->take_damage = false;

		gi.LinkEntity(ent);
		return;
	}

	// or spawn a player
	ent->s.event = EV_TELEPORT;

	// hold in place briefly
	cl->ps.pmove.pm_flags = PMF_TIME_TELEPORT;
	cl->ps.pmove.pm_time = 20;

	cl->persistent.match_num = g_level.match_num;
	cl->persistent.round_num = g_level.round_num;

	gi.UnlinkEntity(ent);

	G_KillBox(ent); // telefrag anyone in our spot

	gi.LinkEntity(ent);

	// force the current weapon up
	cl->new_weapon = cl->persistent.weapon;
	G_ChangeWeapon(ent);
}
示例#9
0
/*
===========
PlayerSpawn

Called every time a player is placed fresh in the world:
after the first PlayerBegin, and after each respawn
Initializes all non-persistant parts of playerState
============
*/
void PlayerSpawn(gentity_t *ent) {
	int		index;
	vec3_t	spawn_origin, spawn_angles;
	gplayer_t	*player;
	int		i;
	playerPersistant_t	saved;
	playerSession_t		savedSess;
	int		persistant[MAX_PERSISTANT];
	gentity_t	*spawnPoint;
	gentity_t *tent;
	int		flags;
	int		savedPing;
//	char	*savedAreaBits;
	int		accuracy_hits, accuracy_shots;
	int		eventSequence;
	int 	startWeapon, startAmmo;

	index = ent - g_entities;
	player = ent->player;

	VectorClear(spawn_origin);

	// find a spawn point
	// do it before setting health back up, so farthest
	// ranging doesn't count this player
	if ( player->sess.sessionTeam == TEAM_SPECTATOR ) {
		spawnPoint = SelectSpectatorSpawnPoint ( 
						spawn_origin, spawn_angles);
	} else if (g_gametype.integer >= GT_CTF ) {
		// all base oriented team games use the CTF spawn points
		spawnPoint = SelectCTFSpawnPoint ( 
						player->sess.sessionTeam, 
						player->pers.teamState.state, 
						spawn_origin, spawn_angles,
						!!(ent->r.svFlags & SVF_BOT));
	}
	else
	{
		// the first spawn should be at a good looking spot
		if ( player->pers.initialSpawn && player->pers.localClient )
		{
			spawnPoint = SelectInitialSpawnPoint(spawn_origin, spawn_angles,
							     !!(ent->r.svFlags & SVF_BOT));
		}
		else
		{
			// don't spawn near existing origin if possible
			spawnPoint = SelectSpawnPoint ( 
				player->ps.origin, 
				spawn_origin, spawn_angles, !!(ent->r.svFlags & SVF_BOT));
		}
	}
	player->pers.teamState.state = TEAM_ACTIVE;

	// always clear the kamikaze flag
	ent->s.eFlags &= ~EF_KAMIKAZE;

	// toggle the teleport bit so the client knows to not lerp
	// and never clear the voted flag
	flags = ent->player->ps.eFlags & (EF_TELEPORT_BIT | EF_VOTED | EF_TEAMVOTED);
	flags ^= EF_TELEPORT_BIT;

	// clear everything but the persistant data

	saved = player->pers;
	savedSess = player->sess;
	savedPing = player->ps.ping;
//	savedAreaBits = player->areabits;
	accuracy_hits = player->accuracy_hits;
	accuracy_shots = player->accuracy_shots;
	for ( i = 0 ; i < MAX_PERSISTANT ; i++ ) {
		persistant[i] = player->ps.persistant[i];
	}
	eventSequence = player->ps.eventSequence;

	Com_Memset (player, 0, sizeof(*player));

	player->pers = saved;
	player->sess = savedSess;
	player->ps.ping = savedPing;
//	player->areabits = savedAreaBits;
	player->accuracy_hits = accuracy_hits;
	player->accuracy_shots = accuracy_shots;
	player->lastkilled_player = -1;

	for ( i = 0 ; i < MAX_PERSISTANT ; i++ ) {
		player->ps.persistant[i] = persistant[i];
	}
	player->ps.eventSequence = eventSequence;
	// increment the spawncount so the client will detect the respawn
	player->ps.persistant[PERS_SPAWN_COUNT]++;
	player->ps.persistant[PERS_TEAM] = player->sess.sessionTeam;

	player->airOutTime = level.time + 12000;

	// set max health
	player->pers.maxHealth = PlayerHandicap( player );
	// clear entity values
	player->ps.stats[STAT_MAX_HEALTH] = player->pers.maxHealth;
	player->ps.eFlags = flags;
	player->ps.contents = CONTENTS_BODY;
	player->ps.collisionType = ( g_playerCapsule.integer == 1 ) ? CT_CAPSULE : CT_AABB;

	ent->s.groundEntityNum = ENTITYNUM_NONE;
	ent->player = &level.players[index];
	ent->takedamage = qtrue;
	ent->inuse = qtrue;
	ent->classname = "player";
	ent->clipmask = MASK_PLAYERSOLID;
	ent->die = player_die;
	ent->waterlevel = 0;
	ent->watertype = 0;
	ent->flags = 0;
	ent->player->headless = qfalse;
	
	VectorCopy (playerMins, player->ps.mins);
	VectorCopy (playerMaxs, player->ps.maxs);

	player->ps.playerNum = index;

	if ( g_instaGib.integer == 1 ) {
		startWeapon = WP_RAILGUN;
		startAmmo = 50;
	} else if ( g_instaGib.integer == 2 ) {
		startWeapon = WP_ROCKET_LAUNCHER;
		startAmmo = 50;
	} else {
		startWeapon = WP_MACHINEGUN;
		startAmmo = 100;
	}

	player->ps.stats[STAT_WEAPONS] = ( 1 << startWeapon );

	player->ps.ammo[startWeapon] = startAmmo;

	player->ps.stats[STAT_WEAPONS] |= ( 1 << WP_GAUNTLET );
	player->ps.ammo[WP_GAUNTLET] = -1;
	player->ps.ammo[WP_GRAPPLING_HOOK] = -1;

	// health will count down towards max_health
	ent->health = player->ps.stats[STAT_HEALTH] = player->ps.stats[STAT_MAX_HEALTH] = MAX_HEALTH;

	G_SetOrigin( ent, spawn_origin );
	VectorCopy( spawn_origin, player->ps.origin );

	// the respawned flag will be cleared after the attack and jump keys come up
	player->ps.pm_flags |= PMF_RESPAWNED;

	trap_GetUsercmd( player - level.players, &ent->player->pers.cmd );
	SetPlayerViewAngle( ent, spawn_angles );
	// don't allow full run speed for a bit
	player->ps.pm_flags |= PMF_TIME_KNOCKBACK;
	player->ps.pm_time = 100;

	player->respawnTime = level.time;
	player->inactivityTime = level.time + g_inactivity.integer * 1000;
	player->latched_buttons = 0;

	// set default animations
	player->ps.torsoAnim = TORSO_STAND;
	player->ps.legsAnim = LEGS_IDLE;

	if (!level.intermissiontime) {
		if (ent->player->sess.sessionTeam != TEAM_SPECTATOR) {
			G_KillBox(ent);
			// force the base weapon up
			player->ps.weapon = startWeapon;
			player->ps.weaponstate = WEAPON_READY;
			// fire the targets of the spawn point
			G_UseTargets(spawnPoint, ent);
			// select the highest weapon number available, after any spawn given items have fired
			player->ps.weapon = 1;

			for (i = WP_NUM_WEAPONS - 1 ; i > 0 ; i--) {
				if (player->ps.stats[STAT_WEAPONS] & (1 << i)) {
					player->ps.weapon = i;
					break;
				}
			}
			// positively link the player, even if the command times are weird
			VectorCopy(ent->player->ps.origin, ent->r.currentOrigin);

			tent = G_TempEntity(ent->player->ps.origin, EV_PLAYER_TELEPORT_IN);
			tent->s.playerNum = ent->s.playerNum;

			trap_LinkEntity (ent);
		}
	} else {
		// move players to intermission
		MovePlayerToIntermission(ent);
	}
	// run a player frame to drop exactly to the floor,
	// initialize animations and other things
	player->ps.commandTime = level.time - 100;
	ent->player->pers.cmd.serverTime = level.time;
	PlayerThink( ent-g_entities );
	// run the presend to set anything else, follow spectators wait
	// until all players have been reconnected after map_restart
	if ( ent->player->sess.spectatorState != SPECTATOR_FOLLOW ) {
		PlayerEndFrame( ent );
	}

	// clear entity state values
	BG_PlayerStateToEntityState( &player->ps, &ent->s, qtrue );

	// we don't want players being backward-reconciled to the place they died
	G_ResetHistory( ent );
}
示例#10
0
/*
===========
ClientSpawn

Called every time a client is placed fresh in the world:
after the first ClientBegin, and after each respawn
Initializes all non-persistant parts of playerState
============
*/
void ClientSpawn(gentity_t *ent) {
	int		index;
	vec3_t	spawn_origin, spawn_angles;
	gclient_t	*client;
	int		i;
	clientPersistant_t	saved;
	clientSession_t		savedSess;
	int		persistant[MAX_PERSISTANT];
	gentity_t	*spawnPoint;
	int		flags;
	int		savedPing;
//	char	*savedAreaBits;
	int		accuracy_hits, accuracy_shots;
	int		eventSequence;
//	char	userinfo[MAX_INFO_STRING];
	forcedata_t			savedForce;
	void		*ghoul2save;
	int		saveSaberNum = ENTITYNUM_NONE;
	int		wDisable = 0;

	index = ent - g_entities;
	client = ent->client;

	if (client->ps.fd.forceDoInit)
	{ //force a reread of force powers
		WP_InitForcePowers( ent );
		client->ps.fd.forceDoInit = 0;
	}
	// find a spawn point
	// do it before setting health back up, so farthest
	// ranging doesn't count this client
	if ( client->sess.sessionTeam == TEAM_SPECTATOR ) {
		spawnPoint = SelectSpectatorSpawnPoint ( 
						spawn_origin, spawn_angles);
	} else if (g_gametype.integer == GT_CTF || g_gametype.integer == GT_CTY) {
		// all base oriented team games use the CTF spawn points
		spawnPoint = SelectCTFSpawnPoint ( 
						client->sess.sessionTeam, 
						client->pers.teamState.state, 
						spawn_origin, spawn_angles);
	}
	else if (g_gametype.integer == GT_SAGA)
	{
		spawnPoint = SelectSagaSpawnPoint ( 
						client->sess.sessionTeam, 
						client->pers.teamState.state, 
						spawn_origin, spawn_angles);
	}
	else {
		do {
			// the first spawn should be at a good looking spot
			if ( !client->pers.initialSpawn && client->pers.localClient ) {
				client->pers.initialSpawn = qtrue;
				spawnPoint = SelectInitialSpawnPoint( spawn_origin, spawn_angles );
			} else {
				// don't spawn near existing origin if possible
				spawnPoint = SelectSpawnPoint ( 
					client->ps.origin, 
					spawn_origin, spawn_angles);
			}

			// Tim needs to prevent bots from spawning at the initial point
			// on q3dm0...
			if ( ( spawnPoint->flags & FL_NO_BOTS ) && ( ent->r.svFlags & SVF_BOT ) ) {
				continue;	// try again
			}
			// just to be symetric, we have a nohumans option...
			if ( ( spawnPoint->flags & FL_NO_HUMANS ) && !( ent->r.svFlags & SVF_BOT ) ) {
				continue;	// try again
			}

			break;

		} while ( 1 );
	}
	client->pers.teamState.state = TEAM_ACTIVE;

	// toggle the teleport bit so the client knows to not lerp
	// and never clear the voted flag
	flags = ent->client->ps.eFlags & (EF_TELEPORT_BIT | EF_VOTED | EF_TEAMVOTED);
	flags ^= EF_TELEPORT_BIT;

	// clear everything but the persistant data

	saved = client->pers;
	savedSess = client->sess;
	savedPing = client->ps.ping;
//	savedAreaBits = client->areabits;
	accuracy_hits = client->accuracy_hits;
	accuracy_shots = client->accuracy_shots;
	for ( i = 0 ; i < MAX_PERSISTANT ; i++ ) {
		persistant[i] = client->ps.persistant[i];
	}
	eventSequence = client->ps.eventSequence;

	savedForce = client->ps.fd;

	ghoul2save = client->ghoul2;

	saveSaberNum = client->ps.saberEntityNum;

	memset (client, 0, sizeof(*client)); // bk FIXME: Com_Memset?

	//rww - Don't wipe the ghoul2 instance or the animation data
	client->ghoul2 = ghoul2save;

	//or the saber ent num
	client->ps.saberEntityNum = saveSaberNum;

	client->ps.fd = savedForce;

	client->ps.duelIndex = ENTITYNUM_NONE;

	client->pers = saved;
	client->sess = savedSess;
	client->ps.ping = savedPing;
//	client->areabits = savedAreaBits;
	client->accuracy_hits = accuracy_hits;
	client->accuracy_shots = accuracy_shots;
	client->lastkilled_client = -1;

	for ( i = 0 ; i < MAX_PERSISTANT ; i++ ) {
		client->ps.persistant[i] = persistant[i];
	}
	client->ps.eventSequence = eventSequence;
	// increment the spawncount so the client will detect the respawn
	client->ps.persistant[PERS_SPAWN_COUNT]++;
	client->ps.persistant[PERS_TEAM] = client->sess.sessionTeam;

	client->airOutTime = level.time + 12000;

//	trap_GetUserinfo( index, userinfo, sizeof(userinfo) );
	// set max health
	client->pers.maxHealth = 100;//atoi( Info_ValueForKey( userinfo, "handicap" ) );
	if ( client->pers.maxHealth < 1 || client->pers.maxHealth > 100 ) {
		client->pers.maxHealth = 100;
	}
	// clear entity values
	client->ps.stats[STAT_MAX_HEALTH] = client->pers.maxHealth;
	client->ps.eFlags = flags;

	ent->s.groundEntityNum = ENTITYNUM_NONE;
	ent->client = &level.clients[index];
	ent->takedamage = qtrue;
	ent->inuse = qtrue;
	ent->classname = "player";
	ent->r.contents = CONTENTS_BODY;
	ent->clipmask = MASK_PLAYERSOLID;
	ent->die = player_die;
	ent->waterlevel = 0;
	ent->watertype = 0;
	ent->flags = 0;
	
	VectorCopy (playerMins, ent->r.mins);
	VectorCopy (playerMaxs, ent->r.maxs);

	client->ps.clientNum = index;
	//give default weapons
	client->ps.stats[STAT_WEAPONS] = ( 1 << WP_NONE );

	if (g_gametype.integer == GT_HOLOCRON)
	{
		//always get free saber level 1 in holocron
		client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_SABER );	//these are precached in g_items, ClearRegisteredItems()
	}
	else
	{
		if (client->ps.fd.forcePowerLevel[FP_SABERATTACK])
		{
			client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_SABER );	//these are precached in g_items, ClearRegisteredItems()
		}
		else
		{ //if you don't have saber attack rank then you don't get a saber
			client->ps.stats[STAT_WEAPONS] |= (1 << WP_STUN_BATON);
		}
	}

	if (g_gametype.integer == GT_TOURNAMENT)
	{
		wDisable = g_duelWeaponDisable.integer;
	}
	else
	{
		wDisable = g_weaponDisable.integer;
	}

	if (!wDisable || !(wDisable & (1 << WP_BRYAR_PISTOL)))
	{
		client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_BRYAR_PISTOL );
	}
	else if (g_gametype.integer == GT_JEDIMASTER)
	{
		client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_BRYAR_PISTOL );
	}

	if (g_gametype.integer == GT_JEDIMASTER)
	{
		client->ps.stats[STAT_WEAPONS] &= ~(1 << WP_SABER);
		client->ps.stats[STAT_WEAPONS] |= (1 << WP_STUN_BATON);
	}

	if (client->ps.stats[STAT_WEAPONS] & (1 << WP_BRYAR_PISTOL))
	{
		client->ps.weapon = WP_BRYAR_PISTOL;
	}
	else if (client->ps.stats[STAT_WEAPONS] & (1 << WP_SABER))
	{
		client->ps.weapon = WP_SABER;
	}
	else
	{
		client->ps.weapon = WP_STUN_BATON;
	}

	/*
	client->ps.stats[STAT_HOLDABLE_ITEMS] |= ( 1 << HI_BINOCULARS );
	client->ps.stats[STAT_HOLDABLE_ITEM] = BG_GetItemIndexByTag(HI_BINOCULARS, IT_HOLDABLE);
	*/

	client->ps.stats[STAT_HOLDABLE_ITEMS] = 0;
	client->ps.stats[STAT_HOLDABLE_ITEM] = 0;

	if ( client->sess.sessionTeam == TEAM_SPECTATOR )
	{
		client->ps.stats[STAT_WEAPONS] = 0;
		client->ps.stats[STAT_HOLDABLE_ITEMS] = 0;
		client->ps.stats[STAT_HOLDABLE_ITEM] = 0;
	}

	client->ps.ammo[AMMO_BLASTER] = 100; //ammoData[AMMO_BLASTER].max; //100 seems fair.
//	client->ps.ammo[AMMO_POWERCELL] = ammoData[AMMO_POWERCELL].max;
//	client->ps.ammo[AMMO_FORCE] = ammoData[AMMO_FORCE].max;
//	client->ps.ammo[AMMO_METAL_BOLTS] = ammoData[AMMO_METAL_BOLTS].max;
//	client->ps.ammo[AMMO_ROCKETS] = ammoData[AMMO_ROCKETS].max;
/*
	client->ps.stats[STAT_WEAPONS] = ( 1 << WP_BRYAR_PISTOL);
	if ( g_gametype.integer == GT_TEAM ) {
		client->ps.ammo[WP_BRYAR_PISTOL] = 50;
	} else {
		client->ps.ammo[WP_BRYAR_PISTOL] = 100;
	}
*/
	client->ps.rocketLockIndex = MAX_CLIENTS;
	client->ps.rocketLockTime = 0;

	//rww - Set here to initialize the circling seeker drone to off.
	//A quick note about this so I don't forget how it works again:
	//ps.genericEnemyIndex is kept in sync between the server and client.
	//When it gets set then an entitystate value of the same name gets
	//set along with an entitystate flag in the shared bg code. Which
	//is why a value needs to be both on the player state and entity state.
	//(it doesn't seem to just carry over the entitystate value automatically
	//because entity state value is derived from player state data or some
	//such)
	client->ps.genericEnemyIndex = -1;

	client->ps.isJediMaster = qfalse;

	client->ps.fallingToDeath = 0;

	//Do per-spawn force power initialization
	WP_SpawnInitForcePowers( ent );

	// health will count down towards max_health
	ent->health = client->ps.stats[STAT_HEALTH] = client->ps.stats[STAT_MAX_HEALTH];// * 1.25;		Boot - no extra 25 hp on start.

	// Start with a small amount of armor as well.
	client->ps.stats[STAT_ARMOR] = client->ps.stats[STAT_MAX_HEALTH] * 0.25;

	G_SetOrigin( ent, spawn_origin );
	VectorCopy( spawn_origin, client->ps.origin );

	// the respawned flag will be cleared after the attack and jump keys come up
	client->ps.pm_flags |= PMF_RESPAWNED;

	trap_GetUsercmd( client - level.clients, &ent->client->pers.cmd );
	SetClientViewAngle( ent, spawn_angles );

	if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) {

	} else {
		G_KillBox( ent );
		trap_LinkEntity (ent);

		// force the base weapon up
		client->ps.weapon = WP_BRYAR_PISTOL;
		client->ps.weaponstate = FIRST_WEAPON;

	}

	// don't allow full run speed for a bit
	client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
	client->ps.pm_time = 100;

	client->respawnTime = level.time;
	client->inactivityTime = level.time + g_inactivity.integer * 1000;
	client->latched_buttons = 0;

	// set default animations
	client->ps.torsoAnim = WeaponReadyAnim[client->ps.weapon];
	client->ps.legsAnim = WeaponReadyAnim[client->ps.weapon];

	if ( level.intermissiontime ) {
		MoveClientToIntermission( ent );
	} else {
		// fire the targets of the spawn point
		G_UseTargets( spawnPoint, ent );

		// select the highest weapon number available, after any
		// spawn given items have fired
		client->ps.weapon = 1;
		for ( i = WP_NUM_WEAPONS - 1 ; i > 0 ; i-- ) {
			if ( client->ps.stats[STAT_WEAPONS] & ( 1 << i ) ) {
				client->ps.weapon = i;
				break;
			}
		}
	}

	// run a client frame to drop exactly to the floor,
	// initialize animations and other things
	client->ps.commandTime = level.time - 100;
	ent->client->pers.cmd.serverTime = level.time;
	ClientThink( ent-g_entities );

	// positively link the client, even if the command times are weird
	if ( ent->client->sess.sessionTeam != TEAM_SPECTATOR ) {
		BG_PlayerStateToEntityState( &client->ps, &ent->s, qtrue );
		VectorCopy( ent->client->ps.origin, ent->r.currentOrigin );
		trap_LinkEntity( ent );
	}

	if (g_spawnInvulnerability.integer)
	{
		ent->client->ps.eFlags |= EF_INVULNERABLE;
		ent->client->invulnerableTimer = level.time + g_spawnInvulnerability.integer;
	}

	// run the presend to set anything else
	ClientEndFrame( ent );

	// clear entity state values
	BG_PlayerStateToEntityState( &client->ps, &ent->s, qtrue );
}
示例#11
0
/*
===========
ClientSpawn

Called every time a client is placed fresh in the world:
after the first ClientBegin, and after each respawn
Initializes all non-persistant parts of playerState
============
*/
void ClientSpawn(gentity_t *ent) {
	int		index;
	vec3_t	spawn_origin, spawn_angles;
	gclient_t	*client;
	int		i;
	clientPersistant_t	saved;
	clientSession_t		savedSess;
	int		persistant[MAX_PERSISTANT];
	gentity_t	*spawnPoint;
	int		flags;
	int		savedPing;
//	char	*savedAreaBits;
	int		accuracy_hits, accuracy_shots;
	int		eventSequence;
	char	userinfo[MAX_INFO_STRING];

	index = ent - g_entities;
	client = ent->client;

	// find a spawn point
	// do it before setting health back up, so farthest
	// ranging doesn't count this client
	if ( client->sess.sessionTeam == TEAM_SPECTATOR ) {
		spawnPoint = SelectSpectatorSpawnPoint ( 
						spawn_origin, spawn_angles);
	} else {
		do {
			// the first spawn should be at a good looking spot
			if ( !client->pers.initialSpawn && client->pers.localClient ) {
				client->pers.initialSpawn = qtrue;
				spawnPoint = SelectInitialSpawnPoint( spawn_origin, spawn_angles );
			} else {
				// don't spawn near existing origin if possible
				spawnPoint = SelectSpawnPoint ( 
					client->ps.origin, 
					spawn_origin, spawn_angles);
			}

			// Tim needs to prevent bots from spawning at the initial point
			// on q3dm0...
			if ( ( spawnPoint->flags & FL_NO_BOTS ) && ( ent->r.svFlags & SVF_BOT ) ) {
				continue;	// try again
			}
			// just to be symetric, we have a nohumans option...
			if ( ( spawnPoint->flags & FL_NO_HUMANS ) && !( ent->r.svFlags & SVF_BOT ) ) {
				continue;	// try again
			}

			break;

		} while ( 1 );
	}
	client->pers.teamState.state = TEAM_ACTIVE;

	// always clear the kamikaze flag
//	ent->s.eFlags &= ~EF_KAMIKAZE;

	// toggle the teleport bit so the client knows to not lerp
	// and never clear the voted flag
	flags = ent->s.eFlags & (EF_TELEPORT_BIT | EF_VOTED | EF_TEAMVOTED);
	flags ^= EF_TELEPORT_BIT;

	// clear everything but the persistant data

	saved = client->pers;
	savedSess = client->sess;
	savedPing = client->ps.ping;
//	savedAreaBits = client->areabits;
	accuracy_hits = client->accuracy_hits;
	accuracy_shots = client->accuracy_shots;

	Com_Memset (client, 0, sizeof(*client));

	client->ps.stats[STAT_ATTACKERCLIENT] = -1;
	client->ps.stats[STAT_INFOCLIENT] = -1;

	client->pers = saved;
	client->sess = savedSess;
	client->ps.ping = savedPing;
//	client->areabits = savedAreaBits;
	client->accuracy_hits = accuracy_hits;
	client->accuracy_shots = accuracy_shots;
	client->lastkilled_client = -1;

	client->airOutTime = level.time + 12000;

	trap_GetUserinfo( index, userinfo, sizeof(userinfo) );
	// set max health
	client->pers.maxHealth = atoi( Info_ValueForKey( userinfo, "handicap" ) );
	if ( client->pers.maxHealth < 1 || client->pers.maxHealth > 100 ) {
		client->pers.maxHealth = 100;
	}
	// clear entity values
	client->ps.stats[STAT_MAX_HEALTH] = client->pers.maxHealth;
	ent->s.eFlags = flags;

	ent->s.groundEntityNum = ENTITYNUM_NONE;
	ent->client = &level.clients[index];
	ent->takedamage = qtrue;
	ent->inuse = qtrue;
	ent->classname = "player";
	ent->r.contents = CONTENTS_BODY;
	ent->clipmask = MASK_PLAYERSOLID;
	ent->die = player_die;
	ent->waterlevel = 0;
	ent->watertype = 0;
	ent->flags = 0;
	
	VectorCopy (playerMins, ent->r.mins);
	VectorCopy (playerMaxs, ent->r.maxs);

	client->ps.clientNum = index;



	// health will count down towards max_health
	ent->health = client->ps.stats[STAT_HEALTH] = client->ps.stats[STAT_MAX_HEALTH] + 25;

	G_SetOrigin( ent, spawn_origin );
	VectorCopy( spawn_origin, client->ps.origin );

	// the respawned flag will be cleared after the attack and jump keys come up
	client->ps.pm_flags |= PMF_RESPAWNED;

	trap_GetUsercmd( client - level.clients, &ent->client->pers.cmd );
	SetClientViewAngle( ent, spawn_angles );

	if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) {

	} else {
		G_KillBox( ent );
		trap_LinkEntity (ent);

	

	}

	// don't allow full run speed for a bit
	client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
	client->ps.pm_time = 100;

	client->respawnTime = level.time;
	client->inactivityTime = level.time + g_inactivity.integer * 1000;
	client->latched_buttons = 0;

	if ( level.intermissiontime ) {
		MoveClientToIntermission( ent );
	} else {
		// fire the targets of the spawn point
		G_UseTargets( spawnPoint, ent );

	}

	// run a client frame to drop exactly to the floor,
	// initialize animations and other things
	client->ps.commandTime = level.time - 100;
	ent->client->pers.cmd.serverTime = level.time;
	ClientThink( ent-g_entities );

	// positively link the client, even if the command times are weird
	if ( ent->client->sess.sessionTeam != TEAM_SPECTATOR ) {
		BG_PlayerStateToEntityState( &client->ps, &ent->s, qtrue );
		VectorCopy( ent->client->ps.origin, ent->r.currentOrigin );
		trap_LinkEntity( ent );
	}

	// run the presend to set anything else
	ClientEndFrame( ent );

	// clear entity state values
	BG_PlayerStateToEntityState( &client->ps, &ent->s, qtrue );

	ent->s.modelindex = G_ModelIndex("models/human/coxswain.tik");
}
示例#12
0
void TeleportPlayer( gentity_t *player, vec3_t origin, vec3_t angles ) {
	gentity_t	*tent;

	// use temp events at source and destination to prevent the effect
	// from getting dropped by a second player event
#ifndef SMOKINGUNS
	if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) {
#else
	if ( player->client->sess.sessionTeam < TEAM_SPECTATOR ) {
#endif
		tent = G_TempEntity( player->client->ps.origin, EV_PLAYER_TELEPORT_OUT );
		tent->s.clientNum = player->s.clientNum;

		tent = G_TempEntity( origin, EV_PLAYER_TELEPORT_IN );
		tent->s.clientNum = player->s.clientNum;
	}

	// unlink to make sure it can't possibly interfere with G_KillBox
	trap_UnlinkEntity (player);

	VectorCopy ( origin, player->client->ps.origin );
	player->client->ps.origin[2] += 1;

	// spit the player out
	AngleVectors( angles, player->client->ps.velocity, NULL, NULL );
	VectorScale( player->client->ps.velocity, 400, player->client->ps.velocity );
	player->client->ps.pm_time = 160;		// hold time
	player->client->ps.pm_flags |= PMF_TIME_KNOCKBACK;

	// toggle the teleport bit so the client knows to not lerp
	player->client->ps.eFlags ^= EF_TELEPORT_BIT;

#ifdef SMOKINGUNS
//unlagged - backward reconciliation #3
	// we don't want players being backward-reconciled back through teleporters
	G_ResetHistory( player );
//unlagged - backward reconciliation #3
#endif

	// set angles
	SetClientViewAngle( player, angles );

	// kill anything at the destination
#ifndef SMOKINGUNS
	if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) {
#else
	if ( player->client->sess.sessionTeam < TEAM_SPECTATOR ) {
#endif
		G_KillBox (player);
#ifdef SMOKINGUNS
		// Tequila comment: G_KillBox will set dontTelefrag as needed
		if (player->client->dontTelefrag) {
#ifdef DEBUG_TELEFRAG_CASE
			G_Printf(S_COLOR_MAGENTA "TeleportPlayer: Telefrag case delayed at respawn for %s...\n",player->client->pers.netname);
#endif
			trap_SendServerCommand( player->s.clientNum, va("print \"Go away %s\n\"",player->client->pers.netname) );
			// So we will link the player entity later with normal content
			player->r.contents = 0;
		}
#endif
	}

	// save results of pmove
	BG_PlayerStateToEntityState( &player->client->ps, &player->s, qtrue );

	// use the precise origin for linking
	VectorCopy( player->client->ps.origin, player->r.currentOrigin );

#ifndef SMOKINGUNS
	if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) {
#else
	if ( player->client->sess.sessionTeam < TEAM_SPECTATOR ) {
#endif
		trap_LinkEntity (player);
	}
}


/*QUAKED misc_teleporter_dest (1 0 0) (-32 -32 -24) (32 32 -16)
Point teleporters at these.
Now that we don't have teleport destination pads, this is just
an info_notnull
*/
void SP_misc_teleporter_dest( gentity_t *ent ) {
}


#ifdef SMOKINGUNS
// Imported from WoP OpenSource project
//===========================================================

/*QUAKED misc_externalmodel (1 0 0) (-16 -16 -16) (16 16 16)
"model"		arbitrary .md3 file to display
"wait"		time in seconds before the animation begins
*/
#define ANIMATION_THINKTIME	50

static void Think_AnimationExternalmodel( gentity_t *ent ) {

	if(ent->animationEnd>ent->animationStart) {
		ent->s.frame = (int)((float)level.time*0.001f*ent->animationFPS)%(ent->animationEnd-ent->animationStart);
		ent->s.frame += ent->animationStart;

		ent->nextthink = level.time + ANIMATION_THINKTIME;
	}
}

void SP_misc_externalmodel( gentity_t *ent )
{
	ent->s.modelindex = G_ModelIndex( ent->model );
//	VectorSet (ent->mins, -16, -16, -16);
//	VectorSet (ent->maxs, 16, 16, 16);
	trap_LinkEntity (ent);

	G_SetOrigin( ent, ent->s.origin );
	VectorCopy( ent->s.angles, ent->s.apos.trBase );

	if(ent->animationEnd>ent->animationStart && ent->animationFPS>0.0f) {
		ent->think = Think_AnimationExternalmodel;

		ent->nextthink = level.time + ANIMATION_THINKTIME;

		// Tequila: Support for new entity features
		if (ent->wait>0.0f)
			ent->nextthink += (int)(ent->wait*1000);
	}
}
#endif
//===========================================================

/*QUAKED misc_model (1 0 0) (-16 -16 -16) (16 16 16)
"model"		arbitrary .md3 file to display
*/
void SP_misc_model( gentity_t *ent ) {

#if 0
	ent->s.modelindex = G_ModelIndex( ent->model );
	VectorSet (ent->mins, -16, -16, -16);
	VectorSet (ent->maxs, 16, 16, 16);
	trap_LinkEntity (ent);

	G_SetOrigin( ent, ent->s.origin );
	VectorCopy( ent->s.angles, ent->s.apos.trBase );
#else
	G_FreeEntity( ent );
#endif
}

//===========================================================

void locateCamera( gentity_t *ent ) {
	vec3_t		dir;
	gentity_t	*target;
	gentity_t	*owner;

	owner = G_PickTarget( ent->target );
	if ( !owner ) {
		G_Printf( "Couldn't find target for misc_portal_surface\n" );
		G_FreeEntity( ent );
		return;
	}
	ent->r.ownerNum = owner->s.number;

	// frame holds the rotate speed
	if ( owner->spawnflags & 1 ) {
		ent->s.frame = 25;
	} else if ( owner->spawnflags & 2 ) {
		ent->s.frame = 75;
	}

#ifndef SMOKINGUNS
	// swing camera ?
	if ( owner->spawnflags & 4 ) {
		// set to 0 for no rotation at all
		ent->s.powerups = 0;
	}
	else {
		ent->s.powerups = 1;
	}
#else
	// set to 0 for no rotation at all
	ent->s.powerups = 1;
#endif

	// clientNum holds the rotate offset
	ent->s.clientNum = owner->s.clientNum;

	VectorCopy( owner->s.origin, ent->s.origin2 );

	// see if the portal_camera has a target
	target = G_PickTarget( owner->target );
	if ( target ) {
		VectorSubtract( target->s.origin, owner->s.origin, dir );
		VectorNormalize( dir );
	} else {
		G_SetMovedir( owner->s.angles, dir );
	}

	ent->s.eventParm = DirToByte( dir );
}
示例#13
0
void TeleportPlayer( gentity_t *player, vec3_t origin, vec3_t angles, qboolean spit ) {
    gentity_t	*tent;

    // use temp events at source and destination to prevent the effect
    // from getting dropped by a second player event
    /*freeze
    	if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) {
    freeze*/
    if ( (g_gametype.integer == GT_FREEZE && !is_spectator( player->client )) ||
            (g_gametype.integer != GT_FREEZE && player->client->sess.sessionTeam != TEAM_SPECTATOR) ) {
//freeze
        tent = G_TempEntity( player->client->ps.origin, EV_PLAYER_TELEPORT_OUT );
        tent->s.clientNum = player->s.clientNum;

        tent = G_TempEntity( origin, EV_PLAYER_TELEPORT_IN );
        tent->s.clientNum = player->s.clientNum;
    }

    // unlink to make sure it can't possibly interfere with G_KillBox
    //player->relink = 0;
    trap_UnlinkEntity (player);

    VectorCopy ( origin, player->client->ps.origin );
    player->client->ps.origin[2] += 1;

    // spit the player out
    if (spit == qtrue) {
        AngleVectors( angles, player->client->ps.velocity, NULL, NULL );
        VectorScale( player->client->ps.velocity, 400, player->client->ps.velocity );
        player->client->ps.pm_time = 160;		// hold time
        player->client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
    }

    // toggle the teleport bit so the client knows to not lerp
    player->client->ps.eFlags ^= EF_TELEPORT_BIT;

//unlagged - backward reconciliation #3
    // we don't want players being backward-reconciled back through teleporters
    G_ResetHistory( player );
//unlagged - backward reconciliation #3

    // set angles
    if (player->client->pers.fixedTeleporterAngles == qfalse)
        SetClientViewAngle( player, angles );

    // kill anything at the destination
    /*freeze
    	if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) {
    freeze*/
    if ( (g_gametype.integer == GT_FREEZE && !is_spectator( player->client )) ||
            (g_gametype.integer != GT_FREEZE && player->client->sess.sessionTeam != TEAM_SPECTATOR) ) {
//freeze
        G_KillBox (player);
    }

    // save results of pmove
    BG_PlayerStateToEntityState( &player->client->ps, &player->s, qtrue );

    // use the precise origin for linking
    VectorCopy( player->client->ps.origin, player->r.currentOrigin );

    /*freeze
    	if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) {
    freeze*/
    if ( (g_gametype.integer == GT_FREEZE && !is_spectator( player->client )) ||
            (g_gametype.integer != GT_FREEZE && player->client->sess.sessionTeam != TEAM_SPECTATOR) ) {
//freeze
        trap_LinkEntity (player);
    }
}
示例#14
0
/**
Called every time a client is placed fresh in the world:
after the first ClientBegin, and after each respawn
Initializes all non-persistant parts of playerState
*/
void ClientSpawn(gentity_t *ent)
{
	int		index;
	vec3_t	spawn_origin, spawn_angles;
	gclient_t	*client;
	clientPersistant_t	saved;
	clientSession_t		savedSess;
	int				persistant[MAX_PERSISTANT];
	gentity_t		*spawnPoint;
	gentity_t		*tent;
	int		flags;
	int		eventSequence;
	char	userinfo[MAX_INFO_STRING];

	index = ent - g_entities;
	client = ent->client;

	// follow other players when eliminated
	if (!level.warmupTime && g_gametype.integer == GT_ELIMINATION
		&& client->sess.sessionTeam != TEAM_SPECTATOR)
	{
		if (level.roundStarted) {
			client->sess.spectatorState = SPECTATOR_FREE;
			client->eliminated = qtrue;
			return;
		} else {
			client->sess.spectatorState = SPECTATOR_NOT;
			client->eliminated = qfalse;
		}
	}

	VectorClear(spawn_origin);

	// find a spawn point
	// do it before setting health back up, so farthest
	// ranging doesn't count this client
	if (client->sess.sessionTeam == TEAM_SPECTATOR) {
		SelectSpectatorSpawnPoint(spawn_origin, spawn_angles);
	} else if (g_gametype.integer == GT_DEFRAG) {
		spawnPoint = SelectDefragSpawnPoint(spawn_origin, spawn_angles);
	} else if (g_gametype.integer == GT_CTF) {
		spawnPoint = SelectCTFSpawnPoint(client->sess.sessionTeam,
			spawn_origin, spawn_angles, !!(ent->r.svFlags & SVF_BOT));
	} else if (client->pers.lastKiller) {
		spawnPoint = SelectSpawnPoint(client->pers.lastKiller->ps.origin, spawn_origin,
			spawn_angles, ent->r.svFlags & SVF_BOT);
	} else {
		spawnPoint = SelectSpawnPoint(client->ps.origin, spawn_origin,
			spawn_angles, ent->r.svFlags & SVF_BOT);
	}

	if (!spawnPoint) {
		G_Error("Cannot find a spawn point.\n");
		return;
	}

	// toggle the teleport bit so the client knows to not lerp
	flags = ent->client->ps.eFlags & (EF_TELEPORT_BIT);
	flags ^= EF_TELEPORT_BIT;

	// unlagged - backward reconciliation #3
	// we don't want players being backward-reconciled to the place they died
	G_ResetHistory( ent );
	// and this is as good a time as any to clear the saved state
	ent->client->saved.leveltime = 0;

	// clear everything but the persistant data

	saved = client->pers;
	savedSess = client->sess;
	eventSequence = client->ps.eventSequence;
	Com_Memcpy(persistant, client->ps.persistant, sizeof persistant);

	Com_Memset(client, 0, sizeof(*client));

	client->pers = saved;
	client->sess = savedSess;
	client->ps.eventSequence = eventSequence;
	Com_Memcpy(client->ps.persistant, persistant, sizeof client->ps.persistant);

	// increment the spawncount so the client will detect the respawn
	client->ps.persistant[PERS_SPAWN_COUNT]++;
	client->ps.persistant[PERS_TEAM] = client->sess.sessionTeam;

	client->airOutTime = level.time + 12000;

	trap_GetUserinfo(index, userinfo, sizeof(userinfo));
	// set max health
	client->pers.maxHealth = atoi(Info_ValueForKey(userinfo, "handicap"));
	if (client->pers.maxHealth < 1 || client->pers.maxHealth > 100) {
		client->pers.maxHealth = 100;
	}
	// clear entity values
	client->ps.stats[STAT_MAX_HEALTH] = client->pers.maxHealth;
	client->ps.eFlags = flags;

	ent->s.groundEntityNum = ENTITYNUM_NONE;
	ent->client = &level.clients[index];
	ent->takedamage = qtrue;
	ent->inuse = qtrue;
	ent->classname = "player";
	ent->r.contents = CONTENTS_BODY;
	ent->clipmask = MASK_PLAYERSOLID;
	ent->die = player_die;
	ent->waterlevel = 0;
	ent->watertype = 0;
	ent->flags &= ~FL_NO_KNOCKBACK;
	ent->flags &= ~FL_FORCE_GESTURE;

	VectorCopy(playerMins, ent->r.mins);
	VectorCopy(playerMaxs, ent->r.maxs);

	client->ps.clientNum = index;

	ClientGiveWeapons(client);

	if (g_gametype.integer == GT_ELIMINATION) {
		client->ps.stats[STAT_HEALTH] = client->ps.stats[STAT_MAX_HEALTH] * 2;
		client->ps.stats[STAT_ARMOR] = client->ps.stats[STAT_MAX_HEALTH] * 1.5;
	} else {
		client->ps.stats[STAT_HEALTH] = client->ps.stats[STAT_MAX_HEALTH] + 25;
	}
	ent->health = client->ps.stats[STAT_HEALTH];

	G_SetOrigin(ent, spawn_origin);
	VectorCopy(spawn_origin, client->ps.origin);

	// the respawned flag will be cleared after the attack and jump keys come up
	client->ps.pm_flags |= PMF_RESPAWNED;

	trap_GetUsercmd(client - level.clients, &ent->client->pers.cmd);
	SetClientViewAngle(ent, spawn_angles);
	// don't allow full run speed for a bit
	client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
	client->ps.pm_time = 100;

	client->respawnTime = level.time;
	client->inactivityTime = level.time + g_inactivity.integer * 1000;
	client->latched_buttons = 0;

	// set default animations
	client->ps.torsoAnim = TORSO_STAND;
	client->ps.legsAnim = LEGS_IDLE;

	if (level.intermissiontime) {
		// move players to intermission
		MoveClientToIntermission(ent);
	} else if (ent->client->sess.sessionTeam != TEAM_SPECTATOR) {
		G_KillBox(ent);

		// fire the targets of the spawn point
		G_UseTargets(spawnPoint, ent);

		// positively link the client, even if the command times are weird
		VectorCopy(ent->client->ps.origin, ent->r.currentOrigin);

		tent = G_TempEntity(ent->client->ps.origin, EV_PLAYER_TELEPORT_IN);
		tent->s.clientNum = ent->s.clientNum;

		trap_LinkEntity (ent);
	}

	// run a client frame to drop exactly to the floor,
	// initialize animations and other things
	client->ps.commandTime = level.totalTime - 100;
	client->pers.cmd.serverTime = level.totalTime;
	ClientThink(ent-g_entities);
	// run the presend to set anything else, follow spectators wait
	// until all clients have been reconnected after map_restart
	if (ent->client->sess.spectatorState != SPECTATOR_FOLLOW) {
		ClientEndFrame(ent);
	}

	// clear entity state values
	BG_PlayerStateToEntityState(&client->ps, &ent->s, qtrue);
}