Пример #1
0
/*
===============
UI_DrawPlayer
===============
*/
void UI_DrawPlayer( float x, float y, float w, float h, playerInfo_t *pi, int time ) {
	refdef_t		refdef;
	refEntity_t		legs;
	refEntity_t		torso;
	refEntity_t		head;
	refEntity_t		gun;
	refEntity_t		barrel;
	refEntity_t		flash;
	vec3_t			origin;
	int				renderfx;
	vec3_t			mins = {-16, -16, -24};
	vec3_t			maxs = {16, 16, 32};
	float			len;
	float			xx;
	float			xscale;
	float			yscale;

	if ( !pi->legsModel || !pi->torsoModel || !pi->headModel || !pi->animations[0].numFrames ) {
		return;
	}

	dp_realtime = time;

	if ( pi->pendingWeapon != WP_NUM_WEAPONS && dp_realtime > pi->weaponTimer ) {
		pi->weapon = pi->pendingWeapon;
		pi->lastWeapon = pi->pendingWeapon;
		pi->pendingWeapon = WP_NUM_WEAPONS;
		pi->weaponTimer = 0;
		if( pi->currentWeapon != pi->weapon ) {
			trap_S_StartLocalSound( weaponChangeSound, CHAN_LOCAL );
		}
	}

	CG_AdjustFrom640( &x, &y, &w, &h );

	y -= jumpHeight;

	memset( &refdef, 0, sizeof( refdef ) );
	memset( &legs, 0, sizeof(legs) );
	memset( &torso, 0, sizeof(torso) );
	memset( &head, 0, sizeof(head) );

	refdef.rdflags = RDF_NOWORLDMODEL;

	AxisClear( refdef.viewaxis );

	refdef.x = x;
	refdef.y = y;
	refdef.width = w;
	refdef.height = h;

	if ( ui_stretch.integer ) {
		xscale = cgs.screenXScaleStretch;
		yscale = cgs.screenYScaleStretch;
	} else {
		xscale = cgs.screenXScale;
		yscale = cgs.screenYScale;
	}

	refdef.fov_x = (int)((float)refdef.width / xscale / 640.0f * 90.0f);
	xx = refdef.width / xscale / tan( refdef.fov_x / 360 * M_PI );
	refdef.fov_y = atan2( refdef.height / yscale, xx );
	refdef.fov_y *= ( 360 / M_PI );

	// calculate distance so the player nearly fills the box
	len = 0.7 * ( maxs[2] - mins[2] );		
	origin[0] = len / tan( DEG2RAD(refdef.fov_x) * 0.5 );
	origin[1] = 0.5 * ( mins[1] + maxs[1] );
	origin[2] = -0.5 * ( mins[2] + maxs[2] );

	refdef.time = dp_realtime;

	trap_R_ClearScene();

	// get the rotation information
	UI_PlayerAngles( pi, legs.axis, torso.axis, head.axis );
	
	// get the animation state (after rotation, to allow feet shuffle)
	UI_PlayerAnimation( pi, &legs.oldframe, &legs.frame, &legs.backlerp,
		 &torso.oldframe, &torso.frame, &torso.backlerp );

	renderfx = RF_LIGHTING_ORIGIN | RF_NOSHADOW;

	//
	// add the legs
	//
	legs.hModel = pi->legsModel;
	legs.customSkin = CG_AddSkinToFrame( &pi->modelSkin );

	VectorCopy( origin, legs.origin );

	VectorCopy( origin, legs.lightingOrigin );
	legs.renderfx = renderfx;
	VectorCopy (legs.origin, legs.oldorigin);

	CG_AddRefEntityWithMinLight( &legs );

	if (!legs.hModel) {
		return;
	}

	//
	// add the torso
	//
	torso.hModel = pi->torsoModel;
	if (!torso.hModel) {
		return;
	}

	torso.customSkin = legs.customSkin;

	VectorCopy( origin, torso.lightingOrigin );

	UI_PositionRotatedEntityOnTag( &torso, &legs, pi->legsModel, "tag_torso");

	torso.renderfx = renderfx;

	CG_AddRefEntityWithMinLight( &torso );

	//
	// add the head
	//
	head.hModel = pi->headModel;
	if (!head.hModel) {
		return;
	}
	head.customSkin = legs.customSkin;

	VectorCopy( origin, head.lightingOrigin );

	UI_PositionRotatedEntityOnTag( &head, &torso, pi->torsoModel, "tag_head");

	head.renderfx = renderfx;

	CG_AddRefEntityWithMinLight( &head );

	//
	// add the gun
	//
	if ( pi->currentWeapon != WP_NONE ) {
		memset( &gun, 0, sizeof(gun) );
		gun.hModel = pi->weaponModel;
		if( pi->currentWeapon == WP_RAILGUN ) {
			Byte4Copy( pi->c1RGBA, gun.shaderRGBA );
		}
		else {
			Byte4Copy( colorWhite, gun.shaderRGBA );
		}
		VectorCopy( origin, gun.lightingOrigin );
		UI_PositionEntityOnTag( &gun, &torso, pi->torsoModel, "tag_weapon");
		gun.renderfx = renderfx;
		CG_AddRefEntityWithMinLight( &gun );
	}

	//
	// add the spinning barrel
	//
	if ( pi->realWeapon == WP_MACHINEGUN || pi->realWeapon == WP_GAUNTLET || pi->realWeapon == WP_BFG
#ifdef MISSIONPACK
		|| pi->realWeapon == WP_CHAINGUN
#endif
		) {
		vec3_t	angles;

		memset( &barrel, 0, sizeof(barrel) );
		VectorCopy( origin, barrel.lightingOrigin );
		barrel.renderfx = renderfx;

		barrel.hModel = pi->barrelModel;
		angles[YAW] = 0;
		angles[PITCH] = 0;
		angles[ROLL] = UI_MachinegunSpinAngle( pi );
		if( pi->realWeapon == WP_GAUNTLET || pi->realWeapon == WP_BFG ) {
			angles[PITCH] = angles[ROLL];
			angles[ROLL] = 0;
		}
		AnglesToAxis( angles, barrel.axis );

		UI_PositionRotatedEntityOnTag( &barrel, &gun, pi->weaponModel, "tag_barrel");

		CG_AddRefEntityWithMinLight( &barrel );
	}

	//
	// add muzzle flash
	//
	if ( dp_realtime <= pi->muzzleFlashTime ) {
		if ( pi->flashModel ) {
			memset( &flash, 0, sizeof(flash) );
			flash.hModel = pi->flashModel;
			if( pi->currentWeapon == WP_RAILGUN ) {
				Byte4Copy( pi->c1RGBA, flash.shaderRGBA );
			}
			else {
				Byte4Copy( colorWhite, flash.shaderRGBA );
			}
			VectorCopy( origin, flash.lightingOrigin );
			UI_PositionEntityOnTag( &flash, &gun, pi->weaponModel, "tag_flash");
			flash.renderfx = renderfx;
			CG_AddRefEntityWithMinLight( &flash );
		}

		// make a dlight for the flash
		if ( pi->flashDlightColor[0] || pi->flashDlightColor[1] || pi->flashDlightColor[2] ) {
			trap_R_AddLightToScene( flash.origin, 200 + (rand()&31), 1.0f, pi->flashDlightColor[0],
				pi->flashDlightColor[1], pi->flashDlightColor[2] );
		}
	}

	//
	// add the chat icon
	//
	if ( pi->chat ) {
		UI_PlayerFloatSprite( pi, origin, trap_R_RegisterShaderNoMip( "sprites/balloon3" ) );
	}

	//
	// add an accent light
	//
	origin[0] -= 100;	// + = behind, - = in front
	origin[1] += 100;	// + = left, - = right
	origin[2] += 100;	// + = above, - = below
	trap_R_AddLightToScene( origin, 500, 1.0, 1.0, 1.0, 1.0 );

	origin[0] -= 100;
	origin[1] -= 100;
	origin[2] -= 100;
	trap_R_AddLightToScene( origin, 500, 1.0, 1.0, 0.0, 0.0 );

	trap_R_RenderScene( &refdef );
}
Пример #2
0
void target_laser_think (edict_t *self)
{
	edict_t	*ignore;
	vec3_t	start;
	vec3_t	end;
	trace_t	tr;
	vec3_t	point;
	vec3_t	last_movedir;
	int		count;

	if (self->spawnflags & 0x80000000)
		count = 8;
	else
		count = 4;

	if (self->enemy)
	{
		VectorCopy (self->movedir, last_movedir);
		VectorMA (self->enemy->absmin, 0.5, self->enemy->size, point);
		VectorSubtract (point, self->s.origin, self->movedir);
		VectorNormalize (self->movedir);
		if (!VectorCompare(self->movedir, last_movedir))
			self->spawnflags |= 0x80000000;
	}

	ignore = self;
	VectorCopy (self->s.origin, start);
	VectorMA (start, 2048, self->movedir, end);
	while(1)
	{
		tr = gi.trace (start, NULL, NULL, end, ignore, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_DEADMONSTER);

		VectorCopy (tr.endpos,self->moveinfo.end_origin);

		if (!tr.ent)
			break;

		// hurt it if we can
		if ((tr.ent->takedamage) && !(tr.ent->flags & FL_IMMUNE_LASER))
			T_Damage (tr.ent, self, self->activator, self->movedir, tr.endpos, vec3_origin, self->dmg, 1, DAMAGE_ENERGY, MOD_TARGET_LASER);

		// if we hit something that's not a monster or player or is immune to lasers, we're done
		if (!(tr.ent->svflags & SVF_MONSTER) && (!tr.ent->client))
		{
			if (self->spawnflags & 0x80000000)
			{
				self->spawnflags &= ~0x80000000;
				gi.WriteByte (svc_temp_entity);
				gi.WriteByte (TE_LASER_SPARKS);
				gi.WriteByte (count);
				gi.WritePosition (tr.endpos);
				gi.WriteDir (tr.plane.normal);
				gi.WriteByte (self->s.skinnum);
				gi.multicast (tr.endpos, MULTICAST_PVS);
			}
			break;
		}

		ignore = tr.ent;
		VectorCopy (tr.endpos, start);
	}

	VectorCopy (tr.endpos, self->s.old_origin);

	self->nextthink = level.time + FRAMETIME;
}
Пример #3
0
void ClientThink_real( gentity_t *ent, usercmd_t *ucmd ) 
{
	gclient_t	*client;
	pmove_t		pm;
	vec3_t		oldOrigin;
	int			oldEventSequence;
	int			msec;

	//Don't let the player do anything if in a camera
	if ( ent->s.number == 0 ) {
extern cvar_t	*g_skippingcin;
		if ( in_camera )
		{
			// watch the code here, you MUST "return" within this IF(), *unless* you're stopping the cinematic skip.
			//
			if ( ClientCinematicThink(ent->client) )
			{
				if (g_skippingcin->integer)	// already doing cinematic skip?
				{
					// yes...   so stop skipping...
					gi.cvar_set("skippingCinematic", "0");
					gi.cvar_set("timescale", "1");
				}
				else
				{
					// no... so start skipping...
					gi.cvar_set("skippingCinematic", "1");
					gi.cvar_set("timescale", "100");
					return;
				}
			}
			else
			{
				return;
			}
		}
		else 
		{
			if ( g_skippingcin->integer )
			{//We're skipping the cinematic and it's over now
				gi.cvar_set("timescale", "1");
				gi.cvar_set("skippingCinematic", "0");
			}
			if ( ent->client->ps.pm_type == PM_DEAD && cg.missionStatusDeadTime < level.time )
			{//mission status screen is up because player is dead, stop all scripts
				if (Q_stricmpn(level.mapname,"_holo",5)) {
					stop_icarus = qtrue;
				}
			}
		}

		// Don't allow the player to adjust the pitch when they are in third person overhead cam.
extern vmCvar_t cg_thirdPerson;
		if ( cg_thirdPerson.integer == 2 )
		{
			ucmd->angles[PITCH] = 0;
		}

		if ( player_locked && ent->client->ps.pm_type < PM_DEAD ) {//lock out player control unless dead
			VectorClear(ucmd->angles) ;
			ucmd->forwardmove = 0;
			ucmd->rightmove = 0;
			ucmd->buttons = 0;
			ucmd->upmove = 0;
		}
	}
	else
	{
		G_NPCMunroMatchPlayerWeapon( ent );
	}
	client = ent->client;

	// mark the time, so the connection sprite can be removed
	client->lastCmdTime = level.time;
	client->pers.lastCommand = *ucmd;

	// sanity check the command time to prevent speedup cheating
	if ( ucmd->serverTime > level.time + 200 ) 
	{
		ucmd->serverTime = level.time + 200;
	}
	if ( ucmd->serverTime < level.time - 1000 ) 
	{
		ucmd->serverTime = level.time - 1000;
	} 

	msec = ucmd->serverTime - client->ps.commandTime;
	if ( msec < 1 ) 
	{
		msec = 1;
	}
	if ( msec > 200 ) 
	{
		msec = 200;
	}

	// check for inactivity timer, but never drop the local client of a non-dedicated server
	if ( !ClientInactivityTimer( client ) ) 
		return;

	if ( client->noclip ) 
	{
		client->ps.pm_type = PM_NOCLIP;
	} 
	else if ( client->ps.stats[STAT_HEALTH] <= 0 ) 
	{
		client->ps.pm_type = PM_DEAD;
	} 
	else 
	{
		client->ps.pm_type = PM_NORMAL;
	}

	//FIXME: if global gravity changes this should update everyone's personal gravity...
	if ( !(ent->svFlags & SVF_CUSTOM_GRAVITY) )
	{
		client->ps.gravity = g_gravity->value;
	}

	// set speed
	if ( ent->NPC != NULL )
	{//we don't actually scale the ucmd, we use actual speeds
		if ( ent->NPC->combatMove == qfalse )
		{
			if ( !(ucmd->buttons & BUTTON_USE) )
			{//Not leaning
				qboolean Flying = (ucmd->upmove && ent->NPC->stats.moveType == MT_FLYSWIM);
				qboolean Climbing = (ucmd->upmove && ent->watertype&CONTENTS_LADDER );

				client->ps.friction = 6;

				if ( ucmd->forwardmove || ucmd->rightmove || Flying )
				{
					if ( ent->NPC->behaviorState != BS_FORMATION )
					{//In - Formation NPCs set thier desiredSpeed themselves
						if ( ucmd->buttons & BUTTON_WALKING )
						{
							ent->NPC->desiredSpeed = NPC_GetWalkSpeed( ent );//ent->NPC->stats.walkSpeed;
						}
						else//running
						{
							ent->NPC->desiredSpeed = NPC_GetRunSpeed( ent );//ent->NPC->stats.runSpeed;
						}

						if ( ent->NPC->currentSpeed >= 80 )
						{//At higher speeds, need to slow down close to stuff
							//Slow down as you approach your goal
							if ( ent->NPC->distToGoal < SLOWDOWN_DIST && client->race != RACE_BORG && !(ent->NPC->aiFlags&NPCAI_NO_SLOWDOWN) )//128
							{
								if ( ent->NPC->desiredSpeed > MIN_NPC_SPEED )
								{
									float slowdownSpeed = ((float)ent->NPC->desiredSpeed) * ent->NPC->distToGoal / SLOWDOWN_DIST;

									ent->NPC->desiredSpeed = ceil(slowdownSpeed);
									if ( ent->NPC->desiredSpeed < MIN_NPC_SPEED )
									{//don't slow down too much
										ent->NPC->desiredSpeed = MIN_NPC_SPEED;
									}
								}
							}
						}
					}
				}
				else if ( Climbing )
				{
					ent->NPC->desiredSpeed = ent->NPC->stats.walkSpeed;
				}
				else
				{//We want to stop
					ent->NPC->desiredSpeed = 0;
				}

				NPC_Accelerate( ent, (ent->NPC->behaviorState==BS_FORMATION), (ent->NPC->behaviorState==BS_FORMATION) );

				if ( ent->NPC->currentSpeed <= 24 && ent->NPC->desiredSpeed < ent->NPC->currentSpeed )
				{//No-one walks this slow
					client->ps.speed = ent->NPC->currentSpeed = 0;//Full stop
					ucmd->forwardmove = 0;
					ucmd->rightmove = 0;
				}
				else
				{
					if ( ent->NPC->currentSpeed <= ent->NPC->stats.walkSpeed )
					{//Play the walkanim
						ucmd->buttons |= BUTTON_WALKING;
					}
					else
					{
						ucmd->buttons &= ~BUTTON_WALKING;
					}

					if ( ent->NPC->currentSpeed > 0 )
					{//We should be moving
						if ( Climbing || Flying )
						{
							if ( !ucmd->upmove )
							{//We need to force them to take a couple more steps until stopped
								ucmd->upmove = ent->NPC->last_ucmd.upmove;//was last_upmove;
							}
						}
						else if ( !ucmd->forwardmove && !ucmd->rightmove )
						{//We need to force them to take a couple more steps until stopped
							ucmd->forwardmove = ent->NPC->last_ucmd.forwardmove;//was last_forwardmove;
							ucmd->rightmove = ent->NPC->last_ucmd.rightmove;//was last_rightmove;
						}
					}

					client->ps.speed = ent->NPC->currentSpeed;
					//Slow down on turns - don't orbit!!!
					float turndelta = (180 - fabs( AngleDelta( ent->currentAngles[YAW], ent->NPC->desiredYaw ) ))/180;
					
					if ( turndelta < 0.75f )
					{
						client->ps.speed = 0;
					}
					else if ( ent->NPC->distToGoal < 100 && turndelta < 1.0 )
					{//Turn is greater than 45 degrees or closer than 100 to goal
						client->ps.speed = floor(((float)(client->ps.speed))*turndelta);
					}
				}
			}
		}
		else
		{	
			ent->NPC->desiredSpeed = ( ucmd->buttons & BUTTON_WALKING ) ? NPC_GetWalkSpeed( ent ) : NPC_GetRunSpeed( ent );

			client->ps.speed = ent->NPC->desiredSpeed;
		}
	}
	else
	{//Client sets ucmds and such for speed alterations
		client->ps.speed = g_speed->value;//default is 320
	}

	//Apply forced movement
	if ( client->forced_forwardmove )
	{
		ucmd->forwardmove = client->forced_forwardmove;
		if ( !client->ps.speed )
		{
			if ( ent->NPC != NULL )
			{
				client->ps.speed = ent->NPC->stats.runSpeed;
			}
			else
			{
				client->ps.speed = g_speed->value;//default is 320
			}
		}
	}

	if ( client->forced_rightmove )
	{
		ucmd->rightmove = client->forced_rightmove;
		if ( !client->ps.speed )
		{
			if ( ent->NPC != NULL  )
			{
				client->ps.speed = ent->NPC->stats.runSpeed;
			}
			else
			{
				client->ps.speed = g_speed->value;//default is 320
			}
		}
	}

	//FIXME: need to do this before check to avoid walls and cliffs (or just cliffs?)
	BG_AddPushVecToUcmd( ent, ucmd );

	BG_CalculateOffsetAngles( ent, ucmd );

	// set up for pmove
	oldEventSequence = client->ps.eventSequence;

	memset( &pm, 0, sizeof(pm) );

	pm.gent = ent;
	pm.ps = &client->ps;
	pm.cmd = *ucmd;
//	pm.tracemask = MASK_PLAYERSOLID;	// used differently for navgen
	pm.tracemask = ent->clipmask;
	pm.trace = gi.trace;
	pm.pointcontents = gi.pointcontents;
	pm.debugLevel = g_debugMove->integer;
	pm.noFootsteps = 0;//( g_dmflags->integer & DF_NO_FOOTSTEPS ) > 0;

	VectorCopy( client->ps.origin, oldOrigin );

	// perform a pmove
	Pmove( &pm );

	// save results of pmove
	if ( ent->client->ps.eventSequence != oldEventSequence ) 
	{
		ent->eventTime = level.time;
		{
			int		seq;

			seq = (ent->client->ps.eventSequence-1) & (MAX_PS_EVENTS-1);
			ent->s.event = ent->client->ps.events[ seq ] | ( ( ent->client->ps.eventSequence & 3 ) << 8 );
			ent->s.eventParm = ent->client->ps.eventParms[ seq ];
		}
	}
	PlayerStateToEntityState( &ent->client->ps, &ent->s );

	VectorCopy ( ent->currentOrigin, ent->lastOrigin );
#if 1
	// use the precise origin for linking
	VectorCopy( ent->client->ps.origin, ent->currentOrigin );
#else
	//We don't use prediction anymore, so screw this
	// use the snapped origin for linking so it matches client predicted versions
	VectorCopy( ent->s.pos.trBase, ent->currentOrigin );
#endif

	VectorCopy (pm.mins, ent->mins);
	VectorCopy (pm.maxs, ent->maxs);

	ent->waterlevel = pm.waterlevel;
	ent->watertype = pm.watertype;

	VectorCopy( ucmd->angles, client->pers.cmd_angles );

	// execute client events
	ClientEvents( ent, oldEventSequence );

	if ( pm.useEvent )
	{
		//TODO: Use
		TryUse( ent );
	}

	// link entity now, after any personal teleporters have been used
	gi.linkentity( ent );
	ent->client->hiddenDist = 0;
	if ( !ent->client->noclip ) 
	{
		G_TouchTriggersLerped( ent );
	}

	// touch other objects
	ClientImpacts( ent, &pm );

	// swap and latch button actions
	client->oldbuttons = client->buttons;
	client->buttons = ucmd->buttons;
	client->latched_buttons |= client->buttons & ~client->oldbuttons;

	// check for respawning
	if ( client->ps.stats[STAT_HEALTH] <= 0 ) 
	{
		// wait for the attack button to be pressed
		if ( ent->NPC == NULL && level.time > client->respawnTime ) 
		{
			// don't allow respawn if they are still flying through the
			// air, unless 10 extra seconds have passed, meaning something
			// strange is going on, like the corpse is caught in a wind tunnel
			if ( level.time < client->respawnTime + 10000 ) 
			{
				if ( client->ps.groundEntityNum == ENTITYNUM_NONE ) 
				{
					return;
				}
			}

			// pressing attack or use is the normal respawn method
			if ( ucmd->buttons & ( BUTTON_ATTACK | BUTTON_USE_HOLDABLE ) ) 
			{
				respawn( ent );
			}
		}
		return;
	}

	if ((cg.missionStatusShow) && ((cg.missionStatusDeadTime + 1) < level.time))
	{
		if ( ucmd->buttons & ( BUTTON_ATTACK | BUTTON_USE_HOLDABLE ) ) 
		{
			cg.missionStatusShow = 0;
			ScoreBoardReset();
//			Q3_TaskIDComplete( ent, TID_MISSIONSTATUS );
		}
	}
	// perform once-a-second actions
	//ClientTimerActions( ent, msec );

	//DEBUG INFO
/*
	if ( client->ps.clientNum < 1 )
	{//Only a player
		if ( ucmd->buttons & BUTTON_USE )
		{
			NAV_PrintLocalWpDebugInfo( ent );
		}
	}
*/
}
Пример #4
0
void BotUpdateEntityItems() {
	int ent, i, modelindex;
	vec3_t dir;
	levelitem_t* li, * nextli;
	aas_entityinfo_t entinfo;
	itemconfig_t* ic;

	//timeout current entity items if necessary
	for ( li = levelitems; li; li = nextli ) {
		nextli = li->next;
		//if it is a item that will time out
		if ( li->timeout ) {
			//timeout the item
			if ( li->timeout < AAS_Time() ) {
				RemoveLevelItemFromList( li );
				FreeLevelItem( li );
			}	//end if
		}	//end if
	}	//end for
		//find new entity items
	ic = itemconfig;
	if ( !itemconfig ) {
		return;
	}
	//
	for ( ent = AAS_NextEntity( 0 ); ent; ent = AAS_NextEntity( ent ) ) {
		if ( AAS_EntityType( ent ) != Q3ET_ITEM ) {
			continue;
		}
		//get the model index of the entity
		modelindex = AAS_EntityModelindex( ent );
		//
		if ( !modelindex ) {
			continue;
		}
		//get info about the entity
		AAS_EntityInfo( ent, &entinfo );
		//FIXME: don't do this
		//skip all floating items for now
		if ( !( GGameType & GAME_Quake3 ) && entinfo.groundent != Q3ENTITYNUM_WORLD ) {
			continue;
		}
		//if the entity is still moving
		if ( entinfo.origin[ 0 ] != entinfo.lastvisorigin[ 0 ] ||
			 entinfo.origin[ 1 ] != entinfo.lastvisorigin[ 1 ] ||
			 entinfo.origin[ 2 ] != entinfo.lastvisorigin[ 2 ] ) {
			continue;
		}
		//check if the entity is already stored as a level item
		for ( li = levelitems; li; li = li->next ) {
			if ( GGameType & GAME_Quake3 ) {
				//if the level item is linked to an entity
				if ( li->entitynum && li->entitynum == ent ) {
					//the entity is re-used if the models are different
					if ( ic->iteminfo[ li->iteminfo ].modelindex != modelindex ) {
						//remove this level item
						RemoveLevelItemFromList( li );
						FreeLevelItem( li );
						li = NULL;
						break;
					} else {
						if ( entinfo.origin[ 0 ] != li->origin[ 0 ] ||
							 entinfo.origin[ 1 ] != li->origin[ 1 ] ||
							 entinfo.origin[ 2 ] != li->origin[ 2 ] ) {
							VectorCopy( entinfo.origin, li->origin );
							//also update the goal area number
							li->goalareanum = AAS_BestReachableArea( li->origin,
								ic->iteminfo[ li->iteminfo ].mins, ic->iteminfo[ li->iteminfo ].maxs,
								li->goalorigin );
						}
						break;
					}
				}
			} else {
				//if the model of the level item and the entity are different
				if ( ic->iteminfo[ li->iteminfo ].modelindex != modelindex ) {
					continue;
				}
				//if the level item is linked to an entity
				if ( li->entitynum ) {
					if ( li->entitynum == ent ) {
						VectorCopy( entinfo.origin, li->origin );
						break;
					}	//end if
				}	//end if
				else {
					//check if the entity is very close
					VectorSubtract( li->origin, entinfo.origin, dir );
					if ( VectorLength( dir ) < 30 ) {
						//found an entity for this level item
						li->entitynum = ent;
						//keep updating the entity origin
						VectorCopy( entinfo.origin, li->origin );
						//also update the goal area number
						li->goalareanum = AAS_BestReachableArea( li->origin,
							ic->iteminfo[ li->iteminfo ].mins, ic->iteminfo[ li->iteminfo ].maxs,
							li->goalorigin );
						//Log_Write("found item %s entity", ic->iteminfo[li->iteminfo].classname);
						break;
					}	//end if
						//else BotImport_Print(PRT_MESSAGE, "item %s has no attached entity\n",
						//						ic->iteminfo[li->iteminfo].name);
				}	//end else
			}
		}	//end for
		if ( li ) {
			continue;
		}
		if ( GGameType & GAME_Quake3 ) {
			//try to link the entity to a level item
			for ( li = levelitems; li; li = li->next ) {
				//if this level item is already linked
				if ( li->entitynum ) {
					continue;
				}

				if ( g_gametype == Q3GT_SINGLE_PLAYER ) {
					if ( li->flags & IFL_NOTSINGLE ) {
						continue;
					}
				} else if ( g_gametype >= Q3GT_TEAM ) {
					if ( li->flags & IFL_NOTTEAM ) {
						continue;
					}
				} else {
					if ( li->flags & IFL_NOTFREE ) {
						continue;
					}
				}
				//if the model of the level item and the entity are the same
				if ( ic->iteminfo[ li->iteminfo ].modelindex == modelindex ) {
					//check if the entity is very close
					VectorSubtract( li->origin, entinfo.origin, dir );
					if ( VectorLength( dir ) < 30 ) {
						//found an entity for this level item
						li->entitynum = ent;
						//if the origin is different
						if ( entinfo.origin[ 0 ] != li->origin[ 0 ] ||
							 entinfo.origin[ 1 ] != li->origin[ 1 ] ||
							 entinfo.origin[ 2 ] != li->origin[ 2 ] ) {
							//update the level item origin
							VectorCopy( entinfo.origin, li->origin );
							//also update the goal area number
							li->goalareanum = AAS_BestReachableArea( li->origin,
								ic->iteminfo[ li->iteminfo ].mins, ic->iteminfo[ li->iteminfo ].maxs,
								li->goalorigin );
						}
#ifdef DEBUG
						Log_Write( "linked item %s to an entity", ic->iteminfo[ li->iteminfo ].classname );
#endif
						break;
					}
				}
			}
			if ( li ) {
				continue;
			}
		}
		//check if the model is from a known item
		for ( i = 0; i < ic->numiteminfo; i++ ) {
			if ( ic->iteminfo[ i ].modelindex == modelindex ) {
				break;
			}	//end if
		}	//end for
			//if the model is not from a known item
		if ( i >= ic->numiteminfo ) {
			continue;
		}
		//allocate a new level item
		li = AllocLevelItem();
		//
		if ( !li ) {
			continue;
		}
		//entity number of the level item
		li->entitynum = ent;
		//number for the level item
		li->number = numlevelitems + ent;
		//set the item info index for the level item
		li->iteminfo = i;
		//origin of the item
		VectorCopy( entinfo.origin, li->origin );
		//get the item goal area and goal origin
		li->goalareanum = AAS_BestReachableArea( li->origin,
			ic->iteminfo[ i ].mins, ic->iteminfo[ i ].maxs,
			li->goalorigin );
		//never go for items dropped into jumppads
		if ( AAS_AreaJumpPad( li->goalareanum ) ) {
			FreeLevelItem( li );
			continue;
		}	//end if
			//time this item out after 30 seconds
			//dropped items disappear after 30 seconds
		li->timeout = AAS_Time() + 30;
		//add the level item to the list
		AddLevelItemToList( li );
	}
}
Пример #5
0
int BotGetLevelItemGoalQ3( int index, const char* name, bot_goal_q3_t* goal ) {
	if ( !itemconfig ) {
		return -1;
	}
	levelitem_t* li = levelitems;
	if ( index >= 0 ) {
		for (; li; li = li->next ) {
			if ( li->number == index ) {
				li = li->next;
				break;
			}
		}
	}
	for (; li; li = li->next ) {
		if ( GGameType & GAME_WolfSP ) {
			if ( g_gametype == Q3GT_SINGLE_PLAYER ) {
				if ( li->flags & IFL_NOTSINGLE ) {
					continue;
				}
			} else if ( g_gametype >= Q3GT_TEAM ) {
				if ( li->flags & IFL_NOTTEAM ) {
					continue;
				}
			} else {
				if ( li->flags & IFL_NOTFREE ) {
					continue;
				}
			}
		} else if ( GGameType & GAME_WolfMP ) {
			if ( g_gametype == Q3GT_SINGLE_PLAYER ) {
				if ( li->flags & IFL_NOTSINGLE ) {
					continue;
				}
			} else if ( g_gametype >= Q3GT_TEAM ) {
				if ( li->flags & IFL_NOTTEAM ) {
					continue;
				}
			} else {
				if ( li->flags & IFL_NOTFREE ) {
					continue;
				}
			}
		} else {
			if ( g_gametype == Q3GT_SINGLE_PLAYER ) {
				if ( li->flags & IFL_NOTSINGLE ) {
					continue;
				}
			} else if ( g_gametype >= Q3GT_TEAM ) {
				if ( li->flags & IFL_NOTTEAM ) {
					continue;
				}
			} else {
				if ( li->flags & IFL_NOTFREE ) {
					continue;
				}
			}
			if ( li->flags & IFL_NOTBOT ) {
				continue;
			}
		}

		if ( !String::ICmp( name, itemconfig->iteminfo[ li->iteminfo ].name ) ) {
			goal->areanum = li->goalareanum;
			VectorCopy( li->goalorigin, goal->origin );
			goal->entitynum = li->entitynum;
			VectorCopy( itemconfig->iteminfo[ li->iteminfo ].mins, goal->mins );
			VectorCopy( itemconfig->iteminfo[ li->iteminfo ].maxs, goal->maxs );
			goal->number = li->number;
			if ( GGameType & GAME_Quake3 ) {
				goal->flags = GFL_ITEM;
				if ( li->timeout ) {
					goal->flags |= GFL_DROPPED;
				}
			}
			return li->number;
		}
	}
	return -1;
}
Пример #6
0
/*
==================
BotAIStartFrame
==================
*/
int BotAIStartFrame(int time) {
	int i;
	gentity_t	*ent;
	bot_entitystate_t state;
	int elapsed_time, thinktime;
	static int local_time;
	static int botlib_residual;
	static int lastbotthink_time;

	G_CheckBotSpawn();

	trap_Cvar_Update(&bot_rocketjump);
	trap_Cvar_Update(&bot_grapple);
	trap_Cvar_Update(&bot_fastchat);
	trap_Cvar_Update(&bot_nochat);
	trap_Cvar_Update(&bot_testrchat);
	trap_Cvar_Update(&bot_thinktime);
	trap_Cvar_Update(&bot_memorydump);
	trap_Cvar_Update(&bot_saveroutingcache);
	trap_Cvar_Update(&bot_pause);
	trap_Cvar_Update(&bot_report);

	if (bot_report.integer) {
//		BotTeamplayReport();
//		trap_Cvar_Set("bot_report", "0");
		BotUpdateInfoConfigStrings();
	}

	if (bot_pause.integer) {
		// execute bot user commands every frame
		for( i = 0; i < MAX_CLIENTS; i++ ) {
			if( !botstates[i] || !botstates[i]->inuse ) {
				continue;
			}
			if( g_entities[i].client->pers.connected != CON_CONNECTED ) {
				continue;
			}
			botstates[i]->lastucmd.forwardmove = 0;
			botstates[i]->lastucmd.rightmove = 0;
			botstates[i]->lastucmd.upmove = 0;
			botstates[i]->lastucmd.buttons = 0;
			botstates[i]->lastucmd.serverTime = time;
			trap_BotUserCommand(botstates[i]->client, &botstates[i]->lastucmd);
		}
		return qtrue;
	}

	if (bot_memorydump.integer) {
		trap_BotLibVarSet("memorydump", "1");
		trap_Cvar_Set("bot_memorydump", "0");
	}
	if (bot_saveroutingcache.integer) {
		trap_BotLibVarSet("saveroutingcache", "1");
		trap_Cvar_Set("bot_saveroutingcache", "0");
	}
	//check if bot interbreeding is activated
	BotInterbreeding();
	//cap the bot think time
	if (bot_thinktime.integer > 200) {
		trap_Cvar_Set("bot_thinktime", "200");
	}
	//if the bot think time changed we should reschedule the bots
	if (bot_thinktime.integer != lastbotthink_time) {
		lastbotthink_time = bot_thinktime.integer;
		BotScheduleBotThink();
	}

	elapsed_time = time - local_time;
	local_time = time;

	botlib_residual += elapsed_time;

	if (elapsed_time > bot_thinktime.integer) thinktime = elapsed_time;
	else thinktime = bot_thinktime.integer;

	// update the bot library
	if ( botlib_residual >= thinktime ) {
		botlib_residual -= thinktime;

		trap_BotLibStartFrame((float) time / 1000);

		if (!trap_AAS_Initialized()) return qfalse;

		//update entities in the botlib
		for (i = 0; i < MAX_GENTITIES; i++) {
			ent = &g_entities[i];
			if (!ent->inuse) {
				trap_BotLibUpdateEntity(i, NULL);
				continue;
			}
			if (!ent->r.linked) {
				trap_BotLibUpdateEntity(i, NULL);
				continue;
			}
			if (ent->r.svFlags & SVF_NOCLIENT) {
				trap_BotLibUpdateEntity(i, NULL);
				continue;
			}
			// do not update missiles
			if (ent->s.eType == ET_MISSILE && ent->s.weapon != WP_GRAPPLING_HOOK) {
				trap_BotLibUpdateEntity(i, NULL);
				continue;
			}
			// do not update event only entities
			if (ent->s.eType > ET_EVENTS) {
				trap_BotLibUpdateEntity(i, NULL);
				continue;
			}
#ifdef MISSIONPACK
			// never link prox mine triggers
			if (ent->r.contents == CONTENTS_TRIGGER) {
				if (ent->touch == ProximityMine_Trigger) {
					trap_BotLibUpdateEntity(i, NULL);
					continue;
				}
			}
#endif
			//
			memset(&state, 0, sizeof(bot_entitystate_t));
			//
			VectorCopy(ent->r.currentOrigin, state.origin);
			if (i < MAX_CLIENTS) {
				VectorCopy(ent->s.apos.trBase, state.angles);
			} else {
				VectorCopy(ent->r.currentAngles, state.angles);
			}
			VectorCopy(ent->s.origin2, state.old_origin);
			VectorCopy(ent->r.mins, state.mins);
			VectorCopy(ent->r.maxs, state.maxs);
			state.type = ent->s.eType;
			state.flags = ent->s.eFlags;
			if (ent->r.bmodel) state.solid = SOLID_BSP;
			else state.solid = SOLID_BBOX;
			state.groundent = ent->s.groundEntityNum;
			state.modelindex = ent->s.modelindex;
			state.modelindex2 = ent->s.modelindex2;
			state.frame = ent->s.frame;
			state.event = ent->s.event;
			state.eventParm = ent->s.eventParm;
			state.powerups = ent->s.powerups;
			state.legsAnim = ent->s.legsAnim;
			state.torsoAnim = ent->s.torsoAnim;
			state.weapon = ent->s.weapon;
			//
			trap_BotLibUpdateEntity(i, &state);
		}

		BotAIRegularUpdate();
	}

	floattime = trap_AAS_Time();

	// execute scheduled bot AI
	for( i = 0; i < MAX_CLIENTS; i++ ) {
		if( !botstates[i] || !botstates[i]->inuse ) {
			continue;
		}
		//
		botstates[i]->botthink_residual += elapsed_time;
		//
		if ( botstates[i]->botthink_residual >= thinktime ) {
			botstates[i]->botthink_residual -= thinktime;

			if (!trap_AAS_Initialized()) return qfalse;

			if (g_entities[i].client->pers.connected == CON_CONNECTED) {
				BotAI(i, (float) thinktime / 1000);
			}
		}
	}


	// execute bot user commands every frame
	for( i = 0; i < MAX_CLIENTS; i++ ) {
		if( !botstates[i] || !botstates[i]->inuse ) {
			continue;
		}
		if( g_entities[i].client->pers.connected != CON_CONNECTED ) {
			continue;
		}

		BotUpdateInput(botstates[i], time, elapsed_time);
		trap_BotUserCommand(botstates[i]->client, &botstates[i]->lastucmd);
	}

	return qtrue;
}
Пример #7
0
/*
====================
CL_GetMessage

Handles recording and playback of demos, on top of NET_ code
====================
*/
int CL_GetMessage (void)
{
	int		r, i;
	float	f;
	
	if	(cls.demoplayback)
	{
	// decide if it is time to grab the next message		
		if (cls.signon == SIGNONS)	// allways grab until fully connected
		{
			if (cls.timedemo)
			{
				if (host_framecount == cls.td_lastframe)
					return 0;		// allready read this frame's message
				cls.td_lastframe = host_framecount;
			// if this is the second frame, grab the real td_starttime
			// so the bogus time on the first frame doesn't count
				if (host_framecount == cls.td_startframe + 1)
					cls.td_starttime = realtime;
			}
			else if ( /* cl.time > 0 && */ cl.time <= cl.mtime[0])
			{
					return 0;		// don't need another message yet
			}
		}
		
	// get the next message
		fread (&net_message.cursize, 4, 1, cls.demofile);
		VectorCopy (cl.mviewangles[0], cl.mviewangles[1]);
		for (i=0 ; i<3 ; i++)
		{
			r = fread (&f, 4, 1, cls.demofile);
			cl.mviewangles[0][i] = LittleFloat (f);
		}
		
		net_message.cursize = LittleLong (net_message.cursize);
		if (net_message.cursize > MAX_MSGLEN)
			Sys_Error ("Demo message > MAX_MSGLEN");
		r = fread (net_message.data, net_message.cursize, 1, cls.demofile);
		if (r != 1)
		{
			CL_StopPlayback ();
			return 0;
		}
	
		return 1;
	}

	while (1)
	{
		r = NET_GetMessage (cls.netcon);
		
		if (r != 1 && r != 2)
			return r;
	
	// discard nop keepalive message
		if (net_message.cursize == 1 && net_message.data[0] == svc_nop)
			Con_Printf ("<-- server to client keepalive\n");
		else
			break;
	}

	if (cls.demorecording)
		CL_WriteDemoMessage ();
	
	return r;
}
Пример #8
0
/*
===========
Drag_Begin
===========
*/
void Drag_Begin (int x, int y, int buttons,
		   vec3_t xaxis, vec3_t yaxis,
		   vec3_t origin, vec3_t dir)
{
	trace_t	t;

	drag_ok = false;
	VectorCopy (vec3_origin, pressdelta);
	VectorCopy (vec3_origin, vPressStart);

	drag_first = true;
	peLink = NULL;

	// shift LBUTTON = select entire brush
	if (buttons == (MK_LBUTTON | MK_SHIFT) && g_qeglobals.d_select_mode != sel_curvepoint)
	{
    int nFlag = (static_cast<bool>(::GetAsyncKeyState(VK_MENU))) ? SF_CYCLE : 0;
		if (dir[0] == 0 || dir[1] == 0 || dir[2] == 0)  // extremely low chance of this happening from camera
			Select_Ray (origin, dir, nFlag | SF_ENTITIES_FIRST);	// hack for XY
		else
			Select_Ray (origin, dir, nFlag);
		return;
	}

	// ctrl-shift LBUTTON = select single face
	if (buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT) && g_qeglobals.d_select_mode != sel_curvepoint)
	{
		Select_Deselect ();
		Select_Ray (origin, dir, SF_SINGLEFACE);
		return;
	}

	// LBUTTON + all other modifiers = manipulate selection
	if (buttons & MK_LBUTTON)
	{
		Drag_Setup (x, y, buttons, xaxis, yaxis, origin, dir);
		return;
	}

  int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
	// middle button = grab texture
	if (buttons == nMouseButton)
	{
		t = Test_Ray (origin, dir, false);
		if (t.face)
		{
			g_qeglobals.d_new_brush_bottom_z = t.brush->mins[2];
			g_qeglobals.d_new_brush_top_z = t.brush->maxs[2];
			Texture_SetTexture (&t.face->texdef);
      UpdateSurfaceDialog();
	  UpdatePatchInspector();
		}
		else
			Sys_Printf ("Did not select a texture\n");
		return;
	}

	// ctrl-middle button = set entire brush to texture
	if (buttons == (nMouseButton|MK_CONTROL) )
	{
		t = Test_Ray (origin, dir, false);
		if (t.brush)
		{
			if (t.brush->brush_faces->texdef.name[0] == '(')
				Sys_Printf ("Can't change an entity texture\n");
			else
			{					
				Brush_SetTexture (t.brush, &g_qeglobals.d_texturewin.texdef, false, false);
				Sys_UpdateWindows (W_ALL);
			}
		}
		else
			Sys_Printf ("Didn't hit a btrush\n");
		return;
	}

	// ctrl-shift-middle button = set single face to texture
	if (buttons == (nMouseButton|MK_SHIFT|MK_CONTROL) )
	{
		t = Test_Ray (origin, dir, false);
		if (t.brush)
		{
			if (t.brush->brush_faces->texdef.name[0] == '(')
				Sys_Printf ("Can't change an entity texture\n");
			else
			{									
				SetFaceTexdef (t.brush, t.face, &g_qeglobals.d_texturewin.texdef, false, false);
				Brush_Build( t.brush );
				Sys_UpdateWindows (W_ALL);
			}
		}
		else
			Sys_Printf ("Didn't hit a btrush\n");
		return;
	}

	// shift-middle = (if light) 
	//						set face texture info (err...whatever),
	//					else
	//						set brush to texture but preserve any system faces
	//
	if (buttons == (nMouseButton | MK_SHIFT))
	{
		Sys_Printf("Set brush face texture info\n");
		t = Test_Ray (origin, dir, false);
		if (t.brush)
		{
			if (t.brush->brush_faces->texdef.name[0] == '(')
			{
				if (strcmpi(t.brush->owner->eclass->name, "light") == 0)
				{
					CString strBuff;
					qtexture_t* pTex = Texture_ForName(g_qeglobals.d_texturewin.texdef.name);
					if (pTex)
					{
						vec3_t vColor;
						VectorCopy(pTex->color, vColor);
						
						float fLargest = 0.0f;
						for (int i = 0; i < 3; i++)
						{
							if (vColor[i] > fLargest)
								fLargest = vColor[i];
						}
						
						if (fLargest == 0.0f)
						{
							vColor[0] = vColor[1] = vColor[2] = 1.0f;
						}
						else
						{
							float fScale = 1.0f / fLargest;
							for (int i = 0; i < 3; i++)
							{
								vColor[i] *= fScale;
							}
						}
						strBuff.Format("%f %f %f",pTex->color[0], pTex->color[1], pTex->color[2]);
						SetKeyValue(t.brush->owner, "_color", strBuff.GetBuffer(0));
						Sys_UpdateWindows (W_ALL);
					}
				}
				else
				{
					Sys_Printf ("Can't select an entity brush face\n");
				}
			}
			else
			{
				Brush_SetTexture (t.brush, &g_qeglobals.d_texturewin.texdef, false, true);
				Sys_UpdateWindows (W_ALL);
			}
		}
		else
			Sys_Printf ("Didn't hit a brush\n");
		return;
	}

}
Пример #9
0
//
//===========
//MoveSelection
//===========
//
void MoveSelection (vec3_t move)
{
	int		i;
	brush_t	*b;
  CString strStatus;
  vec3_t vTemp, vTemp2;

	if (!move[0] && !move[1] && !move[2])
		return;

  if (g_pParentWnd->ActiveXY()->RotateMode() || g_bPatchBendMode)
  {
    float fDeg = -move[2];
    float fAdj = move[2];
    int nAxis = 0;
    if (g_pParentWnd->ActiveXY()->GetViewType() == XY)
    {
      fDeg = -move[1];
      fAdj = move[1];
      nAxis = 2;
    }
    else 
    if (g_pParentWnd->ActiveXY()->GetViewType() == XZ)
    {
      fDeg = move[2];
      fAdj = move[2];
      nAxis = 1;
    }
    else
      nAxis = 0;

    g_pParentWnd->ActiveXY()->Rotation()[nAxis] += fAdj;
    strStatus.Format("%s x:: %.1f  y:: %.1f  z:: %.1f", (g_bPatchBendMode) ? "Bend angle" : "Rotation", g_pParentWnd->ActiveXY()->Rotation()[0], g_pParentWnd->ActiveXY()->Rotation()[1], g_pParentWnd->ActiveXY()->Rotation()[2]);
    g_pParentWnd->SetStatusText(2, strStatus);

    if (g_bPatchBendMode)
    {
      Patch_SelectBendNormal();
      Select_RotateAxis(nAxis, fDeg*2, false, true);
      Patch_SelectBendAxis();
      Select_RotateAxis(nAxis, fDeg, false, true);
    }
    else
    {
      Select_RotateAxis(nAxis, fDeg, false, true);
    }
    return;
  }

  if (g_pParentWnd->ActiveXY()->ScaleMode())
  {
    vec3_t v;
    v[0] = v[1] = v[2] = 1.0;
    if (move[1] > 0)
    {
      v[0] = 1.1;
      v[1] = 1.1;
      v[2] = 1.1;
    }
    else 
    if (move[1] < 0)
    {
      v[0] = 0.9;
      v[1] = 0.9;
      v[2] = 0.9;
    }

    Select_Scale((g_nScaleHow & SCALE_X) ? v[0] : 1.0,
                 (g_nScaleHow & SCALE_Y) ? v[1] : 1.0,
                 (g_nScaleHow & SCALE_Z) ? v[2] : 1.0);
	  Sys_UpdateWindows (W_ALL);
    return;
  }


  vec3_t vDistance;
  VectorSubtract(pressdelta, vPressStart, vDistance);
  strStatus.Format("Distance x: %.1f  y: %.1f  z: %.1f", vDistance[0], vDistance[1], vDistance[2]);
  g_pParentWnd->SetStatusText(3, strStatus);

	//
	// dragging only a part of the selection
	//

  // this is fairly crappy way to deal with curvepoint and area selection
  // but it touches the smallest amount of code this way
  // 
	if (g_qeglobals.d_num_move_points || g_qeglobals.d_select_mode == sel_area)
	{
    if (g_qeglobals.d_select_mode == sel_area)
    {
      VectorAdd(g_qeglobals.d_vAreaBR, move, g_qeglobals.d_vAreaBR);
      return;
    }

    if (g_qeglobals.d_select_mode == sel_curvepoint)
    {
      Patch_UpdateSelected(move);
      return;
    }
    else
    {
		  for (i=0 ; i<g_qeglobals.d_num_move_points ; i++)
			  VectorAdd (g_qeglobals.d_move_points[i], move, g_qeglobals.d_move_points[i]);
    }
    //VectorScale(move, .5, move);
		//for (i=0 ; i<g_qeglobals.d_num_move_points2 ; i++)
		//	VectorAdd (g_qeglobals.d_move_points2[i], move, g_qeglobals.d_move_points2[i]);


		for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
		{
      VectorCopy(b->maxs, vTemp);
      VectorSubtract(vTemp, b->mins, vTemp);
			Brush_Build( b );
			for (i=0 ; i<3 ; i++)
				if (b->mins[i] > b->maxs[i]
				|| b->maxs[i] - b->mins[i] > WORLD_SIZE)
					break;	// dragged backwards or fucked up
			if (i != 3)
				break;
      if (b->patchBrush)
      {
        VectorCopy(b->maxs, vTemp2);
        VectorSubtract(vTemp2, b->mins, vTemp2);
        VectorSubtract(vTemp2, vTemp, vTemp2);
        if (!Patch_DragScale(b->nPatchID, vTemp2, move))
        {
          b = NULL;
          break;
        }
      }
		}

		// if any of the brushes were crushed out of existance
		// calcel the entire move
		if (b != &selected_brushes)
		{
			Sys_Printf ("Brush dragged backwards, move canceled\n");
			for (i=0 ; i<g_qeglobals.d_num_move_points ; i++)
				VectorSubtract (g_qeglobals.d_move_points[i], move, g_qeglobals.d_move_points[i]);

			for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
				Brush_Build( b );
		}

	}
	else
	{
		//
		// if there are lots of brushes selected, just translate instead
		// of rebuilding the brushes
		//
		if (drag_yvec[2] == 0 && selected_brushes.next->next != &selected_brushes)
		{
			Select_Move (move);
			//VectorAdd (g_qeglobals.d_select_translate, move, g_qeglobals.d_select_translate);
		}
		else
		{
			Select_Move (move);
		}
	}
}
Пример #10
0
//-----------------------------------------------------------------------------
// Method to sample the windspeed at a particular time
//-----------------------------------------------------------------------------
void GetWindspeedAtTime( float flTime, Vector &vecVelocity )
{
	// For now, ignore history and time.. fix later when we use wind to affect
	// client-side prediction
	VectorCopy( s_vecWindVelocity, vecVelocity );
}
Пример #11
0
void CLH2_UpdateStreams() {
	h2stream_t* stream = clh2_Streams;
	for ( int streamIndex = 0; streamIndex < MAX_STREAMS_H2; streamIndex++, stream++ ) {
		if ( !stream->models[ 0 ] ) {
			// Inactive
			continue;
		}

		if ( stream->endTime < cl.serverTime ) {
			// Inactive
			if ( stream->type != H2TE_STREAM_LIGHTNING && stream->type != H2TE_STREAM_LIGHTNING_SMALL ) {
				continue;
			} else if ( stream->endTime + 250 < cl.serverTime ) {
				continue;
			}
		}

		if ( stream->flags & H2STREAM_ATTACHED && stream->endTime >= cl.serverTime ) {
			// Attach the start position to owner
			h2entity_state_t* state = CLH2_FindState( stream->entity );
			if ( state ) {
				VectorAdd( state->origin, stream->offset, stream->source );
			}
		}

		vec3_t dist;
		VectorSubtract( stream->dest, stream->source, dist );
		vec3_t angles;
		VecToAnglesBuggy( dist, angles );

		vec3_t org;
		VectorCopy( stream->source, org );
		float d = VectorNormalize( dist );

		vec3_t right, up;
		float cosTime, sinTime, lifeTime, cos2Time, sin2Time;
		if ( ( GGameType & GAME_HexenWorld ) && stream->type == H2TE_STREAM_SUNSTAFF2 ) {
			vec3_t discard;
			AngleVectors( angles, discard, right, up );

			lifeTime = ( stream->endTime - cl.serverTime ) / 800.0f;
			cosTime = cos( cl.serverTime * 0.001 * 5 );
			sinTime = sin( cl.serverTime * 0.001 * 5 );
			cos2Time = cos( cl.serverTime * 0.001 * 5 + 3.14 );
			sin2Time = sin( cl.serverTime * 0.001 * 5 + 3.14 );
		}

		int segmentCount = 0;
		if ( stream->type == H2TE_STREAM_ICECHUNKS ) {
			int offset = ( cl.serverTime / 25 ) % 30;
			for ( int i = 0; i < 3; i++ ) {
				org[ i ] += dist[ i ] * offset;
			}
		}
		while ( d > 0 ) {
			refEntity_t ent;
			Com_Memset( &ent, 0, sizeof ( ent ) );
			ent.reType = RT_MODEL;
			VectorCopy( org, ent.origin );
			ent.hModel = stream->models[ 0 ];
			switch ( stream->type ) {
			case H2TE_STREAM_CHAIN:
				angles[ 2 ] = 0;
				CLH2_SetRefEntAxis( &ent, angles, oldvec3_origin, 0, 128, H2MLS_ABSLIGHT );
				R_AddRefEntityToScene( &ent );
				break;
			case H2TE_STREAM_SUNSTAFF1:
				angles[ 2 ] = ( cl.serverTime / 100 ) % 360;
				if ( GGameType & GAME_HexenWorld ) {
					CLH2_SetRefEntAxis( &ent, angles, oldvec3_origin, 50 + ( stream->endTime - cl.serverTime ) / 3, 128, H2MLS_ABSLIGHT );
				} else {
					CLH2_SetRefEntAxis( &ent, angles, oldvec3_origin, 0, 128, H2MLS_ABSLIGHT );
				}
				R_AddRefEntityToScene( &ent );

				Com_Memset( &ent, 0, sizeof ( ent ) );
				ent.reType = RT_MODEL;
				VectorCopy( org, ent.origin );
				ent.hModel = stream->models[ 1 ];
				angles[ 2 ] = ( cl.serverTime / 20 ) % 360;
				if ( GGameType & GAME_HexenWorld ) {
					CLH2_SetRefEntAxis( &ent, angles, oldvec3_origin, 50 + ( stream->endTime - cl.serverTime ) * 0.2f, 128, H2MLS_ABSLIGHT | H2DRF_TRANSLUCENT );
				} else {
					CLH2_SetRefEntAxis( &ent, angles, oldvec3_origin, 0, 128, H2MLS_ABSLIGHT | H2DRF_TRANSLUCENT );
				}
				R_AddRefEntityToScene( &ent );
				break;
			case H2TE_STREAM_SUNSTAFF2:
				if ( !( GGameType & GAME_HexenWorld ) ) {
					angles[ 2 ] = ( cl.serverTime / 100 ) % 360;
					ent.frame = ( cl.serverTime / 100 ) % 8;
					CLH2_SetRefEntAxis( &ent, angles, oldvec3_origin, 0, 128, H2MLS_ABSLIGHT );
					R_AddRefEntityToScene( &ent );
				} else {
					angles[ 2 ] = ( int )( cl.serverTime * 0.001 * 100 ) % 360;
					VectorMA( ent.origin, cosTime * ( 40 * lifeTime ), right,  ent.origin );
					VectorMA( ent.origin, sinTime * ( 40 * lifeTime ), up,  ent.origin );
					CLH2_SetRefEntAxis( &ent, angles, oldvec3_origin, 100 + 150 * lifeTime, 128, H2MLS_ABSLIGHT | H2DRF_TRANSLUCENT );
					R_AddRefEntityToScene( &ent );

					Com_Memset( &ent, 0, sizeof ( ent ) );
					ent.reType = RT_MODEL;
					VectorCopy( org, ent.origin );
					ent.hModel = stream->models[ 0 ];
					angles[ 2 ] = ( int )( cl.serverTime * 0.001 * 100 ) % 360;
					VectorMA( ent.origin, cos2Time * ( 40 * lifeTime ), right,  ent.origin );
					VectorMA( ent.origin, sin2Time * ( 40 * lifeTime ), up,  ent.origin );
					CLH2_SetRefEntAxis( &ent, angles, oldvec3_origin, 100 + 150 * lifeTime, 128, H2MLS_ABSLIGHT | H2DRF_TRANSLUCENT );
					R_AddRefEntityToScene( &ent );

					for ( int ix = 0; ix < 2; ix++ ) {
						Com_Memset( &ent, 0, sizeof ( ent ) );
						ent.reType = RT_MODEL;
						VectorCopy( org, ent.origin );
						if ( ix ) {
							VectorMA( ent.origin, cos2Time * ( 40 * lifeTime ), right,  ent.origin );
							VectorMA( ent.origin, sin2Time * ( 40 * lifeTime ), up,  ent.origin );
						} else {
							VectorMA( ent.origin, cosTime * ( 40 * lifeTime ), right,  ent.origin );
							VectorMA( ent.origin, sinTime * ( 40 * lifeTime ), up,  ent.origin );
						}
						ent.hModel = stream->models[ 1 ];
						angles[ 2 ] = ( int )( cl.serverTime * 0.001 * 20 ) % 360;
						CLH2_SetRefEntAxis( &ent, angles, oldvec3_origin, 100 + 150 * lifeTime, 128, H2MLS_ABSLIGHT );
						R_AddRefEntityToScene( &ent );
					}
				}
				break;
			case H2TE_STREAM_LIGHTNING:
				if ( stream->endTime < cl.serverTime ) {//fixme: keep last non-translucent frame and angle
					angles[ 2 ] = 0;
					CLH2_SetRefEntAxis( &ent, angles, oldvec3_origin, 0, 128 + ( stream->endTime - cl.serverTime ) * 192 / 1000.0, H2MLS_ABSLIGHT | H2DRF_TRANSLUCENT );
				} else {
					angles[ 2 ] = rand() % 360;
					ent.frame = rand() % 6;
					CLH2_SetRefEntAxis( &ent, angles, oldvec3_origin, 0, 128, H2MLS_ABSLIGHT );
				}
				R_AddRefEntityToScene( &ent );
				break;
			case H2TE_STREAM_LIGHTNING_SMALL:
			case HWTE_STREAM_LIGHTNING_SMALL:
				if ( stream->endTime < cl.serverTime ) {
					angles[ 2 ] = 0;
					CLH2_SetRefEntAxis( &ent, angles, oldvec3_origin, 0, 128 + ( stream->endTime - cl.serverTime ) * 192 / 1000.0, H2MLS_ABSLIGHT | H2DRF_TRANSLUCENT );
				} else {
					angles[ 2 ] = rand() % 360;
					ent.frame = rand() % 6;
					CLH2_SetRefEntAxis( &ent, angles, oldvec3_origin, 0, 128, H2MLS_ABSLIGHT );
				}
				R_AddRefEntityToScene( &ent );
				break;
			case H2TE_STREAM_FAMINE:
				angles[ 2 ] = rand() % 360;
				ent.frame = 0;
				CLH2_SetRefEntAxis( &ent, angles, oldvec3_origin, 0, 128, H2MLS_ABSLIGHT );
				R_AddRefEntityToScene( &ent );
				break;
			case H2TE_STREAM_COLORBEAM:
				angles[ 2 ] = 0;
				ent.skinNum = stream->skin;
				CLH2_SetRefEntAxis( &ent, angles, oldvec3_origin, 0, 128, H2MLS_ABSLIGHT );
				CLH2_HandleCustomSkin( &ent );
				R_AddRefEntityToScene( &ent );
				break;
			case H2TE_STREAM_GAZE:
				angles[ 2 ] = 0;
				ent.frame = ( cl.serverTime /  25 ) % 36;
				CLH2_SetRefEntAxis( &ent, angles, oldvec3_origin, 0, 128, H2MLS_ABSLIGHT );
				R_AddRefEntityToScene( &ent );
				break;
			case H2TE_STREAM_ICECHUNKS:
				angles[ 2 ] = rand() % 360;
				ent.frame = rand() % 5;
				CLH2_SetRefEntAxis( &ent, angles, oldvec3_origin, 0, 128, H2MLS_ABSLIGHT );
				R_AddRefEntityToScene( &ent );
				break;
			default:
				angles[ 2 ] = 0;
				CLH2_SetRefEntAxis( &ent, angles, oldvec3_origin, 0, 0, 0 );
				R_AddRefEntityToScene( &ent );
			}
			for ( int i = 0; i < 3; i++ ) {
				org[ i ] += dist[ i ] * 30;
			}
			d -= 30;
			segmentCount++;
		}
		if ( stream->type == H2TE_STREAM_SUNSTAFF1 ||
			 ( !( GGameType & GAME_HexenWorld ) && stream->type == H2TE_STREAM_SUNSTAFF2 ) ) {
			if ( stream->lastTrailTime + 200 < cl.serverTime ) {
				stream->lastTrailTime = cl.serverTime;
				CLH2_SunStaffTrail( stream->source, stream->dest );
			}

			refEntity_t ent;
			Com_Memset( &ent, 0, sizeof ( ent ) );
			ent.reType = RT_MODEL;
			VectorCopy( stream->dest, ent.origin );
			ent.hModel = stream->models[ 2 ];
			CLH2_SetRefEntAxis( &ent, oldvec3_origin, oldvec3_origin, 80 + ( rand() & 15 ), 128, H2MLS_ABSLIGHT );
			R_AddRefEntityToScene( &ent );

			Com_Memset( &ent, 0, sizeof ( ent ) );
			ent.reType = RT_MODEL;
			VectorCopy( stream->dest, ent.origin );
			ent.hModel = stream->models[ 3 ];
			CLH2_SetRefEntAxis( &ent, oldvec3_origin, oldvec3_origin, 150 + ( rand() & 15 ), 128, H2MLS_ABSLIGHT | H2DRF_TRANSLUCENT );
			R_AddRefEntityToScene( &ent );
		}
	}
}
Пример #12
0
void LoadJTRAIL(edict_t *ent,char filename[MAX_STR_LEN],qboolean pdm,int clean,int colorp,int sizep)
{
	
	FILE *jtrail_file;
	char *token="\0";
	char buf2[1000];
	char message[256];
	int lbuf2,color,mass;
	edict_t *laser = NULL;
	vec3_t start;
	int lasttrailnum=0;
	char JTRAILFile[MAX_STR_LEN];
	int delcount=0;
	char tok[2]="";
	int clean_count=0;
	int total_good_lines=0;
	
	if (TrailsBanned()) return;

	if (pdm)
	{
		if (!Q_stricmp(filename,"lastdemo"))
			sprintf(JTRAILFile, GAMEVERSION "/puppetdemo/%i.pdm",ent->client->resp.id);
		else
			sprintf(JTRAILFile, GAMEVERSION "/puppetdemo/%s-%s.pdm",level.mapname,filename);
	}
	else
		sprintf(JTRAILFile, GAMEVERSION "/jtrail/%s-%s.jtrail",level.mapname,filename);

	jtrail_file = fopen(JTRAILFile, "r");
	if (jtrail_file == NULL)
	{
		if (pdm)
		{
			if (!Q_stricmp(filename,"lastdemo"))
				gi.cprintf(ent,PRINT_HIGH,"\"%i.pdm\" was not found!\n",ent->client->resp.id);
			else
				gi.cprintf(ent,PRINT_HIGH,"\"%s-%s.pdm\" was not found!\n",level.mapname,filename);
		}
		else
			gi.cprintf(ent,PRINT_HIGH,"\"%s-%s.jtrail\" was not found!\n",level.mapname,filename);
		return;
	}
	
    if (pdm)
		tok[0] = ',';	//puppet demos parsed with ','
	else
		tok[0] = ' ';	//trail files parsed with ' '
	tok[1] = '\0';

	//grab the total good lines, for new clean-on-load usage
	while (fgets(buf2, 900, jtrail_file) != NULL)
	{
		if (!(((buf2[0] > '0') && (buf2[0] < '9')) || (buf2[0] == '-')))
			continue;
		total_good_lines++;
	}
	fclose(jtrail_file);

	//reopen the file to start reading again... we know it exists so no check on that
	jtrail_file = fopen(JTRAILFile, "r");
	jtrail_num_lines = 0;
	ltrails++;
	while (fgets(buf2, 900, jtrail_file) != NULL)
	{
		double time;

		if (!(((buf2[0] > '0') && (buf2[0] < '9')) || (buf2[0] == '-')))
			continue;

		if (clean_count != clean)
		{
			if ((jtrail_num_lines != 0) && (jtrail_num_lines != total_good_lines))
			{
				clean_count++;
				continue;
			}
			clean_count++;
		}
		else
			clean_count = 0;

		message[0]='\0';
		lbuf2 = strlen(buf2);
		while (buf2[lbuf2-1] == '\r' || buf2[lbuf2-1] == '\n')
		{
			buf2[lbuf2-1] = 0;
			lbuf2--;
		}
		
		start[0] = start[1] = start[2] = color = mass = 0;

		if (ltnodes <= traillimit->value)
		{
			laser = G_Spawn();
			//		laser->owner = ent;

			ltnodes++;
			laser->classnum = jtrail_num_lines+1;//ltnodes;
			laser->classname = "LaserTrailLink";
			laser->s.frame = 4;
			VectorSet (laser->mins, -8, -8, -8);
			VectorSet (laser->maxs, 8, 8, 8);
			
			//Load Coords
			token = strtok( buf2, tok );
			start[0] = atoi(token);
			token = strtok( NULL, tok );
			if ((token == NULL) && pdm)
				break;
			start[1] = atoi(token);
			token = strtok( NULL, tok );
			start[2] = atoi(token);
			VectorCopy(start,laser->s.origin);

			if (pdm)
			{
				if (colorp == -1)
					laser->s.skinnum = NUMtoCOLOR(1); //color (green)
				else
					laser->s.skinnum = NUMtoCOLOR(colorp);

				if (sizep == -1)
					laser->s.frame = 4; //size
				else
					laser->s.frame = sizep;
				laser->mass = ltrails; //num (never gonna be multiple paths to load this way)
			}
			else
			{
				//Load Color
				token = strtok( NULL, tok );
				color = atoi(token);
				laser->s.skinnum = color;
				
				//Load Size
				token = strtok( NULL, tok );
				color = atoi(token);
				laser->s.frame = color;
				
				//Load Gravity
				token = strtok( NULL, tok );
				color = atoi(token);
				
				if (lasttrailnum != color)
				{
					ltrails++;
					lasttrailnum = color;
				}
				
				laser->mass = color+ltrails;
			}
			
			time = level.time + (jtrail_num_lines/10);
			
			laser->think = DelayLaserLinkOn;//MODIFY ME!!!WHY?!!//DelayMarkerLoad_Think;
			laser->nextthink = time;
			
			gi.linkentity(laser);
		}
		else
		{
			delcount++;
		}
		
		jtrail_num_lines++;
	}

	fclose(jtrail_file);
	
	if (delcount !=0)
	{
		if (delcount == jtrail_num_lines)
			gi.bprintf(PRINT_HIGH,"%s: \"%s\" could not be loaded due to traillimit hit!\n",ent->client->pers.netname,JTRAILFile);
		else
		{
			gi.bprintf(PRINT_HIGH,"%s: \"%s\" was partially loaded due to traillimit hit! (%i/%i link",ent->client->pers.netname,JTRAILFile,jtrail_num_lines-delcount,jtrail_num_lines);
			if (jtrail_num_lines != 1)
				gi.bprintf(PRINT_HIGH,"s");
			if (jtrail_num_lines-delcount > 10)
				gi.bprintf(PRINT_HIGH," (%i in queue))\n",jtrail_num_lines-delcount-10);
			else
				gi.bprintf(PRINT_HIGH,")\n");
		}
	}
	else
	{
		gi.bprintf(PRINT_HIGH,"%s: \"%s\" was loaded successfully! (%i link",ent->client->pers.netname,JTRAILFile,jtrail_num_lines);
		if (jtrail_num_lines != 1)
			gi.bprintf(PRINT_HIGH,"s");
		if (jtrail_num_lines > 10)
			gi.bprintf(PRINT_HIGH," (%i in queue))\n",jtrail_num_lines-10);
		else
			gi.bprintf(PRINT_HIGH,")\n");
	}
}
Пример #13
0
/*
==============
ClientThink

This will be called once for each client frame, which will
usually be a couple times for each server frame.
==============
*/
void ClientThink (edict_t *ent, usercmd_t *ucmd)
{
	gclient_t	*client;
	edict_t	*other;
	int		i, j;
	pmove_t	pm;

	level.current_entity = ent;
	client = ent->client;

	if (level.intermissiontime)
	{
		client->ps.pmove.pm_type = PM_FREEZE;
		// can exit intermission after five seconds
		if (level.time > level.intermissiontime + 5.0 
			&& (ucmd->buttons & BUTTON_ANY) )
			level.exitintermission = true;
		return;
	}

	pm_passent = ent;

	if (ent->client->chase_target) {

		client->resp.cmd_angles[0] = SHORT2ANGLE(ucmd->angles[0]);
		client->resp.cmd_angles[1] = SHORT2ANGLE(ucmd->angles[1]);
		client->resp.cmd_angles[2] = SHORT2ANGLE(ucmd->angles[2]);

	} else {

		// set up for pmove
		memset (&pm, 0, sizeof(pm));

		if (ent->movetype == MOVETYPE_NOCLIP)
			client->ps.pmove.pm_type = PM_SPECTATOR;
		else if (ent->s.modelindex != 255)
			client->ps.pmove.pm_type = PM_GIB;
		else if (ent->deadflag)
			client->ps.pmove.pm_type = PM_DEAD;
		else
			client->ps.pmove.pm_type = PM_NORMAL;

		client->ps.pmove.gravity = sv_gravity->value;
		pm.s = client->ps.pmove;

		for (i=0 ; i<3 ; i++)
		{
			pm.s.origin[i] = ent->s.origin[i]*8;
			pm.s.velocity[i] = ent->velocity[i]*8;
		}

		if (memcmp(&client->old_pmove, &pm.s, sizeof(pm.s)))
		{
			pm.snapinitial = true;
	//		gi.dprintf ("pmove changed!\n");
		}

		pm.cmd = *ucmd;

		pm.trace = PM_trace;	// adds default parms
		pm.pointcontents = gi.pointcontents;

		// perform a pmove
		gi.Pmove (&pm);

		// save results of pmove

		client->ps.pmove = pm.s;
		client->old_pmove = pm.s;

		for (i=0 ; i<3 ; i++)
		{
			ent->s.origin[i] = pm.s.origin[i]*0.125;
			ent->velocity[i] = pm.s.velocity[i]*0.125;
		}

		VectorCopy (pm.mins, ent->mins);
		VectorCopy (pm.maxs, ent->maxs);

		client->resp.cmd_angles[0] = SHORT2ANGLE(ucmd->angles[0]);
		client->resp.cmd_angles[1] = SHORT2ANGLE(ucmd->angles[1]);
		client->resp.cmd_angles[2] = SHORT2ANGLE(ucmd->angles[2]);

		if (ent->groundentity && !pm.groundentity && (pm.cmd.upmove >= 10) && (pm.waterlevel == 0))
		{
			gi.sound(ent, CHAN_VOICE, gi.soundindex("*jump1.wav"), 1, ATTN_NORM, 0);
			PlayerNoise(ent, ent->s.origin, PNOISE_SELF);
		}

		ent->viewheight = pm.viewheight;
		ent->waterlevel = pm.waterlevel;
		ent->watertype = pm.watertype;
		ent->groundentity = pm.groundentity;
		if (pm.groundentity)
			ent->groundentity_linkcount = pm.groundentity->linkcount;

		if (ent->deadflag)
		{
			client->ps.viewangles[ROLL] = 40;
			client->ps.viewangles[PITCH] = -15;
			client->ps.viewangles[YAW] = client->killer_yaw;
		}
		else
		{
			VectorCopy (pm.viewangles, client->v_angle);
			VectorCopy (pm.viewangles, client->ps.viewangles);
		}

		gi.linkentity (ent);

		if (ent->movetype != MOVETYPE_NOCLIP)
			G_TouchTriggers (ent);

		// touch other objects
		for (i=0 ; i<pm.numtouch ; i++)
		{
			other = pm.touchents[i];
			for (j=0 ; j<i ; j++)
				if (pm.touchents[j] == other)
					break;
			if (j != i)
				continue;	// duplicated
			if (!other->touch)
				continue;
			other->touch (other, ent, NULL, NULL);
		}

	}

	client->oldbuttons = client->buttons;
	client->buttons = ucmd->buttons;
	client->latched_buttons |= client->buttons & ~client->oldbuttons;

	// save light level the player is standing on for
	// monster sighting AI
	ent->light_level = ucmd->lightlevel;

	// fire weapon from final position if needed
	if (client->latched_buttons & BUTTON_ATTACK)
	{
		if (client->resp.spectator) {

			client->latched_buttons = 0;

			if (client->chase_target) {
				client->chase_target = NULL;
				client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION;
			} else
				GetChaseTarget(ent);

		} else if (!client->weapon_thunk) {
			client->weapon_thunk = true;
			Think_Weapon (ent);
		}
	}

	if (client->resp.spectator) {
		if (ucmd->upmove >= 10) {
			if (!(client->ps.pmove.pm_flags & PMF_JUMP_HELD)) {
				client->ps.pmove.pm_flags |= PMF_JUMP_HELD;
				if (client->chase_target)
					ChaseNext(ent);
				else
					GetChaseTarget(ent);
			}
		} else
			client->ps.pmove.pm_flags &= ~PMF_JUMP_HELD;
	}

	// update chase cam if being followed
	for (i = 1; i <= maxclients->value; i++) {
		other = g_edicts + i;
		if (other->inuse && other->client->chase_target == ent)
			UpdateChaseCam(other);
	}
}
Пример #14
0
/*
===========
PutClientInServer

Called when a player connects to a server or respawns in
a deathmatch.
============
*/
void PutClientInServer (edict_t *ent)
{
	vec3_t	mins = {-16, -16, -24};
	vec3_t	maxs = {16, 16, 32};
	int		index;
	vec3_t	spawn_origin, spawn_angles;
	gclient_t	*client;
	int		i;
	client_persistant_t	saved;
	client_respawn_t	resp;

	// find a spawn point
	// do it before setting health back up, so farthest
	// ranging doesn't count this client
	SelectSpawnPoint (ent, spawn_origin, spawn_angles);

	index = ent-g_edicts-1;
	client = ent->client;

	// deathmatch wipes most client data every spawn
	if (deathmatch->value)
	{
		char		userinfo[MAX_INFO_STRING];

		resp = client->resp;
		memcpy (userinfo, client->pers.userinfo, sizeof(userinfo));
		InitClientPersistant (client);
		ClientUserinfoChanged (ent, userinfo);
	}
	else if (coop->value)
	{
//		int			n;
		char		userinfo[MAX_INFO_STRING];

		resp = client->resp;
		memcpy (userinfo, client->pers.userinfo, sizeof(userinfo));
		// this is kind of ugly, but it's how we want to handle keys in coop
//		for (n = 0; n < game.num_items; n++)
//		{
//			if (itemlist[n].flags & IT_KEY)
//				resp.coop_respawn.inventory[n] = client->pers.inventory[n];
//		}
		resp.coop_respawn.game_helpchanged = client->pers.game_helpchanged;
		resp.coop_respawn.helpchanged = client->pers.helpchanged;
		client->pers = resp.coop_respawn;
		ClientUserinfoChanged (ent, userinfo);
		if (resp.score > client->pers.score)
			client->pers.score = resp.score;
	}
	else
	{
		memset (&resp, 0, sizeof(resp));
	}

	// clear everything but the persistant data
	saved = client->pers;
	memset (client, 0, sizeof(*client));
	client->pers = saved;
	if (client->pers.health <= 0)
		InitClientPersistant(client);
	client->resp = resp;

	// copy some data from the client to the entity
	FetchClientEntData (ent);

	// clear entity values
	ent->groundentity = NULL;
	ent->client = &game.clients[index];
	ent->takedamage = DAMAGE_AIM;
	ent->movetype = MOVETYPE_WALK;
	ent->viewheight = 22;
	ent->inuse = true;
	ent->classname = "player";
	ent->mass = 200;
	ent->solid = SOLID_BBOX;
	ent->deadflag = DEAD_NO;
	ent->air_finished = level.time + 12;
	ent->clipmask = MASK_PLAYERSOLID;
	ent->model = "players/male/tris.md2";
	ent->pain = player_pain;
	ent->die = player_die;
	ent->waterlevel = 0;
	ent->watertype = 0;
	ent->flags &= ~FL_NO_KNOCKBACK;
	ent->svflags &= ~SVF_DEADMONSTER;

	VectorCopy (mins, ent->mins);
	VectorCopy (maxs, ent->maxs);
	VectorClear (ent->velocity);

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

	client->ps.pmove.origin[0] = spawn_origin[0]*8;
	client->ps.pmove.origin[1] = spawn_origin[1]*8;
	client->ps.pmove.origin[2] = spawn_origin[2]*8;

	if (deathmatch->value && ((int)dmflags->value & DF_FIXED_FOV))
	{
		client->ps.fov = 90;
	}
	else
	{
		client->ps.fov = atoi(Info_ValueForKey(client->pers.userinfo, "fov"));
		if (client->ps.fov < 1)
			client->ps.fov = 90;
		else if (client->ps.fov > 160)
			client->ps.fov = 160;
	}

	client->ps.gunindex = gi.modelindex(client->pers.weapon->view_model);

	// clear entity state values
	ent->s.effects = 0;
	ent->s.modelindex = 255;		// will use the skin specified model
	ent->s.modelindex2 = 255;		// custom gun model
	// sknum is player num and weapon number
	// weapon number will be added in changeweapon
	ent->s.skinnum = ent - g_edicts - 1;

	ent->s.frame = 0;
	VectorCopy (spawn_origin, ent->s.origin);
	ent->s.origin[2] += 1;	// make sure off ground
	VectorCopy (ent->s.origin, ent->s.old_origin);

	// set the delta angle
	for (i=0 ; i<3 ; i++)
	{
		client->ps.pmove.delta_angles[i] = ANGLE2SHORT(spawn_angles[i] - client->resp.cmd_angles[i]);
	}

	ent->s.angles[PITCH] = 0;
	ent->s.angles[YAW] = spawn_angles[YAW];
	ent->s.angles[ROLL] = 0;
	VectorCopy (ent->s.angles, client->ps.viewangles);
	VectorCopy (ent->s.angles, client->v_angle);

	// spawn a spectator
	if (client->pers.spectator) {
		client->chase_target = NULL;

		client->resp.spectator = true;

		ent->movetype = MOVETYPE_NOCLIP;
		ent->solid = SOLID_NOT;
		ent->svflags |= SVF_NOCLIENT;
		ent->client->ps.gunindex = 0;
		gi.linkentity (ent);
		return;
	} else
		client->resp.spectator = false;

	if (!KillBox (ent))
	{	// could't spawn in?
	}

	gi.linkentity (ent);

	// force the current weapon up
	client->newweapon = client->pers.weapon;
	ChangeWeapon (ent);
}
Пример #15
0
void CGCam_Update( void )
{
	int	i;
	qboolean	checkFollow = qfalse;
	qboolean	checkTrack = qfalse;

	// Apply new roff data to the camera as needed
	if ( client_camera.info_state & CAMERA_ROFFING )
	{
		CGCam_Roff();
	}

	//Check for a zoom
	if ( client_camera.info_state & CAMERA_ZOOMING )
	{
		float	actualFOV_X;

		if ( client_camera.FOV_time + client_camera.FOV_duration < cg.time )
		{
			actualFOV_X = client_camera.FOV = client_camera.FOV2;
			client_camera.info_state &= ~CAMERA_ZOOMING;
		}
		else
		{
			actualFOV_X = client_camera.FOV + (( ( client_camera.FOV2 - client_camera.FOV ) ) / client_camera.FOV_duration ) * ( cg.time - client_camera.FOV_time );
		}
		CG_CalcFOVFromX( actualFOV_X );
	}
	else
	{
		CG_CalcFOVFromX( client_camera.FOV );
	}

	//Check for pan
	if ( client_camera.info_state & CAMERA_PANNING )
	{
		//Note: does not actually change the camera's angles until the pan time is done!
		if ( client_camera.pan_time + client_camera.pan_duration < cg.time )
		{//finished panning
			for ( i = 0; i < 3; i++ )
			{
				client_camera.angles[i] = AngleNormalize360( ( client_camera.angles[i] + client_camera.angles2[i] ) );
			}

			client_camera.info_state &= ~CAMERA_PANNING;
			VectorCopy(client_camera.angles, cg.refdefViewAngles );
		}
		else
		{//still panning
			for ( i = 0; i < 3; i++ )
			{
				//NOTE: does not store the resultant angle in client_camera.angles until pan is done
				cg.refdefViewAngles[i] = client_camera.angles[i] + ( client_camera.angles2[i] / client_camera.pan_duration ) * ( cg.time - client_camera.pan_time );
			}
		}
	}
	else 
	{
		checkFollow = qtrue;
	}

	AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis );

	//Check for movement
	if ( client_camera.info_state & CAMERA_MOVING )
	{
		//NOTE: does not actually move the camera until the movement time is done!
		if ( client_camera.move_time + client_camera.move_duration < cg.time )
		{
			VectorCopy( client_camera.origin2, client_camera.origin );
			client_camera.info_state &= ~CAMERA_MOVING;
			VectorCopy( client_camera.origin, cg.refdef.vieworg );
		}
		else
		{
			for ( i = 0; i < 3; i++ )
				cg.refdef.vieworg[i] = client_camera.origin[i] + (( ( client_camera.origin2[i] - client_camera.origin[i] ) ) / client_camera.move_duration ) * ( cg.time - client_camera.move_time );
		}
	}
	else
	{
		checkTrack = qtrue;
	}

	if ( checkFollow )
	{
		if ( client_camera.info_state & CAMERA_FOLLOWING )
		{//This needs to be done after camera movement
			CGCam_FollowUpdate();
		}
		VectorCopy(client_camera.angles, cg.refdefViewAngles );
	}

	if ( checkTrack )
	{
		if ( client_camera.info_state & CAMERA_TRACKING )
		{//This has to run AFTER Follow if the camera is following a cameraGroup
			CGCam_TrackUpdate();
		}

		VectorCopy( client_camera.origin, cg.refdef.vieworg );
	}

	//Bar fading
	if ( client_camera.info_state & CAMERA_BAR_FADING )
	{
		CGCam_UpdateBarFade();
	}

	//Normal fading - separate call because can finish after camera is disabled
	CGCam_UpdateFade();

	//Update shaking if there's any
	CGCam_UpdateShake( cg.refdef.vieworg, cg.refdefViewAngles );
}
Пример #16
0
/*
===========
Drag_Setup
===========
*/
void Drag_Setup (int x, int y, int buttons,
		   vec3_t xaxis, vec3_t yaxis,
		   vec3_t origin, vec3_t dir)
{
	trace_t	t;
	face_t	*f;

	drag_first = true;
	
  VectorCopy (vec3_origin, pressdelta);
	pressx = x;
	pressy = y;

	VectorCopy (xaxis, drag_xvec);
	AxializeVector (drag_xvec);
	VectorCopy (yaxis, drag_yvec);
	AxializeVector (drag_yvec);


  extern void SelectCurvePointByRay (vec3_t org, vec3_t dir, int buttons);
  if (g_qeglobals.d_select_mode == sel_curvepoint)
	{
    //if ((buttons == MK_LBUTTON))
    //  g_qeglobals.d_num_move_points = 0;

		SelectCurvePointByRay (origin, dir, buttons);	
		
    if (g_qeglobals.d_num_move_points || g_qeglobals.d_select_mode == sel_area)
		{
			drag_ok = true;
		}
    
    Sys_UpdateWindows(W_ALL);
		return;

  }
  else
  {
    g_qeglobals.d_num_move_points = 0;
  }

	if (selected_brushes.next == &selected_brushes)
	{
		Sys_Status("No selection to drag\n", 0);
		return;
	}


	if (g_qeglobals.d_select_mode == sel_vertex)
	{
		SelectVertexByRay (origin, dir);	
		if (g_qeglobals.d_num_move_points)
		{
			drag_ok = true;
			return;
		}
	}

  if (g_qeglobals.d_select_mode == sel_edge)
	{
		SelectEdgeByRay (origin, dir);	
		if (g_qeglobals.d_num_move_points)
		{
			drag_ok = true;
			return;
		}
	}


	//
	// check for direct hit first
	//
	t = Test_Ray (origin, dir, true);
	if (t.selected)
	{
		drag_ok = true;

		if (buttons == (MK_LBUTTON|MK_CONTROL) )
		{
			Sys_Printf ("Shear dragging face\n");
			Brush_SelectFaceForDragging (t.brush, t.face, true);
		}
		else if (buttons == (MK_LBUTTON|MK_CONTROL|MK_SHIFT) )
		{
			Sys_Printf ("Sticky dragging brush\n");
			for (f=t.brush->brush_faces ; f ; f=f->next)
				Brush_SelectFaceForDragging (t.brush, f, false);
		}
		else
			Sys_Printf ("Dragging entire selection\n");
		
		return;
	}

	if (g_qeglobals.d_select_mode == sel_vertex || g_qeglobals.d_select_mode == sel_edge)
		return;

	//
	// check for side hit
	//
  // multiple brushes selected?
	if (selected_brushes.next->next != &selected_brushes)
  {
    // yes, special handling
    bool bOK = (g_PrefsDlg.m_bALTEdge) ? (static_cast<bool>(::GetAsyncKeyState(VK_MENU))) : true;
    if (bOK)
    {
	    for (brush_t* pBrush = selected_brushes.next ; pBrush != &selected_brushes ; pBrush = pBrush->next)
	    {
	      if (buttons & MK_CONTROL)
		      Brush_SideSelect (pBrush, origin, dir, true);
	      else
		      Brush_SideSelect (pBrush, origin, dir, false);
      }
    }
    else
    {
		  Sys_Printf ("press ALT to drag multiple edges\n");
		  return;
    }

  }
  else
  {
    // single select.. trying to drag fixed entities handle themselves and just move
	  if (buttons & MK_CONTROL)
		  Brush_SideSelect (selected_brushes.next, origin, dir, true);
	  else
		  Brush_SideSelect (selected_brushes.next, origin, dir, false);
  }
	Sys_Printf ("Side stretch\n");
	drag_ok = true;
}
Пример #17
0
/**
 * @brief Kills an actor (all that is needed is the local entity state set to STATE_DEAD).
 * @note Also changes the animation to a random death sequence and appends the dead animation
 * @param[in] msg The netchannel message
 * @param[in] self Pointer to the event structure that is currently executed
 */
