Exemple #1
0
/*
* Con_DrawInput
*
* The input line scrolls horizontally if typing goes beyond the right edge
*/
static void Con_DrawInput( int vislines )
{
    char draw_search_text[MAXCMDLINE*2+4];
    const char *text = key_lines[edit_line];
    int smallCharHeight = SCR_strHeight( cls.fontSystemSmall );
    int text_y = vislines - 14 - smallCharHeight;
    const int left_margin = 8, right_margin = 8;
    int promptwidth = SCR_strWidth( "]", cls.fontSystemSmall, 1 );
    int cursorwidth = SCR_strWidth( "_", cls.fontSystemSmall, 1 );
    int input_width = viddef.width - left_margin - right_margin;
    int prewidth;	// width of input line before cursor

    if( cls.key_dest != key_console )
        return;

    if( search_text[0] ) {
        text = draw_search_text;
        Q_snprintfz( draw_search_text, sizeof( draw_search_text ), "%s : %s", key_lines[edit_line], search_text );
    }

    prewidth = SCR_strWidth( text, cls.fontSystemSmall, key_linepos );

    // don't let the cursor go beyond the left screen edge
    clamp_high( input_prestep, prewidth - promptwidth);
    // don't let it go beyond the right screen edge
    clamp_low( input_prestep, prewidth - ( input_width - cursorwidth ) );

    SCR_DrawClampString( left_margin - input_prestep,
                         text_y, text, left_margin, text_y,
                         viddef.width - right_margin, viddef.height, cls.fontSystemSmall, colorWhite );

    if( (int)( cls.realtime>>8 )&1 )
        SCR_DrawRawChar( left_margin + prewidth - input_prestep, text_y, '_',
                         cls.fontSystemSmall, colorWhite );
}
Exemple #2
0
/*
* source_setup
*/
static void source_setup( src_t *src, sfx_t *sfx, int priority, int entNum, int channel, float fvol, float attenuation )
{
	ALuint buffer;

	// Mark the SFX as used, and grab the raw AL buffer
	S_UseBuffer( sfx );
	buffer = S_GetALBuffer( sfx );

	clamp_low( attenuation, 0.0f );

	src->lastUse = trap_Milliseconds();
	src->sfx = sfx;
	src->priority = priority;
	src->entNum = entNum;
	src->channel = channel;
	src->fvol = fvol;
	src->attenuation = attenuation;
	src->isActive = qtrue;
	src->isLocked = qfalse;
	src->isLooping = qfalse;
	src->isTracking = qfalse;
	VectorClear( src->origin );
	VectorClear( src->velocity );

	qalSourcefv( src->source, AL_POSITION, vec3_origin );
	qalSourcefv( src->source, AL_VELOCITY, vec3_origin );
	qalSourcef( src->source, AL_GAIN, fvol * s_volume->value );
	qalSourcei( src->source, AL_SOURCE_RELATIVE, AL_FALSE );
	qalSourcei( src->source, AL_LOOPING, AL_FALSE );
	qalSourcei( src->source, AL_BUFFER, buffer );

	qalSourcef( src->source, AL_REFERENCE_DISTANCE, s_attenuation_refdistance );
	qalSourcef( src->source, AL_MAX_DISTANCE, s_attenuation_maxdistance );
	qalSourcef( src->source, AL_ROLLOFF_FACTOR, attenuation );
}
Exemple #3
0
void objectString_Release( asstring_t *obj )
{
	obj->asRefCount--;
	clamp_low( obj->asRefCount, 0 );

	if( !obj->asRefCount )
	{
		QAS_Free( obj->buffer );
		QAS_Free( obj );
	}
}
Exemple #4
0
/*
* SCR_DrawClampFillRect
* 
* Fills a scissored box of pixels with a single color
*/
void SCR_DrawClampFillRect( int x, int y, int w, int h, int xmin, int ymin, int xmax, int ymax, vec4_t color )
{
	int x2 = x + w;
	int y2 = y + h;

	if( ( xmax <= xmin ) || ( ymax <= ymin ) )
		return;

	clamp_low( x, xmin );
	clamp_low( y, ymin );
	clamp_high( x2, xmax );
	clamp_high( y2, ymax );

	w = x2 - x;
	h = y2 - y;
	if( ( w <= 0 ) || ( h <= 0 ) )
		return;

	re.DrawStretchPic( x, y, w, h, 0, 0, 1, 1, color, cls.whiteShader );
}
Exemple #5
0
void objectString_Release( asstring_t *obj )
{
    obj->asRefCount--;
    clamp_low( obj->asRefCount, 0 );

    if( !obj->asRefCount )
    {
        if( ( obj->size & CONST_STRING_BITFLAG ) == 0 )
        {
            delete[] obj->buffer;
            delete obj;
        }
        else
        {
            qbyte *rawmem = ( qbyte * )obj;
            delete[] rawmem;
        }
    }
}
Exemple #6
0
void RF_BeginFrame( float cameraSeparation, bool forceClear, bool forceVsync, bool uncappedFPS )
{
	int swapInterval;

	RF_CheckCvars();

	// run cinematic passes on shaders
	R_RunAllCinematics();

	if( uncappedFPS ) {
		rrf.adapter.maxfps = 0;
	}
	else {
		rrf.adapter.maxfps = r_maxfps->integer;
	}

	// take the frame the backend is not busy processing
	if( glConfig.multithreading ) {
		ri.Mutex_Lock( rrf.adapter.frameLock );
		if( rrf.lastFrameNum == rrf.adapter.frameNum )
			rrf.frameNum = (rrf.adapter.frameNum + 1) % 3;
		else
			rrf.frameNum = 3 - (rrf.adapter.frameNum + rrf.lastFrameNum);
		if( rrf.frameNum == 3 ) {
			rrf.frameNum = 1;
		}
		rrf.frame = rrf.frames[rrf.frameNum];
		ri.Mutex_Unlock( rrf.adapter.frameLock );
	}

	rrf.frame->Clear( rrf.frame );
	rrf.cameraSeparation = cameraSeparation;

	R_DataSync();

	swapInterval = r_swapinterval->integer || forceVsync ? 1 : 0;
	clamp_low( swapInterval, r_swapinterval_min->integer );

	rrf.frame->BeginFrame( rrf.frame, cameraSeparation, forceClear, swapInterval );
}
Exemple #7
0
void G_Items_RespawnByType( unsigned int typeMask, int item_tag, float delay )
{
	edict_t *ent;
	int msecs;

	for( ent = game.edicts + gs.maxclients + BODY_QUEUE_SIZE; ENTNUM( ent ) < game.maxentities; ent++ )
	{
		if( !ent->r.inuse || !ent->item )
			continue;

		if( typeMask && !( ent->item->type & typeMask ) )
			continue;

		if( ent->spawnflags & ( DROPPED_ITEM|DROPPED_PLAYER_ITEM ) )
		{
			G_FreeEdict( ent );
			continue;
		}

		if( !G_Gametype_CanRespawnItem( ent->item ) )
			continue;

		// if a tag is specified, ignore others of the same type
		if( item_tag > 0 && ( ent->item->tag != item_tag ) )
			continue;

		msecs = (int)( delay * 1000 );
		if( msecs >= 0 )
			clamp_low( msecs, 1 );

		// megahealth is different
		if( ( ent->style & HEALTH_TIMED ) && ent->r.owner )
			ent->r.owner = NULL;

		SetRespawn( ent, msecs );
	}
}
Exemple #8
0
//==========================================
// AI_PickShortRangeGoal
// Pick best goal based on importance and range. This function
// overrides the long range goal selection for items that
// are very close to the bot and are reachable.
//==========================================
static void AI_PickShortRangeGoal( edict_t *self )
{
	edict_t *bestGoal = NULL;
	float bestWeight = 0;
	nav_ents_t *goalEnt;
	const gsitem_t *item;
	bool canPickupItems;
	int i;

	if( !self->r.client || G_ISGHOSTING( self ) )
		return;

	if( self->ai->state_combat_timeout > level.time )
	{
		self->ai->shortRangeGoalTimeout = self->ai->state_combat_timeout;
		return;
	}

	if( self->ai->shortRangeGoalTimeout > level.time )
		return;

	canPickupItems = (self->r.client->ps.pmove.stats[PM_STAT_FEATURES] & PMFEAT_ITEMPICK) != 0 ? true : false;

	self->ai->shortRangeGoalTimeout = level.time + AI_SHORT_RANGE_GOAL_DELAY;

	self->movetarget = NULL;

	FOREACH_GOALENT( goalEnt )
	{
		float dist;

		i = goalEnt->id;
		if( !goalEnt->ent->r.inuse || goalEnt->ent->r.solid == SOLID_NOT )
			continue;

		if( goalEnt->ent->r.client )
			continue;

		if( self->ai->status.entityWeights[i] <= 0.0f )
			continue;

		item = goalEnt->ent->item;
		if( canPickupItems && item ) {
			if( !G_Gametype_CanPickUpItem( item ) || !( item->flags & ITFLAG_PICKABLE ) ) {
				continue;
			}
		}

		dist = DistanceFast( self->s.origin, goalEnt->ent->s.origin );
		if( goalEnt == self->ai->goalEnt ) {
			if( dist > AI_GOAL_SR_LR_RADIUS )
				continue;			
		}
		else {
			if( dist > AI_GOAL_SR_RADIUS )
				continue;
		}		

		clamp_low( dist, 0.01f );

		if( AI_ShortRangeReachable( self, goalEnt->ent->s.origin ) )
		{
			float weight;
			bool in_front = G_InFront( self, goalEnt->ent );

			// Long range goal gets top priority
			if( in_front && goalEnt == self->ai->goalEnt ) 
			{
				bestGoal = goalEnt->ent;
				break;
			}

			// get the one with the best weight
			weight = self->ai->status.entityWeights[i] / dist * (in_front ? 1.0f : 0.5f);
			if( weight > bestWeight )
			{
				bestWeight = weight;
				bestGoal = goalEnt->ent;
			}
		}
	}

	if( bestGoal )
	{
		self->movetarget = bestGoal;
		if( nav.debugMode && bot_showsrgoal->integer )
			G_PrintChasersf( self, "%i %s: selected a %s for SR goal.\n", level.framenum, self->ai->pers.netname, self->movetarget->classname );
	}
	else
	{
		// got nothing else to do so keep scanning
		self->ai->shortRangeGoalTimeout = level.time + AI_SHORT_RANGE_GOAL_DELAY_IDLE;
	}
}
Exemple #9
0
//==========================================
// AI_PickLongRangeGoal
//
// Evaluate the best long range goal and send the bot on
// its way. This is a good time waster, so use it sparingly.
// Do not call it for every think cycle.
//
// jal: I don't think there is any problem by calling it,
// now that we have stored the costs at the nav.costs table (I don't do it anyway)
//==========================================
void AI_PickLongRangeGoal( edict_t *self )
{
#define WEIGHT_MAXDISTANCE_FACTOR 20000.0f
#define COST_INFLUENCE	0.5f
	int i;
	float weight, bestWeight = 0.0;
	int current_node;
	float cost;
	float dist;
	nav_ents_t *goalEnt, *bestGoalEnt = NULL;

	AI_ClearGoal( self );

	if( G_ISGHOSTING( self ) )
		return;

	if( self->ai->longRangeGoalTimeout > level.time )
		return;

	if( !self->r.client->ps.pmove.stats[PM_STAT_MAXSPEED] ) {
		return;
	}

	self->ai->longRangeGoalTimeout = level.time + AI_LONG_RANGE_GOAL_DELAY + brandom( 0, 1000 );

	// look for a target
	current_node = AI_FindClosestReachableNode( self->s.origin, self, ( ( 1 + self->ai->nearest_node_tries ) * NODE_DENSITY ), NODE_ALL );
	self->ai->current_node = current_node;

	if( current_node == NODE_INVALID )
	{
		if( nav.debugMode && bot_showlrgoal->integer )
			G_PrintChasersf( self, "%s: LRGOAL: Closest node not found. Tries:%i\n", self->ai->pers.netname, self->ai->nearest_node_tries );

		self->ai->nearest_node_tries++; // extend search radius with each try
		return;
	}

	self->ai->nearest_node_tries = 0;

	// Run the list of potential goal entities
	FOREACH_GOALENT( goalEnt )
	{
		i = goalEnt->id;
		if( !goalEnt->ent )
			continue;

		if( !goalEnt->ent->r.inuse )
		{
			goalEnt->node = NODE_INVALID;
			continue;
		}

		if( goalEnt->ent->r.client )
		{
			if( G_ISGHOSTING( goalEnt->ent ) || goalEnt->ent->flags & (FL_NOTARGET|FL_BUSY) )
				goalEnt->node = NODE_INVALID;
			else
				goalEnt->node = AI_FindClosestReachableNode( goalEnt->ent->s.origin, goalEnt->ent, NODE_DENSITY, NODE_ALL );
		}

		if( goalEnt->ent->item )
		{
			if( !G_Gametype_CanPickUpItem( goalEnt->ent->item ) )
				continue;
		}

		if( goalEnt->node == NODE_INVALID )
			continue;

		weight = self->ai->status.entityWeights[i];

		if( weight <= 0.0f )
			continue;

		// don't try to find cost for too far away objects
		dist = DistanceFast( self->s.origin, goalEnt->ent->s.origin );
		if( dist > WEIGHT_MAXDISTANCE_FACTOR * weight/* || dist < AI_GOAL_SR_RADIUS*/ )
			continue;

		cost = AI_FindCost( current_node, goalEnt->node, self->ai->status.moveTypesMask );
		if( cost == NODE_INVALID )
			continue;

		cost -= brandom( 0, 2000 ); // allow random variations
		clamp_low( cost, 1 );
		weight = ( 1000 * weight ) / ( cost * COST_INFLUENCE ); // Check against cost of getting there

		if( weight > bestWeight )
		{
			bestWeight = weight;
			bestGoalEnt = goalEnt;
		}
	}

	if( bestGoalEnt )
	{
		self->ai->goalEnt = bestGoalEnt;
		AI_SetGoal( self, bestGoalEnt->node );

		if( self->ai->goalEnt != NULL && nav.debugMode && bot_showlrgoal->integer )
			G_PrintChasersf( self, "%s: selected a %s at node %d for LR goal. (weight %f)\n", self->ai->pers.netname, self->ai->goalEnt->ent->classname, self->ai->goalEnt->node, bestWeight );

		return;
	}

	if( nav.debugMode && bot_showlrgoal->integer )
		G_PrintChasersf( self, "%s: did not find a LR goal.\n", self->ai->pers.netname );

#undef WEIGHT_MAXDISTANCE_FACTOR
#undef COST_INFLUENCE
}
Exemple #10
0
/*
** CG_DrawChat
*/
void CG_DrawChat( cg_gamechat_t *chat, int x, int y, char *fontName, struct qfontface_s *font, int fontSize,
				  int width, int height, int padding_x, int padding_y, vec4_t backColor, struct shader_s *backShader ) {
	int i, j;
	int s, e, w;
	int utf_len;
	int l, total_lines, lines;
	int x_offset, y_offset;
	int font_height;
	int pass;
	int lastcolor;
	int message_mode;
	int wait_time, fade_time;
	const cg_gamemessage_t *msg;
	const char *text;
	char tstr[GAMECHAT_STRING_SIZE];
	vec4_t fontColor;
	bool chat_active = false;
	bool background_drawn = false;
	int corner_radius = 12 * cgs.vidHeight / 600;
	int background_y;
	int first_candidate;

	font_height = trap_SCR_FontHeight( font );
	message_mode = (int)trap_Cvar_Value( "con_messageMode" );
	chat_active = ( chat->lastMsgTime + GAMECHAT_WAIT_IN_TIME + GAMECHAT_FADE_IN_TIME > cg.realTime || message_mode );
	lines = 0;
	total_lines = /*!message_mode ? 0 : */ 1;

	if( chat_active ) {
		wait_time = GAMECHAT_WAIT_IN_TIME;
		fade_time = GAMECHAT_FADE_IN_TIME;
	} else {
		wait_time = GAMECHAT_WAIT_OUT_TIME;
		fade_time = GAMECHAT_FADE_OUT_TIME;
	}

	if( chat_active != chat->lastActive ) {
		// smooth fade ins and fade outs
		chat->lastActiveChangeTime = cg.realTime - ( 1.0 - chat->activeFrac ) * ( wait_time + fade_time );
	}

	if( cg.realTime >= chat->lastActiveChangeTime + wait_time ) {
		int time_diff, time_interval;

		time_diff = cg.realTime - ( chat->lastActiveChangeTime + wait_time );
		time_interval = fade_time;

		if( time_diff <= time_interval ) {
			chat->activeFrac = (float)time_diff / time_interval;
		} else {
			chat->activeFrac = 1;
		}
	} else {
		chat->activeFrac = 0;
	}

	if( chat_active ) {
		backColor[3] *= chat->activeFrac;
	} else {
		backColor[3] *= ( 1.0 - chat->activeFrac );
	}

	for( i = 0; i < GAMECHAT_STACK_SIZE; i++ ) {
		bool old_msg;

		l = chat->nextMsg - 1 - i;
		if( l < 0 ) {
			l = GAMECHAT_STACK_SIZE + l;
		}

		msg = &chat->messages[l];
		text = msg->text;
		old_msg = !message_mode && ( cg.realTime > msg->time + GAMECHAT_NOTIFY_TIME );

		if( !background_drawn && backColor[3] ) {
			if( old_msg ) {
				// keep the box being drawn for a while to prevent it from flickering
				// upon arrival of the possibly entered chat message
				if( !( !chat_active && cg.realTime <= chat->lastActiveChangeTime + 200 ) ) {
					break;
				}
			}

			background_y = y;
			trap_R_DrawStretchPic( x, background_y, width, height - corner_radius,
								   0.0f, 0.0f, 1.0f, 0.5f, backColor, backShader );
			background_y += height - corner_radius;

			if( trap_IN_IME_GetCandidates( NULL, 0, 10, NULL, &first_candidate ) ) {
				int candidates_height = ( first_candidate ? 3 : 5 ) * font_height;
				trap_R_DrawStretchPic( x, background_y, width, candidates_height,
									   0.0f, 0.5f, 1.0f, 0.5f, backColor, backShader );
				background_y += candidates_height;
			}

			trap_R_DrawStretchPic( x, background_y, corner_radius, corner_radius,
								   0.0f, 0.5f, 0.5f, 1.0f, backColor, backShader );
			trap_R_DrawStretchPic( x + corner_radius, background_y, width - corner_radius * 2, corner_radius,
								   0.5f, 0.5f, 0.5f, 1.0f, backColor, backShader );
			trap_R_DrawStretchPic( x + width - corner_radius, background_y, corner_radius, corner_radius,
								   0.5f, 0.5f, 1.0f, 1.0f, backColor, backShader );

			background_drawn = true;
		}

		// unless user is typing something, only display recent messages
		if( old_msg ) {
			break;
		}

		pass = 0;
		lines = 0;
		lastcolor = ColorIndex( COLOR_WHITE );

parse_string:
		l = 1;
		s = e = 0;
		while( 1 ) {
			int len;

			memset( tstr, 0, sizeof( tstr ) );

			// skip whitespaces at start
			for( ; text[s] == '\n' || Q_IsBreakingSpace( text + s ); s = Q_Utf8SyncPos( text, s + 1, UTF8SYNC_RIGHT ) ) ;

			// empty string
			if( !text[s] ) {
				break;
			}

			w = -1;
			len = trap_SCR_StrlenForWidth( text + s, font, width - padding_x * 2 );
			clamp_low( len, 1 );

			for( j = s; ( j < ( s + len ) ) && text[j] != '\0'; j += utf_len ) {
				utf_len = Q_Utf8SyncPos( text + j, 1, UTF8SYNC_RIGHT );
				memcpy( tstr + j - s, text + j, utf_len );

				if( text[j] == '\n' || Q_IsBreakingSpace( text + j ) ) {
					w = j; // last whitespace
				}
				if( text[j] == '\n' ) {
					break;
				}
			}
			e = j; // end

			// try to word avoid splitting words, unless no other options
			if( text[j] != '\0' && w > 0 ) {
				// stop at the last encountered whitespace
				j = w;
			}

			tstr[j - s] = '\0';

			Vector4Copy( color_table[lastcolor], fontColor );
			fontColor[3] = chat_active ? chat->activeFrac : 1.0 - chat->activeFrac;

			if( pass ) {
				// now actually render the line
				x_offset = padding_x;
				y_offset = height - padding_y - font_height - ( total_lines + lines - l ) * ( font_height + 2 );
				if( y_offset < padding_y ) {
					break;
				}

				trap_SCR_DrawClampString( x + x_offset, y + y_offset, tstr,
										  x + padding_x, y + padding_y, x - padding_x + width, y - padding_y + height, font, fontColor );

				l++;
			} else {
				// increase the lines counter
				lines++;
			}

			if( !text[j] ) {
				// fast path: we don't need two passes in case of one-liners..
				if( lines == 1 ) {
					x_offset = padding_x;
					y_offset = height - font_height - total_lines * ( font_height + 2 );
					if( y_offset < padding_y ) {
						break;
					}

					trap_SCR_DrawClampString( x + x_offset, y + y_offset, tstr,
											  x + padding_x, y + padding_y, x - padding_x + width, y - padding_y + height, font, fontColor );

					total_lines++;
					pass++;
				}
				break;
			}

			if( pass ) {
				// grab the last color token to carry it over to the next line
				lastcolor = Q_ColorStrLastColor( lastcolor, tstr, j - s );
			}

			s = j;
		}

		if( !pass ) {
			pass++;
			goto parse_string;
		} else {
			total_lines += lines;
		}
	}

	// let the engine know where the input line should be drawn
	trap_SCR_DrawChat( x + padding_x, y + height - padding_y - font_height, width - padding_x, font );

	chat->lastActive = chat_active;
}
Exemple #11
0
/*
* CG_AddLocalEntities
*/
void CG_AddLocalEntities( void )
{
#define FADEINFRAMES 2
	int f;
	lentity_t *le, *next, *hnode;
	entity_t *ent;
	float scale, frac, fade, time, scaleIn, fadeIn;
	float backlerp;
	vec3_t angles;

	time = cg.frameTime;
	backlerp = 1.0f - cg.lerpfrac;

	hnode = &cg_localents_headnode;
	for( le = hnode->next; le != hnode; le = next )
	{
		next = le->next;

		frac = ( cg.time - le->start ) * 0.01f;
		f = ( int )floor( frac );
		clamp_low( f, 0 );

		// it's time to DIE
		if( f >= le->frames - 1 )
		{
			le->type = LE_FREE;
			CG_FreeLocalEntity( le );
			continue;
		}

		if( le->frames > 1 )
		{
			scale = 1.0f - frac / ( le->frames - 1 );
			scale = bound( 0.0f, scale, 1.0f );
			fade = scale * 255.0f;

			// quick fade in, if time enough
			if( le->frames > FADEINFRAMES * 2 )
			{
				scaleIn = frac / (float)FADEINFRAMES;
				clamp( scaleIn, 0.0f, 1.0f );
				fadeIn = scaleIn * 255.0f;
			}
			else
				fadeIn = 255.0f;
		}
		else
		{
			scale = 1.0f;
			fade = 255.0f;
			fadeIn = 255.0f;
		}

		ent = &le->ent;

		if( le->light && scale )
			CG_AddLightToScene( ent->origin, le->light * scale, le->lightcolor[0], le->lightcolor[1], le->lightcolor[2], NULL );

		if( le->type == LE_LASER )
		{
			CG_QuickPolyBeam( ent->origin, ent->origin2, ent->radius, ent->customShader ); // wsw : jalfixme: missing the color (comes inside ent->skinnum)
			continue;
		}

		if( le->type == LE_DASH_SCALE )
		{
			if( f < 1 ) ent->scale = 0.2 * frac;
			else
			{
				VecToAngles( ent->axis[1], angles );
				ent->axis[1][1] += 0.005f *sin( DEG2RAD ( angles[YAW] ) ); //length
				ent->axis[1][0] += 0.005f *cos( DEG2RAD ( angles[YAW] ) ); //length
				ent->axis[0][1] += 0.008f *cos( DEG2RAD ( angles[YAW] ) ); //width
				ent->axis[0][0] -= 0.008f *sin( DEG2RAD ( angles[YAW] ) ); //width
				ent->axis[2][2] -= 0.052f;              //height

				if( ent->axis[2][2] <= 0 )
				{
					le->type = LE_FREE;
					CG_FreeLocalEntity( le );
				}
			}
		}
		if( le->type == LE_DASH_SCALE_2 )
		{
			if( f < 1 ) ent->scale = 0.25 * frac;
			else
			{
				VecToAngles( ent->axis[1], angles );
				ent->axis[1][1] += 0.005f *sin( DEG2RAD ( angles[YAW] ) ); //length
				ent->axis[1][0] += 0.005f *cos( DEG2RAD ( angles[YAW] ) ); //length
				ent->axis[0][1] += 0.008f *cos( DEG2RAD ( angles[YAW] ) ); //width
				ent->axis[0][0] -= 0.008f *sin( DEG2RAD ( angles[YAW] ) ); //width
				ent->axis[2][2] -= 0.018f;              //height

				ent->origin[1]  -= 0.6f *sin( DEG2RAD ( angles[YAW] ) ); //velocity
				ent->origin[0]  -= 0.6f *cos( DEG2RAD ( angles[YAW] ) ); //velocity

				if( ent->axis[2][2] <= 0 )
				{
					le->type = LE_FREE;
					CG_FreeLocalEntity( le );
				}
			}
		}
		if( le->type == LE_PUFF_SCALE )
		{
			if( frac < 1 ) ent->scale = 7.0f*frac;
			else ent->scale = 7.0f - 4.0f*( frac-1 );
			if( ent->scale < 0 )
			{
				le->type = LE_FREE;
				CG_FreeLocalEntity( le );
			}

		}
		if( le->type == LE_PUFF_SCALE_2 )
		{
			if( le->frames - f < 4 )
				ent->scale = 1.0f - 1.0f * ( frac - abs( 4-le->frames ) )/4;
		}
		if( le->type == LE_PUFF_SHRINK )
		{
			if( frac < 3 )
				ent->scale = 1.0f - 0.2f * frac/4;
			else
			{
				ent->scale = 0.8 - 0.8*( frac-3 )/3;
				VectorScale( le->velocity, 0.85f, le->velocity );
			}
		}

		if( le->type == LE_EXPLOSION_TRACER )
		{
			if( cg.time - ent->rotation > 10.0f )
			{
				ent->rotation = cg.time;
				if( ent->radius - 16*frac > 4 )
					CG_Explosion_Puff( ent->origin, ent->radius-16*frac, le->frames - f );
			}
		}

		switch( le->type )
		{
		case LE_NO_FADE:
			break;
		case LE_RGB_FADE:
			fade = min( fade, fadeIn );
			ent->shaderRGBA[0] = ( qbyte )( fade * le->color[0] );
			ent->shaderRGBA[1] = ( qbyte )( fade * le->color[1] );
			ent->shaderRGBA[2] = ( qbyte )( fade * le->color[2] );
			break;
		case LE_SCALE_ALPHA_FADE:
			fade = min( fade, fadeIn );
			ent->scale = 1.0f + 1.0f / scale;
			ent->scale = min( ent->scale, 5.0f );
			ent->shaderRGBA[3] = ( qbyte )( fade * le->color[3] );
			break;
		case LE_INVERSESCALE_ALPHA_FADE:
			fade = min( fade, fadeIn );
			ent->scale = scale + 0.1f;
			clamp( ent->scale, 0.1f, 1.0f );
			ent->shaderRGBA[3] = ( qbyte )( fade * le->color[3] );
			break;
		case LE_ALPHA_FADE:
			fade = min( fade, fadeIn );
			ent->shaderRGBA[3] = ( qbyte )( fade * le->color[3] );
			break;
		default:
			break;
		}

		ent->backlerp = backlerp;

		if( le->bounce )
		{
			trace_t	trace;
			vec3_t next_origin;

			VectorMA( ent->origin, time, le->velocity, next_origin );

			CG_Trace( &trace, ent->origin, debris_mins, debris_maxs, next_origin, 0, MASK_SOLID );

			// remove the particle when going out of the map
			if( ( trace.contents & CONTENTS_NODROP ) || ( trace.surfFlags & SURF_SKY ) )
			{
				le->frames = 0;
			}
			else if( trace.fraction != 1.0 ) // found solid
			{
				float dot;
				vec3_t vel;
				float xzyspeed;

				// Reflect velocity
				VectorSubtract( next_origin, ent->origin, vel );
				dot = -2 *DotProduct( vel, trace.plane.normal );
				VectorMA( vel, dot, trace.plane.normal, le->velocity );
				//put new origin in the impact point, but move it out a bit along the normal
				VectorMA( trace.endpos, 1, trace.plane.normal, ent->origin );

				//the entity has not speed enough. Stop checks
				xzyspeed = sqrt( le->velocity[0]*le->velocity[0] + le->velocity[1]*le->velocity[1] + le->velocity[2]*le->velocity[2] );
				if( xzyspeed * time < 1.0f )
				{
					trace_t traceground;
					vec3_t ground_origin;
					//see if we have ground
					VectorCopy( ent->origin, ground_origin );
					ground_origin[2] += ( debris_mins[2] - 4 );
					CG_Trace( &traceground, ent->origin, debris_mins, debris_maxs, ground_origin, 0, MASK_SOLID );
					if( traceground.fraction != 1.0 )
					{
						le->bounce = qfalse;
						VectorClear( le->velocity );
						VectorClear( le->accel );
						if( le->type == LE_EXPLOSION_TRACER )
						{               // blx
							le->type = LE_FREE;
							CG_FreeLocalEntity( le );
						}
					}
				}
				else
					VectorScale( le->velocity, le->bounce * time, le->velocity );
			}
			else
			{
				VectorCopy( ent->origin, ent->origin2 );
				VectorCopy( next_origin, ent->origin );
			}
		}
		else
		{
			VectorCopy( ent->origin, ent->origin2 );
			VectorMA( ent->origin, time, le->velocity, ent->origin );
		}

		VectorCopy( ent->origin, ent->lightingOrigin );
		VectorMA( le->velocity, time, le->accel, le->velocity );

		CG_AddEntityToScene( ent );
	}
}
Exemple #12
0
/*
* Con_DrawNotify
*
* Draws the last few lines of output transparently over the game top
*/
void Con_DrawNotify( void )
{
    int v;
    char *text;
    const char *say;
    const char *translated;
    int i;
    int time;
    char *s;

    v = 0;
    if( con_drawNotify->integer )
    {
        for( i = min( NUM_CON_TIMES, con.numlines ) - 1; i >= 0; i-- )
        {
            time = con.times[i];
            if( time == 0 )
                continue;
            time = cls.realtime - time;
            if( time > con_notifytime->value*1000 )
                continue;
            text = con.text[i] ? con.text[i] : "";

            SCR_DrawString( 8, v, ALIGN_LEFT_TOP, text, cls.fontSystemSmall, colorWhite );

            v += SCR_strHeight( cls.fontSystemSmall );
        }
    }

    if( cls.key_dest == key_message )
    {
        int x, y;
        int width, prewidth;
        int promptwidth, cursorwidth;
        struct qfontface_s *font = NULL;

        if( con_chatCGame->integer )
        {
            width = con_chatWidth->integer;

            if( *con_chatFontFamily->string && con_chatFontSize->integer ) {
                font = SCR_RegisterFont( con_chatFontFamily->string, con_chatFontStyle->integer, con_chatFontSize->integer );
            }
            if( !font )
                font = cls.fontSystemSmall;

            x = con_chatX->integer;
            y = con_chatY->integer;
        }
        else
        {
            width = viddef.width;
            x = 8;
            y = v;
            font = cls.fontSystemSmall;
        }

        // 48 is an arbitrary offset for not overlapping the FPS and clock prints
        width -= 48;
        cursorwidth = SCR_strWidth( "_", font, 0 );

        if( chat_team )
        {
            say = "say_team:";
        }
        else
        {
            say = "say:";
        }

        translated = L10n_TranslateString( "common", say );
        if( !translated ) {
            translated = say;
        }
        SCR_DrawString( x, y, ALIGN_LEFT_TOP, translated, font, colorWhite );
        promptwidth = SCR_strWidth( translated, font, 0 ) + SCR_strWidth( " ", font, 0 );

        s = chat_buffer;
        prewidth = chat_linepos ? SCR_strWidth( s, font, chat_linepos ) : 0;

        // don't let the cursor go beyond the left screen edge
        clamp_high( chat_prestep, prewidth );

        // don't let it go beyond the right screen edge
        clamp_low( chat_prestep, prewidth - ( width - promptwidth - cursorwidth ) );

        // FIXME: we double the font height to compensate for alignment issues
        SCR_DrawClampString( x + promptwidth - chat_prestep,
                             y, s, x + promptwidth, y,
                             x + width, y + SCR_strHeight( font ) * 2, font, colorWhite );

        if( (int)( cls.realtime>>8 )&1 )
            SCR_DrawRawChar( x + promptwidth + prewidth - chat_prestep, y, '_',
                             font, colorWhite );
    }
Exemple #13
0
/*
* CG_AddLocalEntities
*/
void CG_AddLocalEntities( void )
{
#define FADEINFRAMES 2
	int f;
	lentity_t *le, *next, *hnode;
	entity_t *ent;
	float scale, frac, fade, time, scaleIn, fadeIn;
	float backlerp;
	vec3_t angles;

	time = cg.frameTime;
	backlerp = 1.0f - cg.lerpfrac;

	hnode = &cg_localents_headnode;
	for( le = hnode->next; le != hnode; le = next )
	{
		next = le->next;

		frac = ( cg.time - le->start ) * 0.01f;
		f = ( int )floor( frac );
		clamp_low( f, 0 );

		// it's time to DIE
		if( f >= le->frames - 1 )
		{
			le->type = LE_FREE;
			CG_FreeLocalEntity( le );
			continue;
		}

		if( le->frames > 1 )
		{
			scale = 1.0f - frac / ( le->frames - 1 );
			scale = bound( 0.0f, scale, 1.0f );
			fade = scale * 255.0f;

			// quick fade in, if time enough
			if( le->frames > FADEINFRAMES * 2 )
			{
				scaleIn = frac / (float)FADEINFRAMES;
				clamp( scaleIn, 0.0f, 1.0f );
				fadeIn = scaleIn * 255.0f;
			}
			else
				fadeIn = 255.0f;
		}
		else
		{
			scale = 1.0f;
			fade = 255.0f;
			fadeIn = 255.0f;
		}

		ent = &le->ent;

		if( le->light && scale )
			CG_AddLightToScene( ent->origin, le->light * scale, le->lightcolor[0], le->lightcolor[1], le->lightcolor[2] );

		if( le->type == LE_LASER )
		{
			CG_QuickPolyBeam( ent->origin, ent->origin2, ent->radius, ent->customShader ); // wsw : jalfixme: missing the color (comes inside ent->skinnum)
			continue;
		}

		if( le->type == LE_DASH_SCALE )
		{
			if( f < 1 ) ent->scale = 0.15 * frac;
			else
			{
				VecToAngles( &ent->axis[AXIS_RIGHT], angles );
				ent->axis[1*3+1] += 0.005f *sin( DEG2RAD ( angles[YAW] ) ); //length
				ent->axis[1*3+0] += 0.005f *cos( DEG2RAD ( angles[YAW] ) ); //length
				ent->axis[0*3+1] += 0.008f *cos( DEG2RAD ( angles[YAW] ) ); //width
				ent->axis[0*3+0] -= 0.008f *sin( DEG2RAD ( angles[YAW] ) ); //width
				ent->axis[2*3+2] -= 0.052f;              //height

				if( ent->axis[AXIS_UP+2] <= 0 )
				{
					le->type = LE_FREE;
					CG_FreeLocalEntity( le );
				}
			}
		}
		if( le->type == LE_PUFF_SCALE )
		{
			if( le->frames - f < 4 )
				ent->scale = 1.0f - 1.0f * ( frac - abs( 4-le->frames ) )/4;
		}
		if( le->type == LE_PUFF_SHRINK )
		{
			if( frac < 3 )
				ent->scale = 1.0f - 0.2f * frac/4;
			else
			{
				ent->scale = 0.8 - 0.8*( frac-3 )/3;
				VectorScale( le->velocity, 0.85f, le->velocity );
			}
		}

		if( le->type == LE_EXPLOSION_TRACER )
		{
			if( cg.time - ent->rotation > 10.0f )
			{
				ent->rotation = cg.time;
				if( ent->radius - 16*frac > 4 )
					CG_Explosion_Puff( ent->origin, ent->radius-16*frac, le->frames - f );
			}
		}

		switch( le->type )
		{
		case LE_NO_FADE:
			break;
		case LE_RGB_FADE:
			fade = min( fade, fadeIn );
			ent->shaderRGBA[0] = ( uint8_t )( fade * le->color[0] );
			ent->shaderRGBA[1] = ( uint8_t )( fade * le->color[1] );
			ent->shaderRGBA[2] = ( uint8_t )( fade * le->color[2] );
			break;
		case LE_SCALE_ALPHA_FADE:
			fade = min( fade, fadeIn );
			ent->scale = 1.0f + 1.0f / scale;
			ent->scale = min( ent->scale, 5.0f );
			ent->shaderRGBA[3] = ( uint8_t )( fade * le->color[3] );
			break;
		case LE_INVERSESCALE_ALPHA_FADE:
			fade = min( fade, fadeIn );
			ent->scale = scale + 0.1f;
			clamp( ent->scale, 0.1f, 1.0f );
			ent->shaderRGBA[3] = ( uint8_t )( fade * le->color[3] );
			break;
		case LE_ALPHA_FADE:
			fade = min( fade, fadeIn );
			ent->shaderRGBA[3] = ( uint8_t )( fade * le->color[3] );
			break;
		default:
			break;
		}

		ent->backlerp = backlerp;

		if ( le->avelocity[0] || le->avelocity[1] || le->avelocity[2] ) {
			VectorMA( le->angles, time, le->avelocity, le->angles );
			AnglesToAxis( le->angles, le->ent.axis );
		}

		// apply rotational friction
		if( le->bounce ) { // FIXME?
			int i;
			const float adj = 100 * 6 * time; // magic constants here

			for( i = 0; i < 3; i++ ) {
				if( le->avelocity[i] > 0.0f ) {
					le->avelocity[i] -= adj;
					if( le->avelocity[i] < 0.0f ) {
						le->avelocity[i] = 0.0f;
					}
				}
				else if ( le->avelocity[i] < 0.0f ) {
					le->avelocity[i] += adj;
					if ( le->avelocity[i] > 0.0f ) {
						le->avelocity[i] = 0.0f;
					}
				}
			}
		}

		if( le->bounce )
		{
			trace_t	trace;
			vec3_t next_origin;

			VectorMA( ent->origin, time, le->velocity, next_origin );

			CG_Trace( &trace, ent->origin, debris_mins, debris_maxs, next_origin, 0, MASK_SOLID );

			// remove the particle when going out of the map
			if( ( trace.contents & CONTENTS_NODROP ) || ( trace.surfFlags & SURF_SKY ) )
			{
				le->frames = 0;
			}
			else if( trace.fraction != 1.0 ) // found solid
			{
				float dot;
				float xyzspeed, orig_xyzspeed;
				float bounce;
				
				orig_xyzspeed = VectorLength( le->velocity );

				// Reflect velocity
				dot = DotProduct( le->velocity, trace.plane.normal );
				VectorMA( le->velocity, -2.0f * dot, trace.plane.normal, le->velocity );
				//put new origin in the impact point, but move it out a bit along the normal
				VectorMA( trace.endpos, 1, trace.plane.normal, ent->origin );

				// make sure we don't gain speed from bouncing off
				bounce = 2.0f * le->bounce * 0.01f;
				if( bounce < 1.5f )
					bounce = 1.5f;
				xyzspeed = orig_xyzspeed / bounce;

				VectorNormalize( le->velocity );
				VectorScale( le->velocity, xyzspeed, le->velocity );
	
				//the entity has not speed enough. Stop checks
				if( xyzspeed * time < 1.0f )
				{
					trace_t traceground;
					vec3_t ground_origin;
					//see if we have ground
					VectorCopy( ent->origin, ground_origin );
					ground_origin[2] += ( debris_mins[2] - 4 );
					CG_Trace( &traceground, ent->origin, debris_mins, debris_maxs, ground_origin, 0, MASK_SOLID );
					if( traceground.fraction != 1.0 )
					{
						le->bounce = 0;
						VectorClear( le->velocity );
						VectorClear( le->accel );
						VectorClear( le->avelocity );
						if( le->type == LE_EXPLOSION_TRACER )
						{
							// blx
							le->type = LE_FREE;
							CG_FreeLocalEntity( le );
						}
					}
				}

			}
			else
			{
				VectorCopy( ent->origin, ent->origin2 );
				VectorCopy( next_origin, ent->origin );
			}
		}
		else
		{
			VectorCopy( ent->origin, ent->origin2 );
			VectorMA( ent->origin, time, le->velocity, ent->origin );
		}

		VectorCopy( ent->origin, ent->lightingOrigin );
		VectorMA( le->velocity, time, le->accel, le->velocity );

		CG_AddEntityToScene( ent );
	}
}
Exemple #14
0
void CG_RenderView( float frameTime, float realFrameTime, int realTime, unsigned int serverTime, float stereo_separation, unsigned int extrapolationTime, bool flipped )
{
	refdef_t *rd = &cg.view.refdef;

	// update time
	cg.realTime = realTime;
	cg.frameTime = frameTime;
	cg.realFrameTime = realFrameTime;
	cg.frameCount++;
	cg.time = serverTime;

	if( !cgs.precacheDone || !cg.frame.valid )
	{
		CG_Precache();
		CG_DrawLoading();
		return;
	}

	{
		float snapTime = ( cg.frame.serverTime - cg.oldFrame.serverTime );

		if( !snapTime )
			snapTime = cgs.snapFrameTime;

		// moved this from CG_Init here
		cgs.extrapolationTime = extrapolationTime;

		if( cg.oldFrame.serverTime == cg.frame.serverTime )
			cg.lerpfrac = 1.0f;
		else
			cg.lerpfrac = ( (double)( cg.time - cgs.extrapolationTime ) - (double)cg.oldFrame.serverTime ) / (double)snapTime;

		if( cgs.extrapolationTime )
		{
			cg.xerpTime = 0.001f * ( (double)cg.time - (double)cg.frame.serverTime );
			cg.oldXerpTime = 0.001f * ( (double)cg.time - (double)cg.oldFrame.serverTime );

			if( cg.time >= cg.frame.serverTime )
			{
				cg.xerpSmoothFrac = (double)( cg.time - cg.frame.serverTime ) / (double)( cgs.extrapolationTime );
				clamp( cg.xerpSmoothFrac, 0.0f, 1.0f );
			}
			else
			{
				cg.xerpSmoothFrac = (double)( cg.frame.serverTime - cg.time ) / (double)( cgs.extrapolationTime );
				clamp( cg.xerpSmoothFrac, -1.0f, 0.0f );
				cg.xerpSmoothFrac = 1.0f - cg.xerpSmoothFrac;
			}

			clamp_low( cg.xerpTime, -( cgs.extrapolationTime * 0.001f ) );
			//clamp( cg.xerpTime, -( cgs.extrapolationTime * 0.001f ), ( cgs.extrapolationTime * 0.001f ) );
			//clamp( cg.oldXerpTime, 0, ( ( snapTime + cgs.extrapolationTime ) * 0.001f ) );
		}
		else
		{
			cg.xerpTime = 0.0f;
			cg.xerpSmoothFrac = 0.0f;
		}
	}

	if( cg_showClamp->integer )
	{
		if( cg.lerpfrac > 1.0f )
			CG_Printf( "high clamp %f\n", cg.lerpfrac );
		else if( cg.lerpfrac < 0.0f )
			CG_Printf( "low clamp  %f\n", cg.lerpfrac );
	}

	clamp( cg.lerpfrac, 0.0f, 1.0f );

	if( !cgs.configStrings[CS_WORLDMODEL][0] )
	{
		CG_AddLocalSounds();

		trap_R_DrawStretchPic( 0, 0, cgs.vidWidth, cgs.vidHeight, 0, 0, 1, 1, colorBlack, cgs.shaderWhite );

		trap_S_Update( vec3_origin, vec3_origin, axis_identity, cgs.clientInfo[cgs.playerNum].name );

		return;
	}

	// bring up the game menu after reconnecting
	if( !cgs.tv && !cgs.demoPlaying ) {
		if( ISREALSPECTATOR() && !cg.firstFrame ) {
			if( !cgs.gameMenuRequested ) {
				trap_Cmd_ExecuteText( EXEC_NOW, "gamemenu\n" );
			}
			cgs.gameMenuRequested = true;
		}
	}

	if( !cg.viewFrameCount )
		cg.firstViewRealTime = cg.realTime;

	CG_FlashGameWindow(); // notify player of important game events

	CG_CalcVrect(); // find sizes of the 3d drawing screen
	CG_TileClear(); // clear any dirty part of the background

	CG_ChaseCamButtons();

	CG_RunLightStyles();

	CG_ClearFragmentedDecals();

	trap_R_ClearScene();

	if( CG_DemoCam_Update() )
		CG_SetupViewDef( &cg.view, CG_DemoCam_GetViewType(), flipped );
	else
		CG_SetupViewDef( &cg.view, VIEWDEF_PLAYERVIEW, flipped );

	CG_LerpEntities();  // interpolate packet entities positions

	CG_CalcViewWeapon( &cg.weapon );

	CG_FireEvents( false );

	CG_AddEntities();
	CG_AddViewWeapon( &cg.weapon );
	CG_AddLocalEntities();
	CG_AddParticles();
	CG_AddDlights();
	CG_AddShadeBoxes();
	CG_AddDecals();
	CG_AddPolys();
	CG_AddLightStyles();

#ifndef PUBLIC_BUILD
	CG_AddTest();
#endif

	// offset vieworg appropriately if we're doing stereo separation
	VectorMA( cg.view.origin, stereo_separation, &cg.view.axis[AXIS_RIGHT], rd->vieworg );

	// never let it sit exactly on a node line, because a water plane can
	// disappear when viewed with the eye exactly on it.
	// the server protocol only specifies to 1/16 pixel, so add 1/16 in each axis
	rd->vieworg[0] += 1.0/PM_VECTOR_SNAP;
	rd->vieworg[1] += 1.0/PM_VECTOR_SNAP;
	rd->vieworg[2] += 1.0/PM_VECTOR_SNAP;

	AnglesToAxis( cg.view.angles, rd->viewaxis );

	rd->rdflags = CG_RenderFlags();

	// warp if underwater
	if( rd->rdflags & RDF_UNDERWATER )
	{
		float phase = rd->time * 0.001 * WAVE_FREQUENCY * M_TWOPI;
		float v = WAVE_AMPLITUDE * ( sin( phase ) - 1.0 ) + 1;
		rd->fov_x *= v;
		rd->fov_y *= v;
	}

	CG_AddLocalSounds();
	CG_SetSceneTeamColors(); // update the team colors in the renderer

	trap_R_RenderScene( &cg.view.refdef );

	cg.oldAreabits = true;

	trap_S_Update( cg.view.origin, cg.view.velocity, cg.view.axis, cgs.clientInfo[cgs.playerNum].name );

	CG_Draw2D();

	CG_ResetTemporaryBoneposesCache(); // clear for next frame

	cg.viewFrameCount++;
}