示例#1
0
void SP_trigger_push( edict_t *self )
{
	InitTrigger( self );

	if( st.noise && Q_stricmp( st.noise, "default" ) )
	{
		if( Q_stricmp( st.noise, "silent" ) )
		{
			self->moveinfo.sound_start = trap_SoundIndex( st.noise );
			G_PureSound( st.noise );
		}
	}
	else
		self->moveinfo.sound_start = trap_SoundIndex( S_JUMPPAD );

	// gameteam field from editor
	if( st.gameteam >= TEAM_SPECTATOR && st.gameteam < GS_MAX_TEAMS )
		self->s.team = st.gameteam;
	else
		self->s.team = TEAM_SPECTATOR;

	self->touch = trigger_push_touch;
	self->think = trigger_push_setup;
	self->nextThink = level.time + 1;
	self->r.svflags &= ~SVF_NOCLIENT;
	self->s.type = ET_PUSH_TRIGGER;
	self->r.svflags |= SVF_TRANSMITORIGIN2;
	GClip_LinkEntity( self ); // ET_PUSH_TRIGGER gets exceptions at linking so it's added for prediction
	self->timeStamp = level.time;
	if( !self->wait )
		self->wait = MIN_TRIGGER_PUSH_REBOUNCE_TIME * 0.001f;
}
示例#2
0
/*
* W_Fire_Rocket
*/
edict_t *W_Fire_Rocket( edict_t *self, vec3_t start, vec3_t angles, int speed, float damage, int minKnockback, int maxKnockback, int stun, int minDamage, int radius, int timeout, int mod, int timeDelta )
{
	edict_t	*rocket;

	if( GS_Instagib() )
		damage = 9999;

	rocket = W_Fire_LinearProjectile( self, start, angles, speed, damage, minKnockback, maxKnockback, stun, minDamage, radius, timeout, timeDelta );

	rocket->s.type = ET_ROCKET; //rocket trail sfx
	if( mod == MOD_ROCKET_S )
	{
		rocket->s.modelindex = trap_ModelIndex( PATH_ROCKET_STRONG_MODEL );
		rocket->s.effects |= EF_STRONG_WEAPON;
		rocket->s.sound = trap_SoundIndex( S_WEAPON_ROCKET_S_FLY );
	}
	else
	{
		rocket->s.modelindex = trap_ModelIndex( PATH_ROCKET_WEAK_MODEL );
		rocket->s.effects &= ~EF_STRONG_WEAPON;
		rocket->s.sound = trap_SoundIndex( S_WEAPON_ROCKET_W_FLY );
	}
	rocket->touch = W_Touch_Rocket;
	rocket->think = G_FreeEdict;
	rocket->classname = "rocket";
	rocket->style = mod;

	return rocket;
}
示例#3
0
/*
* W_Fire_Plasma
*/
edict_t *W_Fire_Plasma( edict_t *self, vec3_t start, vec3_t angles, float damage, int minKnockback, int maxKnockback, int stun, int minDamage, int radius, int speed, int timeout, int mod, int timeDelta )
{
	edict_t	*plasma;

	if( GS_Instagib() )
		damage = 9999;

	plasma = W_Fire_LinearProjectile( self, start, angles, speed, damage, minKnockback, maxKnockback, stun, minDamage, radius, timeout, timeDelta );
	plasma->s.type = ET_PLASMA;
	plasma->classname = "plasma";
	plasma->style = mod;

	plasma->think = W_Think_Plasma;
	plasma->touch = W_AutoTouch_Plasma;
	plasma->nextThink = level.time + 1;
	plasma->timeout = level.time + timeout;

	if( mod == MOD_PLASMA_S )
	{
		plasma->s.modelindex = trap_ModelIndex( PATH_PLASMA_STRONG_MODEL );
		plasma->s.sound = trap_SoundIndex( S_WEAPON_PLASMAGUN_S_FLY );
		plasma->s.effects |= EF_STRONG_WEAPON;
	}
	else
	{
		plasma->s.modelindex = trap_ModelIndex( PATH_PLASMA_WEAK_MODEL );
		plasma->s.sound = trap_SoundIndex( S_WEAPON_PLASMAGUN_W_FLY );
		plasma->s.effects &= ~EF_STRONG_WEAPON;
	}

	return plasma;
}
示例#4
0
文件: g_items.c 项目: hettoo/racesow
void Touch_ItemSound( edict_t *other, gsitem_t *item )
{
	if( item->pickup_sound )
	{
		if( item->type & IT_POWERUP )
			G_Sound( other, CHAN_ITEM, trap_SoundIndex( item->pickup_sound ), ATTN_NORM );
		else
			G_Sound( other, CHAN_AUTO, trap_SoundIndex( item->pickup_sound ), ATTN_NORM );
	}
}
示例#5
0
void SP_trigger_hurt( edict_t *self )
{
	InitTrigger( self );

	if( self->dmg > 300 ) // HACK: force KILL spawnflag for big damages
		self->spawnflags |= 32;

	if( self->spawnflags & 4 ) // SILENT
	{   
		self->noise_index = 0;
	}
	else if( st.noise )
	{
		self->noise_index = trap_SoundIndex( st.noise );
		G_PureSound( st.noise );
	}
	else if( self->spawnflags & 32 || self->spawnflags & 64 ) // KILL or FALL
	{   
		self->noise_index = trap_SoundIndex( S_PLAYER_FALLDEATH );
	}
	else
	{
		self->noise_index = 0;
	}

	// gameteam field from editor
	if( st.gameteam >= TEAM_SPECTATOR && st.gameteam < GS_MAX_TEAMS )
	{
		self->s.team = st.gameteam;
	}
	else
	{
		self->s.team = TEAM_SPECTATOR;
	}

	self->touch = hurt_touch;

	if( !self->dmg )
		self->dmg = 5;

	if( self->spawnflags & 16 || !self->wait )
		self->wait = 0.1f;

	if( self->spawnflags & 1 )
		self->r.solid = SOLID_NOT;
	else
		self->r.solid = SOLID_TRIGGER;

	if( self->spawnflags & 2 )
		self->use = hurt_use;
}
示例#6
0
/*
* G_SetClientSound
*/
static void G_SetClientSound( edict_t *ent )
{
	if( ent->waterlevel == 3 )
	{
		if( ent->watertype & CONTENTS_LAVA )
			ent->s.sound = trap_SoundIndex( S_WORLD_UNDERLAVA );
		else if( ent->watertype & CONTENTS_SLIME )
			ent->s.sound = trap_SoundIndex( S_WORLD_UNDERSLIME );
		else if( ent->watertype & CONTENTS_WATER )
			ent->s.sound = trap_SoundIndex( S_WORLD_UNDERWATER );
	}
	else
		ent->s.sound = 0;
}
示例#7
0
void G_Gametype_GENERIC_SetUpCountdown( void )
{
	bool any = false;
	int team;

	G_Match_RemoveAllProjectiles();
	G_Items_RespawnByType( 0, 0, 0 ); // respawn all items

	level.gametype.readyAnnouncementEnabled = false;
	level.gametype.scoreAnnouncementEnabled = false;
	level.gametype.countdownEnabled = true;
	level.gametype.pickableItemsMask = 0; // disallow item pickup

	if( GS_TeamBasedGametype() )
	{
		for( team = TEAM_ALPHA; team < GS_MAX_TEAMS; team++ )
			if( G_Teams_LockTeam( team ) )
				any = true;
	}
	else
	{
		if( G_Teams_LockTeam( TEAM_PLAYERS ) )
			any = true;
	}

	if( any )
		G_PrintMsg( NULL, "Teams locked.\n" );

	G_AnnouncerSound( NULL, trap_SoundIndex( va( S_ANNOUNCER_COUNTDOWN_GET_READY_TO_FIGHT_1_to_2, ( rand()&1 )+1 ) ),
		GS_MAX_TEAMS, true, NULL );
}
示例#8
0
void SP_trigger_teleport( edict_t *ent )
{
	if( !ent->target )
	{
		if( developer->integer )
			G_Printf( "teleporter without a target.\n" );
		G_FreeEdict( ent );
		return;
	}

	if( st.noise )
	{
		ent->noise_index = trap_SoundIndex( st.noise );
		G_PureSound( st.noise );
	}

	// gameteam field from editor
	if( st.gameteam >= TEAM_SPECTATOR && st.gameteam < GS_MAX_TEAMS )
	{
		ent->s.team = st.gameteam;
	}
	else
	{
		ent->s.team = TEAM_SPECTATOR;
	}

	InitTrigger( ent );
	ent->touch = old_teleporter_touch;
}
示例#9
0
/*
* G_HideLaser
*/
void G_HideLaser( edict_t *ent )
{
	int soundindex;

	ent->s.modelindex = 0;
	ent->s.sound = 0;
	ent->r.svflags = SVF_NOCLIENT;

	if( ent->s.type == ET_CURVELASERBEAM )
		soundindex = trap_SoundIndex( S_WEAPON_LASERGUN_W_STOP );
	else
		soundindex = trap_SoundIndex( S_WEAPON_LASERGUN_S_STOP );

	G_Sound( game.edicts + ent->s.ownerNum, CHAN_AUTO, soundindex, ATTN_NORM );

	// give it 100 msecs before freeing itself, so we can relink it if we start firing again
	ent->think = G_FreeEdict;
	ent->nextThink = level.time + 100;
}
示例#10
0
void DoRespawn( edict_t *ent )
{
	if( ent->team )
	{
		edict_t	*master;
		int count;
		int choice;

		master = ent->teammaster;
		
		assert( master != NULL );

		if( master ) {
			for( count = 0, ent = master; ent; ent = ent->chain, count++ );

			choice = rand() % count;

			for( count = 0, ent = master; count < choice; ent = ent->chain, count++ );
		}
	}

	ent->r.solid = SOLID_TRIGGER;
	ent->r.svflags &= ~SVF_NOCLIENT;
	ent->s.effects &= ~EF_GHOST;

	GClip_LinkEntity( ent );

	// send an effect
	G_AddEvent( ent, EV_ITEM_RESPAWN, ent->item ? ent->item->tag : 0, true );

	// powerups announce their presence with a global sound
	if( ent->item && ( ent->item->type & IT_POWERUP ) )
	{
		if( ent->item->tag == POWERUP_QUAD )
			G_GlobalSound( CHAN_AUTO, trap_SoundIndex( S_ITEM_QUAD_RESPAWN ) );
		if( ent->item->tag == POWERUP_SHELL )
			G_GlobalSound( CHAN_AUTO, trap_SoundIndex( S_ITEM_WARSHELL_RESPAWN ) );
		if( ent->item->tag == POWERUP_REGEN )
			G_GlobalSound( CHAN_AUTO, trap_SoundIndex( S_ITEM_REGEN_RESPAWN ) );
	}
}
示例#11
0
/*
* G_Match_CheckExtendPlayTime
*/
bool G_Match_CheckExtendPlayTime( void )
{
	// check for extended time/sudden death
	if( GS_MatchState() != MATCH_STATE_PLAYTIME )
		return false;

	if( GS_TeamBasedGametype() && !level.forceExit )
	{
		if( G_Match_Tied() )
		{
			GS_GamestatSetFlag( GAMESTAT_FLAG_MATCHEXTENDED, true );
			gs.gameState.stats[GAMESTAT_MATCHSTATE] = MATCH_STATE_PLAYTIME;
			gs.gameState.longstats[GAMELONG_MATCHSTART] = game.serverTime;

			if( g_match_extendedtime->value )
			{
				if( !GS_MatchExtended() )  // first one
					G_AnnouncerSound( NULL, trap_SoundIndex( S_ANNOUNCER_OVERTIME_GOING_TO_OVERTIME ), GS_MAX_TEAMS, true, NULL );
				else
					G_AnnouncerSound( NULL, trap_SoundIndex( S_ANNOUNCER_OVERTIME_OVERTIME ), GS_MAX_TEAMS, true, NULL );

				G_PrintMsg( NULL, "Match tied. Timelimit extended by %i minutes!\n", g_match_extendedtime->integer );
				G_CenterPrintFormatMsg( NULL, "%s MINUTE OVERTIME\n", va( "%i", g_match_extendedtime->integer ), NULL );
				gs.gameState.longstats[GAMELONG_MATCHDURATION] = (unsigned int)( ( fabs( g_match_extendedtime->value ) * 60 ) * 1000 );
			}
			else
			{
				G_AnnouncerSound( NULL, trap_SoundIndex( va( S_ANNOUNCER_OVERTIME_SUDDENDEATH_1_to_2, ( rand()&1 )+1 ) ), GS_MAX_TEAMS, true, NULL );
				G_PrintMsg( NULL, "Match tied. Sudden death!\n" );
				G_CenterPrintMsg( NULL, "SUDDEN DEATH" );
				gs.gameState.longstats[GAMELONG_MATCHDURATION] = 0;
			}

			return true;
		}
	}

	return false;
}
示例#12
0
void G_Gametype_GENERIC_SetUpEndMatch( void )
{
	edict_t *ent;

	level.gametype.readyAnnouncementEnabled = false;
	level.gametype.scoreAnnouncementEnabled = false;
	level.gametype.pickableItemsMask = 0; // disallow item pickup
	level.gametype.countdownEnabled = false;

	for( ent = game.edicts + 1; PLAYERNUM( ent ) < gs.maxclients; ent++ )
	{
		if( ent->r.inuse && trap_GetClientState( PLAYERNUM( ent ) ) >= CS_SPAWNED )
			G_ClientRespawn( ent, true );
	}

	G_AnnouncerSound( NULL, trap_SoundIndex( va( S_ANNOUNCER_POSTMATCH_GAMEOVER_1_to_2, ( rand()&1 )+1 ) ), GS_MAX_TEAMS, true, NULL );
}
示例#13
0
/*
* W_Fire_Lasergun
*/
edict_t	*W_Fire_Lasergun( edict_t *self, vec3_t start, vec3_t angles, float damage, int knockback, int stun, int range, int mod, int timeDelta )
{
	edict_t	*laser;
	qboolean newLaser;
	trace_t	tr;
	vec3_t dir;

	if( GS_Instagib() )
		damage = 9999;

	laser = _FindOrSpawnLaser( self, ET_LASERBEAM, &newLaser );
	if( newLaser )
	{
		// the quad start sound is added from the server
		if( self->r.client && self->r.client->ps.inventory[POWERUP_QUAD] > 0 )
			G_Sound( self, CHAN_AUTO, trap_SoundIndex( S_QUAD_FIRE ), ATTN_NORM );
	}

	laser_damage = damage;
	laser_knockback = knockback;
	laser_stun = stun;
	laser_attackerNum = ENTNUM( self );
	laser_mod = mod;
	laser_missed = qtrue;

	GS_TraceLaserBeam( &tr, start, angles, range, ENTNUM( self ), timeDelta, _LaserImpact );

	laser->r.svflags |= SVF_FORCEOWNER;
	VectorCopy( start, laser->s.origin );
	AngleVectors( angles, dir, NULL, NULL );
	VectorMA( laser->s.origin, range, dir, laser->s.origin2 );

	laser->think = G_Laser_Think;
	laser->nextThink = level.time + 100;

	if( laser_missed && self->r.client )
		G_AwardPlayerMissedLasergun( self, mod );

	// calculate laser's mins and maxs for linkEntity
	G_SetBoundsForSpanEntity( laser, 8 );

	GClip_LinkEntity( laser );

	return laser;
}
示例#14
0
/*
* W_Fire_GunbladeBlast
*/
edict_t *W_Fire_GunbladeBlast( edict_t *self, vec3_t start, vec3_t angles, float damage, int minKnockback, int maxKnockback, int stun, int minDamage, int radius, int speed, int timeout, int mod, int timeDelta )
{
	edict_t	*blast;

	if( GS_Instagib() )
		damage = 9999;

	blast = W_Fire_LinearProjectile( self, start, angles, speed, damage, minKnockback, maxKnockback, stun, minDamage, radius, timeout, timeDelta );
	blast->s.modelindex = trap_ModelIndex( PATH_GUNBLADEBLAST_STRONG_MODEL );
	blast->s.type = ET_BLASTER;
	blast->s.effects |= EF_STRONG_WEAPON;
	blast->touch = W_Touch_GunbladeBlast;
	blast->classname = "gunblade_blast";
	blast->style = mod;

	blast->s.sound = trap_SoundIndex( S_WEAPON_PLASMAGUN_S_FLY );

	return blast;
}
示例#15
0
/*
* Cmd_Timeout_f
*/
static void Cmd_Timein_f( edict_t *ent )
{
	int num;

	if( ent->s.team == TEAM_SPECTATOR )
		return;

	if( !GS_MatchPaused() )
	{
		G_PrintMsg( ent, "No timeout in progress.\n" );
		return;
	}

	if( level.timeout.endtime - level.timeout.time <= 2 * TIMEIN_TIME )
	{
		G_PrintMsg( ent, "The timeout is about to end already.\n" );
		return;
	}

	if( GS_TeamBasedGametype() )
		num = ent->s.team;
	else
		num = ENTNUM( ent )-1;

	if( level.timeout.caller != num )
	{
		if( GS_TeamBasedGametype() )
			G_PrintMsg( ent, "Your team didn't call this timeout.\n" );
		else
			G_PrintMsg( ent, "You didn't call this timeout.\n" );
		return;
	}

	level.timeout.endtime = level.timeout.time + TIMEIN_TIME + FRAMETIME;

	G_AnnouncerSound( NULL, trap_SoundIndex( va( S_ANNOUNCER_TIMEOUT_TIMEIN_1_to_2, ( rand()&1 )+1 ) ), GS_MAX_TEAMS, true, NULL );

	G_PrintMsg( NULL, "%s%s called a timein\n", ent->r.client->netname, S_COLOR_WHITE );
}
示例#16
0
/*
* Cmd_Timeout_f
*/
static void Cmd_Timeout_f( edict_t *ent )
{
	int num;

	if( ent->s.team == TEAM_SPECTATOR || GS_MatchState() != MATCH_STATE_PLAYTIME )
		return;

	if( GS_TeamBasedGametype() )
		num = ent->s.team;
	else
		num = ENTNUM( ent )-1;

	if( GS_MatchPaused() && ( level.timeout.endtime - level.timeout.time ) >= 2*TIMEIN_TIME )
	{
		G_PrintMsg( ent, "Timeout already in progress\n" );
		return;
	}

	if( g_maxtimeouts->integer != -1 && level.timeout.used[num] >= g_maxtimeouts->integer )
	{
		if( g_maxtimeouts->integer == 0 )
			G_PrintMsg( ent, "Timeouts are not allowed on this server\n" );
		else if( GS_TeamBasedGametype() )
			G_PrintMsg( ent, "Your team doesn't have any timeouts left\n" );
		else
			G_PrintMsg( ent, "You don't have any timeouts left\n" );
		return;
	}

	G_PrintMsg( NULL, "%s%s called a timeout\n", ent->r.client->netname, S_COLOR_WHITE );

	if( !GS_MatchPaused() )
		G_AnnouncerSound( NULL, trap_SoundIndex( va( S_ANNOUNCER_TIMEOUT_TIMEOUT_1_to_2, ( rand()&1 )+1 ) ), GS_MAX_TEAMS, true, NULL );

	level.timeout.used[num]++;
	GS_GamestatSetFlag( GAMESTAT_FLAG_PAUSED, true );
	level.timeout.caller = num;
	level.timeout.endtime = level.timeout.time + TIMEOUT_TIME + FRAMETIME;
}
示例#17
0
void SP_target_speaker( edict_t *ent )
{
	char buffer[MAX_QPATH];

	if( !st.noise )
	{
		if( developer->integer )
			G_Printf( "target_speaker with no noise set at %s\n", vtos( ent->s.origin ) );
		return;
	}

	Q_strncpyz( buffer, st.noise, sizeof( buffer ) );
	ent->noise_index = trap_SoundIndex( buffer );
	G_PureSound( buffer );

	if( ent->attenuation == -1 || ent->spawnflags & 4 )  // use -1 so 0 defaults to ATTN_NONE
		ent->attenuation = ATTN_NONE;
	else if( !ent->attenuation )
		ent->attenuation = ATTN_NORM;

	if( ent->attenuation == ATTN_NONE )
		ent->r.svflags |= SVF_BROADCAST;
	if( ent->spawnflags & 16 )
		ent->r.svflags |= SVF_ONLYOWNER;

	// check for prestarted looping sound
	if( ent->spawnflags & 1 )
	{
		ent->s.sound = ent->noise_index;
		ent->r.svflags &= ~SVF_NOCLIENT;
	}

	ent->use = Use_Target_Speaker;

	// must link the entity so we get areas and clusters so
	// the server can determine who to send updates to
	GClip_LinkEntity( ent );
}
示例#18
0
void G_Gametype_GENERIC_SetUpMatch( void )
{
	int i;

	level.gametype.readyAnnouncementEnabled = false;
	level.gametype.scoreAnnouncementEnabled = true;
	level.gametype.countdownEnabled = true;
	level.gametype.pickableItemsMask = ( level.gametype.spawnableItemsMask|level.gametype.dropableItemsMask );
	if( GS_Instagib() )
		level.gametype.pickableItemsMask &= ~G_INSTAGIB_NEGATE_ITEMMASK;

	// clear player stats and scores, team scores and respawn clients in team lists
	for( i = TEAM_PLAYERS; i < GS_MAX_TEAMS; i++ )
	{
		int j;
		g_teamlist_t *team = &teamlist[i];
		memset( &team->stats, 0, sizeof( team->stats ) );

		// respawn all clients inside the playing teams
		for( j = 0; j < team->numplayers; j++ )
		{
			edict_t *ent = &game.edicts[ team->playerIndices[j] ];
			G_ClientClearStats( ent );
			G_ClientRespawn( ent, false );
		}
	}

	// set items to be spawned with a delay
	G_Items_RespawnByType( IT_ARMOR, ARMOR_RA, 15 );
	G_Items_RespawnByType( IT_ARMOR, ARMOR_RA, 15 );
	G_Items_RespawnByType( IT_HEALTH, HEALTH_MEGA, 15 );
	G_Items_RespawnByType( IT_HEALTH, HEALTH_ULTRA, 15 );
	G_Items_RespawnByType( IT_POWERUP, 0, brandom( 20, 40 ) );
	G_Match_FreeBodyQueue();

	G_AnnouncerSound( NULL, trap_SoundIndex( va( S_ANNOUNCER_COUNTDOWN_FIGHT_1_to_2, ( rand()&1 )+1 ) ), GS_MAX_TEAMS, false, NULL );
	G_CenterPrintMsg( NULL, "FIGHT!" );
}
示例#19
0
void SP_trigger_multiple( edict_t *ent )
{
	GClip_SetBrushModel( ent, ent->model );
	G_PureModel( ent->model );

	if( st.noise )
	{
		ent->noise_index = trap_SoundIndex( st.noise );
		G_PureSound( st.noise );
	}

	// gameteam field from editor
	if( st.gameteam >= TEAM_SPECTATOR && st.gameteam < GS_MAX_TEAMS )
		ent->s.team = st.gameteam;
	else
		ent->s.team = TEAM_SPECTATOR;

	if( !ent->wait )
		ent->wait = 0.2f;

	ent->touch = Touch_Multi;
	ent->movetype = MOVETYPE_NONE;
	ent->r.svflags |= SVF_NOCLIENT;

	if( ent->spawnflags & 4 )
	{
		ent->r.solid = SOLID_NOT;
		ent->use = trigger_enable;
	}
	else
	{
		ent->r.solid = SOLID_TRIGGER;
		ent->use = Use_Multi;
	}

	GClip_LinkEntity( ent );
}
示例#20
0
/*
* ClientThink
*/
void ClientThink( edict_t *ent, usercmd_t *ucmd, int timeDelta )
{
	gclient_t *client;
	int i, j;
	static pmove_t pm;
	int delta, count;

	client = ent->r.client;

	client->ps.POVnum = ENTNUM( ent );
	client->ps.playerNum = PLAYERNUM( ent );

	// anti-lag
	if( ent->r.svflags & SVF_FAKECLIENT )
	{
		client->timeDelta = 0;
	}
	else
	{
		int nudge;
		int fixedNudge = ( game.snapFrameTime ) * 0.5; // fixme: find where this nudge comes from.

		// add smoothing to timeDelta between the last few ucmds and a small fine-tuning nudge.
		nudge = fixedNudge + g_antilag_timenudge->integer;
		timeDelta += nudge;
		clamp( timeDelta, -g_antilag_maxtimedelta->integer, 0 );

		// smooth using last valid deltas
		i = client->timeDeltasHead - 6;
		if( i < 0 ) i = 0;
		for( count = 0, delta = 0; i < client->timeDeltasHead; i++ )
		{
			if( client->timeDeltas[i & G_MAX_TIME_DELTAS_MASK] < 0 )
			{
				delta += client->timeDeltas[i & G_MAX_TIME_DELTAS_MASK];
				count++;
			}
		}

		if( !count )
			client->timeDelta = timeDelta;
		else
		{
			delta /= count;
			client->timeDelta = ( delta + timeDelta ) * 0.5;
		}

		client->timeDeltas[client->timeDeltasHead & G_MAX_TIME_DELTAS_MASK] = timeDelta;
		client->timeDeltasHead++;

#ifdef UCMDTIMENUDGE
		client->timeDelta += client->pers.ucmdTimeNudge;
#endif
	}

	clamp( client->timeDelta, -g_antilag_maxtimedelta->integer, 0 );

	// update activity if he touched any controls
	if( ucmd->forwardmove != 0 || ucmd->sidemove != 0 || ucmd->upmove != 0 || ( ucmd->buttons & ~BUTTON_BUSYICON ) != 0
		|| client->ucmd.angles[PITCH] != ucmd->angles[PITCH] || client->ucmd.angles[YAW] != ucmd->angles[YAW] )
		G_Client_UpdateActivity( client );

	client->ucmd = *ucmd;

	// can exit intermission after two seconds, not counting postmatch
	if( GS_MatchState() == MATCH_STATE_WAITEXIT && ( ucmd->buttons & BUTTON_ATTACK ) && game.serverTime > GS_MatchStartTime() + 2000 )
		level.exitNow = true;

	// (is this really needed?:only if not cared enough about ps in the rest of the code)
	// refresh player state position from the entity
	VectorCopy( ent->s.origin, client->ps.pmove.origin );
	VectorCopy( ent->velocity, client->ps.pmove.velocity );
	VectorCopy( ent->s.angles, client->ps.viewangles );

	client->ps.pmove.gravity = level.gravity;

	if( GS_MatchState() >= MATCH_STATE_POSTMATCH || GS_MatchPaused() 
		|| ( ent->movetype != MOVETYPE_PLAYER && ent->movetype != MOVETYPE_NOCLIP ) )
		client->ps.pmove.pm_type = PM_FREEZE;
	else if( ent->s.type == ET_GIB )
		client->ps.pmove.pm_type = PM_GIB;
	else if( ent->movetype == MOVETYPE_NOCLIP || client->isTV )
		client->ps.pmove.pm_type = PM_SPECTATOR;
	else
		client->ps.pmove.pm_type = PM_NORMAL;

	// set up for pmove
	memset( &pm, 0, sizeof( pmove_t ) );
	pm.playerState = &client->ps;

	if( !client->isTV )
		pm.cmd = *ucmd;

	if( memcmp( &client->old_pmove, &client->ps.pmove, sizeof( pmove_state_t ) ) )
		pm.snapinitial = true;

	// perform a pmove
	Pmove( &pm );

	// save results of pmove
	client->old_pmove = client->ps.pmove;

	// update the entity with the new position
	VectorCopy( client->ps.pmove.origin, ent->s.origin );
	VectorCopy( client->ps.pmove.velocity, ent->velocity );
	VectorCopy( client->ps.viewangles, ent->s.angles );
	ent->viewheight = client->ps.viewheight;
	VectorCopy( pm.mins, ent->r.mins );
	VectorCopy( pm.maxs, ent->r.maxs );

	ent->waterlevel = pm.waterlevel;
	ent->watertype = pm.watertype;
	if( pm.groundentity == -1 )
	{
		ent->groundentity = NULL;
	}
	else
	{
		G_AwardResetPlayerComboStats( ent );

		ent->groundentity = &game.edicts[pm.groundentity];
		ent->groundentity_linkcount = ent->groundentity->linkcount;
	}
	
	GClip_LinkEntity( ent );

	GS_AddLaserbeamPoint( &ent->r.client->resp.trail, &ent->r.client->ps, ucmd->serverTimeStamp );

	// Regeneration
	if( ent->r.client->ps.inventory[POWERUP_REGEN] > 0 && ent->health < 200)
	{
		ent->health += ( game.frametime * 0.001f ) * 10.0f;

		// Regen expires if health reaches 200
		if ( ent->health >= 199.0f )
			ent->r.client->ps.inventory[POWERUP_REGEN]--;
	}

	// fire touch functions
	if( ent->movetype != MOVETYPE_NOCLIP )
	{
		edict_t *other;

		// touch other objects
		for( i = 0; i < pm.numtouch; i++ )
		{
			other = &game.edicts[pm.touchents[i]];
			for( j = 0; j < i; j++ )
			{
				if( &game.edicts[pm.touchents[j]] == other )
					break;
			}
			if( j != i )
				continue; // duplicated

			// player can't touch projectiles, only projectiles can touch the player
			G_CallTouch( other, ent, NULL, 0 );
		}
	}

	ent->s.weapon = GS_ThinkPlayerWeapon( &client->ps, ucmd->buttons, ucmd->msec, client->timeDelta );

	if( G_IsDead( ent ) )
	{
		if( ent->deathTimeStamp + g_respawn_delay_min->integer <= level.time )
			client->resp.snap.buttons |= ucmd->buttons;
	}
	else if( client->ps.pmove.stats[PM_STAT_NOUSERCONTROL] <= 0 )
		client->resp.snap.buttons |= ucmd->buttons;

	// trigger the instashield
	if( GS_Instagib() && g_instashield->integer )
	{
		if( client->ps.pmove.pm_type == PM_NORMAL && pm.cmd.upmove < 0 &&
			client->resp.instashieldCharge == INSTA_SHIELD_MAX && 
			client->ps.inventory[POWERUP_SHELL] == 0 )
		{
			client->ps.inventory[POWERUP_SHELL] = client->resp.instashieldCharge;
			G_Sound( ent, CHAN_AUTO, trap_SoundIndex( GS_FindItemByTag( POWERUP_SHELL )->pickup_sound ), ATTN_NORM );
		}
	}	

	// 
	if( client->ps.pmove.pm_type == PM_NORMAL )
		client->level.stats.had_playtime = true;

	// generating plrkeys (optimized for net communication)
	ClientMakePlrkeys( client, ucmd );
}
示例#21
0
文件: g_phys.cpp 项目: Picmip/qfusion
void SV_Physics_Step (edict_t *ent)
{
	bool	wasonground;
	bool	hitsound = false;
	float		*vel;
	float		speed, newspeed, control;
	float		friction;
	edict_t		*groundentity;
	int			mask;

	// airborn monsters should always check for ground
	if (!ent->groundentity)
		M_CheckGround (ent);

	groundentity = ent->groundentity;

	SV_CheckVelocity (ent);

	if (groundentity)
		wasonground = true;
	else
		wasonground = false;

	if (ent->avelocity[0] || ent->avelocity[1] || ent->avelocity[2])
		SV_AddRotationalFriction (ent);

	// add gravity except:
	//   flying monsters
	//   swimming monsters who are in the water
	if (! wasonground)
		if (!(ent->flags & FL_FLY))
			if (!((ent->flags & FL_SWIM) && (ent->waterlevel > 2)))
			{
				if (ent->velocity[2] < level.gravity*-0.1)
					hitsound = true;
				if (ent->waterlevel == 0)
					SV_AddGravity (ent);
			}

	// friction for flying monsters that have been given vertical velocity
	if ((ent->flags & FL_FLY) && (ent->velocity[2] != 0))
	{
		speed = fabs(ent->velocity[2]);
		control = speed < sv_stopspeed ? sv_stopspeed : speed;
		friction = sv_friction/3;
		newspeed = speed - (FRAMETIME * control * friction);
		if (newspeed < 0)
			newspeed = 0;
		newspeed /= speed;
		ent->velocity[2] *= newspeed;
	}

	// friction for flying monsters that have been given vertical velocity
	if ((ent->flags & FL_SWIM) && (ent->velocity[2] != 0))
	{
		speed = fabs(ent->velocity[2]);
		control = speed < sv_stopspeed ? sv_stopspeed : speed;
		newspeed = speed - (FRAMETIME * control * sv_waterfriction * ent->waterlevel);
		if (newspeed < 0)
			newspeed = 0;
		newspeed /= speed;
		ent->velocity[2] *= newspeed;
	}

	if (ent->velocity[2] || ent->velocity[1] || ent->velocity[0])
	{
		// apply friction
		// let dead monsters who aren't completely onground slide
		if ((wasonground) || (ent->flags & (FL_SWIM|FL_FLY)))
			if (!(ent->health <= 0.0 && !M_CheckBottom(ent)))
			{
				vel = ent->velocity;
				speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]);
				if (speed)
				{
					friction = sv_friction;

					control = speed < sv_stopspeed ? sv_stopspeed : speed;
					newspeed = speed - FRAMETIME*control*friction;

					if (newspeed < 0)
						newspeed = 0;
					newspeed /= speed;

					vel[0] *= newspeed;
					vel[1] *= newspeed;
				}
			}

		if (ent->r.svflags & SVF_MONSTER)
			mask = MASK_MONSTERSOLID;
		else
			mask = MASK_SOLID;
		SV_FlyMove (ent, FRAMETIME, mask);

		GClip_LinkEntity (ent);
		GClip_TouchTriggers (ent);

		if (ent->groundentity)
			if (!wasonground)
				if (hitsound)
					G_Sound (ent, 0, trap_SoundIndex( S_LAND ), ATTN_NORM);
	}
}
示例#22
0
void G_PrecacheMedia( void )
{
	//
	// MODELS
	//

	// THIS ORDER MUST MATCH THE DEFINES IN gs_public.h
	// you can add more, max 255

	trap_ModelIndex( "#gunblade/gunblade.md3" );      // WEAP_GUNBLADE
	trap_ModelIndex( "#machinegun/machinegun.md3" );    // WEAP_MACHINEGUN
	trap_ModelIndex( "#riotgun/riotgun.md3" );        // WEAP_RIOTGUN
	trap_ModelIndex( "#glauncher/glauncher.md3" );    // WEAP_GRENADELAUNCHER
	trap_ModelIndex( "#rlauncher/rlauncher.md3" );    // WEAP_ROCKETLAUNCHER
	trap_ModelIndex( "#plasmagun/plasmagun.md3" );    // WEAP_PLASMAGUN
	trap_ModelIndex( "#lasergun/lasergun.md3" );      // WEAP_LASERGUN
	trap_ModelIndex( "#electrobolt/electrobolt.md3" ); // WEAP_ELECTROBOLT
	trap_ModelIndex( "#instagun/instagun.md3" );      // WEAP_INSTAGUN

	//-------------------

	// precache our basic player models, they are just a very few
	trap_ModelIndex( "$models/players/bigvic" );

	trap_SkinIndex( "models/players/bigvic/default" );

	// FIXME: Temporarily use normal gib until the head is fixed
	trap_ModelIndex( "models/objects/gibs/illuminati1/illuminati1.md3" );

	//
	// SOUNDS
	//

	// jalfixme : most of these sounds can be played from the clients

	trap_SoundIndex( S_WORLD_WATER_IN );    // feet hitting water
	trap_SoundIndex( S_WORLD_WATER_OUT );       // feet leaving water
	trap_SoundIndex( S_WORLD_UNDERWATER );

	trap_SoundIndex( S_WORLD_SLIME_IN );
	trap_SoundIndex( S_WORLD_SLIME_OUT );
	trap_SoundIndex( S_WORLD_UNDERSLIME );

	trap_SoundIndex( S_WORLD_LAVA_IN );
	trap_SoundIndex( S_WORLD_LAVA_OUT );
	trap_SoundIndex( S_WORLD_UNDERLAVA );

	trap_SoundIndex( va( S_PLAYER_BURN_1_to_2, 1 ) );
	trap_SoundIndex( va( S_PLAYER_BURN_1_to_2, 2 ) );

	//wsw: pb disable unreferenced sounds
	//trap_SoundIndex (S_LAND);				// landing thud
	trap_SoundIndex( S_HIT_WATER );

	trap_SoundIndex( S_WEAPON_NOAMMO );

	// announcer

	// readyup
	trap_SoundIndex( S_ANNOUNCER_READY_UP_POLITE );
	trap_SoundIndex( S_ANNOUNCER_READY_UP_PISSEDOFF );

	// countdown
	trap_SoundIndex( va( S_ANNOUNCER_COUNTDOWN_GET_READY_TO_FIGHT_1_to_2, 1 ) );
	trap_SoundIndex( va( S_ANNOUNCER_COUNTDOWN_GET_READY_TO_FIGHT_1_to_2, 2 ) );
	trap_SoundIndex( va( S_ANNOUNCER_COUNTDOWN_READY_1_to_2, 1 ) );
	trap_SoundIndex( va( S_ANNOUNCER_COUNTDOWN_READY_1_to_2, 2 ) );
	trap_SoundIndex( va( S_ANNOUNCER_COUNTDOWN_COUNT_1_to_3_SET_1_to_2, 1, 1 ) );
	trap_SoundIndex( va( S_ANNOUNCER_COUNTDOWN_COUNT_1_to_3_SET_1_to_2, 2, 1 ) );
	trap_SoundIndex( va( S_ANNOUNCER_COUNTDOWN_COUNT_1_to_3_SET_1_to_2, 3, 1 ) );
	trap_SoundIndex( va( S_ANNOUNCER_COUNTDOWN_COUNT_1_to_3_SET_1_to_2, 1, 2 ) );
	trap_SoundIndex( va( S_ANNOUNCER_COUNTDOWN_COUNT_1_to_3_SET_1_to_2, 2, 2 ) );
	trap_SoundIndex( va( S_ANNOUNCER_COUNTDOWN_COUNT_1_to_3_SET_1_to_2, 3, 2 ) );
	trap_SoundIndex( va( S_ANNOUNCER_COUNTDOWN_FIGHT_1_to_2, 1 ) );
	trap_SoundIndex( va( S_ANNOUNCER_COUNTDOWN_FIGHT_1_to_2, 2 ) );

	// postmatch
	trap_SoundIndex( va( S_ANNOUNCER_POSTMATCH_GAMEOVER_1_to_2, 1 ) );
	trap_SoundIndex( va( S_ANNOUNCER_POSTMATCH_GAMEOVER_1_to_2, 2 ) );

	// timeout
	trap_SoundIndex( va( S_ANNOUNCER_TIMEOUT_MATCH_RESUMED_1_to_2, 1 ) );
	trap_SoundIndex( va( S_ANNOUNCER_TIMEOUT_MATCH_RESUMED_1_to_2, 2 ) );
	trap_SoundIndex( va( S_ANNOUNCER_TIMEOUT_TIMEOUT_1_to_2, 1 ) );
	trap_SoundIndex( va( S_ANNOUNCER_TIMEOUT_TIMEOUT_1_to_2, 2 ) );
	trap_SoundIndex( va( S_ANNOUNCER_TIMEOUT_TIMEIN_1_to_2, 1 ) );
	trap_SoundIndex( va( S_ANNOUNCER_TIMEOUT_TIMEIN_1_to_2, 2 ) );

	// callvote
	trap_SoundIndex( va( S_ANNOUNCER_CALLVOTE_CALLED_1_to_2, 1 ) );
	trap_SoundIndex( va( S_ANNOUNCER_CALLVOTE_CALLED_1_to_2, 2 ) );
	trap_SoundIndex( va( S_ANNOUNCER_CALLVOTE_FAILED_1_to_2, 1 ) );
	trap_SoundIndex( va( S_ANNOUNCER_CALLVOTE_FAILED_1_to_2, 2 ) );
	trap_SoundIndex( va( S_ANNOUNCER_CALLVOTE_PASSED_1_to_2, 1 ) );
	trap_SoundIndex( va( S_ANNOUNCER_CALLVOTE_PASSED_1_to_2, 2 ) );
	trap_SoundIndex( S_ANNOUNCER_CALLVOTE_VOTE_NOW );

	// overtime
	trap_SoundIndex( S_ANNOUNCER_OVERTIME_GOING_TO_OVERTIME );
	trap_SoundIndex( S_ANNOUNCER_OVERTIME_OVERTIME );
	trap_SoundIndex( va( S_ANNOUNCER_OVERTIME_SUDDENDEATH_1_to_2, 1 ) );
	trap_SoundIndex( va( S_ANNOUNCER_OVERTIME_SUDDENDEATH_1_to_2, 2 ) );

	// score
	trap_SoundIndex( va( S_ANNOUNCER_SCORE_TAKEN_LEAD_1_to_2, 1 ) );
	trap_SoundIndex( va( S_ANNOUNCER_SCORE_TAKEN_LEAD_1_to_2, 2 ) );
	trap_SoundIndex( va( S_ANNOUNCER_SCORE_LOST_LEAD_1_to_2, 1 ) );
	trap_SoundIndex( va( S_ANNOUNCER_SCORE_LOST_LEAD_1_to_2, 2 ) );
	trap_SoundIndex( va( S_ANNOUNCER_SCORE_TIED_LEAD_1_to_2, 1 ) );
	trap_SoundIndex( va( S_ANNOUNCER_SCORE_TIED_LEAD_1_to_2, 2 ) );

	if( GS_TeamBasedGametype() )
	{
		trap_SoundIndex( va( S_ANNOUNCER_SCORE_TEAM_TAKEN_LEAD_1_to_2, 1 ) );
		trap_SoundIndex( va( S_ANNOUNCER_SCORE_TEAM_TAKEN_LEAD_1_to_2, 2 ) );
		trap_SoundIndex( va( S_ANNOUNCER_SCORE_TEAM_LOST_LEAD_1_to_2, 1 ) );
		trap_SoundIndex( va( S_ANNOUNCER_SCORE_TEAM_LOST_LEAD_1_to_2, 2 ) );
		trap_SoundIndex( va( S_ANNOUNCER_SCORE_TEAM_TIED_LEAD_1_to_2, 1 ) );
		trap_SoundIndex( va( S_ANNOUNCER_SCORE_TEAM_TIED_LEAD_1_to_2, 2 ) );
		trap_SoundIndex( va( S_ANNOUNCER_SCORE_TEAM_TIED_LEAD_1_to_2, 1 ) );
		trap_SoundIndex( va( S_ANNOUNCER_SCORE_TEAM_TIED_LEAD_1_to_2, 2 ) );
		//trap_SoundIndex( va( S_ANNOUNCER_SCORE_TEAM_1_to_4_TAKEN_LEAD_1_to_2, 3, 1 ) );
		//trap_SoundIndex( va( S_ANNOUNCER_SCORE_TEAM_1_to_4_TAKEN_LEAD_1_to_2, 3, 2 ) );
		//trap_SoundIndex( va( S_ANNOUNCER_SCORE_TEAM_1_to_4_TAKEN_LEAD_1_to_2, 4, 1 ) );
		//trap_SoundIndex( va( S_ANNOUNCER_SCORE_TEAM_1_to_4_TAKEN_LEAD_1_to_2, 4, 2 ) );
	}

	//
	// LIGHTSTYLES
	//

	// light animation tables. 'a' is total darkness, 'z' is doublebright.

	// 0 normal
	trap_ConfigString( CS_LIGHTS+0, "m" );

	// 1 FLICKER (first variety)
	trap_ConfigString( CS_LIGHTS+1, "mmnmmommommnonmmonqnmmo" );

	// 2 SLOW STRONG PULSE
	trap_ConfigString( CS_LIGHTS+2, "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba" );

	// 3 CANDLE (first variety)
	trap_ConfigString( CS_LIGHTS+3, "mmmmmaaaaammmmmaaaaaabcdefgabcdefg" );

	// 4 FAST STROBE
	trap_ConfigString( CS_LIGHTS+4, "mamamamamama" );

	// 5 GENTLE PULSE 1
	trap_ConfigString( CS_LIGHTS+5, "jklmnopqrstuvwxyzyxwvutsrqponmlkj" );

	// 6 FLICKER (second variety)
	trap_ConfigString( CS_LIGHTS+6, "nmonqnmomnmomomno" );

	// 7 CANDLE (second variety)
	trap_ConfigString( CS_LIGHTS+7, "mmmaaaabcdefgmmmmaaaammmaamm" );

	// 8 CANDLE (third variety)
	trap_ConfigString( CS_LIGHTS+8, "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa" );

	// 9 SLOW STROBE (fourth variety)
	trap_ConfigString( CS_LIGHTS+9, "aaaaaaaazzzzzzzz" );

	// 10 FLUORESCENT FLICKER
	trap_ConfigString( CS_LIGHTS+10, "mmamammmmammamamaaamammma" );

	// 11 SLOW PULSE NOT FADE TO BLACK
	trap_ConfigString( CS_LIGHTS+11, "abcdefghijklmnopqrrqponmlkjihgfedcba" );

	// styles 32-62 are assigned by the light program for switchable lights

	// 63 testing
	trap_ConfigString( CS_LIGHTS+63, "a" );
}
示例#23
0
/*
* G_Match_ReadyAnnouncement
*/
static void G_Match_ReadyAnnouncement( void )
{
	int i;
	edict_t *e;
	int team;
	bool readyupwarnings = false;
	int START_TEAM, END_TEAM;

	if( !level.gametype.readyAnnouncementEnabled )
		return;

	// ready up announcements

	if( GS_TeamBasedGametype() )
	{
		START_TEAM = TEAM_ALPHA;
		END_TEAM = GS_MAX_TEAMS;
	}
	else
	{
		START_TEAM = TEAM_PLAYERS;
		END_TEAM = TEAM_PLAYERS+1;
	}

	for( team = START_TEAM; team < END_TEAM; team++ )
	{
		if( !teamlist[team].numplayers )
			continue;

		for( i = 0; i < teamlist[team].numplayers; i++ )
		{
			e = game.edicts + teamlist[team].playerIndices[i];
			if( e->r.svflags & SVF_FAKECLIENT )
				continue;

			if( level.ready[teamlist[team].playerIndices[i]-1] )
			{
				readyupwarnings = true;
				break;
			}
		}
	}

	if( !readyupwarnings )
		return;

	// now let's repeat and warn
	for( team = START_TEAM; team < END_TEAM; team++ )
	{
		if( !teamlist[team].numplayers )
			continue;
		for( i = 0; i < teamlist[team].numplayers; i++ )
		{
			if( !level.ready[teamlist[team].playerIndices[i]-1] )
			{
				e = game.edicts + teamlist[team].playerIndices[i];
				if( !e->r.client || trap_GetClientState( PLAYERNUM( e ) ) != CS_SPAWNED )
					continue;

				if( e->r.client->teamstate.readyUpWarningNext < game.realtime )
				{
					e->r.client->teamstate.readyUpWarningNext = game.realtime + G_ANNOUNCER_READYUP_DELAY;
					e->r.client->teamstate.readyUpWarningCount++;
					if( e->r.client->teamstate.readyUpWarningCount > 3 )
					{
						G_AnnouncerSound( e, trap_SoundIndex( S_ANNOUNCER_READY_UP_PISSEDOFF ), GS_MAX_TEAMS, true, NULL );
						e->r.client->teamstate.readyUpWarningCount = 0;
					}
					else
					{
						G_AnnouncerSound( e, trap_SoundIndex( S_ANNOUNCER_READY_UP_POLITE ), GS_MAX_TEAMS, true, NULL );
					}
				}
			}
		}
	}
}
示例#24
0
//QUAKED misc_particles (.6 .7 .7) (-8 -8 -8) (8 8 8) SPHERICAL SOLID GRAVITY LIGHT EXPAND_EFFECT SHRINK_EFFECT START_OFF
//-------- KEYS --------
//angles: direction in which particles will be thrown.
//shader : particleShader
void SP_misc_particles( edict_t *ent )
{
	ent->r.svflags &= ~SVF_NOCLIENT;
	ent->r.svflags |= SVF_BROADCAST;
	ent->r.solid = SOLID_NOT;
	ent->s.type = ET_PARTICLES;

	if( st.noise )
	{
		ent->s.sound = trap_SoundIndex( st.noise );
		G_PureSound( st.noise );
	}

	if( st.gameteam >= TEAM_ALPHA && st.gameteam < GS_MAX_TEAMS )
		ent->s.team = st.gameteam;
	else
		ent->s.team = 0;

	if( ent->speed > 0 )
		ent->particlesInfo.speed = ((int)ent->speed) & 255;

	if( ent->count > 0 )
		ent->particlesInfo.frequency = ent->count & 255;

	if( st.shaderName )
		ent->particlesInfo.shaderIndex = trap_ImageIndex( st.shaderName );
	else
		ent->particlesInfo.shaderIndex = trap_ImageIndex( "particle" );

	if( st.size )
		ent->particlesInfo.size = st.size & 255;
	else
		ent->particlesInfo.size = 16;

	ent->particlesInfo.time = ent->delay;
	if( !ent->particlesInfo.time )
		ent->particlesInfo.time = 4;

	if( ent->spawnflags & 1 ) // SPHERICAL
		ent->particlesInfo.spherical = true;

	if( ent->spawnflags & 2 ) // BOUNCE
		ent->particlesInfo.bounce = true;

	if( ent->spawnflags & 4 ) // GRAVITY
		ent->particlesInfo.gravity = true;

	if( ent->spawnflags & 8 ) // LIGHT
	{
		ent->s.light = COLOR_RGB( (qbyte)(ent->color[0] * 255), (qbyte)(ent->color[1] * 255), (qbyte)(ent->color[2] * 255) );
		if( !ent->s.light )
			ent->s.light = COLOR_RGB( 255, 255, 255 );
	}

	if( ent->spawnflags & 16 ) // EXPAND_EFFECT
		ent->particlesInfo.expandEffect = true;

	if( ent->spawnflags & 32 ) // SHRINK_EFFECT
		ent->particlesInfo.shrinkEffect = true;

	if( ent->spawnflags & 64 ) // START_OFF
		ent->r.svflags |= SVF_NOCLIENT;

	if( st.radius > 0 )
	{
		ent->particlesInfo.spread = st.radius;
		clamp( ent->particlesInfo.spread, 0, 255 );
	}

	ent->think = SP_misc_particles_finish;
	ent->nextThink = level.time + 1;
	ent->use = SP_misc_particles_use;

	GClip_LinkEntity( ent );
}
示例#25
0
文件: g_phys.cpp 项目: Picmip/qfusion
/*
* SV_Physics_Toss
*
* Toss, bounce, and fly movement.  When onground, do nothing.
*
* FIXME: This function needs a serious rewrite
*/
static void SV_Physics_Toss( edict_t *ent ) {
	trace_t trace;
	vec3_t move;
	float backoff;
	edict_t *slave;
	bool wasinwater;
	bool isinwater;
	vec3_t old_origin;
	float oldSpeed;

	// if not a team captain, so movement will be handled elsewhere
	if( ent->flags & FL_TEAMSLAVE ) {
		return;
	}

	// refresh the ground entity
	if( ent->movetype == MOVETYPE_BOUNCE || ent->movetype == MOVETYPE_BOUNCEGRENADE ) {
		if( ent->velocity[2] > 0.1f ) {
			ent->groundentity = NULL;
		}
	}

	if( ent->groundentity && ent->groundentity != world && !ent->groundentity->r.inuse ) {
		ent->groundentity = NULL;
	}

	oldSpeed = VectorLength( ent->velocity );

	if( ent->groundentity ) {
		if( !oldSpeed ) {
			return;
		}

		if( ent->movetype == MOVETYPE_TOSS ) {
			if( ent->velocity[2] >= 8 ) {
				ent->groundentity = NULL;
			} else {
				VectorClear( ent->velocity );
				VectorClear( ent->avelocity );
				G_CallStop( ent );
				return;
			}
		}
	}

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

	if( ent->accel != 0 ) {
		if( ent->accel < 0 && VectorLength( ent->velocity ) < 50 ) {
			VectorClear( ent->velocity );
		} else {
			vec3_t acceldir;
			VectorNormalize2( ent->velocity, acceldir );
			VectorScale( acceldir, ent->accel * FRAMETIME, acceldir );
			VectorAdd( ent->velocity, acceldir, ent->velocity );
		}
	}

	SV_CheckVelocity( ent );

	// add gravity
	if( ent->movetype != MOVETYPE_FLY && !ent->groundentity ) {
		SV_AddGravity( ent );
	}

	// move angles
	VectorMA( ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles );

	// move origin
	VectorScale( ent->velocity, FRAMETIME, move );

	trace = SV_PushEntity( ent, move );
	if( !ent->r.inuse ) {
		return;
	}

	if( trace.fraction < 1.0f ) {
		if( ent->movetype == MOVETYPE_BOUNCE ) {
			backoff = 1.5;
		} else if( ent->movetype == MOVETYPE_BOUNCEGRENADE ) {
			backoff = 1.5;
		} else {
			backoff = 1;
		}

		GS_ClipVelocity( ent->velocity, trace.plane.normal, ent->velocity, backoff );

		// stop if on ground

		if( ent->movetype == MOVETYPE_BOUNCE || ent->movetype == MOVETYPE_BOUNCEGRENADE ) {
			// stop dead on allsolid

			// LA: hopefully will fix grenades bouncing down slopes
			// method taken from Darkplaces sourcecode
			if( trace.allsolid ||
				( ISWALKABLEPLANE( &trace.plane ) &&
				  fabs( DotProduct( trace.plane.normal, ent->velocity ) ) < 40
				)
				) {
				ent->groundentity = &game.edicts[trace.ent];
				ent->groundentity_linkcount = ent->groundentity->linkcount;
				VectorClear( ent->velocity );
				VectorClear( ent->avelocity );
				G_CallStop( ent );
			}
		} else {
			// in movetype_toss things stop dead when touching ground
#if 0
			G_CheckGround( ent );

			if( ent->groundentity ) {
#else

			// walkable or trapped inside solid brush
			if( trace.allsolid || ISWALKABLEPLANE( &trace.plane ) ) {
				ent->groundentity = trace.ent < 0 ? world : &game.edicts[trace.ent];
				ent->groundentity_linkcount = ent->groundentity->linkcount;
#endif
				VectorClear( ent->velocity );
				VectorClear( ent->avelocity );
				G_CallStop( ent );
			}
		}
	}

	// check for water transition
	wasinwater = ( ent->watertype & MASK_WATER ) ? true : false;
	ent->watertype = G_PointContents( ent->s.origin );
	isinwater = ent->watertype & MASK_WATER ? true : false;

	// never allow items in CONTENTS_NODROP
	if( ent->item && ( ent->watertype & CONTENTS_NODROP ) ) {
		G_FreeEdict( ent );
		return;
	}

	if( isinwater ) {
		ent->waterlevel = 1;
	} else {
		ent->waterlevel = 0;
	}

	if( !wasinwater && isinwater ) {
		G_PositionedSound( old_origin, CHAN_AUTO, trap_SoundIndex( S_HIT_WATER ), ATTN_IDLE );
	} else if( wasinwater && !isinwater ) {
		G_PositionedSound( ent->s.origin, CHAN_AUTO, trap_SoundIndex( S_HIT_WATER ), ATTN_IDLE );
	}

	// move teamslaves
	for( slave = ent->teamchain; slave; slave = slave->teamchain ) {
		VectorCopy( ent->s.origin, slave->s.origin );
		GClip_LinkEntity( slave );
	}
}

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

void SV_Physics_LinearProjectile( edict_t *ent ) {
	vec3_t start, end;
	int mask;
	float startFlyTime, endFlyTime;
	trace_t trace;
	int old_waterLevel;

	// if not a team captain movement will be handled elsewhere
	if( ent->flags & FL_TEAMSLAVE ) {
		return;
	}

	old_waterLevel = ent->waterlevel;

	mask = ( ent->r.clipmask ) ? ent->r.clipmask : MASK_SOLID;

	// find it's current position given the starting timeStamp
	startFlyTime = (float)( max( game.prevServerTime - ent->s.linearMovementTimeStamp, 0 ) ) * 0.001f;
	endFlyTime = (float)( game.serverTime - ent->s.linearMovementTimeStamp ) * 0.001f;

	VectorMA( ent->s.linearMovementBegin, startFlyTime, ent->s.linearMovementVelocity, start );
	VectorMA( ent->s.linearMovementBegin, endFlyTime, ent->s.linearMovementVelocity, end );

	G_Trace4D( &trace, start, ent->r.mins, ent->r.maxs, end, ent, mask, ent->timeDelta );
	VectorCopy( trace.endpos, ent->s.origin );
	GClip_LinkEntity( ent );
	SV_Impact( ent, &trace );

	if( !ent->r.inuse ) { // the projectile may be freed if touched something
		return;
	}

	// update some data required for the transmission
	//VectorCopy( ent->velocity, ent->s.linearMovementVelocity );

	GClip_TouchTriggers( ent );
	ent->groundentity = NULL; // projectiles never have ground entity
	ent->waterlevel = ( G_PointContents4D( ent->s.origin, ent->timeDelta ) & MASK_WATER ) ? true : false;

	if( !old_waterLevel && ent->waterlevel ) {
		G_PositionedSound( start, CHAN_AUTO, trap_SoundIndex( S_HIT_WATER ), ATTN_IDLE );
	} else if( old_waterLevel && !ent->waterlevel ) {
		G_PositionedSound( ent->s.origin, CHAN_AUTO, trap_SoundIndex( S_HIT_WATER ), ATTN_IDLE );
	}
}
示例#26
0
文件: g_items.c 项目: hettoo/racesow
/*
* PrecacheItem
* 
* Precaches all data needed for a given item.
* This will be called for each item spawned in a level,
* and for each item in each client's inventory.
*/
void PrecacheItem( gsitem_t *it )
{
	int i;
	const char *s, *start;
	char data[MAX_QPATH];
	int len;
	gsitem_t	*ammo;

	if( !it )
		return;

	if( it->pickup_sound )
		trap_SoundIndex( it->pickup_sound );
	for( i = 0; i < MAX_ITEM_MODELS; i++ )
	{
		if( it->world_model[i] )
			trap_ModelIndex( it->world_model[i] );
	}

	if( it->icon )
		trap_ImageIndex( it->icon );

	// parse everything for its ammo
	if( it->ammo_tag )
	{
		ammo = GS_FindItemByTag( it->ammo_tag );
		if( ammo != it )
			PrecacheItem( ammo );
	}

	// parse the space separated precache string for other items
	for( i = 0; i < 3; i++ )
	{
		if( i == 0 )
			s = it->precache_models;
		else if( i == 1 )
			s = it->precache_sounds;
		else
			s = it->precache_images;

		if( !s || !s[0] )
			continue;

		while( *s )
		{
			start = s;
			while( *s && *s != ' ' )
				s++;

			len = s-start;
			if( len >= MAX_QPATH || len < 5 )
				G_Error( "PrecacheItem: %s has bad precache string", it->classname );
			memcpy( data, start, len );
			data[len] = 0;
			if( *s )
				s++;

			if( i == 0 )
				trap_ModelIndex( data );
			else if( i == 1 )
				trap_SoundIndex( data );
			else
				trap_ImageIndex( data );
		}
	}
}
示例#27
0
/*
* G_Timeout_Update
* 
* Updates the timeout struct and informs clients about the status of the pause
*/
static void G_Timeout_Update( unsigned int msec )
{
	static int timeout_printtime = 0;
	static int timeout_last_endtime = 0;
	static int countdown_set = 1;

	if( !GS_MatchPaused() )
		return;

	game.frametime = 0;

	if( timeout_last_endtime != level.timeout.endtime ) // force print when endtime is changed
	{
		timeout_printtime = 0;
		timeout_last_endtime = level.timeout.endtime;
	}

	level.timeout.time += msec;
	if( level.timeout.endtime && level.timeout.time >= level.timeout.endtime )
	{
		level.timeout.time = 0;
		level.timeout.caller = -1;
		GS_GamestatSetFlag( GAMESTAT_FLAG_PAUSED, false );

		timeout_printtime = 0;
		timeout_last_endtime = -1;

		G_AnnouncerSound( NULL, trap_SoundIndex( va( S_ANNOUNCER_TIMEOUT_MATCH_RESUMED_1_to_2, ( rand()&1 )+1 ) ),
			GS_MAX_TEAMS, true, NULL );
		G_CenterPrintMsg( NULL, "Match resumed" );
		G_PrintMsg( NULL, "Match resumed\n" );
	}
	else if( timeout_printtime == 0 || level.timeout.time - timeout_printtime >= 1000 )
	{
		if( level.timeout.endtime )
		{
			int seconds_left = (int)( ( level.timeout.endtime - level.timeout.time ) / 1000.0 + 0.5 );

			if( seconds_left == ( TIMEIN_TIME * 2 ) / 1000 )
			{
				G_AnnouncerSound( NULL, trap_SoundIndex( va( S_ANNOUNCER_COUNTDOWN_READY_1_to_2, ( rand()&1 )+1 ) ),
					GS_MAX_TEAMS, false, NULL );
				countdown_set = ( rand()&1 )+1;
			}
			else if( seconds_left >= 1 && seconds_left <= 3 )
			{
				G_AnnouncerSound( NULL, trap_SoundIndex( va( S_ANNOUNCER_COUNTDOWN_COUNT_1_to_3_SET_1_to_2, seconds_left,
					countdown_set ) ), GS_MAX_TEAMS, false, NULL );
			}

			if( seconds_left > 1 )
				G_CenterPrintFormatMsg( NULL, "Match will resume in %s seconds", va( "%i", seconds_left ), NULL );
			else
				G_CenterPrintMsg( NULL, "Match will resume in 1 second" );
		}
		else
		{
			G_CenterPrintMsg( NULL, "Match paused" );
		}

		timeout_printtime = level.timeout.time;
	}
}
示例#28
0
/*
* G_Match_ScoreAnnouncement
*/
static void G_Match_ScoreAnnouncement( void )
{
	int i;
	edict_t *e, *chased;
	int num_leaders, team;

	if( !level.gametype.scoreAnnouncementEnabled )
		return;

	num_leaders = 0;
	memset( leaders, 0, sizeof( leaders ) );

	if( GS_TeamBasedGametype() )
	{
		int score_max = -999999999;

		for( team = TEAM_ALPHA; team < GS_MAX_TEAMS; team++ )
		{
			if( !teamlist[team].numplayers )
				continue;

			if( teamlist[team].stats.score > score_max )
			{
				score_max = teamlist[team].stats.score;
				leaders[0] = team;
				num_leaders = 1;
			}
			else if( teamlist[team].stats.score == score_max )
			{
				leaders[num_leaders++] = team;
			}
		}
		leaders[num_leaders] = 0;
	}
	else
	{
		int score_max = -999999999;

		for( i = 0; i < MAX_CLIENTS && i < teamlist[TEAM_PLAYERS].numplayers; i++ )
		{
			if( game.clients[teamlist[TEAM_PLAYERS].playerIndices[i]-1].level.stats.score > score_max )
			{
				score_max = game.clients[teamlist[TEAM_PLAYERS].playerIndices[i]-1].level.stats.score;
				leaders[0] = teamlist[TEAM_PLAYERS].playerIndices[i];
				num_leaders = 1;
			}
			else if( game.clients[teamlist[TEAM_PLAYERS].playerIndices[i]-1].level.stats.score == score_max )
			{
				leaders[num_leaders++] = teamlist[TEAM_PLAYERS].playerIndices[i];
			}
		}
		leaders[num_leaders] = 0;
	}

	if( !score_announcement_init )
	{
		// copy over to last_leaders
		memcpy( last_leaders, leaders, sizeof( leaders ) );
		score_announcement_init = true;
		return;
	}

	for( e = game.edicts + 1; PLAYERNUM( e ) < gs.maxclients; e++ )
	{
		if( !e->r.client || trap_GetClientState( PLAYERNUM( e ) ) < CS_SPAWNED )
			continue;

		if( e->r.client->resp.chase.active )
			chased = &game.edicts[e->r.client->resp.chase.target];
		else
			chased = e;

		// floating spectator
		if( chased->s.team == TEAM_SPECTATOR )
		{
			if( !GS_TeamBasedGametype() )
				continue;

			if( last_leaders[1] == 0 && leaders[1] != 0 )
			{
				G_AnnouncerSound( e, trap_SoundIndex( va( S_ANNOUNCER_SCORE_TEAM_TIED_LEAD_1_to_2, ( rand()&1 )+1 ) ),
					GS_MAX_TEAMS, true, NULL );
			}
			else if( leaders[1] == 0 && ( last_leaders[0] != leaders[0] || last_leaders[1] != 0 ) )
			{
				//G_AnnouncerSound( e, trap_SoundIndex( va( S_ANNOUNCER_SCORE_TEAM_1_to_4_TAKEN_LEAD_1_to_2,
				//	leaders[0]-1, ( rand()&1 )+1 ) ), GS_MAX_TEAMS, true, NULL );
			}
			continue;
		}

		// in the game or chasing someone who is
		if( G_WasLeading( chased ) && !G_IsLeading( chased ) )
		{
			if( GS_TeamBasedGametype() && !GS_InvidualGameType() )
				G_AnnouncerSound( e, trap_SoundIndex( va( S_ANNOUNCER_SCORE_TEAM_LOST_LEAD_1_to_2, ( rand()&1 )+1 ) ),
				GS_MAX_TEAMS, true, NULL );
			else
				G_AnnouncerSound( e, trap_SoundIndex( va( S_ANNOUNCER_SCORE_LOST_LEAD_1_to_2, ( rand()&1 )+1 ) ),
				GS_MAX_TEAMS, true, NULL );
		}
		else if( ( !G_WasLeading( chased ) || ( last_leaders[1] != 0 ) ) && G_IsLeading( chased ) && ( leaders[1] == 0 ) )
		{
			if( GS_TeamBasedGametype() && !GS_InvidualGameType() )
				G_AnnouncerSound( e, trap_SoundIndex( va( S_ANNOUNCER_SCORE_TEAM_TAKEN_LEAD_1_to_2, ( rand()&1 )+1 ) ),
				GS_MAX_TEAMS, true, NULL );
			else
				G_AnnouncerSound( e, trap_SoundIndex( va( S_ANNOUNCER_SCORE_TAKEN_LEAD_1_to_2, ( rand()&1 )+1 ) ),
				GS_MAX_TEAMS, true, NULL );
		}
		else if( ( !G_WasLeading( chased ) || ( last_leaders[1] == 0 ) ) && G_IsLeading( chased ) && ( leaders[1] != 0 ) )
		{
			if( GS_TeamBasedGametype() && !GS_InvidualGameType() )
				G_AnnouncerSound( e, trap_SoundIndex( va( S_ANNOUNCER_SCORE_TEAM_TIED_LEAD_1_to_2, ( rand()&1 )+1 ) ),
				GS_MAX_TEAMS, true, NULL );
			else
				G_AnnouncerSound( e, trap_SoundIndex( va( S_ANNOUNCER_SCORE_TIED_LEAD_1_to_2, ( rand()&1 )+1 ) ),
				GS_MAX_TEAMS, true, NULL );
		}
	}

	// copy over to last_leaders
	memcpy( last_leaders, leaders, sizeof( leaders ) );
}
示例#29
0
/*
* G_PlayerWorldEffects
*/
static void G_PlayerWorldEffects( edict_t *ent )
{
	int waterlevel, old_waterlevel;
	int watertype, old_watertype;

	if( ent->movetype == MOVETYPE_NOCLIP )
	{
		ent->air_finished = level.time + ( 12*1000 ); // don't need air
		return;
	}

	waterlevel = ent->waterlevel;
	watertype = ent->watertype;
	old_waterlevel = ent->r.client->resp.old_waterlevel;
	old_watertype = ent->r.client->resp.old_watertype;
	ent->r.client->resp.old_waterlevel = waterlevel;
	ent->r.client->resp.old_watertype = watertype;

	//
	// if just entered a water volume, play a sound
	//
	if( !old_waterlevel && waterlevel )
	{
		if( ent->watertype & CONTENTS_LAVA )
			G_Sound( ent, CHAN_AUTO, trap_SoundIndex( S_WORLD_LAVA_IN ), ATTN_NORM );
		else if( ent->watertype & CONTENTS_SLIME )
			G_Sound( ent, CHAN_AUTO, trap_SoundIndex( S_WORLD_SLIME_IN ), ATTN_NORM );
		else if( ent->watertype & CONTENTS_WATER )
			G_Sound( ent, CHAN_AUTO, trap_SoundIndex( S_WORLD_WATER_IN ), ATTN_NORM );

		ent->flags |= FL_INWATER;
	}

	//
	// if just completely exited a water volume, play a sound
	//
	if( old_waterlevel && !waterlevel )
	{
		if( old_watertype & CONTENTS_LAVA )
			G_Sound( ent, CHAN_AUTO, trap_SoundIndex( S_WORLD_LAVA_OUT ), ATTN_NORM );
		else if( old_watertype & CONTENTS_SLIME )
			G_Sound( ent, CHAN_AUTO, trap_SoundIndex( S_WORLD_SLIME_OUT ), ATTN_NORM );
		else if( old_watertype & CONTENTS_WATER )
			G_Sound( ent, CHAN_AUTO, trap_SoundIndex( S_WORLD_WATER_OUT ), ATTN_NORM );

		ent->flags &= ~FL_INWATER;
	}

	//
	// check for head just coming out of water
	//
	if( old_waterlevel == 3 && waterlevel != 3 )
	{
		if( ent->air_finished < level.time )
		{ // gasp for air
			// wsw : jal : todo : better variations of gasp sounds
			G_AddEvent( ent, EV_SEXEDSOUND, 1, true );
		}
		else if( ent->air_finished < level.time + 11000 )
		{ // just break surface
			// wsw : jal : todo : better variations of gasp sounds
			G_AddEvent( ent, EV_SEXEDSOUND, 2, true );
		}
	}

	//
	// check for drowning
	//
	if( waterlevel == 3 )
	{
		// if out of air, start drowning
		if( ent->air_finished < level.time )
		{ // drown!
			if( ent->r.client->resp.next_drown_time < level.time && !G_IsDead( ent ) )
			{
				ent->r.client->resp.next_drown_time = level.time + 1000;

				// take more damage the longer underwater
				ent->r.client->resp.drowningDamage += 2;
				if( ent->r.client->resp.drowningDamage > 15 )
					ent->r.client->resp.drowningDamage = 15;

				// wsw : jal : todo : better variations of gasp sounds
				// play a gurp sound instead of a normal pain sound
				if( HEALTH_TO_INT( ent->health ) - ent->r.client->resp.drowningDamage <= 0 )
					G_AddEvent( ent, EV_SEXEDSOUND, 2, true );
				else
					G_AddEvent( ent, EV_SEXEDSOUND, 1, true );
				ent->pain_debounce_time = level.time;

				G_Damage( ent, world, world, vec3_origin, vec3_origin, ent->s.origin, ent->r.client->resp.drowningDamage, 0, 0, DAMAGE_NO_ARMOR, MOD_WATER );
			}
		}
	}
	else
	{
		ent->air_finished = level.time + 12000;
		ent->r.client->resp.drowningDamage = 2;
	}

	//
	// check for sizzle damage
	//
	if( waterlevel && ( ent->watertype & ( CONTENTS_LAVA|CONTENTS_SLIME ) ) )
	{
		if( ent->watertype & CONTENTS_LAVA )
		{
			// wsw: Medar: We don't have the sounds yet and this seems to overwrite the normal pain sounds
			//if( !G_IsDead(ent) && ent->pain_debounce_time <= level.time )
			//{
			//	G_Sound( ent, CHAN_BODY, trap_SoundIndex(va(S_PLAYER_BURN_1_to_2, (rand()&1)+1)), 1, ATTN_NORM );
			//	ent->pain_debounce_time = level.time + 1000;
			//}
			G_Damage( ent, world, world, vec3_origin, vec3_origin, ent->s.origin,
				( 30 * waterlevel ) * game.snapFrameTime / 1000.0f, 0, 0, 0, MOD_LAVA );
		}

		if( ent->watertype & CONTENTS_SLIME )
		{
			G_Damage( ent, world, world, vec3_origin, vec3_origin, ent->s.origin,
				( 10 * waterlevel ) * game.snapFrameTime / 1000.0f, 0, 0, 0, MOD_SLIME );
		}
	}
}