void CL_ActorRevitalised (const eventRegister_t *self, struct dbuffer *msg)
{
	le_t *le, *floor;
	int entnum, state;

	NET_ReadFormat(msg, self->formatString, &entnum, &state);

	/* get les */
	le = LE_Get(entnum);

	if (!le)
		LE_NotFoundError(entnum);

	if (!LE_IsStunned(le) && !LE_IsLivingActor(le))
		Com_Error(ERR_DROP, "CL_ActorRevitalised: Can't revitalise, LE is not a dead or stunned actor");

	LE_Lock(le);

	/* link any floor container into the actor temp floor container */
	floor = LE_Find(ET_ITEM, le->pos);
	if (floor)
		FLOOR(le) = FLOOR(floor);

	le->state = state;

	/* play animation */
	LE_SetThink(le, LET_StartIdle);

	/* Print some info about the death or stun. */
	if (le->team == cls.team) {
		const character_t *chr = CL_ActorGetChr(le);
		if (chr) {
			char tmpbuf[128];
			Com_sprintf(tmpbuf, lengthof(tmpbuf), _("%s was revitalised\n"), chr->name);
			HUD_DisplayMessage(tmpbuf);
		}
	} else {
		switch (le->team) {
		case (TEAM_CIVILIAN):
			HUD_DisplayMessage(_("A civilian was revitalised.\n"));
			break;
		case (TEAM_ALIEN):
			HUD_DisplayMessage(_("An alien was revitalised.\n"));
			break;
		case (TEAM_PHALANX):
			HUD_DisplayMessage(_("A soldier was revitalised.\n"));
			break;
		default:
			HUD_DisplayMessage(va(_("A member of team %i was revitalised.\n"), le->team));
			break;
		}
	}

	VectorCopy(player_maxs, le->maxs);

	/* add team members to the actor list */
	CL_ActorAddToTeamList(le);

	/* update pathing as we maybe not can walk onto this actor anymore */
	CL_ActorConditionalMoveCalc(selActor);
	LE_Unlock(le);
}
Пример #18
0
void CGCam_SetPosition( vec3_t org )
{
	VectorCopy( org, client_camera.origin );
	VectorCopy( client_camera.origin, cg.refdef.vieworg );
}
Пример #19
0
/*
==============
BotAI
==============
*/
int BotAI(int client, float thinktime) {
	bot_state_t *bs;
	char buf[1024], *args;
	int j;

	trap_EA_ResetInput(client);
	//
	bs = botstates[client];
	if (!bs || !bs->inuse) {
		BotAI_Print(PRT_FATAL, "BotAI: client %d is not setup\n", client);
		return qfalse;
	}

	//retrieve the current client state
	BotAI_GetClientState( client, &bs->cur_ps );

	//retrieve any waiting server commands
	while( trap_BotGetServerCommand(client, buf, sizeof(buf)) ) {
		//have buf point to the command and args to the command arguments
		args = strchr( buf, ' ');
		if (!args) continue;
		*args++ = '\0';

		//remove color espace sequences from the arguments
		RemoveColorEscapeSequences( args );

		if (!Q_stricmp(buf, "cp "))
			{ /*CenterPrintf*/ }
		else if (!Q_stricmp(buf, "cs"))
			{ /*ConfigStringModified*/ }
		else if (!Q_stricmp(buf, "print")) {
			//remove first and last quote from the chat message
			memmove(args, args+1, strlen(args));
			args[strlen(args)-1] = '\0';
			trap_BotQueueConsoleMessage(bs->cs, CMS_NORMAL, args);
		}
		else if (!Q_stricmp(buf, "chat")) {
			//remove first and last quote from the chat message
			memmove(args, args+1, strlen(args));
			args[strlen(args)-1] = '\0';
			trap_BotQueueConsoleMessage(bs->cs, CMS_CHAT, args);
		}
		else if (!Q_stricmp(buf, "tchat")) {
			//remove first and last quote from the chat message
			memmove(args, args+1, strlen(args));
			args[strlen(args)-1] = '\0';
			trap_BotQueueConsoleMessage(bs->cs, CMS_CHAT, args);
		}
#ifdef MISSIONPACK
		else if (!Q_stricmp(buf, "vchat")) {
			BotVoiceChatCommand(bs, SAY_ALL, args);
		}
		else if (!Q_stricmp(buf, "vtchat")) {
			BotVoiceChatCommand(bs, SAY_TEAM, args);
		}
		else if (!Q_stricmp(buf, "vtell")) {
			BotVoiceChatCommand(bs, SAY_TELL, args);
		}
#endif
		else if (!Q_stricmp(buf, "scores"))
			{ /*FIXME: parse scores?*/ }
		else if (!Q_stricmp(buf, "clientLevelShot"))
			{ /*ignore*/ }
	}
	//add the delta angles to the bot's current view angles
	for (j = 0; j < 3; j++) {
		bs->viewangles[j] = AngleMod(bs->viewangles[j] + SHORT2ANGLE(bs->cur_ps.delta_angles[j]));
	}
	//increase the local time of the bot
	bs->ltime += thinktime;
	//
	bs->thinktime = thinktime;
	//origin of the bot
	VectorCopy(bs->cur_ps.origin, bs->origin);
	//eye coordinates of the bot
	VectorCopy(bs->cur_ps.origin, bs->eye);
	bs->eye[2] += bs->cur_ps.viewheight;
	//get the area the bot is in
	bs->areanum = BotPointAreaNum(bs->origin);
	//the real AI
	BotDeathmatchAI(bs, thinktime);
	//set the weapon selection every AI frame
	trap_EA_SelectWeapon(bs->client, bs->weaponnum);
	//subtract the delta angles
	for (j = 0; j < 3; j++) {
		bs->viewangles[j] = AngleMod(bs->viewangles[j] - SHORT2ANGLE(bs->cur_ps.delta_angles[j]));
	}
	//everything was ok
	return qtrue;
}
Пример #20
0
void CGCam_SetAngles( vec3_t ang )
{
	VectorCopy( ang, client_camera.angles );
	VectorCopy(client_camera.angles, cg.refdefViewAngles );
}
Пример #21
0
void
CL_ParseUpdate ( int bits )
{
	model_t		*model;
	qboolean	forcelink;
	entity_t	*ent;
	int		modnum, num, i;

	if (cls.signon == SIGNONS - 1)
	{	// first update is the final signon stage
		cls.signon = SIGNONS;
		CL_SignonReply ();
	}

	if (bits & U_MOREBITS)
	{
		i = MSG_ReadByte ();
		bits |= (i<<8);
	}

	if (bits & U_LONGENTITY)
		num = MSG_ReadShort ();
	else
		num = MSG_ReadByte ();

	ent = CL_EntityNum (num);

	for (i=0 ; i<16 ; i++)
		if (bits&(1<<i))
			bitcounts[i]++;

	if (ent->msgtime != cl.mtime[1])
		forcelink = true;	// no previous frame to lerp from
	else
		forcelink = false;

	ent->msgtime = cl.mtime[0];

	if (bits & U_MODEL)
	{
		modnum = MSG_ReadByte ();
		if (modnum >= MAX_MODELS)
			Host_Error ("CL_ParseModel: bad modnum");
	}
	else
		modnum = ent->baseline.modelindex;

	model = cl.model_precache[modnum];
	if (model != ent->model)
	{
		ent->model = model;
	// automatic animation (torches, etc) can be either all together
	// or randomized
		if (model)
		{
			if (model->synctype == ST_RAND)
				ent->syncbase = (float)(rand()&0x7fff) / 0x7fff;
			else
				ent->syncbase = 0.0;
		}
		else
			forcelink = true;	// hack to make null model players work
		if (num > 0 && num <= cl.maxclients)
			R_TranslatePlayerSkin (num - 1);
	}

	if (bits & U_FRAME)
		ent->frame = MSG_ReadByte ();
	else
		ent->frame = ent->baseline.frame;

	if (bits & U_COLORMAP)
		i = MSG_ReadByte();
	else
		i = ent->baseline.colormap;
	if (!i)
		ent->colormap = vid.colormap;
	else
	{
		if (i > cl.maxclients)
			Sys_Error ("i >= cl.maxclients");
		ent->colormap = cl.scores[i-1].translations;
	}

	{
		int	skin;

		if (bits & U_SKIN)
			skin = MSG_ReadByte();
		else
			skin = ent->baseline.skinnum;
		if (skin != ent->skinnum) {
			ent->skinnum = skin;
			if (num > 0 && num <= cl.maxclients)
				R_TranslatePlayerSkin (num - 1);
		}
	}

	if (bits & U_EFFECTS)
		ent->effects = MSG_ReadByte();
	else
		ent->effects = ent->baseline.effects;

// shift the known values for interpolation
	VectorCopy (ent->msg_origins[0], ent->msg_origins[1]);
	VectorCopy (ent->msg_angles[0], ent->msg_angles[1]);

	if (bits & U_ORIGIN1)
		ent->msg_origins[0][0] = MSG_ReadCoord ();
	else
		ent->msg_origins[0][0] = ent->baseline.origin[0];
	if (bits & U_ANGLE1)
		ent->msg_angles[0][0] = MSG_ReadAngle();
	else
		ent->msg_angles[0][0] = ent->baseline.angles[0];

	if (bits & U_ORIGIN2)
		ent->msg_origins[0][1] = MSG_ReadCoord ();
	else
		ent->msg_origins[0][1] = ent->baseline.origin[1];
	if (bits & U_ANGLE2)
		ent->msg_angles[0][1] = MSG_ReadAngle();
	else
		ent->msg_angles[0][1] = ent->baseline.angles[1];

	if (bits & U_ORIGIN3)
		ent->msg_origins[0][2] = MSG_ReadCoord ();
	else
		ent->msg_origins[0][2] = ent->baseline.origin[2];
	if (bits & U_ANGLE3)
		ent->msg_angles[0][2] = MSG_ReadAngle();
	else
		ent->msg_angles[0][2] = ent->baseline.angles[2];

	if ( bits & U_NOLERP )
		ent->forcelink = true;

	if ( forcelink )
	{	// didn't have an update last message
		VectorCopy (ent->msg_origins[0], ent->msg_origins[1]);
		VectorCopy (ent->msg_origins[0], ent->origin);
		VectorCopy (ent->msg_angles[0], ent->msg_angles[1]);
		VectorCopy (ent->msg_angles[0], ent->angles);
		ent->forcelink = true;
	}
}
Пример #22
0
//void CGCam_Track( char *trackName, float speed, float duration )
void CGCam_Track( const char *trackName, float speed, float initLerp )
{
	gentity_t	*trackEnt = NULL;

	CGCam_TrackDisable();

	if(Q_stricmp("none", (char *)trackName) == 0)
	{//turn off tracking
		return;
	}

	//NOTE: if this interrupts a move before it's done, need to copy the cg.refdef.vieworg to the camera.origin!
	//This will find a path_corner now, not a misc_camera_track
	trackEnt = G_Find(NULL, FOFS(targetname), (char *)trackName);

	if ( !trackEnt )
	{
		gi.Printf(S_COLOR_RED"ERROR: %s camera track target not found\n", trackName);
		return;
	}

	client_camera.info_state |= CAMERA_TRACKING;
	client_camera.info_state &= ~CAMERA_MOVING;

	client_camera.trackEntNum = trackEnt->s.number;
	client_camera.initSpeed = speed/10.0f;
	client_camera.speed = speed;
	client_camera.nextTrackEntUpdateTime = cg.time;

	if ( initLerp )
	{
		client_camera.trackInitLerp = qtrue;
	}
	else
	{
		client_camera.trackInitLerp = qfalse;
	}
	/*
	if ( client_camera.info_state & CAMERA_FOLLOWING )
	{//Used to snap angles?  Do what...?
	}
	*/

	//Set a moveDir
	VectorSubtract( trackEnt->currentOrigin, client_camera.origin, client_camera.moveDir );

	if ( !client_camera.trackInitLerp )
	{//want to snap to first position
		//Snap to trackEnt's origin
		VectorCopy( trackEnt->currentOrigin, client_camera.origin );

		//Set new moveDir if trackEnt has a next path_corner
		//Possible that track has no next point, in which case we won't be moving anyway
		if ( trackEnt->target && trackEnt->target[0] )
		{
			gentity_t *newTrackEnt = G_Find( NULL, FOFS(targetname), trackEnt->target );
			if ( newTrackEnt )
			{
				VectorSubtract( newTrackEnt->currentOrigin, client_camera.origin, client_camera.moveDir );
			}
		}
	}

	VectorNormalize( client_camera.moveDir );
}
Пример #23
0
static bool BotChooseNBGItem( int goalstate, const vec3_t origin, const int* inventory, int travelflags,
	const bot_goal_t* ltg, float maxtime ) {
	bot_goalstate_t* gs = BotGoalStateFromHandle( goalstate );
	if ( !gs ) {
		return false;
	}
	if ( !gs->itemweightconfig ) {
		return false;
	}
	//get the area the bot is in
	int areanum = BotReachabilityArea( origin, gs->client );
	//if the bot is in solid or if the area the bot is in has no reachability links
	if ( !areanum || !AAS_AreaReachability( areanum ) ) {
		//use the last valid area the bot was in
		areanum = gs->lastreachabilityarea;
	}
	//remember the last area with reachabilities the bot was in
	gs->lastreachabilityarea = areanum;
	//if still in solid
	if ( !areanum ) {
		return false;
	}

	int ltg_time;
	if ( ltg ) {
		ltg_time = AAS_AreaTravelTimeToGoalArea( areanum, origin, ltg->areanum, travelflags );
	} else {
		ltg_time = 99999;
	}
	//the item configuration
	itemconfig_t* ic = itemconfig;
	if ( !itemconfig ) {
		return false;
	}
	//best weight and item so far
	float bestweight = 0;
	levelitem_t* bestitem = NULL;
	//go through the items in the level
	for ( levelitem_t* li = levelitems; li; li = li->next ) {
		if ( GGameType & GAME_ET ) {
			if ( g_singleplayer ) {
				if ( li->flags & IFL_NOTSINGLE ) {
					continue;
				}
			}
		} else {
			if ( g_gametype == Q3GT_SINGLE_PLAYER ) {
				if ( li->flags & IFL_NOTSINGLE ) {
					continue;
				}
			} else if ( g_gametype >= Q3GT_TEAM ) {
				if ( li->flags & IFL_NOTTEAM ) {
					continue;
				}
			} else {
				if ( li->flags & IFL_NOTFREE ) {
					continue;
				}
			}
		}
		if ( GGameType & GAME_Quake3 && li->flags & IFL_NOTBOT ) {
			continue;
		}
		//if the item is in a possible goal area
		if ( !li->goalareanum ) {
			continue;
		}
		//FIXME: is this a good thing? added this for items that never spawned into the game (f.i. CTF flags in obelisk)
		if ( GGameType & GAME_Quake3 && !li->entitynum && !( li->flags & IFL_ROAM ) ) {
			continue;
		}
		//get the fuzzy weight function for this item
		iteminfo_t* iteminfo = &ic->iteminfo[ li->iteminfo ];
		int weightnum = gs->itemweightindex[ iteminfo->number ];
		if ( weightnum < 0 ) {
			continue;
		}
		//if this goal is in the avoid goals
		if ( !( GGameType & GAME_Quake3 ) && BotAvoidGoalTime( goalstate, li->number ) > 0 ) {
			continue;
		}

		float weight = FuzzyWeightUndecided( inventory, gs->itemweightconfig, weightnum );
		//HACK: to make dropped items more attractive
		if ( li->timeout ) {
			weight += GGameType & GAME_Quake3 ? droppedweight->value : 1000;
		}
		//use weight scale for item_botroam
		if ( GGameType & GAME_Quake3 && li->flags & IFL_ROAM ) {
			weight *= li->weight;
		}

		if ( weight > 0 ) {
			//get the travel time towards the goal area
			int t = AAS_AreaTravelTimeToGoalArea( areanum, origin, li->goalareanum, travelflags );
			//if the goal is reachable
			if ( t > 0 && t < maxtime ) {
				if ( GGameType & GAME_Quake3 ) {
					//if this item won't respawn before we get there
					float avoidtime = BotAvoidGoalTime( goalstate, li->number );
					if ( avoidtime - t * 0.009 > 0 ) {
						continue;
					}
				}

				weight /= ( float )t * TRAVELTIME_SCALE;

				if ( weight > bestweight ) {
					t = 0;
					if ( ltg && !li->timeout ) {
						//get the travel time from the goal to the long term goal
						t = AAS_AreaTravelTimeToGoalArea( li->goalareanum, li->goalorigin, ltg->areanum, travelflags );
					}
					//if the travel back is possible and doesn't take too long
					if ( t <= ltg_time ) {
						bestweight = weight;
						bestitem = li;
					}
				}
			}
		}
	}
	//if no goal item found
	if ( !bestitem ) {
		return false;
	}
	//create a bot goal for this item
	bot_goal_t goal;
	Com_Memset( &goal, 0, sizeof ( bot_goal_t ) );
	iteminfo_t* iteminfo = &ic->iteminfo[ bestitem->iteminfo ];
	VectorCopy( bestitem->goalorigin, goal.origin );
	VectorCopy( iteminfo->mins, goal.mins );
	VectorCopy( iteminfo->maxs, goal.maxs );
	goal.areanum = bestitem->goalareanum;
	goal.entitynum = bestitem->entitynum;
	goal.number = bestitem->number;
	goal.flags = GFL_ITEM;
	if ( GGameType & GAME_Quake3 ) {
		if ( bestitem->timeout ) {
			goal.flags |= GFL_DROPPED;
		}
		if ( bestitem->flags & IFL_ROAM ) {
			goal.flags |= GFL_ROAM;
		}
	}
	goal.iteminfo = bestitem->iteminfo;
	float avoidtime;
	if ( GGameType & GAME_Quake3 ) {
		//if it's a dropped item
		if ( bestitem->timeout ) {
			avoidtime = AVOID_DROPPED_TIME;
		} else {
			avoidtime = iteminfo->respawntime;
			if ( !avoidtime ) {
				avoidtime = AVOID_DEFAULT_TIME;
			}
			if ( avoidtime < AVOID_MINIMUM_TIME ) {
				avoidtime = AVOID_MINIMUM_TIME;
			}
		}
	} else {
		avoidtime = iteminfo->respawntime * 0.5;
		if ( avoidtime < 10 ) {
			avoidtime = AVOID_DEFAULT_TIME;
		}
		//if it's a dropped item
		if ( bestitem->timeout ) {
			avoidtime = AVOID_DROPPED_TIME_WOLF;
		}
	}
	//add the chosen goal to the goals to avoid for a while
	BotAddToAvoidGoals( gs, bestitem->number, avoidtime );
	//push the goal on the stack
	BotPushGoal( goalstate, &goal, sizeof ( goal ) );
	return true;
}
Пример #24
0
void CGCam_FollowUpdate ( void )
{
	vec3_t		center, dir, cameraAngles, vec, focus[MAX_CAMERA_GROUP_SUBJECTS];//No more than 16 subjects in a cameraGroup
	gentity_t	*from = NULL;
	centity_t	*fromCent = NULL;
	int			num_subjects = 0, i;
	
	if ( client_camera.cameraGroup && client_camera.cameraGroup[0] )
	{
		//Stay centered in my cameraGroup, if I have one
		while( NULL != (from = G_Find(from, FOFS(cameraGroup), client_camera.cameraGroup)))
		{
			/*
			if ( from->s.number == client_camera.aimEntNum )
			{//This is the misc_camera_focus, we'll be removing this ent altogether eventually
				continue;
			}
			*/

			if ( num_subjects >= MAX_CAMERA_GROUP_SUBJECTS )
			{
				gi.Printf(S_COLOR_RED"ERROR: Too many subjects in shot composition %s", client_camera.cameraGroup);
				break;
			}

			fromCent = &cg_entities[from->s.number];
			if ( !fromCent )
			{
				continue;
			}

			if ( from->s.pos.trType == TR_INTERPOLATE )
			{//use interpolated origin?
				VectorCopy(fromCent->lerpOrigin, focus[num_subjects]);
			}
			else
			{
				VectorCopy(from->currentOrigin, focus[num_subjects]);
			}
			//FIXME: make a list here of their s.numbers instead so we can do other stuff with the list below
			if ( from->client )
			{//Track to their eyes - FIXME: maybe go off a tag?
				//FIXME: 
				//Based on FOV and distance to subject from camera, pick the point that
				//keeps eyes 3/4 up from bottom of screen... what about bars?
				focus[num_subjects][2] += from->client->ps.viewheight;
			}
			num_subjects++;
		}

		if ( !num_subjects )	// Bad cameragroup 
		{
			gi.Printf(S_COLOR_RED"ERROR: Camera Focus unable to locate cameragroup: %s\n", client_camera.cameraGroup);
			return;
		}

		//Now average all points
		VectorCopy( focus[0], center );
		for( i = 1; i < num_subjects; i++ )
		{
			VectorAdd( focus[i], center, center );
		}
		VectorScale( center, 1.0f/((float)num_subjects), center );
	}
	else
	{
		return;
	}

	//Need to set a speed to keep a distance from
	//the subject- fixme: only do this if have a distance
	//set
	VectorSubtract( client_camera.subjectPos, center, vec );
	client_camera.subjectSpeed = VectorLengthSquared( vec ) * 100.0f / cg.frametime;

	VectorCopy( center, client_camera.subjectPos );

	VectorSubtract( center, cg.refdef.vieworg, dir );//can't use client_camera.origin because it's not updated until the end of the move.

	//Get desired angle
	vectoangles(dir, cameraAngles);
	
	if ( client_camera.followInitLerp )
	{//Lerping
		for( i = 0; i < 3; i++ )
		{
			cameraAngles[i] = LerpAngle( client_camera.angles[i], cameraAngles[i], cg.frametime/100.0f * client_camera.followSpeed/100.f );
		}
	}
	else
	{//Snapping, should do this first time if follow_lerp_to_start_duration is zero
		//will lerp from this point on
		client_camera.followInitLerp = qtrue;
		//So tracker doesn't move right away thinking the first angle change
		//is the subject moving... FIXME: shouldn't set this until lerp done OR snapped?
		client_camera.subjectSpeed = 0;
	}

	//Point camera to lerp angles
	VectorCopy( cameraAngles, client_camera.angles );
}
Пример #25
0
void BotInitLevelItems() {
	//initialize the map locations and camp spots
	BotInitInfoEntities();

	//initialize the level item heap
	InitLevelItemHeap();
	levelitems = NULL;
	numlevelitems = 0;

	itemconfig_t* ic = itemconfig;
	if ( !ic ) {
		return;
	}

	//if there's no AAS file loaded
	if ( !AAS_Loaded() ) {
		return;
	}

	//update the modelindexes of the item info
	for ( int i = 0; i < ic->numiteminfo; i++ ) {
		if ( !ic->iteminfo[ i ].modelindex ) {
			Log_Write( "item %s has modelindex 0", ic->iteminfo[ i ].classname );
		}
	}

	for ( int ent = AAS_NextBSPEntity( 0 ); ent; ent = AAS_NextBSPEntity( ent ) ) {
		char classname[ MAX_EPAIRKEY ];
		if ( !AAS_ValueForBSPEpairKey( ent, "classname", classname, MAX_EPAIRKEY ) ) {
			continue;
		}

		int spawnflags = 0;
		AAS_IntForBSPEpairKey( ent, "spawnflags", &spawnflags );

		int i;
		for ( i = 0; i < ic->numiteminfo; i++ ) {
			if ( !String::Cmp( classname, ic->iteminfo[ i ].classname ) ) {
				break;
			}
		}
		if ( i >= ic->numiteminfo ) {
			Log_Write( "entity %s unknown item\r\n", classname );
			continue;
		}
		//get the origin of the item
		vec3_t origin;
		if ( !AAS_VectorForBSPEpairKey( ent, "origin", origin ) ) {
			BotImport_Print( PRT_ERROR, "item %s without origin\n", classname );
			continue;
		}

		int goalareanum = 0;
		//if it is a floating item
		if ( spawnflags & 1 ) {
			if ( !( GGameType & GAME_Quake3 ) ) {
				continue;
			}
			//if the item is not floating in water
			if ( !( AAS_PointContents( origin ) & BSP46CONTENTS_WATER ) ) {
				vec3_t end;
				VectorCopy( origin, end );
				end[ 2 ] -= 32;
				bsp_trace_t trace = AAS_Trace( origin, ic->iteminfo[ i ].mins, ic->iteminfo[ i ].maxs, end, -1, BSP46CONTENTS_SOLID | BSP46CONTENTS_PLAYERCLIP );
				//if the item not near the ground
				if ( trace.fraction >= 1 ) {
					//if the item is not reachable from a jumppad
					goalareanum = AAS_BestReachableFromJumpPadArea( origin, ic->iteminfo[ i ].mins, ic->iteminfo[ i ].maxs );
					Log_Write( "item %s reachable from jumppad area %d\r\n", ic->iteminfo[ i ].classname, goalareanum );
					if ( !goalareanum ) {
						continue;
					}
				}
			}
		}

		levelitem_t* li = AllocLevelItem();
		if ( !li ) {
			return;
		}

		li->number = ++numlevelitems;
		li->timeout = 0;
		li->entitynum = 0;

		li->flags = 0;
		int value;
		AAS_IntForBSPEpairKey( ent, "notfree", &value );
		if ( value ) {
			li->flags |= IFL_NOTFREE;
		}
		AAS_IntForBSPEpairKey( ent, "notteam", &value );
		if ( value ) {
			li->flags |= IFL_NOTTEAM;
		}
		AAS_IntForBSPEpairKey( ent, "notsingle", &value );
		if ( value ) {
			li->flags |= IFL_NOTSINGLE;
		}
		if ( GGameType & GAME_Quake3 ) {
			AAS_IntForBSPEpairKey( ent, "notbot", &value );
			if ( value ) {
				li->flags |= IFL_NOTBOT;
			}
			if ( !String::Cmp( classname, "item_botroam" ) ) {
				li->flags |= IFL_ROAM;
				AAS_FloatForBSPEpairKey( ent, "weight", &li->weight );
			}
		}
		//if not a stationary item
		if ( !( spawnflags & 1 ) ) {
			if ( !AAS_DropToFloor( origin, ic->iteminfo[ i ].mins, ic->iteminfo[ i ].maxs ) ) {
				BotImport_Print( PRT_MESSAGE, "%s in solid at (%1.1f %1.1f %1.1f)\n",
					classname, origin[ 0 ], origin[ 1 ], origin[ 2 ] );
			}
		}
		//item info of the level item
		li->iteminfo = i;
		//origin of the item
		VectorCopy( origin, li->origin );

		if ( goalareanum ) {
			li->goalareanum = goalareanum;
			VectorCopy( origin, li->goalorigin );
		} else {
			//get the item goal area and goal origin
			li->goalareanum = AAS_BestReachableArea( origin,
				ic->iteminfo[ i ].mins, ic->iteminfo[ i ].maxs,
				li->goalorigin );
			if ( !li->goalareanum ) {
				BotImport_Print( PRT_MESSAGE, "%s not reachable for bots at (%1.1f %1.1f %1.1f)\n",
					classname, origin[ 0 ], origin[ 1 ], origin[ 2 ] );
			}
		}

		AddLevelItemToList( li );
	}
	BotImport_Print( PRT_MESSAGE, "found %d level items\n", numlevelitems );
}
Пример #26
0
void CGCam_TrackEntUpdate ( void )
{//FIXME: only do every 100 ms
	gentity_t	*trackEnt = NULL;
	gentity_t	*newTrackEnt = NULL;
	qboolean	reached = qfalse;
	vec3_t		vec;
	float		dist;

	if ( client_camera.trackEntNum >= 0 && client_camera.trackEntNum < ENTITYNUM_WORLD )
	{//We're already heading to a path_corner
		trackEnt = &g_entities[client_camera.trackEntNum];
		VectorSubtract( trackEnt->currentOrigin, client_camera.origin, vec );
		dist = VectorLengthSquared( vec );
		if ( dist < 256 )//16 squared
		{//FIXME: who should be doing the using here?
			G_UseTargets( trackEnt, trackEnt );
			reached = qtrue;
		}
	}
	
	if ( trackEnt && reached )
	{
		
		if ( trackEnt->target && trackEnt->target[0] )
		{//Find our next path_corner
			newTrackEnt = G_Find( NULL, FOFS(targetname), trackEnt->target );
			if ( newTrackEnt )
			{
				if ( newTrackEnt->radius < 0 )
				{//Don't bother trying to maintain a radius
					client_camera.distance = 0;
					client_camera.speed = client_camera.initSpeed;
				}
				else if ( newTrackEnt->radius > 0 )
				{
					client_camera.distance = newTrackEnt->radius;
				}

				if ( newTrackEnt->speed < 0 )
				{//go back to our default speed
					client_camera.speed = client_camera.initSpeed;
				}
				else if ( newTrackEnt->speed > 0 )
				{
					client_camera.speed = newTrackEnt->speed/10.0f;
				}
			}
		}
		else
		{//stop thinking if this is the last one
			CGCam_TrackDisable();
		}
	}

	if ( newTrackEnt )
	{//Update will lerp this
		client_camera.info_state |= CAMERA_TRACKING; 
		client_camera.trackEntNum = newTrackEnt->s.number; 
		VectorCopy( newTrackEnt->currentOrigin, client_camera.trackToOrg );
	}

	client_camera.nextTrackEntUpdateTime = cg.time + 100;
}
Пример #27
0
/*
============
G_TouchTriggersLerped

Find all trigger entities that ent's current position touches.
Spectators will only interact with teleporters.

This version checks at 6 unit steps between last and current origins
============
*/
void	G_TouchTriggersLerped( gentity_t *ent ) {
	int			i, num;
	float		dist, curDist = 0;
	gentity_t	*touch[MAX_GENTITIES], *hit;
	trace_t		trace;
	vec3_t		end, mins, maxs, diff;
	const vec3_t	range = { 40, 40, 52 };
	qboolean	touched[MAX_GENTITIES];
	qboolean	done = qfalse;

	if ( !ent->client ) {
		return;
	}

	// dead clients don't activate triggers!
	if ( ent->client->ps.stats[STAT_HEALTH] <= 0 ) {
		return;
	}

	VectorSubtract( ent->currentOrigin, ent->lastOrigin, diff );
	dist = VectorNormalize( diff );

	memset (touched, qfalse, sizeof(touched) );

	for ( curDist = 0; !done; curDist += (float)ent->maxs[1]/2.0f )
	{
		if ( curDist >= dist )
		{
			VectorCopy( ent->currentOrigin, end );
			done = qtrue;
		}
		else
		{
			VectorMA( ent->lastOrigin, curDist, diff, end );
		}
		VectorSubtract( end, range, mins );
		VectorAdd( end, range, maxs );

		num = gi.EntitiesInBox( mins, maxs, touch, MAX_GENTITIES );

		// can't use ent->absmin, because that has a one unit pad
		VectorAdd( end, ent->mins, mins );
		VectorAdd( end, ent->maxs, maxs );

		for ( i=0 ; i<num ; i++ ) {
			hit = touch[i];

			if ( (hit->e_TouchFunc == touchF_NULL) && (ent->e_TouchFunc == touchF_NULL) ) {
				continue;
			}
			if ( !( hit->contents & CONTENTS_TRIGGER ) ) {
				continue;
			}

			if ( touched[i] == qtrue ) {
				continue;//already touched this move
			}
			// use seperate code for determining if an item is picked up
			// so you don't have to actually contact its bounding box
			/*
			if ( hit->s.eType == ET_ITEM ) {
				if ( !BG_PlayerTouchesItem( &ent->client->ps, &hit->s, level.time ) ) {
					continue;
				}
			} else */
			{
				if ( !gi.EntityContact( mins, maxs, hit ) ) {
					continue;
				}
			}

			touched[i] = qtrue;

			memset( &trace, 0, sizeof(trace) );

			if ( hit->e_TouchFunc != touchF_NULL ) {
				GEntity_TouchFunc(hit, ent, &trace);
			}

			if ( ( ent->NPC != NULL ) && ( ent->e_TouchFunc != touchF_NULL ) ) {
				GEntity_TouchFunc( ent, hit, &trace );
			}
		}
	}
}
Пример #28
0
void CGCam_TrackUpdate ( void )
{
	vec3_t		goalVec, curVec, trackPos, vec;
	float		goalDist, dist;
	qboolean	slowDown = qfalse;

	if ( client_camera.nextTrackEntUpdateTime <= cg.time )
	{
		CGCam_TrackEntUpdate();
	}

	VectorSubtract( client_camera.trackToOrg, client_camera.origin, goalVec );
	goalDist = VectorNormalize( goalVec );
	if ( goalDist > 100 )
	{
		goalDist = 100;
	}
	else if ( goalDist < 10 )
	{
		goalDist = 10;
	}

	if ( client_camera.distance && client_camera.info_state & CAMERA_FOLLOWING )
	{
		float	adjust = 0.0f, desiredSpeed = 0.0f;
		float	dot;

		if ( !client_camera.distanceInitLerp )
		{
			VectorSubtract( client_camera.origin, client_camera.subjectPos, vec );
			VectorNormalize( vec );
			//FIXME: use client_camera.moveDir here?
			VectorMA( client_camera.subjectPos, client_camera.distance, vec, client_camera.origin );
			//Snap to first time only
			client_camera.distanceInitLerp = qtrue;
			return;
		}
		else if ( client_camera.subjectSpeed > 0.05f )
		{//Don't start moving until subject moves 
			VectorSubtract( client_camera.subjectPos, client_camera.origin, vec );
			dist = VectorNormalize(vec);
			dot = DotProduct(goalVec, vec);

			if ( dist > client_camera.distance )
			{//too far away
				if ( dot > 0 )
				{//Camera is moving toward the subject
					adjust = (dist - client_camera.distance);//Speed up
				}
				else if ( dot < 0 )
				{//Camera is moving away from the subject
					adjust = (dist - client_camera.distance) * -1.0f;//Slow down
				}
			}
			else if ( dist < client_camera.distance )
			{//too close
				if(dot > 0)
				{//Camera is moving toward the subject
					adjust = (client_camera.distance - dist) * -1.0f;//Slow down
				}
				else if(dot < 0)
				{//Camera is moving away from the subject
					adjust = (client_camera.distance - dist);//Speed up
				}
			}
			
			//Speed of the focus + our error
			//desiredSpeed = aimCent->gent->speed + (adjust * cg.frametime/100.0f);//cg.frameInterpolation);
			desiredSpeed = (adjust);// * cg.frametime/100.0f);//cg.frameInterpolation);
			
			//self->moveInfo.speed = desiredSpeed;
			
			//Don't change speeds faster than 10 every 10th of a second
			float	max_allowed_accel = MAX_ACCEL_PER_FRAME * (cg.frametime/100.0f);

			if ( !client_camera.subjectSpeed )
			{//full stop
				client_camera.speed = desiredSpeed;
			}
			else if ( client_camera.speed - desiredSpeed > max_allowed_accel )
			{//new speed much slower, slow down at max accel
				client_camera.speed -= max_allowed_accel;
			}
			else if ( desiredSpeed - client_camera.speed > max_allowed_accel )
			{//new speed much faster, speed up at max accel
				client_camera.speed += max_allowed_accel;
			}
			else
			{//remember this speed
				client_camera.speed = desiredSpeed;
			}

			//Com_Printf("Speed: %4.2f (%4.2f)\n", self->moveInfo.speed, aimCent->gent->speed);
		}
	}
	else
	{
		//slowDown = qtrue;
	}
	

	//FIXME: this probably isn't right, round it out more
	VectorScale( goalVec, cg.frametime/100.0f, goalVec );
	VectorScale( client_camera.moveDir, (100.0f - cg.frametime)/100.0f, curVec );
	VectorAdd( goalVec, curVec, client_camera.moveDir );
	VectorNormalize( client_camera.moveDir );
	if(slowDown)
	{
		VectorMA( client_camera.origin, client_camera.speed * goalDist/100.0f * cg.frametime/100.0f, client_camera.moveDir, trackPos );
	}
	else
	{
		VectorMA( client_camera.origin, client_camera.speed * cg.frametime/100.0f , client_camera.moveDir, trackPos );
	}

	//FIXME: Implement
	//Need to find point on camera's path that is closest to the desired distance from subject
	//OR: Need to intelligently pick this desired distance based on framing...
	VectorCopy( trackPos, client_camera.origin );
}
Пример #29
0
/*
==================
RB_AddFlare

This is called at surface tesselation time
==================
*/
void RB_AddFlare( void *surface, int fogNum, vec3_t point, vec3_t color, vec3_t normal ) {
	int				i;
	flare_t			*f;
	vec3_t			local;
	float			d = 1;
	vec4_t			eye, clip, normalized, window;

	backEnd.pc.c_flareAdds++;

	if(normal && (normal[0] || normal[1] || normal[2]))
	{
		VectorSubtract( backEnd.viewParms.or.origin, point, local );
		VectorNormalizeFast(local);
		d = DotProduct(local, normal);

		// If the viewer is behind the flare don't add it.
		if(d < 0)
			return;
	}

	// if the point is off the screen, don't bother adding it
	// calculate screen coordinates and depth
	R_TransformModelToClip( point, backEnd.or.modelMatrix, 
		backEnd.viewParms.projectionMatrix, eye, clip );

	// check to see if the point is completely off screen
	for ( i = 0 ; i < 3 ; i++ ) {
		if ( clip[i] >= clip[3] || clip[i] <= -clip[3] ) {
			return;
		}
	}

	R_TransformClipToWindow( clip, &backEnd.viewParms, normalized, window );

	if ( window[0] < 0 || window[0] >= backEnd.viewParms.viewportWidth
		|| window[1] < 0 || window[1] >= backEnd.viewParms.viewportHeight ) {
		return;	// shouldn't happen, since we check the clip[] above, except for FP rounding
	}

	// see if a flare with a matching surface, scene, and view exists
	for ( f = r_activeFlares ; f ; f = f->next ) {
		if ( f->surface == surface && f->frameSceneNum == backEnd.viewParms.frameSceneNum
			&& f->inPortal == backEnd.viewParms.isPortal ) {
			break;
		}
	}

	// allocate a new one
	if (!f ) {
		if ( !r_inactiveFlares ) {
			// the list is completely full
			return;
		}
		f = r_inactiveFlares;
		r_inactiveFlares = r_inactiveFlares->next;
		f->next = r_activeFlares;
		r_activeFlares = f;

		f->surface = surface;
		f->frameSceneNum = backEnd.viewParms.frameSceneNum;
		f->inPortal = backEnd.viewParms.isPortal;
		f->addedFrame = -1;
	}

	if ( f->addedFrame != backEnd.viewParms.frameCount - 1 ) {
		f->visible = qfalse;
		f->fadeTime = backEnd.refdef.time - 2000;
	}

	f->addedFrame = backEnd.viewParms.frameCount;
	f->fogNum = fogNum;

	VectorCopy(point, f->origin);
	VectorCopy( color, f->color );

	// fade the intensity of the flare down as the
	// light surface turns away from the viewer
	VectorScale( f->color, d, f->color ); 

	// save info needed to test
	f->windowX = backEnd.viewParms.viewportX + window[0];
	f->windowY = backEnd.viewParms.viewportY + window[1];

	f->eyeZ = eye[2];
}
Пример #30
0
/*
===============
UI_PlayerInfo_SetInfo
===============
*/
void UI_PlayerInfo_SetInfo( playerInfo_t *pi, int legsAnim, int torsoAnim, vec3_t viewAngles, vec3_t moveAngles, weapon_t weaponNumber, qboolean chat ) {
	int			currentAnim;
	weapon_t	weaponNum;
	int			c;

	pi->chat = chat;

	c = (int)trap_Cvar_VariableValue( "color1" );
 
	VectorClear( pi->color1 );

	if( c < 1 || c > 7 ) {
		VectorSet( pi->color1, 1, 1, 1 );
	}
	else {
		if( c & 1 ) {
			pi->color1[2] = 1.0f;
		}

		if( c & 2 ) {
			pi->color1[1] = 1.0f;
		}

		if( c & 4 ) {
			pi->color1[0] = 1.0f;
		}
	}

	pi->c1RGBA[0] = 255 * pi->color1[0];
	pi->c1RGBA[1] = 255 * pi->color1[1];
	pi->c1RGBA[2] = 255 * pi->color1[2];
	pi->c1RGBA[3] = 255;

	// view angles
	VectorCopy( viewAngles, pi->viewAngles );

	// move angles
	VectorCopy( moveAngles, pi->moveAngles );

	if ( pi->newModel ) {
		pi->newModel = qfalse;

		jumpHeight = 0;
		pi->pendingLegsAnim = 0;
		UI_ForceLegsAnim( pi, legsAnim );
		pi->legs.yawAngle = viewAngles[YAW];
		pi->legs.yawing = qfalse;

		pi->pendingTorsoAnim = 0;
		UI_ForceTorsoAnim( pi, torsoAnim );
		pi->torso.yawAngle = viewAngles[YAW];
		pi->torso.yawing = qfalse;

		if ( weaponNumber != WP_NUM_WEAPONS ) {
			pi->weapon = weaponNumber;
			pi->currentWeapon = weaponNumber;
			pi->lastWeapon = weaponNumber;
			pi->pendingWeapon = WP_NUM_WEAPONS;
			pi->weaponTimer = 0;
			UI_PlayerInfo_SetWeapon( pi, pi->weapon );
		}

		return;
	}

	// weapon
	if ( weaponNumber == WP_NUM_WEAPONS ) {
		pi->pendingWeapon = WP_NUM_WEAPONS;
		pi->weaponTimer = 0;
	}
	else if ( weaponNumber != WP_NONE ) {
		pi->pendingWeapon = weaponNumber;
		pi->weaponTimer = dp_realtime + UI_TIMER_WEAPON_DELAY;
	}
	weaponNum = pi->lastWeapon;
	pi->weapon = weaponNum;

	if ( torsoAnim == BOTH_DEATH1 || legsAnim == BOTH_DEATH1 ) {
		torsoAnim = legsAnim = BOTH_DEATH1;
		pi->weapon = pi->currentWeapon = WP_NONE;
		UI_PlayerInfo_SetWeapon( pi, pi->weapon );

		jumpHeight = 0;
		pi->pendingLegsAnim = 0;
		UI_ForceLegsAnim( pi, legsAnim );

		pi->pendingTorsoAnim = 0;
		UI_ForceTorsoAnim( pi, torsoAnim );

		return;
	}

	// leg animation
	currentAnim = pi->legsAnim & ~ANIM_TOGGLEBIT;
	if ( legsAnim != LEGS_JUMP && ( currentAnim == LEGS_JUMP || currentAnim == LEGS_LAND ) ) {
		pi->pendingLegsAnim = legsAnim;
	}
	else if ( legsAnim != currentAnim ) {
		jumpHeight = 0;
		pi->pendingLegsAnim = 0;
		UI_ForceLegsAnim( pi, legsAnim );
	}

	// torso animation
	if ( torsoAnim == TORSO_STAND || torsoAnim == TORSO_STAND2 ) {
		if ( weaponNum == WP_NONE || weaponNum == WP_GAUNTLET ) {
			torsoAnim = TORSO_STAND2;
		}
		else {
			torsoAnim = TORSO_STAND;
		}
	}

	if ( torsoAnim == TORSO_ATTACK || torsoAnim == TORSO_ATTACK2 ) {
		if ( weaponNum == WP_NONE || weaponNum == WP_GAUNTLET ) {
			torsoAnim = TORSO_ATTACK2;
		}
		else {
			torsoAnim = TORSO_ATTACK;
		}
		pi->muzzleFlashTime = dp_realtime + UI_TIMER_MUZZLE_FLASH;
		//FIXME play firing sound here
	}

	currentAnim = pi->torsoAnim & ~ANIM_TOGGLEBIT;

	if ( weaponNum != pi->currentWeapon || currentAnim == TORSO_RAISE || currentAnim == TORSO_DROP ) {
		pi->pendingTorsoAnim = torsoAnim;
	}
	else if ( ( currentAnim == TORSO_GESTURE || currentAnim == TORSO_ATTACK ) && ( torsoAnim != currentAnim ) ) {
		pi->pendingTorsoAnim = torsoAnim;
	}
	else if ( torsoAnim != currentAnim ) {
		pi->pendingTorsoAnim = 0;
		UI_ForceTorsoAnim( pi, torsoAnim );
	}
}