示例#1
0
/*
==============
RB_DrawSun
	(SA) FIXME: sun should render behind clouds, so passing dark areas cover it up
==============
*/
void RB_DrawSun( void ) {
	float size;
	float dist;
	vec3_t origin, vec1, vec2;
	vec3_t temp;
	byte color[4];

	if ( !tr.sunShader ) {
		return;
	}

	if ( !backEnd.skyRenderedThisView ) {
		return;
	}
	if ( !r_drawSun->integer ) {
		return;
	}
	qglPushMatrix();
	qglLoadMatrixf( backEnd.viewParms.world.modelMatrix );
	qglTranslatef( backEnd.viewParms.orientation.origin[0], backEnd.viewParms.orientation.origin[1], backEnd.viewParms.orientation.origin[2] );

	dist =  backEnd.viewParms.zFar / 1.75;      // div sqrt(3)

	// (SA) shrunk the size of the sun
	size = dist * 0.2;

	VectorScale( tr.sunDirection, dist, origin );
	PerpendicularVector( vec1, tr.sunDirection );
	CrossProduct( tr.sunDirection, vec1, vec2 );

	VectorScale( vec1, size, vec1 );
	VectorScale( vec2, size, vec2 );

	// farthest depth range
	qglDepthRange( 1.0, 1.0 );

	color[0] = color[1] = color[2] = color[3] = 255;

	// (SA) simpler sun drawing
	RB_BeginSurface( tr.sunShader, tess.fogNum );

	RB_AddQuadStamp( origin, vec1, vec2, color );
/*
		VectorCopy( origin, temp );
		VectorSubtract( temp, vec1, temp );
		VectorSubtract( temp, vec2, temp );
		VectorCopy( temp, tess.xyz[tess.numVertexes].v );
		tess.texCoords0[tess.numVertexes].v[0] = 0;
		tess.texCoords0[tess.numVertexes].v[1] = 0;
		tess.vertexColors[tess.numVertexes].v[0] = 255;
		tess.vertexColors[tess.numVertexes].v[1] = 255;
		tess.vertexColors[tess.numVertexes].v[2] = 255;
		tess.numVertexes++;

		VectorCopy( origin, temp );
		VectorAdd( temp, vec1, temp );
		VectorSubtract( temp, vec2, temp );
		VectorCopy( temp, tess.xyz[tess.numVertexes].v );
		tess.texCoords0[tess.numVertexes].v[0] = 0;
		tess.texCoords0[tess.numVertexes].v[1] = 1;
		tess.vertexColors[tess.numVertexes].v[0] = 255;
		tess.vertexColors[tess.numVertexes].v[1] = 255;
		tess.vertexColors[tess.numVertexes].v[2] = 255;
		tess.numVertexes++;

		VectorCopy( origin, temp );
		VectorAdd( temp, vec1, temp );
		VectorAdd( temp, vec2, temp );
		VectorCopy( temp, tess.xyz[tess.numVertexes].v );
		tess.texCoords0[tess.numVertexes].v[0] = 1;
		tess.texCoords0[tess.numVertexes].v[1] = 1;
		tess.vertexColors[tess.numVertexes].v[0] = 255;
		tess.vertexColors[tess.numVertexes].v[1] = 255;
		tess.vertexColors[tess.numVertexes].v[2] = 255;
		tess.numVertexes++;

		VectorCopy( origin, temp );
		VectorSubtract( temp, vec1, temp );
		VectorAdd( temp, vec2, temp );
		VectorCopy( temp, tess.xyz[tess.numVertexes].v );
		tess.texCoords0[tess.numVertexes].v[0] = 1;
		tess.texCoords0[tess.numVertexes].v[1] = 0;
		tess.vertexColors[tess.numVertexes].v[0] = 255;
		tess.vertexColors[tess.numVertexes].v[1] = 255;
		tess.vertexColors[tess.numVertexes].v[2] = 255;
		tess.numVertexes++;

		tess.indexes[tess.numIndexes++] = 0;
		tess.indexes[tess.numIndexes++] = 1;
		tess.indexes[tess.numIndexes++] = 2;
		tess.indexes[tess.numIndexes++] = 0;
		tess.indexes[tess.numIndexes++] = 2;
		tess.indexes[tess.numIndexes++] = 3;
*/
	RB_EndSurface();


	if ( r_drawSun->integer > 1 ) { // draw flare effect
		// (SA) FYI:	This is cheezy and was only a test so far.
		//				If we decide to use the flare business I will /definatly/ improve all this

		// get a point a little closer
		dist = dist * 0.7;
		VectorScale( tr.sunDirection, dist, origin );

		// and make the flare a little smaller
		VectorScale( vec1, 0.5f, vec1 );
		VectorScale( vec2, 0.5f, vec2 );

		// add the vectors to give an 'off angle' result
		VectorAdd( tr.sunDirection, backEnd.viewParms.orientation.axis[0], temp );
		VectorNormalize( temp );

		// amplify the result
		origin[0] += temp[0] * 500.0;
		origin[1] += temp[1] * 500.0;
		origin[2] += temp[2] * 500.0;

		// (SA) FIXME: todo: flare effect should render last (on top of everything else) and only when sun is in view (sun moving out of camera past degree n should start to cause flare dimming until view angle to sun is off by angle n + x.

		// draw the flare
		RB_BeginSurface( tr.sunflareShader[0], tess.fogNum );
		RB_AddQuadStamp( origin, vec1, vec2, color );
		RB_EndSurface();
	}

	// back to normal depth range
	qglDepthRange( 0.0, 1.0 );
	qglPopMatrix();
}
示例#2
0
// Change a polygon into a bunch of text polygons
void DeformText( const char *text ) {
	int		i;
	vector3	origin, width, height;
	int		len;
	int		ch;
	byte	color[4];
	float	bottom, top;
	vector3	mid;

	height.x = 0;
	height.y = 0;
	height.z = -1;
	CrossProduct( &tess.normal[0], &height, &width );

	// find the midpoint of the box
	VectorClear( &mid );
	bottom = 999999;
	top = -999999;
	for ( i = 0 ; i < 4 ; i++ ) {
		VectorAdd( &tess.xyz[i], &mid, &mid );
		if ( tess.xyz[i].z < bottom ) {
			bottom = tess.xyz[i].z;
		}
		if ( tess.xyz[i].z > top ) {
			top = tess.xyz[i].z;
		}
	}
	VectorScale( &mid, 0.25f, &origin );

	// determine the individual character size
	height.x = 0;
	height.y = 0;
	height.z = ( top - bottom ) * 0.5f;

	VectorScale( &width, height.z * -0.75f, &width );

	// determine the starting position
	len = strlen( text );
	VectorMA( &origin, (float)(len-1), &width, &origin );

	// clear the shader indexes
	tess.numIndexes = 0;
	tess.numVertexes = 0;

	color[0] = color[1] = color[2] = color[3] = 255;

	// draw each character
	for ( i = 0 ; i < len ; i++ ) {
		ch = text[i];
		ch &= 255;

		if ( ch != ' ' ) {
			int		row, col;
			float	frow, fcol, size;

			row = ch>>4;
			col = ch&15;

			frow = row*0.0625f;
			fcol = col*0.0625f;
			size = 0.0625f;

			RB_AddQuadStampExt( &origin, &width, &height, color, fcol, frow, fcol + size, frow + size );
		}
		VectorMA( &origin, -2, &width, &origin );
	}
示例#3
0
文件: g_reflect.c 项目: qbism/qbq2
void AddReflection (edict_t *ent)
{
	gclient_t	*cl;
	edict_t		*mirror;
	float		roll;
	int			i, m;
	qboolean	is_reflected;
	vec3_t		forward;
	vec3_t		org;

	for(i=0; i<6; i++)
	{
		is_reflected = false;
		for(m=0; m<level.num_reflectors && !is_reflected; m++)
		{
			mirror = g_mirror[m];
			if(!mirror->inuse)
				continue;
			if(mirror->spawnflags & SF_REFLECT_OFF)
				continue;
			if(mirror->style != i)
				continue;
			VectorCopy(ent->s.origin,org);
			switch(i)
			{
			case 0: org[2] = 2*mirror->absmax[2] - ent->s.origin[2] - mirror->moveinfo.distance - 2; break;
			case 1: org[2] = 2*mirror->absmin[2] - ent->s.origin[2] + mirror->moveinfo.distance + 2; break;
			case 2: org[0] = 2*mirror->absmin[0] - ent->s.origin[0] + mirror->moveinfo.distance + 2; break;
			case 3: org[0] = 2*mirror->absmax[0] - ent->s.origin[0] - mirror->moveinfo.distance - 2; break;
			case 4: org[1] = 2*mirror->absmin[1] - ent->s.origin[1] + mirror->moveinfo.distance + 2; break;
			case 5: org[1] = 2*mirror->absmax[1] - ent->s.origin[1] - mirror->moveinfo.distance - 2; break;
			}
			if(org[0] < mirror->absmin[0]) continue;
			if(org[0] > mirror->absmax[0]) continue;
			if(org[1] < mirror->absmin[1]) continue;
			if(org[1] > mirror->absmax[1]) continue;
			if(org[2] < mirror->absmin[2]) continue;
			if(org[2] > mirror->absmax[2]) continue;
			is_reflected = true;
		}
		if(is_reflected)
		{
			if (!ent->reflection[i])
			{			
				ent->reflection[i] = G_Spawn();
			
				if(ent->s.effects & EF_ROTATE)
				{
					ent->s.effects &= ~EF_ROTATE;
					gi.linkentity(ent);
				}
				ent->reflection[i]->movetype = MOVETYPE_NONE;
				ent->reflection[i]->solid = SOLID_NOT;
				ent->reflection[i]->classname = "reflection";
				ent->reflection[i]->flags = FL_REFLECT;
				ent->reflection[i]->takedamage = DAMAGE_NO;
			}
			if (ent->client && !ent->reflection[i]->client)
			{
				cl = (gclient_t *)malloc(sizeof(gclient_t)); 
				ent->reflection[i]->client = cl; 
			}
			if (ent->client && ent->reflection[i]->client)
			{
//				Lazarus: Hmm.. this crashes when loading saved game.
//				         Not sure what use pers is anyhow?
//				ent->reflection[i]->client->pers = ent->client->pers;
				ent->reflection[i]->s = ent->s;
			}
			ent->reflection[i]->s.number     = ent->reflection[i] - g_edicts;
			ent->reflection[i]->s.modelindex = ent->s.modelindex;
			ent->reflection[i]->s.modelindex2 = ent->s.modelindex2;
			ent->reflection[i]->s.modelindex3 = ent->s.modelindex3;
			ent->reflection[i]->s.modelindex4 = ent->s.modelindex4;
		#ifdef KMQUAKE2_ENGINE_MOD
			ent->reflection[i]->s.modelindex5 = ent->s.modelindex5;
			ent->reflection[i]->s.modelindex6 = ent->s.modelindex6;
		#ifndef LOOP_SOUND_ATTENUATION
			ent->reflection[i]->s.modelindex7 = ent->s.modelindex7;
			ent->reflection[i]->s.modelindex8 = ent->s.modelindex8;
		#endif
			ent->reflection[i]->s.alpha = ent->s.alpha;
		#endif
			ent->reflection[i]->s.skinnum = ent->s.skinnum;
			ent->reflection[i]->s.frame = ent->s.frame;
			ent->reflection[i]->s.effects = ent->s.effects;
			ent->reflection[i]->s.renderfx = ent->s.renderfx;
			ent->reflection[i]->s.renderfx &= ~RF_IR_VISIBLE;
		#ifdef KMQUAKE2_ENGINE_MOD
			// Don't flip if left handed player model
			if ( !(ent->s.modelindex == (MAX_MODELS-1) && hand->value == 1) )
				ent->reflection[i]->s.renderfx |= RF_MIRRORMODEL; // Knightmare added- flip reflected models
		#endif
			VectorCopy (ent->s.angles, ent->reflection[i]->s.angles);
			switch(i)
			{
			case 0:
			case 1:
				ent->reflection[i]->s.angles[0]+=180;
				ent->reflection[i]->s.angles[1]+=180;
				ent->reflection[i]->s.angles[2]=360-ent->reflection[i]->s.angles[2];
				break;
			case 2:
			case 3:
				AngleVectors(ent->reflection[i]->s.angles,forward,NULL,NULL);
				roll = ent->reflection[i]->s.angles[2];
				forward[0] = -forward[0];
				vectoangles(forward,ent->reflection[i]->s.angles);
				ent->reflection[i]->s.angles[2] = 360-roll;
				break;
			case 4:
			case 5:
				AngleVectors(ent->reflection[i]->s.angles,forward,NULL,NULL);
				roll = ent->reflection[i]->s.angles[2];
				forward[1] = -forward[1];
				vectoangles(forward,ent->reflection[i]->s.angles);
				ent->reflection[i]->s.angles[2] = 360-roll;
			}

			VectorCopy (org, ent->reflection[i]->s.origin);
			if(ent->s.renderfx & RF_BEAM)
			{
				vec3_t	delta;

				VectorSubtract(ent->reflection[i]->s.origin,ent->s.origin,delta);
				VectorAdd(ent->s.old_origin,delta,ent->reflection[i]->s.old_origin);
			}
			else
				VectorCopy(ent->reflection[i]->s.origin, ent->reflection[i]->s.old_origin);
			gi.linkentity (ent->reflection[i]);
		}
		else if (ent->reflection[i])
		{
			DeleteReflection(ent,i);
		}
	}
}
示例#4
0
文件: g_items.cpp 项目: Joanxt/OpenJK
/*
================
G_BounceItem

================
*/
void G_BounceItem( gentity_t *ent, trace_t *trace ) {
	vec3_t	velocity;
	float	dot;
	int		hitTime;
	qboolean droppedSaber = qtrue;

	if ( ent->item
		&& ent->item->giType == IT_WEAPON
		&& ent->item->giTag == WP_SABER 
		&& (ent->flags&FL_DROPPED_ITEM) )
	{
		droppedSaber = qtrue;
	}

	// reflect the velocity on the trace plane
	hitTime = level.previousTime + ( level.time - level.previousTime ) * trace->fraction;
	EvaluateTrajectoryDelta( &ent->s.pos, hitTime, velocity );
	dot = DotProduct( velocity, trace->plane.normal );
	VectorMA( velocity, -2*dot, trace->plane.normal, ent->s.pos.trDelta );

	// cut the velocity to keep from bouncing forever
	VectorScale( ent->s.pos.trDelta, ent->physicsBounce, ent->s.pos.trDelta );

	if ( droppedSaber )
	{//a dropped saber item
		//FIXME: use NPC_type (as saberType) to get proper bounce sound?
		WP_SaberFallSound( NULL, ent );
	}

	// check for stop
	if ( trace->plane.normal[2] > 0 && ent->s.pos.trDelta[2] < 40 ) 
	{//stop
		G_SetOrigin( ent, trace->endpos );
		ent->s.groundEntityNum = trace->entityNum;
		if ( droppedSaber )
		{//a dropped saber item
			//stop rotation
			VectorClear( ent->s.apos.trDelta );
			ent->currentAngles[PITCH] = SABER_PITCH_HACK;
			ent->currentAngles[ROLL] = 0;
			if ( ent->NPC_type 
				&& ent->NPC_type[0] )
			{//we have a valid saber for this
				saberInfo_t saber;
				if ( WP_SaberParseParms( ent->NPC_type, &saber ) )
				{
					if ( (saber.saberFlags&SFL_BOLT_TO_WRIST) )
					{
						ent->currentAngles[PITCH] = 0;
					}
				}
			}
			pitch_roll_for_slope( ent, trace->plane.normal, ent->currentAngles, qtrue );
			G_SetAngles( ent, ent->currentAngles );
		}
		return;
	}
	//bounce
	if ( droppedSaber )
	{//a dropped saber item
		//change rotation
		VectorCopy( ent->currentAngles, ent->s.apos.trBase );
		ent->s.apos.trType = TR_LINEAR;
		ent->s.apos.trTime = level.time;
		VectorSet( ent->s.apos.trDelta, Q_irand( -300, 300 ), Q_irand( -300, 300 ), Q_irand( -300, 300 ) );
	}

	VectorAdd( ent->currentOrigin, trace->plane.normal, ent->currentOrigin);
	VectorCopy( ent->currentOrigin, ent->s.pos.trBase );
	ent->s.pos.trTime = level.time;
}
示例#5
0
//FIXME since we need to test end position contents here, can we avoid doing
//it again later in catagorize position?
qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink)
{
    float		dz;
    vec3_t		oldorg, neworg, end;
    trace_t		trace;
    int			i;
    float		stepsize;
    vec3_t		test;
    int			contents;

// try the move
    VectorCopy (ent->s.origin, oldorg);
    VectorAdd (ent->s.origin, move, neworg);

// flying monsters don't step up
    if ( ent->flags & (FL_SWIM | FL_FLY) )
    {
        // try one move with vertical motion, then one without
        for (i=0 ; i<2 ; i++)
        {
            VectorAdd (ent->s.origin, move, neworg);
            if (i == 0 && ent->enemy)
            {
                if (!ent->goalentity)
                    ent->goalentity = ent->enemy;
                dz = ent->s.origin[2] - ent->goalentity->s.origin[2];
                if (ent->goalentity->client)
                {
                    if (dz > 40)
                        neworg[2] -= 8;
                    if (!((ent->flags & FL_SWIM) && (ent->waterlevel < 2)))
                        if (dz < 30)
                            neworg[2] += 8;
                }
                else
                {
                    if (dz > 8)
                        neworg[2] -= 8;
                    else if (dz > 0)
                        neworg[2] -= dz;
                    else if (dz < -8)
                        neworg[2] += 8;
                    else
                        neworg[2] += dz;
                }
            }
            trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, neworg, ent, MASK_MONSTERSOLID);

            // fly monsters don't enter water voluntarily
            if (ent->flags & FL_FLY)
            {
                if (!ent->waterlevel)
                {
                    test[0] = trace.endpos[0];
                    test[1] = trace.endpos[1];
                    test[2] = trace.endpos[2] + ent->mins[2] + 1;
                    contents = gi.pointcontents(test);
                    if (contents & MASK_WATER)
                        return false;
                }
            }

            // swim monsters don't exit water voluntarily
            if (ent->flags & FL_SWIM)
            {
                if (ent->waterlevel < 2)
                {
                    test[0] = trace.endpos[0];
                    test[1] = trace.endpos[1];
                    test[2] = trace.endpos[2] + ent->mins[2] + 1;
                    contents = gi.pointcontents(test);
                    if (!(contents & MASK_WATER))
                        return false;
                }
            }

            if (trace.fraction == 1)
            {
                VectorCopy (trace.endpos, ent->s.origin);
                if (relink)
                {
                    gi.linkentity (ent);
                    G_TouchTriggers (ent);
                }
                return true;
            }

            if (!ent->enemy)
                break;
        }

        return false;
    }

// push down from a step height above the wished position
    if (!(ent->monsterinfo.aiflags & AI_NOSTEP))
        stepsize = STEPSIZE;
    else
        stepsize = 1;

    neworg[2] += stepsize;
    VectorCopy (neworg, end);
    end[2] -= stepsize*2;

    trace = gi.trace (neworg, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID);

    if (trace.allsolid)
        return false;

    if (trace.startsolid)
    {
        neworg[2] -= stepsize;
        trace = gi.trace (neworg, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID);
        if (trace.allsolid || trace.startsolid)
            return false;
    }


    // don't go in to water
    if (ent->waterlevel == 0)
    {
        test[0] = trace.endpos[0];
        test[1] = trace.endpos[1];
        test[2] = trace.endpos[2] + ent->mins[2] + 1;
        contents = gi.pointcontents(test);

        if (contents & MASK_WATER)
            return false;
    }

    if (trace.fraction == 1)
    {
        // if monster had the ground pulled out, go ahead and fall
        if ( ent->flags & FL_PARTIALGROUND )
        {
            VectorAdd (ent->s.origin, move, ent->s.origin);
            if (relink)
            {
                gi.linkentity (ent);
                G_TouchTriggers (ent);
            }
            ent->groundentity = NULL;
            return true;
        }

        return false;		// walked off an edge
    }

// check point traces down for dangling corners
    VectorCopy (trace.endpos, ent->s.origin);

    if (!M_CheckBottom (ent))
    {
        if ( ent->flags & FL_PARTIALGROUND )
        {   // entity had floor mostly pulled out from underneath it
            // and is trying to correct
            if (relink)
            {
                gi.linkentity (ent);
                G_TouchTriggers (ent);
            }
            return true;
        }
        VectorCopy (oldorg, ent->s.origin);
        return false;
    }

    if ( ent->flags & FL_PARTIALGROUND )
    {
        ent->flags &= ~FL_PARTIALGROUND;
    }
    ent->groundentity = trace.ent;
    ent->groundentity_linkcount = trace.ent->linkcount;

// the move is ok
    if (relink)
    {
        gi.linkentity (ent);
        G_TouchTriggers (ent);
    }
    return true;
}
示例#6
0
文件: view.c 项目: DrItanium/rogue
/*
=============
SV_CalcBlend
=============
*/
void SV_CalcBlend (edict_t *ent)
{
	int		contents;
	vec3_t	vieworg;
	int		remaining;

	ent->client->ps.blend[0] = ent->client->ps.blend[1] = 
		ent->client->ps.blend[2] = ent->client->ps.blend[3] = 0;

	// add for contents
	VectorAdd (ent->s.origin, ent->client->ps.viewoffset, vieworg);
	contents = gi.pointcontents (vieworg);
	if (contents & (CONTENTS_LAVA|CONTENTS_SLIME|CONTENTS_WATER) )
		ent->client->ps.rdflags |= RDF_UNDERWATER;
	else
		ent->client->ps.rdflags &= ~RDF_UNDERWATER;

	if (contents & (CONTENTS_SOLID|CONTENTS_LAVA))
		SV_AddBlend (1.0, 0.3, 0.0, 0.6, ent->client->ps.blend);
	else if (contents & CONTENTS_SLIME)
		SV_AddBlend (0.0, 0.1, 0.05, 0.6, ent->client->ps.blend);
	else if (contents & CONTENTS_WATER)
		SV_AddBlend (0.5, 0.3, 0.2, 0.4, ent->client->ps.blend);

	// add for powerups
	if (ent->client->quad_framenum > level.framenum)
	{
		remaining = ent->client->quad_framenum - level.framenum;
		if (remaining == 30)	// beginning to fade
			gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage2.wav"), 1, ATTN_NORM, 0);
		if (remaining > 30 || (remaining & 4) )
			SV_AddBlend (0, 0, 1, 0.08, ent->client->ps.blend);
	}
	// PMM - double damage
	else if (ent->client->double_framenum > level.framenum)
	{
		remaining = ent->client->double_framenum - level.framenum;
		if (remaining == 30)	// beginning to fade
			gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/ddamage2.wav"), 1, ATTN_NORM, 0);
		if (remaining > 30 || (remaining & 4) )
			SV_AddBlend (0.9, 0.7, 0, 0.08, ent->client->ps.blend);
	}
	// PMM
	else if (ent->client->invincible_framenum > level.framenum)
	{
		remaining = ent->client->invincible_framenum - level.framenum;
		if (remaining == 30)	// beginning to fade
			gi.sound(ent, CHAN_ITEM, gi.soundindex("items/protect2.wav"), 1, ATTN_NORM, 0);
		if (remaining > 30 || (remaining & 4) )
			SV_AddBlend (1, 1, 0, 0.08, ent->client->ps.blend);
	}
	else if (ent->client->enviro_framenum > level.framenum)
	{
		remaining = ent->client->enviro_framenum - level.framenum;
		if (remaining == 30)	// beginning to fade
			gi.sound(ent, CHAN_ITEM, gi.soundindex("items/airout.wav"), 1, ATTN_NORM, 0);
		if (remaining > 30 || (remaining & 4) )
			SV_AddBlend (0, 1, 0, 0.08, ent->client->ps.blend);
	}
	else if (ent->client->breather_framenum > level.framenum)
	{
		remaining = ent->client->breather_framenum - level.framenum;
		if (remaining == 30)	// beginning to fade
			gi.sound(ent, CHAN_ITEM, gi.soundindex("items/airout.wav"), 1, ATTN_NORM, 0);
		if (remaining > 30 || (remaining & 4) )
			SV_AddBlend (0.4, 1, 0.4, 0.04, ent->client->ps.blend);
	}

	//PGM
	if(ent->client->nuke_framenum > level.framenum)
	{
		float brightness;
		brightness = (ent->client->nuke_framenum - level.framenum) / 20.0;
		SV_AddBlend (1, 1, 1, brightness, ent->client->ps.blend);
	}
	if (ent->client->ir_framenum > level.framenum)
	{
		remaining = ent->client->ir_framenum - level.framenum;
		if(remaining > 30 || (remaining & 4))
		{
			ent->client->ps.rdflags |= RDF_IRGOGGLES;
			SV_AddBlend (1, 0, 0, 0.2, ent->client->ps.blend);
		}
		else
			ent->client->ps.rdflags &= ~RDF_IRGOGGLES;
	}
	else
	{
		ent->client->ps.rdflags &= ~RDF_IRGOGGLES;
	}
	//PGM

	// add for damage
	if (ent->client->damage_alpha > 0)
		SV_AddBlend (ent->client->damage_blend[0],ent->client->damage_blend[1]
		,ent->client->damage_blend[2], ent->client->damage_alpha, ent->client->ps.blend);

	if (ent->client->bonus_alpha > 0)
		SV_AddBlend (0.85, 0.7, 0.3, ent->client->bonus_alpha, ent->client->ps.blend);

	// drop the damage value
	ent->client->damage_alpha -= 0.06;
	if (ent->client->damage_alpha < 0)
		ent->client->damage_alpha = 0;

	// drop the bonus value
	ent->client->bonus_alpha -= 0.1;
	if (ent->client->bonus_alpha < 0)
		ent->client->bonus_alpha = 0;
}
示例#7
0
qboolean	PM_SlideMove( qboolean gravity ) {
	int			bumpcount, numbumps;
	vec3_t		dir;
	float		d;
	int			numplanes;
	vec3_t		planes[MAX_CLIP_PLANES];
	vec3_t		primal_velocity;
	vec3_t		clipVelocity;
	int			i, j, k;
	trace_t	trace;
	vec3_t		end;
	float		time_left;
	float		into;
	vec3_t		endVelocity;
	vec3_t		endClipVelocity;
	
	numbumps = 4;

	VectorCopy (pm->ps->velocity, primal_velocity);

	if ( gravity ) {
		VectorCopy( pm->ps->velocity, endVelocity );
		endVelocity[2] -= pm->ps->gravity * pml.frametime;
		pm->ps->velocity[2] = ( pm->ps->velocity[2] + endVelocity[2] ) * 0.5;
		primal_velocity[2] = endVelocity[2];
		if ( pml.groundPlane ) {
			// slide along the ground plane
			PM_ClipVelocity (pm->ps->velocity, pml.groundTrace.plane.normal, 
				pm->ps->velocity, OVERCLIP );
		}
	}

	time_left = pml.frametime;

	// never turn against the ground plane
	if ( pml.groundPlane ) {
		numplanes = 1;
		VectorCopy( pml.groundTrace.plane.normal, planes[0] );
	} else {
		numplanes = 0;
	}

	// never turn against original velocity
	VectorNormalize2( pm->ps->velocity, planes[numplanes] );
	numplanes++;

	for ( bumpcount=0 ; bumpcount < numbumps ; bumpcount++ ) {

		// calculate position we are trying to move to
		VectorMA( pm->ps->origin, time_left, pm->ps->velocity, end );

		// see if we can make it there
		pm->trace ( &trace, pm->ps->origin, pm->mins, pm->maxs, end, pm->ps->clientNum, pm->tracemask);

		if (trace.allsolid) {
			// entity is completely trapped in another solid
			pm->ps->velocity[2] = 0;	// don't build up falling damage, but allow sideways acceleration
			return qtrue;
		}

		if (trace.fraction > 0) {
			// actually covered some distance
			VectorCopy (trace.endpos, pm->ps->origin);
		}

		if (trace.fraction == 1) {
			 break;		// moved the entire distance
		}

		// save entity for contact
		PM_AddTouchEnt( trace.entityNum );

		time_left -= time_left * trace.fraction;

		if (numplanes >= MAX_CLIP_PLANES) {
			// this shouldn't really happen
			VectorClear( pm->ps->velocity );
			return qtrue;
		}

		//
		// if this is the same plane we hit before, nudge velocity
		// out along it, which fixes some epsilon issues with
		// non-axial planes
		//
		for ( i = 0 ; i < numplanes ; i++ ) {
			if ( DotProduct( trace.plane.normal, planes[i] ) > 0.99 ) {
				VectorAdd( trace.plane.normal, pm->ps->velocity, pm->ps->velocity );
				break;
			}
		}
		if ( i < numplanes ) {
			continue;
		}
		VectorCopy (trace.plane.normal, planes[numplanes]);
		numplanes++;

		//
		// modify velocity so it parallels all of the clip planes
		//

		// find a plane that it enters
		for ( i = 0 ; i < numplanes ; i++ ) {
			into = DotProduct( pm->ps->velocity, planes[i] );
			if ( into >= 0.1 ) {
				continue;		// move doesn't interact with the plane
			}

			// see how hard we are hitting things
			if ( -into > pml.impactSpeed ) {
				pml.impactSpeed = -into;
			}

			// slide along the plane
			PM_ClipVelocity (pm->ps->velocity, planes[i], clipVelocity, OVERCLIP );

			// slide along the plane
			PM_ClipVelocity (endVelocity, planes[i], endClipVelocity, OVERCLIP );

			// see if there is a second plane that the new move enters
			for ( j = 0 ; j < numplanes ; j++ ) {
				if ( j == i ) {
					continue;
				}
				if ( DotProduct( clipVelocity, planes[j] ) >= 0.1 ) {
					continue;		// move doesn't interact with the plane
				}

				// try clipping the move to the plane
				PM_ClipVelocity( clipVelocity, planes[j], clipVelocity, OVERCLIP );
				PM_ClipVelocity( endClipVelocity, planes[j], endClipVelocity, OVERCLIP );

				// see if it goes back into the first clip plane
				if ( DotProduct( clipVelocity, planes[i] ) >= 0 ) {
					continue;
				}

				// slide the original velocity along the crease
				CrossProduct (planes[i], planes[j], dir);
				VectorNormalize( dir );
				d = DotProduct( dir, pm->ps->velocity );
				VectorScale( dir, d, clipVelocity );

				CrossProduct (planes[i], planes[j], dir);
				VectorNormalize( dir );
				d = DotProduct( dir, endVelocity );
				VectorScale( dir, d, endClipVelocity );

				// see if there is a third plane the the new move enters
				for ( k = 0 ; k < numplanes ; k++ ) {
					if ( k == i || k == j ) {
						continue;
					}
					if ( DotProduct( clipVelocity, planes[k] ) >= 0.1 ) {
						continue;		// move doesn't interact with the plane
					}

					// stop dead at a tripple plane interaction
					VectorClear( pm->ps->velocity );
					return qtrue;
				}
			}

			// if we have fixed all interactions, try another move
			VectorCopy( clipVelocity, pm->ps->velocity );
			VectorCopy( endClipVelocity, endVelocity );
			break;
		}
	}

	if ( gravity ) {
		VectorCopy( endVelocity, pm->ps->velocity );
	}

	// don't change velocity if in a timer (FIXME: is this correct?)
	if ( pm->ps->pm_time ) {
		VectorCopy( primal_velocity, pm->ps->velocity );
	}

	return ( bumpcount != 0 );
}
示例#8
0
/*
   ===============
   GrabFrame
   ===============
 */
static void GrabFrame( char *frame ){
	triangle_t      *ptri;
	int i, j;
	trivert_t       *ptrivert;
	int num_tris;
	char file1[1024];
	frame_t         *fr;
	vertexnormals_t vnorms[MAX_VERTS];
	int index_xyz;
	char            *framefile;

	// the frame 'run1' will be looked for as either
	// run.1 or run1.tri, so the new alias sequence save
	// feature an be used
	framefile = FindFrameFile( frame );

	sprintf( file1, "%s/%s", cdarchive, framefile );
	ExpandPathAndArchive( file1 );

	sprintf( file1, "%s/%s",cddir, framefile );

	printf( "grabbing %s  ", file1 );

	if ( model.num_frames >= MAX_FRAMES ) {
		Error( "model.num_frames >= MAX_FRAMES" );
	}
	fr = &g_frames[model.num_frames];
	model.num_frames++;

	strcpy( fr->name, frame );

//
// load the frame
//
	if ( do3ds ) {
		Load3DSTriangleList( file1, &ptri, &num_tris, NULL, NULL );
	}
	else{
		LoadTriangleList( file1, &ptri, &num_tris, NULL, NULL );
	}

	if ( num_tris != model.num_tris ) {
		Error( "%s: number of triangles doesn't match base frame\n", file1 );
	}

//
// allocate storage for the frame's vertices
//
	ptrivert = fr->v;

	for ( i = 0 ; i < model.num_xyz ; i++ )
	{
		vnorms[i].numnormals = 0;
		VectorClear( vnorms[i].normalsum );
	}
	ClearBounds( fr->mins, fr->maxs );

//
// store the frame's vertices in the same order as the base. This assumes the
// triangles and vertices in this frame are in exactly the same order as in the
// base
//
	for ( i = 0 ; i < num_tris ; i++ )
	{
		vec3_t vtemp1, vtemp2, normal;
		float ftemp;

		VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 );
		VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 );
		CrossProduct( vtemp1, vtemp2, normal );

		VectorNormalize( normal, normal );

		// rotate the normal so the model faces down the positive x axis
		ftemp = normal[0];
		normal[0] = -normal[1];
		normal[1] = ftemp;

		for ( j = 0 ; j < 3 ; j++ )
		{
			index_xyz = triangles[i].index_xyz[j];

			// rotate the vertices so the model faces down the positive x axis
			// also adjust the vertices to the desired origin
			ptrivert[index_xyz].v[0] = ( ( -ptri[i].verts[j][1] ) * scale_up ) +
									   adjust[0];
			ptrivert[index_xyz].v[1] = ( ptri[i].verts[j][0] * scale_up ) +
									   adjust[1];
			ptrivert[index_xyz].v[2] = ( ptri[i].verts[j][2] * scale_up ) +
									   adjust[2];

			AddPointToBounds( ptrivert[index_xyz].v, fr->mins, fr->maxs );

			VectorAdd( vnorms[index_xyz].normalsum, normal, vnorms[index_xyz].normalsum );
			vnorms[index_xyz].numnormals++;
		}
	}

//
// calculate the vertex normals, match them to the template list, and store the
// index of the best match
//
	for ( i = 0 ; i < model.num_xyz ; i++ )
	{
		int j;
		vec3_t v;
		float maxdot;
		int maxdotindex;
		int c;

		c = vnorms[i].numnormals;
		if ( !c ) {
			Error( "Vertex with no triangles attached" );
		}

		VectorScale( vnorms[i].normalsum, 1.0 / c, v );
		VectorNormalize( v, v );

		maxdot = -999999.0;
		maxdotindex = -1;

		for ( j = 0 ; j < NUMVERTEXNORMALS ; j++ )
		{
			float dot;

			dot = DotProduct( v, avertexnormals[j] );
			if ( dot > maxdot ) {
				maxdot = dot;
				maxdotindex = j;
			}
		}

		ptrivert[i].lightnormalindex = maxdotindex;
	}

	free( ptri );
}
示例#9
0
void SV_LinkEntity(sharedEntity_t *gEnt) {
	worldSector_t *node;
	int leafs[MAX_TOTAL_ENT_LEAFS];
	int cluster;
	int num_leafs;
	int i, j, k;
	int area;
	int lastLeaf;
	float *origin, *angles;
	svEntity_t *ent;

	ent = SV_SvEntityForGentity(gEnt);
	// sanity check for possible currentOrigin being reset bug
	if (!gEnt->r.bmodel && VectorCompare(gEnt->r.currentOrigin, vec3_origin)) {
		Com_DPrintf("WARNING: BBOX entity is being linked at world origin, this is probably a bug\n");
	}

	if (ent->worldSector) {
		SV_UnlinkEntity(gEnt);   // unlink from old position
	}
	// encode the size into the entityState_t for client prediction
	if (gEnt->r.bmodel) {
		gEnt->s.solid = SOLID_BMODEL;      // a solid_box will never create this value
	} else if (gEnt->r.contents & (CONTENTS_SOLID|CONTENTS_BODY)) {
		// assume that x/y are equal and symetric
		i = gEnt->r.maxs[0];

		if (i < 1) {
			i = 1;
		}

		if (i > 255) {
			i = 255;
		}
		// z is not symetric
		j = (-gEnt->r.mins[2]);

		if (j < 1) {
			j = 1;
		}

		if (j > 255) {
			j = 255;
		}
		// and z maxs can be negative...
		k = (gEnt->r.maxs[2] + 32);

		if (k < 1) {
			k = 1;
		}

		if (k > 255) {
			k = 255;
		}

		gEnt->s.solid = (k << 16)|(j << 8)|i;
	} else {
		gEnt->s.solid = 0;
	}
	// get the position
	origin = gEnt->r.currentOrigin;
	angles = gEnt->r.currentAngles;
	// set the abs box
	if (gEnt->r.bmodel && (angles[0] || angles[1] || angles[2])) {
		// expand for rotation
		float max;

		max = RadiusFromBounds(gEnt->r.mins, gEnt->r.maxs);

		for (i = 0; i < 3; i++) {
			gEnt->r.absmin[i] = origin[i] - max;
			gEnt->r.absmax[i] = origin[i] + max;
		}
	} else {
		// normal
		VectorAdd(origin, gEnt->r.mins, gEnt->r.absmin);
		VectorAdd(origin, gEnt->r.maxs, gEnt->r.absmax);
	}
	// because movement is clipped an epsilon away from an actual edge, we must fully check even when bounding boxes don't quite touch
	gEnt->r.absmin[0] -= 1;
	gEnt->r.absmin[1] -= 1;
	gEnt->r.absmin[2] -= 1;
	gEnt->r.absmax[0] += 1;
	gEnt->r.absmax[1] += 1;
	gEnt->r.absmax[2] += 1;
	// link to PVS leafs
	ent->numClusters = 0;
	ent->lastCluster = 0;
	ent->areanum = -1;
	ent->areanum2 = -1;
	// get all leafs, including solids
	num_leafs = CM_BoxLeafnums(gEnt->r.absmin, gEnt->r.absmax, leafs, MAX_TOTAL_ENT_LEAFS, &lastLeaf);
	// if none of the leafs were inside the map, the entity is outside the world and can be considered unlinked
	if (!num_leafs) {
		return;
	}
	// set areas, even from clusters that don't fit in the entity array
	for (i = 0; i < num_leafs; i++) {
		area = CM_LeafArea(leafs[i]);

		if (area != -1) {
			// doors may legally straggle two areas, but nothing should evern need more than that
			if (ent->areanum != -1 && ent->areanum != area) {
				if (ent->areanum2 != -1 && ent->areanum2 != area && sv.state == SS_LOADING) {
					Com_DPrintf("Object %i touching 3 areas at %f %f %f\n", gEnt->s.number, gEnt->r.absmin[0], gEnt->r.absmin[1], gEnt->r.absmin[2]);
				}

				ent->areanum2 = area;
			} else {
				ent->areanum = area;
			}
		}
	}
	// store as many explicit clusters as we can
	ent->numClusters = 0;

	for (i = 0; i < num_leafs; i++) {
		cluster = CM_LeafCluster(leafs[i]);

		if (cluster != -1) {
			ent->clusternums[ent->numClusters++] = cluster;

			if (ent->numClusters == MAX_ENT_CLUSTERS) {
				break;
			}
		}
	}
	// store off a last cluster if we need to
	if (i != num_leafs) {
		ent->lastCluster = CM_LeafCluster(lastLeaf);
	}

	gEnt->r.linkcount++;
	// find the first world sector node that the ent's box crosses
	node = sv_worldSectors;

	while (1) {
		if (node->axis == -1) {
			break;
		}

		if (gEnt->r.absmin[node->axis] > node->dist) {
			node = node->children[0];
		} else if (gEnt->r.absmax[node->axis] < node->dist) {
			node = node->children[1];
		} else {
			break;     // crosses the node
		}
	}
	// link it in
	ent->worldSector = node;
	ent->nextEntityInWorldSector = node->entities;
	node->entities = ent;

	gEnt->r.linked = qtrue;
}
示例#10
0
/*
=================
fire_lead

This is an internal support routine used for bullet/pellet based weapons.
=================
*/
static void fire_lead (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int te_impact, int hspread, int vspread, int mod)
{
	trace_t		tr;
	vec3_t		dir;
	vec3_t		forward, right, up;
	vec3_t		end;
	float		r;
	float		u;
	vec3_t		water_start;
	qboolean	water = false;
	int			content_mask = MASK_SHOT | MASK_WATER;

	tr = gi.trace (self->s.origin, NULL, NULL, start, self, MASK_SHOT);
	if (!(tr.fraction < 1.0))
	{
		vectoangles (aimdir, dir);
		AngleVectors (dir, forward, right, up);

		r = crandom()*hspread;
		u = crandom()*vspread;
		VectorMA (start, 8192, forward, end);
		VectorMA (end, r, right, end);
		VectorMA (end, u, up, end);

		if (gi.pointcontents (start) & MASK_WATER)
		{
			water = true;
			VectorCopy (start, water_start);
			content_mask &= ~MASK_WATER;
		}

		tr = gi.trace (start, NULL, NULL, end, self, content_mask);

		// see if we hit water
		if (tr.contents & MASK_WATER)
		{
			int		color;

			water = true;
			VectorCopy (tr.endpos, water_start);

			if (!VectorCompare (start, tr.endpos))
			{
				if (tr.contents & CONTENTS_WATER)
				{
					if (strcmp(tr.surface->name, "*brwater") == 0)
						color = SPLASH_BROWN_WATER;
					else
						color = SPLASH_BLUE_WATER;
				}
				else if (tr.contents & CONTENTS_SLIME)
					color = SPLASH_SLIME;
				else if (tr.contents & CONTENTS_LAVA)
					color = SPLASH_LAVA;
				else
					color = SPLASH_UNKNOWN;

				if (color != SPLASH_UNKNOWN)
				{
					gi.WriteByte (svc_temp_entity);
					gi.WriteByte (TE_SPLASH);
					gi.WriteByte (8);
					gi.WritePosition (tr.endpos);
					gi.WriteDir (tr.plane.normal);
					gi.WriteByte (color);
					gi.multicast (tr.endpos, MULTICAST_PVS);
				}

				// change bullet's course when it enters water
				VectorSubtract (end, start, dir);
				vectoangles (dir, dir);
				AngleVectors (dir, forward, right, up);
				r = crandom()*hspread*2;
				u = crandom()*vspread*2;
				VectorMA (water_start, 8192, forward, end);
				VectorMA (end, r, right, end);
				VectorMA (end, u, up, end);
			}

			// re-trace ignoring water this time
			tr = gi.trace (water_start, NULL, NULL, end, self, MASK_SHOT);
		}
	}

	// send gun puff / flash
	if (!((tr.surface) && (tr.surface->flags & SURF_SKY)))
	{
		if (tr.fraction < 1.0)
		{
			if (tr.ent->takedamage)
			{
				T_Damage (tr.ent, self, self, aimdir, tr.endpos, tr.plane.normal, damage, kick, DAMAGE_BULLET, mod);
			}
			else
			{
				if (strncmp (tr.surface->name, "sky", 3) != 0)
				{
					gi.WriteByte (svc_temp_entity);
					gi.WriteByte (te_impact);
					gi.WritePosition (tr.endpos);
					gi.WriteDir (tr.plane.normal);
					gi.multicast (tr.endpos, MULTICAST_PVS);

					if (self->client)
						PlayerNoise(self, tr.endpos, PNOISE_IMPACT);
				}
			}
		}
	}

	// if went through water, determine where the end and make a bubble trail
	if (water)
	{
		vec3_t	pos;

		VectorSubtract (tr.endpos, water_start, dir);
		VectorNormalize (dir);
		VectorMA (tr.endpos, -2, dir, pos);
		if (gi.pointcontents (pos) & MASK_WATER)
			VectorCopy (pos, tr.endpos);
		else
			tr = gi.trace (pos, NULL, NULL, water_start, tr.ent, MASK_WATER);

		VectorAdd (water_start, tr.endpos, pos);
		VectorScale (pos, 0.5, pos);

		gi.WriteByte (svc_temp_entity);
		gi.WriteByte (TE_BUBBLETRAIL);
		gi.WritePosition (water_start);
		gi.WritePosition (tr.endpos);
		gi.multicast (pos, MULTICAST_PVS);
	}
}
示例#11
0
/*
========================
func_explosive_objective
========================
*/
void func_explosive_objective_explode (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
{
	vec3_t	origin;
	vec3_t	chunkorigin;
	vec3_t	size;
	int		count;
	int		mass;
	int		enemy;
	int		otherteam;

	//gi.dprintf(DEVELOPER_MSG_GAME, "self: %s\ninflictor: %s\n attacker: %s\n",
	//	self->classname, inflictor->classname, attacker->classname);

	if (!attacker->client ||
		!attacker->client->resp.mos)
		return;

	// bmodel origins are (0 0 0), we need to adjust that here
	VectorScale (self->size, 0.5, size);
	VectorAdd (self->absmin, size, origin);
	VectorCopy (origin, self->s.origin);

	self->takedamage = DAMAGE_NO;

	if (self->dmg)
		T_RadiusDamage (self, attacker, self->dmg, NULL, self->dmg+40, MOD_EXPLOSIVE);

	VectorSubtract (self->s.origin, inflictor->s.origin, self->velocity);
	VectorNormalize (self->velocity);
	VectorScale (self->velocity, 150, self->velocity);

	// start chunks towards the center
	VectorScale (size, 0.5, size);

	mass = self->mass;
	if (!mass)
		mass = 75;

	// big chunks
	if (mass >= 100)
	{
		count = mass / 100;
		if (count > 8)
			count = 8;
		while(count--)
		{
			chunkorigin[0] = origin[0] + crandom() * size[0];
			chunkorigin[1] = origin[1] + crandom() * size[1];
			chunkorigin[2] = origin[2] + crandom() * size[2];
			ThrowDebris (self, "models/objects/debris1/tris.md2", 1, chunkorigin);
		}
	}

	// small chunks
	count = mass / 25;
	if (count > 16)
		count = 16;
	while(count--)
	{
		chunkorigin[0] = origin[0] + crandom() * size[0];
		chunkorigin[1] = origin[1] + crandom() * size[1];
		chunkorigin[2] = origin[2] + crandom() * size[2];
		ThrowDebris (self, "models/objects/debris2/tris.md2", 2, chunkorigin);
	}

	G_UseTargets (self, attacker);

	// hack for 2 team games

	if (self->obj_owner != 99) {
		team_list[self->obj_owner]->score -= self->obj_loss;
		enemy = (self->obj_owner) ? 0 : 1;
	} else
		enemy = 99;

	if (self->obj_owner != attacker->client->resp.team_on->index)
		team_list[attacker->client->resp.team_on->index]->score += self->obj_gain;
	else if (self->obj_owner == attacker->client->resp.team_on->index && enemy != 99)
		team_list[enemy]->score += self->obj_gain;

	if (dedicated->value)
		safe_cprintf(NULL, PRINT_HIGH, "%s destroyed by %s [%s]\n", 
			self->obj_name, 
			attacker->client->pers.netname,
			team_list[attacker->client->resp.team_on->index]->teamname);

	centerprintall("%s destroyed by:\n\n%s\n%s",
		self->obj_name, 
		attacker->client->pers.netname,
		team_list[attacker->client->resp.team_on->index]->teamname);

	otherteam = (self->obj_owner+1)%2;
	if ((!team_list[otherteam]->kills_and_points && team_list[otherteam]->score < team_list[otherteam]->need_points) ||
	    (team_list[otherteam]->kills_and_points && team_list[otherteam]->kills < team_list[otherteam]->need_kills))
	  gi.sound(self, CHAN_NO_PHS_ADD, gi.soundindex(va("%s/objectives/touch_cap.wav", team_list[otherteam]->teamid)), 1, 0, 0);

//		gi.dprintf(DEVELOPER_MSG_GAME, "pts:%i  ndpts:%i  kills:%i  ndkills:%i\n",team_list[(self->obj_owner+1)%2]->score,team_list[(self->obj_owner+1)%2]->need_points,
//team_list[(self->obj_owner+1)%2]->kills,team_list[(self->obj_owner+1)%2]->need_kills);

	if (self->deathtarget)
	{	
		self->target = self->deathtarget;
		if (self->target)
			G_UseTargets (self, attacker);
	}

	if (self->dmg)
		BecomeExplosion1 (self);
	else
		G_FreeEdict (self);
}
示例#12
0
文件: g_weapon.c 项目: basecq/q2dos
/*
=================
fire_bfg
=================
*/
void bfg_explode (edict_t *self)
{
	edict_t *ent;
	float points;
	vec3_t v;
	float dist;

	if (!self)
	{
		return;
	}

	if (self->s.frame == 0)
	{
		/* the BFG effect */
		ent = NULL;

		while ((ent = findradius(ent, self->s.origin, self->dmg_radius)) != NULL)
		{
			if (!ent->takedamage)
			{
				continue;
			}

			if (ent == self->owner)
			{
				continue;
			}

			if (!CanDamage(ent, self))
			{
				continue;
			}

			if (!CanDamage(ent, self->owner))
			{
				continue;
			}

			VectorAdd(ent->mins, ent->maxs, v);
			VectorMA(ent->s.origin, 0.5, v, v);
			VectorSubtract(self->s.origin, v, v);
			dist = VectorLength(v);
			points = self->radius_dmg * (1.0 - sqrt(dist / self->dmg_radius));

			if (ent == self->owner)
			{
				points = points * 0.5;
			}

			gi.WriteByte(svc_temp_entity);
			gi.WriteByte(TE_BFG_EXPLOSION);
			gi.WritePosition(ent->s.origin);
			gi.multicast(ent->s.origin, MULTICAST_PHS);
			T_Damage(ent, self, self->owner, self->velocity, ent->s.origin,
					vec3_origin, (int)points, 0, DAMAGE_ENERGY, MOD_BFG_EFFECT);
		}
	}

	self->nextthink = level.time + FRAMETIME;
	self->s.frame++;

	if (self->s.frame == 5)
	{
		self->think = G_FreeEdict;
	}
}
示例#13
0
文件: g_weapon.c 项目: basecq/q2dos
/*
=================
fire_grenade
=================
*/
void Grenade_Explode (edict_t *ent)
{
	vec3_t origin;
	int mod;

	if (!ent)
	{
		return;
	}

	if (ent->owner->client)
	{
		PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT);
	}

	if (ent->enemy)
	{
		float points;
		vec3_t v;
		vec3_t dir;

		VectorAdd(ent->enemy->mins, ent->enemy->maxs, v);
		VectorMA(ent->enemy->s.origin, 0.5, v, v);
		VectorSubtract(ent->s.origin, v, v);
		points = ent->dmg - 0.5 * VectorLength(v);
		VectorSubtract(ent->enemy->s.origin, ent->s.origin, dir);

		if (ent->spawnflags & 1)
		{
			mod = MOD_HANDGRENADE;
		}
		else
		{
			mod = MOD_GRENADE;
		}

		T_Damage(ent->enemy, ent, ent->owner, dir, ent->s.origin, vec3_origin,
				(int)points, (int)points, DAMAGE_RADIUS, mod);
	}

	if (ent->spawnflags & 2)
	{
		mod = MOD_HELD_GRENADE;
	}
	else if (ent->spawnflags & 1)
	{
		mod = MOD_HG_SPLASH;
	}
	else
	{
		mod = MOD_G_SPLASH;
	}

	T_RadiusDamage(ent, ent->owner, ent->dmg, ent->enemy, ent->dmg_radius, mod);

	VectorMA(ent->s.origin, -0.02, ent->velocity, origin);
	gi.WriteByte(svc_temp_entity);

	if (ent->waterlevel)
	{
		if (ent->groundentity)
		{
			gi.WriteByte(TE_GRENADE_EXPLOSION_WATER);
		}
		else
		{
			gi.WriteByte(TE_ROCKET_EXPLOSION_WATER);
		}
	}
	else
	{
		if (ent->groundentity)
		{
			gi.WriteByte(TE_GRENADE_EXPLOSION);
		}
		else
		{
			gi.WriteByte(TE_ROCKET_EXPLOSION);
		}
	}

	gi.WritePosition(origin);
	gi.multicast(ent->s.origin, MULTICAST_PHS);

	G_FreeEdict(ent);
}
示例#14
0
文件: g_weapon.c 项目: basecq/q2dos
// RAFAEL
void Trap_Think (edict_t *ent)
{
	edict_t	*target = NULL;
	edict_t	*best = NULL;
	vec3_t	vec;
	int		len, i;
	int		oldlen = 8000;
	vec3_t	forward, right, up;

	if (!ent)
	{
		return;
	}

	if (ent->timestamp < level.time)
	{
		BecomeExplosion1(ent);
		return;
	}

	ent->nextthink = level.time + 0.1;

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

	/* ok lets do the blood effect */
	if (ent->s.frame > 4)
	{
		if (ent->s.frame == 5)
		{
			if (ent->wait == 64)
			{
				gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/trapdown.wav"),
					   	1, ATTN_IDLE, 0);
			}

			ent->wait -= 2;
			ent->delay += level.time;

			for (i = 0; i < 3; i++)
			{
				best = G_Spawn();

				if (strcmp(ent->enemy->classname, "monster_gekk") == 0)
				{
					best->s.modelindex = gi.modelindex("models/objects/gekkgib/torso/tris.md2");
					best->s.effects |= TE_GREENBLOOD;
				}
				else if (ent->mass > 200)
				{
					best->s.modelindex = gi.modelindex("models/objects/gibs/chest/tris.md2");
					best->s.effects |= TE_BLOOD;
				}
				else
				{
					best->s.modelindex = gi.modelindex("models/objects/gibs/sm_meat/tris.md2");
					best->s.effects |= TE_BLOOD;
				}

				AngleVectors(ent->s.angles, forward, right, up);

				RotatePointAroundVector(vec, up, right, ((360.0 / 3) * i) + ent->delay);
				VectorMA(vec, ent->wait / 2, vec, vec);
				VectorAdd(vec, ent->s.origin, vec);
				VectorAdd(vec, forward, best->s.origin);

				best->s.origin[2] = ent->s.origin[2] + ent->wait;

				VectorCopy(ent->s.angles, best->s.angles);

				best->solid = SOLID_NOT;
				best->s.effects |= EF_GIB;
				best->takedamage = DAMAGE_YES;

				best->movetype = MOVETYPE_TOSS;
				best->svflags |= SVF_MONSTER;
				best->deadflag = DEAD_DEAD;

				VectorClear(best->mins);
				VectorClear(best->maxs);

				best->watertype = gi.pointcontents(best->s.origin);

				if (best->watertype & MASK_WATER)
				{
					best->waterlevel = 1;
				}

				best->nextthink = level.time + 0.1;
				best->think = G_FreeEdict;
				gi.linkentity(best);
			}

			if (ent->wait < 19)
			{
				ent->s.frame++;
			}

			return;
		}

		ent->s.frame++;

		if (ent->s.frame == 8)
		{
			ent->nextthink = level.time + 1.0;
			ent->think = G_FreeEdict;

			best = G_Spawn();
			SP_item_foodcube(best);
			VectorCopy(ent->s.origin, best->s.origin);
			best->s.origin[2] += 16;
			best->velocity[2] = 400;
			best->count = ent->mass;
			gi.linkentity(best);
			return;
		}

		return;
	}

	ent->s.effects &= ~EF_TRAP;

	if (ent->s.frame >= 4)
	{
		ent->s.effects |= EF_TRAP;
		VectorClear(ent->mins);
		VectorClear(ent->maxs);
	}

	if (ent->s.frame < 4)
	{
		ent->s.frame++;
	}

	while ((target = findradius(target, ent->s.origin, 256)) != NULL)
	{
		if (target == ent)
		{
			continue;
		}

		if (!(target->svflags & SVF_MONSTER) && !target->client)
		{
			continue;
		}

		if (target->health <= 0)
		{
			continue;
		}

		if (!visible(ent, target))
		{
			continue;
		}

		if (!best)
		{
			best = target;
			continue;
		}

		VectorSubtract(ent->s.origin, target->s.origin, vec);
		len = VectorLength(vec);

		if (len < oldlen)
		{
			oldlen = len;
			best = target;
		}
	}

	/* pull the enemy in */
	if (best)
	{
		vec3_t forward;

		if (best->groundentity)
		{
			best->s.origin[2] += 1;
			best->groundentity = NULL;
		}

		VectorSubtract(ent->s.origin, best->s.origin, vec);
		len = VectorLength(vec);

		if (best->client)
		{
			VectorNormalize(vec);
			VectorMA(best->velocity, 250, vec, best->velocity);
		}
		else
		{
			best->ideal_yaw = vectoyaw(vec);
			M_ChangeYaw(best);
			AngleVectors(best->s.angles, forward, NULL, NULL);
			VectorScale(forward, 256, best->velocity);
		}

		gi.sound(ent, CHAN_VOICE, gi.soundindex(
						"weapons/trapsuck.wav"), 1, ATTN_IDLE, 0);

		if (len < 32)
		{
			if (best->mass < 400)
			{
				T_Damage(best, ent, ent->owner, vec3_origin, best->s.origin,
						vec3_origin, 100000, 1, 0, MOD_TRAP);
				ent->enemy = best;
				ent->wait = 64;
				VectorCopy(ent->s.origin, ent->s.old_origin);
				ent->timestamp = level.time + 30;

				if (deathmatch->value)
				{
					ent->mass = best->mass / 4;
				}
				else
				{
					ent->mass = best->mass / 10;
				}

				/* ok spawn the food cube */
				ent->s.frame = 5;
			}
			else
			{
				BecomeExplosion1(ent);
				return;
			}
		}
	}
}
示例#15
0
void SplitPolygon(vec3_t *polygon,int *signs, int vnum, plane_t *plane, vec3_t *inpts, int *innum, vec3_t *outpts, int *outnum) {

    int out_c = 0;
    int in_c = 0;

    vec3_t *ptA = &polygon[vnum-1];
    vec3_t *ptB, v, newVert;
    int sideA = signs[vnum-1];
    int sideB;
    int i;
    float sect;

    for (i=0;  i<vnum; i++) {

        ptB = &polygon[i];
        sideB = signs[i];

        //is b on "right side"
        if (sideB == 2) {

            if (sideA == 1) {

                // compute the intersection point of the line
                // from point A to point B with the partition
                // plane. This is a simple ray-plane intersection.
                VectorSubtract ((*ptB), (*ptA), v);
                sect = - (DotProduct (plane->normal, (*ptA) )-plane->dist) /
                       DotProduct (plane->normal, v);
                VectorScale (v,sect,v);

                //add a new vertex
                VectorAdd ((*ptA), v, newVert);
                VectorCopy (newVert, inpts[in_c]);
                VectorCopy (newVert, outpts[out_c]);

                out_c++;
                in_c++;
            }
            VectorCopy (polygon[i], outpts[out_c]);
            out_c++;
        }
        //b is on "left" side
        else if (sideB ==1) {

            if (sideA == 2) {

                // compute the intersection point of the line
                // from point A to point B with the partition
                // plane. This is a simple ray-plane intersection.
                VectorSubtract ((*ptB), (*ptA), v);
                sect = - (DotProduct (plane->normal, (*ptA) )-plane->dist) /
                       DotProduct (plane->normal, v);
                VectorScale (v,sect,v);

                //add a new vertex
                VectorAdd ((*ptA), v, newVert);
                VectorCopy (newVert, inpts[in_c]);
                VectorCopy (newVert, outpts[out_c]);

                out_c++;
                in_c++;
            }
            VectorCopy (polygon[i], inpts[in_c]);
            in_c++;
        }
        //b is almost on plane
        else {

            VectorCopy (polygon[i], inpts[in_c]);
            VectorCopy (inpts[in_c], outpts[out_c]);
            in_c++;
            out_c++;
        }
        ptA = ptB;
        sideA = sideB;

        if ((out_c > MAX_POLY_VERT) || (in_c > MAX_POLY_VERT)) {
            Con_Printf ("MAX_POLY_VERT exceeded: %i %i\n", in_c, out_c);

            //just return what we've got
            (*innum) = in_c;
            (*outnum) = out_c;
            return;
        }
    }

    (*innum) = in_c;
    (*outnum) = out_c;
}
示例#16
0
void FanFaceSurface( mapDrawSurface_t *ds ){
	int i, j, k, a, b, c, color[ MAX_LIGHTMAPS ][ 4 ];
	bspDrawVert_t   *verts, *centroid, *dv;
	double iv;


	/* try to early out */
	if ( !ds->numVerts || ( ds->type != SURFACE_FACE && ds->type != SURFACE_DECAL ) ) {
		return;
	}

	/* add a new vertex at the beginning of the surface */
	verts = safe_malloc( ( ds->numVerts + 1 ) * sizeof( bspDrawVert_t ) );
	memset( verts, 0, sizeof( bspDrawVert_t ) );
	memcpy( &verts[ 1 ], ds->verts, ds->numVerts * sizeof( bspDrawVert_t ) );
	free( ds->verts );
	ds->verts = verts;

	/* add up the drawverts to create a centroid */
	centroid = &verts[ 0 ];
	memset( color, 0,  4 * MAX_LIGHTMAPS * sizeof( int ) );
	for ( i = 1, dv = &verts[ 1 ]; i < ( ds->numVerts + 1 ); i++, dv++ )
	{
		VectorAdd( centroid->xyz, dv->xyz, centroid->xyz );
		VectorAdd( centroid->normal, dv->normal, centroid->normal );
		for ( j = 0; j < 4; j++ )
		{
			for ( k = 0; k < MAX_LIGHTMAPS; k++ )
				color[ k ][ j ] += dv->color[ k ][ j ];
			if ( j < 2 ) {
				centroid->st[ j ] += dv->st[ j ];
				for ( k = 0; k < MAX_LIGHTMAPS; k++ )
					centroid->lightmap[ k ][ j ] += dv->lightmap[ k ][ j ];
			}
		}
	}

	/* average the centroid */
	iv = 1.0f / ds->numVerts;
	VectorScale( centroid->xyz, iv, centroid->xyz );
	if ( VectorNormalize( centroid->normal, centroid->normal ) <= 0 ) {
		VectorCopy( verts[ 1 ].normal, centroid->normal );
	}
	for ( j = 0; j < 4; j++ )
	{
		for ( k = 0; k < MAX_LIGHTMAPS; k++ )
		{
			color[ k ][ j ] /= ds->numVerts;
			centroid->color[ k ][ j ] = ( color[ k ][ j ] < 255.0f ? color[ k ][ j ] : 255 );
		}
		if ( j < 2 ) {
			centroid->st[ j ] *= iv;
			for ( k = 0; k < MAX_LIGHTMAPS; k++ )
				centroid->lightmap[ k ][ j ] *= iv;
		}
	}

	/* add to vert count */
	ds->numVerts++;

	/* fill indexes in triangle fan order */
	ds->numIndexes = 0;
	ds->indexes = safe_malloc( ds->numVerts * 3 * sizeof( int ) );
	for ( i = 1; i < ds->numVerts; i++ )
	{
		a = 0;
		b = i;
		c = ( i + 1 ) % ds->numVerts;
		c = c ? c : 1;
		ds->indexes[ ds->numIndexes++ ] = a;
		ds->indexes[ ds->numIndexes++ ] = b;
		ds->indexes[ ds->numIndexes++ ] = c;
	}

	/* add to count */
	numFanSurfaces++;

	/* classify it */
	ClassifySurfaces( 1, ds );
}
示例#17
0
文件: view.c 项目: DrItanium/rogue
/*
===============
SV_CalcViewOffset

Auto pitching on slopes?

  fall from 128: 400 = 160000
  fall from 256: 580 = 336400
  fall from 384: 720 = 518400
  fall from 512: 800 = 640000
  fall from 640: 960 = 

  damage = deltavelocity*deltavelocity  * 0.0001

===============
*/
void SV_CalcViewOffset (edict_t *ent)
{
	float		*angles;
	float		bob;
	float		ratio;
	float		delta;
	vec3_t		v;


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

	// base angles
	angles = ent->client->ps.kick_angles;

	// if dead, fix the angle and don't add any kick
	if (ent->deadflag)
	{
		VectorClear (angles);

		if(ent->flags & FL_SAM_RAIMI)
		{
			ent->client->ps.viewangles[ROLL] = 0;
			ent->client->ps.viewangles[PITCH] = 0;
		}
		else
		{
			ent->client->ps.viewangles[ROLL] = 40;
			ent->client->ps.viewangles[PITCH] = -15;
		}
		ent->client->ps.viewangles[YAW] = ent->client->killer_yaw;
	}
	else
	{
		// add angles based on weapon kick

		VectorCopy (ent->client->kick_angles, angles);

		// add angles based on damage kick

		ratio = (ent->client->v_dmg_time - level.time) / DAMAGE_TIME;
		if (ratio < 0)
		{
			ratio = 0;
			ent->client->v_dmg_pitch = 0;
			ent->client->v_dmg_roll = 0;
		}
		angles[PITCH] += ratio * ent->client->v_dmg_pitch;
		angles[ROLL] += ratio * ent->client->v_dmg_roll;

		// add pitch based on fall kick

		ratio = (ent->client->fall_time - level.time) / FALL_TIME;
		if (ratio < 0)
			ratio = 0;
		angles[PITCH] += ratio * ent->client->fall_value;

		// add angles based on velocity

		delta = DotProduct (ent->velocity, forward);
		angles[PITCH] += delta*run_pitch->value;
		
		delta = DotProduct (ent->velocity, right);
		angles[ROLL] += delta*run_roll->value;

		// add angles based on bob

		delta = bobfracsin * bob_pitch->value * xyspeed;
		if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
			delta *= 6;		// crouching
		angles[PITCH] += delta;
		delta = bobfracsin * bob_roll->value * xyspeed;
		if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
			delta *= 6;		// crouching
		if (bobcycle & 1)
			delta = -delta;
		angles[ROLL] += delta;
	}

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

	// base origin

	VectorClear (v);

	// add view height

	v[2] += ent->viewheight;

	// add fall height

	ratio = (ent->client->fall_time - level.time) / FALL_TIME;
	if (ratio < 0)
		ratio = 0;
	v[2] -= ratio * ent->client->fall_value * 0.4;

	// add bob height

	bob = bobfracsin * xyspeed * bob_up->value;
	if (bob > 6)
		bob = 6;
	//gi.DebugGraph (bob *2, 255);
	v[2] += bob;

	// add kick offset

	VectorAdd (v, ent->client->kick_origin, v);

	// absolutely bound offsets
	// so the view can never be outside the player box

	if (v[0] < -14)
		v[0] = -14;
	else if (v[0] > 14)
		v[0] = 14;
	if (v[1] < -14)
		v[1] = -14;
	else if (v[1] > 14)
		v[1] = 14;
	if (v[2] < -22)
		v[2] = -22;
	else if (v[2] > 30)
		v[2] = 30;

	VectorCopy (v, ent->client->ps.viewoffset);
}
示例#18
0
/*
=================
R_DrawAliasModel

=================
*/
void R_DrawAliasModel (entity_t *e)
{
	int			i;
	int			lnum;
	vec3_t		dist;
	float		add;
	model_t		*clmodel;
	vec3_t		mins, maxs;
	aliashdr_t	*paliashdr;
	float		an;
	int			anim;

	clmodel = currententity->model;

	VectorAdd (currententity->origin, clmodel->mins, mins);
	VectorAdd (currententity->origin, clmodel->maxs, maxs);

	if (R_CullBox (mins, maxs))
		return;


	VectorCopy (currententity->origin, r_entorigin);
	VectorSubtract (r_origin, r_entorigin, modelorg);

	//
	// get lighting information
	//

	ambientlight = shadelight = R_LightPoint (currententity->origin);

	// allways give the gun some light
	if (e == &cl.viewent && ambientlight < 24)
		ambientlight = shadelight = 24;

	for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
	{
		if (cl_dlights[lnum].die >= cl.time)
		{
			VectorSubtract (currententity->origin,
							cl_dlights[lnum].origin,
							dist);
			add = cl_dlights[lnum].radius - Length(dist);

			if (add > 0) {
				ambientlight += add;
				//ZOID models should be affected by dlights as well
				shadelight += add;
			}
		}
	}

	// clamp lighting so it doesn't overbright as much
	if (ambientlight > 128)
		ambientlight = 128;
	if (ambientlight + shadelight > 192)
		shadelight = 192 - ambientlight;

	// ZOID: never allow players to go totally black
	i = currententity - cl_entities;
	if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
		if (ambientlight < 8)
			ambientlight = shadelight = 8;

	// HACK HACK HACK -- no fullbright colors, so make torches full light
	if (!Q_strcmp (clmodel->name, "progs/flame2.mdl")
		|| !Q_strcmp (clmodel->name, "progs/flame.mdl") )
		ambientlight = shadelight = 256;

	shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
	shadelight = shadelight / 200.0;
	
	an = e->angles[1]/180*M_PI;
	shadevector[0] = cos(-an);
	shadevector[1] = sin(-an);
	shadevector[2] = 1;
	VectorNormalize (shadevector);

	//
	// locate the proper data
	//
	paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model);

	c_alias_polys += paliashdr->numtris;

	//
	// draw all the triangles
	//

	GL_DisableMultitexture();

    glPushMatrix ();
	R_RotateForEntity (e);

	if (!Q_strcmp (clmodel->name, "progs/eyes.mdl") && gl_doubleeyes.value) {
		glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2] - (22 + 8));
// double size of eyes, since they are really hard to see in gl
		glScalef (paliashdr->scale[0]*2, paliashdr->scale[1]*2, paliashdr->scale[2]*2);
	} else {
		glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]);
		glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]);
	}

	anim = (int)(cl.time*10) & 3;
    GL_Bind(paliashdr->gl_texturenum[currententity->skinnum][anim]);

	// we can't dynamically colormap textures, so they are cached
	// seperately for the players.  Heads are just uncolored.
	if (currententity->colormap != vid.colormap && !gl_nocolors.value)
	{
		i = currententity - cl_entities;
		if (i >= 1 && i<=cl.maxclients /* && !Q_strcmp (currententity->model->name, "progs/player.mdl") */)
		    GL_Bind(playertextures - 1 + i);
	}

	if (gl_smoothmodels.value)
		glShadeModel (GL_SMOOTH);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

	if (gl_affinemodels.value)
		glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);

	R_SetupAliasFrame (currententity->frame, paliashdr);

	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

	glShadeModel (GL_FLAT);
	if (gl_affinemodels.value)
		glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

	glPopMatrix ();

	if (r_shadows.value)
	{
		glPushMatrix ();
		R_RotateForEntity (e);
		glDisable (GL_TEXTURE_2D);
		glEnable (GL_BLEND);
		glColor4f (0,0,0,0.5);
		GL_DrawAliasShadow (paliashdr, lastposenum);
		glEnable (GL_TEXTURE_2D);
		glDisable (GL_BLEND);
		glColor4f (1,1,1,1);
		glPopMatrix ();
	}

}
示例#19
0
void AAS_AddTeleporterPortals(void)
{
	int j, area2num, facenum, otherareanum;
	char *target, *targetname, *classname;
	bsp_entity_t *entities, *ent, *dest;
	vec3_t origin, destorigin, mins, maxs, end;
	vec3_t bbmins, bbmaxs;
	aas_area_t *area;
	aas_face_t *face;
	aas_trace_t trace;
	aas_link_t *areas, *link;

	entities = AAS_ParseBSPEntities();

	for (ent = entities; ent; ent = ent->next)
	{
		classname = AAS_ValueForBSPEpairKey(ent, "classname");
		if (classname && !strcmp(classname, "misc_teleporter"))
		{
			if (!AAS_VectorForBSPEpairKey(ent, "origin", origin))
			{
				botimport.Print(PRT_ERROR, "teleporter (%s) without origin\n", target);
				continue;
			} //end if
			//
			target = AAS_ValueForBSPEpairKey(ent, "target");
			if (!target)
			{
				botimport.Print(PRT_ERROR, "teleporter (%s) without target\n", target);
				continue;
			} //end if
			for (dest = entities; dest; dest = dest->next)
			{
				classname = AAS_ValueForBSPEpairKey(dest, "classname");
				if (classname && !strcmp(classname, "misc_teleporter_dest"))
				{
					targetname = AAS_ValueForBSPEpairKey(dest, "targetname");
					if (targetname && !strcmp(targetname, target))
					{
						break;
					} //end if
				} //end if
			} //end for
			if (!dest)
			{
				botimport.Print(PRT_ERROR, "teleporter without destination (%s)\n", target);
				continue;
			} //end if
			if (!AAS_VectorForBSPEpairKey(dest, "origin", destorigin))
			{
				botimport.Print(PRT_ERROR, "teleporter destination (%s) without origin\n", target);
				continue;
			} //end if
			destorigin[2] += 24; //just for q2e1m2, the dork has put the telepads in the ground
			VectorCopy(destorigin, end);
			end[2] -= 100;
			trace = AAS_TraceClientBBox(destorigin, end, PRESENCE_CROUCH, -1);
			if (trace.startsolid)
			{
				botimport.Print(PRT_ERROR, "teleporter destination (%s) in solid\n", target);
				continue;
			} //end if
			VectorCopy(trace.endpos, destorigin);
			area2num = AAS_PointAreaNum(destorigin);
			//reset all cluster fields
			for (j = 0; j < aasworld.numareas; j++)
			{
				aasworld.areasettings[j].cluster = 0;
			} //end for
			//
			VectorSet(mins, -8, -8, 8);
			VectorSet(maxs, 8, 8, 24);
			//
			AAS_PresenceTypeBoundingBox(PRESENCE_CROUCH, bbmins, bbmaxs);
			//
			VectorAdd(origin, mins, mins);
			VectorAdd(origin, maxs, maxs);
			//add bounding box size
			VectorSubtract(mins, bbmaxs, mins);
			VectorSubtract(maxs, bbmins, maxs);
			//link an invalid (-1) entity
			areas = AAS_AASLinkEntity(mins, maxs, -1);
			//
			for (link = areas; link; link = link->next_area)
			{
				if (!AAS_AreaGrounded(link->areanum)) continue;
				//add the teleporter portal mark
				aasworld.areasettings[link->areanum].contents |= AREACONTENTS_CLUSTERPORTAL |
																			AREACONTENTS_TELEPORTAL;
			} //end for
			//
			for (link = areas; link; link = link->next_area)
			{
				if (!AAS_AreaGrounded(link->areanum)) continue;
				//find a non-portal area adjacent to the portal area and flood
				//the cluster from there
				area = &aasworld.areas[link->areanum];
				for (j = 0; j < area->numfaces; j++)
				{
					facenum = abs(aasworld.faceindex[area->firstface + j]);
					face = &aasworld.faces[facenum];
					//
					if (face->frontarea != link->areanum) otherareanum = face->frontarea;
					else otherareanum = face->backarea;
					//
					if (!otherareanum) continue;
					//
					if (aasworld.areasettings[otherareanum].contents & AREACONTENTS_CLUSTERPORTAL)
					{
						continue;
					} //end if
					//
					AAS_FloodCluster_r(otherareanum, 1);
				} //end for
			} //end for
			//if the teleport destination IS in the same cluster
			if (aasworld.areasettings[area2num].cluster)
			{
				for (link = areas; link; link = link->next_area)
				{
					if (!AAS_AreaGrounded(link->areanum)) continue;
					//add the teleporter portal mark
					aasworld.areasettings[link->areanum].contents &= ~(AREACONTENTS_CLUSTERPORTAL |
																				AREACONTENTS_TELEPORTAL);
				} //end for
			} //end if
		} //end if
	} //end for
	AAS_FreeBSPEntities(entities);
} //end of the function AAS_AddTeleporterPortals
示例#20
0
qboolean isEntVisible(entityState_t *ent)
{
	trace_t tr;
	vec3_t  start, end, temp;
	vec3_t  forward, up, right, right2;
	float   view_height;

	VectorCopy(cl.cgameClientLerpOrigin, start);
	start[2] += (cl.snap.ps.viewheight - 1);
	if (cl.snap.ps.leanf != 0)
	{
		vec3_t lright, v3ViewAngles;
		VectorCopy(cl.snap.ps.viewangles, v3ViewAngles);
		v3ViewAngles[2] += cl.snap.ps.leanf / 2.0f;
		AngleVectors(v3ViewAngles, NULL, lright, NULL);
		VectorMA(start, cl.snap.ps.leanf, lright, start);
	}

	VectorCopy(ent->pos.trBase, end);

	// Compute vector perpindicular to view to ent
	VectorSubtract(end, start, forward);
	VectorNormalizeFast(forward);
	VectorSet(up, 0, 0, 1);
	CrossProduct(forward, up, right);
	VectorNormalizeFast(right);
	VectorScale(right, 10, right2);
	VectorScale(right, 18, right);

	// Set viewheight
	if (ent->animMovetype)
	{
		view_height = 16;
	}
	else
	{
		view_height = 40;
	}

	// First, viewpoint to viewpoint
	end[2] += view_height;
	CM_BoxTrace(&tr, start, end, NULL, NULL, 0, CONTENTS_SOLID, qfalse);
	if (tr.fraction == 1.f)
	{
		return qtrue;
	}

	// First-b, viewpoint to top of head
	end[2] += 16;
	CM_BoxTrace(&tr, start, end, NULL, NULL, 0, CONTENTS_SOLID, qfalse);
	if (tr.fraction == 1.f)
	{
		return qtrue;
	}
	end[2] -= 16;

	// Second, viewpoint to ent's origin
	end[2] -= view_height;
	CM_BoxTrace(&tr, start, end, NULL, NULL, 0, CONTENTS_SOLID, qfalse);
	if (tr.fraction == 1.f)
	{
		return qtrue;
	}

	// Third, to ent's right knee
	VectorAdd(end, right, temp);
	temp[2] += 8;
	CM_BoxTrace(&tr, start, temp, NULL, NULL, 0, CONTENTS_SOLID, qfalse);
	if (tr.fraction == 1.f)
	{
		return qtrue;
	}

	// Fourth, to ent's right shoulder
	VectorAdd(end, right2, temp);
	if (ent->animMovetype)
	{
		temp[2] += 28;
	}
	else
	{
		temp[2] += 52;
	}
	CM_BoxTrace(&tr, start, temp, NULL, NULL, 0, CONTENTS_SOLID, qfalse);
	if (tr.fraction == 1.f)
	{
		return qtrue;
	}

	// Fifth, to ent's left knee
	VectorScale(right, -1, right);
	VectorScale(right2, -1, right2);
	VectorAdd(end, right2, temp);
	temp[2] += 2;
	CM_BoxTrace(&tr, start, temp, NULL, NULL, 0, CONTENTS_SOLID, qfalse);
	if (tr.fraction == 1.f)
	{
		return qtrue;
	}

	// Sixth, to ent's left shoulder
	VectorAdd(end, right, temp);
	if (ent->animMovetype)
	{
		temp[2] += 16;
	}
	else
	{
		temp[2] += 36;
	}
	CM_BoxTrace(&tr, start, temp, NULL, NULL, 0, CONTENTS_SOLID, qfalse);
	if (tr.fraction == 1.f)
	{
		return qtrue;
	}

	return qfalse;
}
示例#21
0
/*
=================
MakeMeshNormals

Handles all the complicated wrapping and degenerate cases
=================
*/
static void MakeMeshNormals( int width, int height, drawVert_t ctrl[ MAX_GRID_SIZE ][ MAX_GRID_SIZE ] )
{
	int        i, j, k, dist;
	vec3_t     normal;
	vec3_t     sum;
	int        count;
	vec3_t     base;
	vec3_t     delta;
	int        x, y;
	drawVert_t *dv;
	vec3_t     around[ 8 ], temp;
	qboolean   good[ 8 ];
	qboolean   wrapWidth, wrapHeight;
	float      len;
	static int neighbors[ 8 ][ 2 ] =
	{
		{ 0, 1 }, { 1, 1 }, { 1, 0 }, { 1, -1 }, { 0, -1 }, { -1, -1 }, { -1, 0 }, { -1, 1 }
	};

	wrapWidth = qfalse;

	for ( i = 0; i < height; i++ )
	{
		VectorSubtract( ctrl[ i ][ 0 ].xyz, ctrl[ i ][ width - 1 ].xyz, delta );
		len = VectorLengthSquared( delta );

		if ( len > 1.0 )
		{
			break;
		}
	}

	if ( i == height )
	{
		wrapWidth = qtrue;
	}

	wrapHeight = qfalse;

	for ( i = 0; i < width; i++ )
	{
		VectorSubtract( ctrl[ 0 ][ i ].xyz, ctrl[ height - 1 ][ i ].xyz, delta );
		len = VectorLengthSquared( delta );

		if ( len > 1.0 )
		{
			break;
		}
	}

	if ( i == width )
	{
		wrapHeight = qtrue;
	}

	for ( i = 0; i < width; i++ )
	{
		for ( j = 0; j < height; j++ )
		{
			count = 0;
			dv = &ctrl[ j ][ i ];
			VectorCopy( dv->xyz, base );

			for ( k = 0; k < 8; k++ )
			{
				VectorClear( around[ k ] );
				good[ k ] = qfalse;

				for ( dist = 1; dist <= 3; dist++ )
				{
					x = i + neighbors[ k ][ 0 ] * dist;
					y = j + neighbors[ k ][ 1 ] * dist;

					if ( wrapWidth )
					{
						if ( x < 0 )
						{
							x = width - 1 + x;
						}
						else if ( x >= width )
						{
							x = 1 + x - width;
						}
					}

					if ( wrapHeight )
					{
						if ( y < 0 )
						{
							y = height - 1 + y;
						}
						else if ( y >= height )
						{
							y = 1 + y - height;
						}
					}

					if ( x < 0 || x >= width || y < 0 || y >= height )
					{
						break; // edge of patch
					}

					VectorSubtract( ctrl[ y ][ x ].xyz, base, temp );

					if ( VectorNormalize2( temp, temp ) == 0 )
					{
						continue; // degenerate edge, get more dist
					}
					else
					{
						good[ k ] = qtrue;
						VectorCopy( temp, around[ k ] );
						break; // good edge
					}
				}
			}

			VectorClear( sum );

			for ( k = 0; k < 8; k++ )
			{
				if ( !good[ k ] || !good[( k + 1 ) & 7 ] )
				{
					continue; // didn't get two points
				}

				CrossProduct( around[( k + 1 ) & 7 ], around[ k ], normal );

				if ( VectorNormalize2( normal, normal ) == 0 )
				{
					continue;
				}

				VectorAdd( normal, sum, sum );
				count++;
			}

			if ( count == 0 )
			{
//printf("bad normal\n");
				count = 1;
			}

			VectorNormalize2( sum, dv->normal );
		}
	}
}
示例#22
0
/*
==============
RB_SurfaceBeam
==============
*/
static void RB_SurfaceBeam( void )
{
#define NUM_BEAM_SEGS 6
	refEntity_t *e;
	shaderProgram_t *sp = &tr.textureColorShader;
	int	i;
	vec3_t perpvec;
	vec3_t direction, normalized_direction;
	vec3_t	start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS];
	vec3_t oldorigin, origin;

	e = &backEnd.currentEntity->e;

	oldorigin[0] = e->oldorigin[0];
	oldorigin[1] = e->oldorigin[1];
	oldorigin[2] = e->oldorigin[2];

	origin[0] = e->origin[0];
	origin[1] = e->origin[1];
	origin[2] = e->origin[2];

	normalized_direction[0] = direction[0] = oldorigin[0] - origin[0];
	normalized_direction[1] = direction[1] = oldorigin[1] - origin[1];
	normalized_direction[2] = direction[2] = oldorigin[2] - origin[2];

	if ( VectorNormalize( normalized_direction ) == 0 )
		return;

	PerpendicularVector( perpvec, normalized_direction );

	VectorScale( perpvec, 4, perpvec );

	for ( i = 0; i < NUM_BEAM_SEGS ; i++ )
	{
		RotatePointAroundVector( start_points[i], normalized_direction, perpvec, (360.0/NUM_BEAM_SEGS)*i );
//		VectorAdd( start_points[i], origin, start_points[i] );
		VectorAdd( start_points[i], direction, end_points[i] );
	}

	GL_BindToTMU( tr.whiteImage, TB_COLORMAP );

	GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );

	// FIXME: Quake3 doesn't use this, so I never tested it
	tess.numVertexes = 0;
	tess.numIndexes = 0;
	tess.firstIndex = 0;
	tess.minIndex = 0;
	tess.maxIndex = 0;

	for ( i = 0; i <= NUM_BEAM_SEGS; i++ ) {
		VectorCopy(start_points[ i % NUM_BEAM_SEGS ], tess.xyz[tess.numVertexes++]);
		VectorCopy(end_points  [ i % NUM_BEAM_SEGS ], tess.xyz[tess.numVertexes++]);
	}

	for ( i = 0; i < NUM_BEAM_SEGS; i++ ) {
		tess.indexes[tess.numIndexes++] =       i      * 2;
		tess.indexes[tess.numIndexes++] =      (i + 1) * 2;
		tess.indexes[tess.numIndexes++] = 1  +  i      * 2;

		tess.indexes[tess.numIndexes++] = 1  +  i      * 2;
		tess.indexes[tess.numIndexes++] =      (i + 1) * 2;
		tess.indexes[tess.numIndexes++] = 1  + (i + 1) * 2;
	}

	tess.minIndex = 0;
	tess.maxIndex = tess.numVertexes;

	// FIXME: A lot of this can probably be removed for speed, and refactored into a more convenient function
	RB_UpdateTessVao(ATTR_POSITION);
	
	GLSL_BindProgram(sp);
		
	GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
					
	GLSL_SetUniformVec4(sp, UNIFORM_COLOR, colorRed);

	R_DrawElementsVao(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex);

	tess.numIndexes = 0;
	tess.numVertexes = 0;
	tess.firstIndex = 0;
	tess.minIndex = 0;
	tess.maxIndex = 0;
}
示例#23
0
文件: be_aas_move.c 项目: TTimo/bspc
//===========================================================================
// predicts the movement
// assumes regular bounding box sizes
// NOTE: out of water jumping is not included
// NOTE: grappling hook is not included
//
// Parameter:			origin			: origin to start with
//						presencetype	: presence type to start with
//						velocity		: velocity to start with
//						cmdmove			: client command movement
//						cmdframes		: number of frame cmdmove is valid
//						maxframes		: maximum number of predicted frames
//						frametime		: duration of one predicted frame
//						stopevent		: events that stop the prediction
//						stopareanum		: stop as soon as entered this area
// Returns:				aas_clientmove_t
// Changes Globals:		-
//===========================================================================
int AAS_ClientMovementPrediction(struct aas_clientmove_s *move,
								int entnum, vec3_t origin,
								int presencetype, int onground,
								vec3_t velocity, vec3_t cmdmove,
								int cmdframes,
								int maxframes, float frametime,
								int stopevent, int stopareanum,
								vec3_t mins, vec3_t maxs, int visualize)
{
	float phys_friction, phys_stopspeed, phys_gravity, phys_waterfriction;
	float phys_watergravity;
	float phys_walkaccelerate, phys_airaccelerate, phys_swimaccelerate;
	float phys_maxwalkvelocity, phys_maxcrouchvelocity, phys_maxswimvelocity;
	float phys_maxstep, phys_maxsteepness, phys_jumpvel, friction;
	float gravity, delta, maxvel, wishspeed, accelerate;
	//float velchange, newvel;
	int n, i, j, pc, step, swimming, crouch, event, jump_frame, areanum;
	int areas[20], numareas;
	vec3_t points[20];
	vec3_t org, end, feet, start, stepend, lastorg, wishdir;
	vec3_t frame_test_vel, old_frame_test_vel, left_test_vel;
	vec3_t up = {0, 0, 1};
	aas_plane_t *plane, *plane2;
	aas_trace_t trace, steptrace;
	
	if (frametime <= 0) frametime = 0.1f;
	//
	phys_friction = aassettings.phys_friction;
	phys_stopspeed = aassettings.phys_stopspeed;
	phys_gravity = aassettings.phys_gravity;
	phys_waterfriction = aassettings.phys_waterfriction;
	phys_watergravity = aassettings.phys_watergravity;
	phys_maxwalkvelocity = aassettings.phys_maxwalkvelocity;// * frametime;
	phys_maxcrouchvelocity = aassettings.phys_maxcrouchvelocity;// * frametime;
	phys_maxswimvelocity = aassettings.phys_maxswimvelocity;// * frametime;
	phys_walkaccelerate = aassettings.phys_walkaccelerate;
	phys_airaccelerate = aassettings.phys_airaccelerate;
	phys_swimaccelerate = aassettings.phys_swimaccelerate;
	phys_maxstep = aassettings.phys_maxstep;
	phys_maxsteepness = aassettings.phys_maxsteepness;
	phys_jumpvel = aassettings.phys_jumpvel * frametime;
	//
	Com_Memset(move, 0, sizeof(aas_clientmove_t));
	Com_Memset(&trace, 0, sizeof(aas_trace_t));
	//start at the current origin
	VectorCopy(origin, org);
	org[2] += 0.25;
	//velocity to test for the first frame
	VectorScale(velocity, frametime, frame_test_vel);
	//
	jump_frame = -1;
	//predict a maximum of 'maxframes' ahead
	for (n = 0; n < maxframes; n++)
	{
		swimming = AAS_Swimming(org);
		//get gravity depending on swimming or not
		gravity = swimming ? phys_watergravity : phys_gravity;
		//apply gravity at the START of the frame
		frame_test_vel[2] = frame_test_vel[2] - (gravity * 0.1 * frametime);
		//if on the ground or swimming
		if (onground || swimming)
		{
			friction = swimming ? phys_friction : phys_waterfriction;
			//apply friction
			VectorScale(frame_test_vel, 1/frametime, frame_test_vel);
			AAS_ApplyFriction(frame_test_vel, friction, phys_stopspeed, frametime);
			VectorScale(frame_test_vel, frametime, frame_test_vel);
		} //end if
		crouch = qfalse;
		//apply command movement
		if (n < cmdframes)
		{
			maxvel = phys_maxwalkvelocity;
			accelerate = phys_airaccelerate;
			VectorCopy(cmdmove, wishdir);
			if (onground)
			{
				if (cmdmove[2] < -300)
				{
					crouch = qtrue;
					maxvel = phys_maxcrouchvelocity;
				} //end if
				//if not swimming and upmove is positive then jump
				if (!swimming && cmdmove[2] > 1)
				{
					//jump velocity minus the gravity for one frame + 5 for safety
					frame_test_vel[2] = phys_jumpvel - (gravity * 0.1 * frametime) + 5;
					jump_frame = n;
					//jumping so air accelerate
					accelerate = phys_airaccelerate;
				} //end if
				else
				{
					accelerate = phys_walkaccelerate;
				} //end else
			} //end if
			if (swimming)
			{
				maxvel = phys_maxswimvelocity;
				accelerate = phys_swimaccelerate;
			} //end if
			else
			{
				wishdir[2] = 0;
			} //end else
			//
			wishspeed = VectorNormalize(wishdir);
			if (wishspeed > maxvel) wishspeed = maxvel;
			VectorScale(frame_test_vel, 1/frametime, frame_test_vel);
			AAS_Accelerate(frame_test_vel, frametime, wishdir, wishspeed, accelerate);
			VectorScale(frame_test_vel, frametime, frame_test_vel);
		} //end if
		if (crouch)
		{
			presencetype = PRESENCE_CROUCH;
		} //end if
		else if (presencetype == PRESENCE_CROUCH)
		{
			if (AAS_PointPresenceType(org) & PRESENCE_NORMAL)
			{
				presencetype = PRESENCE_NORMAL;
			} //end if
		} //end else
		//save the current origin
		VectorCopy(org, lastorg);
		//move linear during one frame
		VectorCopy(frame_test_vel, left_test_vel);
		j = 0;
		do
		{
			VectorAdd(org, left_test_vel, end);
			//trace a bounding box
			trace = AAS_TraceClientBBox(org, end, presencetype, entnum);
			//
//#ifdef AAS_MOVE_DEBUG
			if (visualize)
			{
				if (trace.startsolid) botimport.Print(PRT_MESSAGE, "PredictMovement: start solid\n");
				AAS_DebugLine(org, trace.endpos, LINECOLOR_RED);
			} //end if
//#endif //AAS_MOVE_DEBUG
			//
			if (stopevent & (SE_ENTERAREA|SE_TOUCHJUMPPAD|SE_TOUCHTELEPORTER|SE_TOUCHCLUSTERPORTAL))
			{
				numareas = AAS_TraceAreas(org, trace.endpos, areas, points, 20);
				for (i = 0; i < numareas; i++)
				{
					if (stopevent & SE_ENTERAREA)
					{
						if (areas[i] == stopareanum)
						{
							VectorCopy(points[i], move->endpos);
							VectorScale(frame_test_vel, 1/frametime, move->velocity);
							move->endarea = areas[i];
							move->trace = trace;
							move->stopevent = SE_ENTERAREA;
							move->presencetype = presencetype;
							move->endcontents = 0;
							move->time = n * frametime;
							move->frames = n;
							return qtrue;
						} //end if
					} //end if
					//NOTE: if not the first frame
					if ((stopevent & SE_TOUCHJUMPPAD) && n)
					{
						if (aasworld.areasettings[areas[i]].contents & AREACONTENTS_JUMPPAD)
						{
							VectorCopy(points[i], move->endpos);
							VectorScale(frame_test_vel, 1/frametime, move->velocity);
							move->endarea = areas[i];
							move->trace = trace;
							move->stopevent = SE_TOUCHJUMPPAD;
							move->presencetype = presencetype;
							move->endcontents = 0;
							move->time = n * frametime;
							move->frames = n;
							return qtrue;
						} //end if
					} //end if
					if (stopevent & SE_TOUCHTELEPORTER)
					{
						if (aasworld.areasettings[areas[i]].contents & AREACONTENTS_TELEPORTER)
						{
							VectorCopy(points[i], move->endpos);
							move->endarea = areas[i];
							VectorScale(frame_test_vel, 1/frametime, move->velocity);
							move->trace = trace;
							move->stopevent = SE_TOUCHTELEPORTER;
							move->presencetype = presencetype;
							move->endcontents = 0;
							move->time = n * frametime;
							move->frames = n;
							return qtrue;
						} //end if
					} //end if
					if (stopevent & SE_TOUCHCLUSTERPORTAL)
					{
						if (aasworld.areasettings[areas[i]].contents & AREACONTENTS_CLUSTERPORTAL)
						{
							VectorCopy(points[i], move->endpos);
							move->endarea = areas[i];
							VectorScale(frame_test_vel, 1/frametime, move->velocity);
							move->trace = trace;
							move->stopevent = SE_TOUCHCLUSTERPORTAL;
							move->presencetype = presencetype;
							move->endcontents = 0;
							move->time = n * frametime;
							move->frames = n;
							return qtrue;
						} //end if
					} //end if
				} //end for
			} //end if
			//
			if (stopevent & SE_HITBOUNDINGBOX)
			{
				if (AAS_ClipToBBox(&trace, org, trace.endpos, presencetype, mins, maxs))
				{
					VectorCopy(trace.endpos, move->endpos);
					move->endarea = AAS_PointAreaNum(move->endpos);
					VectorScale(frame_test_vel, 1/frametime, move->velocity);
					move->trace = trace;
					move->stopevent = SE_HITBOUNDINGBOX;
					move->presencetype = presencetype;
					move->endcontents = 0;
					move->time = n * frametime;
					move->frames = n;
					return qtrue;
				} //end if
			} //end if
			//move the entity to the trace end point
			VectorCopy(trace.endpos, org);
			//if there was a collision
			if (trace.fraction < 1.0)
			{
				//get the plane the bounding box collided with
				plane = AAS_PlaneFromNum(trace.planenum);
				//
				if (stopevent & SE_HITGROUNDAREA)
				{
					if (DotProduct(plane->normal, up) > phys_maxsteepness)
					{
						VectorCopy(org, start);
						start[2] += 0.5;
						if (AAS_PointAreaNum(start) == stopareanum)
						{
							VectorCopy(start, move->endpos);
							move->endarea = stopareanum;
							VectorScale(frame_test_vel, 1/frametime, move->velocity);
							move->trace = trace;
							move->stopevent = SE_HITGROUNDAREA;
							move->presencetype = presencetype;
							move->endcontents = 0;
							move->time = n * frametime;
							move->frames = n;
							return qtrue;
						} //end if
					} //end if
				} //end if
				//assume there's no step
				step = qfalse;
				//if it is a vertical plane and the bot didn't jump recently
				if (plane->normal[2] == 0 && (jump_frame < 0 || n - jump_frame > 2))
				{
					//check for a step
					VectorMA(org, -0.25, plane->normal, start);
					VectorCopy(start, stepend);
					start[2] += phys_maxstep;
					steptrace = AAS_TraceClientBBox(start, stepend, presencetype, entnum);
					//
					if (!steptrace.startsolid)
					{
						plane2 = AAS_PlaneFromNum(steptrace.planenum);
						if (DotProduct(plane2->normal, up) > phys_maxsteepness)
						{
							VectorSubtract(end, steptrace.endpos, left_test_vel);
							left_test_vel[2] = 0;
							frame_test_vel[2] = 0;
//#ifdef AAS_MOVE_DEBUG
							if (visualize)
							{
								if (steptrace.endpos[2] - org[2] > 0.125)
								{
									VectorCopy(org, start);
									start[2] = steptrace.endpos[2];
									AAS_DebugLine(org, start, LINECOLOR_BLUE);
								} //end if
							} //end if
//#endif //AAS_MOVE_DEBUG
							org[2] = steptrace.endpos[2];
							step = qtrue;
						} //end if
					} //end if
				} //end if
				//
				if (!step)
				{
					//velocity left to test for this frame is the projection
					//of the current test velocity into the hit plane 
					VectorMA(left_test_vel, -DotProduct(left_test_vel, plane->normal),
										plane->normal, left_test_vel);
					//store the old velocity for landing check
					VectorCopy(frame_test_vel, old_frame_test_vel);
					//test velocity for the next frame is the projection
					//of the velocity of the current frame into the hit plane 
					VectorMA(frame_test_vel, -DotProduct(frame_test_vel, plane->normal),
										plane->normal, frame_test_vel);
					//check for a landing on an almost horizontal floor
					if (DotProduct(plane->normal, up) > phys_maxsteepness)
					{
						onground = qtrue;
					} //end if
					if (stopevent & SE_HITGROUNDDAMAGE)
					{
						delta = 0;
						if (old_frame_test_vel[2] < 0 &&
								frame_test_vel[2] > old_frame_test_vel[2] &&
								!onground)
						{
							delta = old_frame_test_vel[2];
						} //end if
						else if (onground)
						{
							delta = frame_test_vel[2] - old_frame_test_vel[2];
						} //end else
						if (delta)
						{
							delta = delta * 10;
							delta = delta * delta * 0.0001;
							if (swimming) delta = 0;
							// never take falling damage if completely underwater
							/*
							if (ent->waterlevel == 3) return;
							if (ent->waterlevel == 2) delta *= 0.25;
							if (ent->waterlevel == 1) delta *= 0.5;
							*/
							if (delta > 40)
							{
								VectorCopy(org, move->endpos);
								move->endarea = AAS_PointAreaNum(org);
								VectorCopy(frame_test_vel, move->velocity);
								move->trace = trace;
								move->stopevent = SE_HITGROUNDDAMAGE;
								move->presencetype = presencetype;
								move->endcontents = 0;
								move->time = n * frametime;
								move->frames = n;
								return qtrue;
							} //end if
						} //end if
					} //end if
				} //end if
			} //end if
			//extra check to prevent endless loop
			if (++j > 20) return qfalse;
		//while there is a plane hit
		} while(trace.fraction < 1.0);
		//if going down
		if (frame_test_vel[2] <= 10)
		{
			//check for a liquid at the feet of the bot
			VectorCopy(org, feet);
			feet[2] -= 22;
			pc = AAS_PointContents(feet);
			//get event from pc
			event = SE_NONE;
			if (pc & CONTENTS_LAVA) event |= SE_ENTERLAVA;
			if (pc & CONTENTS_SLIME) event |= SE_ENTERSLIME;
			if (pc & CONTENTS_WATER) event |= SE_ENTERWATER;
			//
			areanum = AAS_PointAreaNum(org);
			if (aasworld.areasettings[areanum].contents & AREACONTENTS_LAVA)
				event |= SE_ENTERLAVA;
			if (aasworld.areasettings[areanum].contents & AREACONTENTS_SLIME)
				event |= SE_ENTERSLIME;
			if (aasworld.areasettings[areanum].contents & AREACONTENTS_WATER)
				event |= SE_ENTERWATER;
			//if in lava or slime
			if (event & stopevent)
			{
				VectorCopy(org, move->endpos);
				move->endarea = areanum;
				VectorScale(frame_test_vel, 1/frametime, move->velocity);
				move->stopevent = event & stopevent;
				move->presencetype = presencetype;
				move->endcontents = pc;
				move->time = n * frametime;
				move->frames = n;
				return qtrue;
			} //end if
		} //end if
		//
		onground = AAS_OnGround(org, presencetype, entnum);
		//if onground and on the ground for at least one whole frame
		if (onground)
		{
			if (stopevent & SE_HITGROUND)
			{
				VectorCopy(org, move->endpos);
				move->endarea = AAS_PointAreaNum(org);
				VectorScale(frame_test_vel, 1/frametime, move->velocity);
				move->trace = trace;
				move->stopevent = SE_HITGROUND;
				move->presencetype = presencetype;
				move->endcontents = 0;
				move->time = n * frametime;
				move->frames = n;
				return qtrue;
			} //end if
		} //end if
		else if (stopevent & SE_LEAVEGROUND)
		{
			VectorCopy(org, move->endpos);
			move->endarea = AAS_PointAreaNum(org);
			VectorScale(frame_test_vel, 1/frametime, move->velocity);
			move->trace = trace;
			move->stopevent = SE_LEAVEGROUND;
			move->presencetype = presencetype;
			move->endcontents = 0;
			move->time = n * frametime;
			move->frames = n;
			return qtrue;
		} //end else if
		else if (stopevent & SE_GAP)
		{
			aas_trace_t gaptrace;

			VectorCopy(org, start);
			VectorCopy(start, end);
			end[2] -= 48 + aassettings.phys_maxbarrier;
			gaptrace = AAS_TraceClientBBox(start, end, PRESENCE_CROUCH, -1);
			//if solid is found the bot cannot walk any further and will not fall into a gap
			if (!gaptrace.startsolid)
			{
				//if it is a gap (lower than one step height)
				if (gaptrace.endpos[2] < org[2] - aassettings.phys_maxstep - 1)
				{
					if (!(AAS_PointContents(end) & CONTENTS_WATER))
					{
						VectorCopy(lastorg, move->endpos);
						move->endarea = AAS_PointAreaNum(lastorg);
						VectorScale(frame_test_vel, 1/frametime, move->velocity);
						move->trace = trace;
						move->stopevent = SE_GAP;
						move->presencetype = presencetype;
						move->endcontents = 0;
						move->time = n * frametime;
						move->frames = n;
						return qtrue;
					} //end if
				} //end if
			} //end if
		} //end else if
	} //end for
	//
	VectorCopy(org, move->endpos);
	move->endarea = AAS_PointAreaNum(org);
	VectorScale(frame_test_vel, 1/frametime, move->velocity);
	move->stopevent = SE_NONE;
	move->presencetype = presencetype;
	move->endcontents = 0;
	move->time = n * frametime;
	move->frames = n;
	//
	return qtrue;
} //end of the function AAS_ClientMovementPrediction
示例#24
0
static void DoRailDiscs( int numSegs, const vec3_t start, const vec3_t dir, const vec3_t right, const vec3_t up )
{
	int i;
	vec3_t	pos[4];
	vec3_t	v;
	int		spanWidth = r_railWidth->integer;
	float c, s;
	float		scale;

	if ( numSegs > 1 )
		numSegs--;
	if ( !numSegs )
		return;

	scale = 0.25;

	for ( i = 0; i < 4; i++ )
	{
		c = cos( DEG2RAD( 45 + i * 90 ) );
		s = sin( DEG2RAD( 45 + i * 90 ) );
		v[0] = ( right[0] * c + up[0] * s ) * scale * spanWidth;
		v[1] = ( right[1] * c + up[1] * s ) * scale * spanWidth;
		v[2] = ( right[2] * c + up[2] * s ) * scale * spanWidth;
		VectorAdd( start, v, pos[i] );

		if ( numSegs > 1 )
		{
			// offset by 1 segment if we're doing a long distance shot
			VectorAdd( pos[i], dir, pos[i] );
		}
	}

	RB_CheckVao(tess.vao);

	for ( i = 0; i < numSegs; i++ )
	{
		int j;

		RB_CHECKOVERFLOW( 4, 6 );

		for ( j = 0; j < 4; j++ )
		{
			VectorCopy( pos[j], tess.xyz[tess.numVertexes] );
			tess.texCoords[tess.numVertexes][0] = (j < 2);
			tess.texCoords[tess.numVertexes][1] = (j && j != 3);
			tess.color[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] * 257;
			tess.color[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] * 257;
			tess.color[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] * 257;
			tess.numVertexes++;

			VectorAdd( pos[j], dir, pos[j] );
		}

		tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 0;
		tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 1;
		tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 3;
		tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 3;
		tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 1;
		tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 2;
	}
}
示例#25
0
qboolean M_CheckBottom (edict_t *ent)
{
    vec3_t	mins, maxs, start, stop;
    trace_t	trace;
    int		x, y;
    float	mid, bottom;

    VectorAdd (ent->s.origin, ent->mins, mins);
    VectorAdd (ent->s.origin, ent->maxs, maxs);

// if all of the points under the corners are solid world, don't bother
// with the tougher checks
// the corners must be within 16 of the midpoint
    start[2] = mins[2] - 1;
    for	(x=0 ; x<=1 ; x++)
        for	(y=0 ; y<=1 ; y++)
        {
            start[0] = x ? maxs[0] : mins[0];
            start[1] = y ? maxs[1] : mins[1];
            if (gi.pointcontents (start) != CONTENTS_SOLID)
                goto realcheck;
        }

    c_yes++;
    return true;		// we got out easy

realcheck:
    c_no++;
//
// check it for real...
//
    start[2] = mins[2];

// the midpoint must be within 16 of the bottom
    start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
    start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
    stop[2] = start[2] - 2*STEPSIZE;
    trace = gi.trace (start, vec3_origin, vec3_origin, stop, ent, MASK_MONSTERSOLID);

    if (trace.fraction == 1.0f)
        return false;
    mid = bottom = trace.endpos[2];

// the corners must be within 16 of the midpoint
    for	(x=0 ; x<=1 ; x++)
        for	(y=0 ; y<=1 ; y++)
        {
            start[0] = stop[0] = x ? maxs[0] : mins[0];
            start[1] = stop[1] = y ? maxs[1] : mins[1];

            trace = gi.trace (start, vec3_origin, vec3_origin, stop, ent, MASK_MONSTERSOLID);

            if (trace.fraction != 1.0f && trace.endpos[2] > bottom)
                bottom = trace.endpos[2];
            if (trace.fraction == 1.0f || mid - trace.endpos[2] > STEPSIZE)
                return false;
        }

    c_yes++;
    return true;
}
示例#26
0
文件: g_arty.c 项目: basecq/q2dos
void Think_Arty (edict_t *ent)
{
	vec3_t	start;
	vec3_t	forward;
	vec3_t	end;
	vec3_t	targetdir;
	vec3_t  tempvec;
	trace_t	tr;
	trace_t tr_2;

	if (!ent->owner ||
	    !ent->owner->client ||
	    !ent->owner->inuse ||
	    !ent->owner->client->resp.team_on ||
		ent->owner->flyingnun)
	{
		G_FreeEdict(ent);
		return;
	}

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

	if (ent->owner->client->airstrike &&
		ent->owner->client->airstrike != ent)
	{
		G_FreeEdict(ent);
		return;
	}

	// find the target point
	VectorCopy(ent->owner->s.origin, start);
	start[2] += ent->owner->viewheight;
	AngleVectors(ent->owner->client->v_angle, forward, NULL, NULL);
	VectorMA(start, 8192, forward, end);
	tr = gi.trace(start, NULL, NULL, end, ent->owner, MASK_SHOT|CONTENTS_SLIME|CONTENTS_LAVA);
	(void)tr;/*** FIXME: 'tr' IS UNUSED HERE! ***/

	// find the direction from the entry point to the target
    VectorSubtract(ent->owner->client->arty_target, ent->owner->client->arty_entry, targetdir);
    VectorNormalize(targetdir);
    VectorAdd(ent->owner->client->arty_entry, targetdir, start);
	
   // check we have a clear line of fire
    tr_2 = gi.trace(start, NULL, NULL, ent->owner->client->arty_target, ent, MASK_SHOT|CONTENTS_SLIME|CONTENTS_LAVA);

	// check to make sure we're not materializing in a solid
	if ( gi.pointcontents(start) == CONTENTS_SOLID || tr_2.fraction < 1.0 )
	{
		safe_cprintf(ent->owner, PRINT_HIGH, "Artillery fire was unsuccessful, sir!\n");
		return;
	}

//    gi.sound(ent, CHAN_AUTO, gi.soundindex(va("%s/arty/hit%i.wav", ent->client->resp.team_on->teamid, ent->client->arty_location)), 1, ATTN_NORM, 0);
  //		if (IsValidPlayer(ent))
	//		gi.sound(ent->owner, CHAN_AUTO, gi.soundindex(va("%s/arty/hit%i.wav", ent->owner->client->resp.team_on->teamid, 1)), 1, ATTN_NORM, 0);

	// fire away!

    /* old arty code
    fire_rocket(ent, start, targetdir, 700, 250, 300, 450);
    fire_rocket(ent, start, targetdir, 600, 450, 200, 430);
    fire_rocket(ent, start, targetdir, 400, 150, 400, 500);
    fire_rocket(ent, start, targetdir, 600, 210, 250, 500);
    fire_rocket(ent, start, targetdir, 300, 430, 200, 450);
    fire_rocket(ent, start, targetdir, 600, 240, 320, 480);
    */

	fire_airstrike(ent->owner, start, targetdir, 700, 250, 300, 450);
	VectorSet(tempvec, 8, 8, 0);
	VectorAdd(tempvec, start, tempvec);
    fire_airstrike(ent->owner, tempvec, targetdir, 600, 450, 200, 430);
	VectorSet(tempvec, 16, 16, 0);
	VectorAdd(tempvec, start, tempvec);
    fire_airstrike(ent->owner, tempvec, targetdir, 400, 150, 400, 500);
	VectorSet(tempvec, 24, 24, 0);
	VectorAdd(tempvec, start, tempvec);
    fire_airstrike(ent->owner, tempvec, targetdir, 600, 210, 250, 500);
	VectorSet(tempvec, 32, 32, 0);
	VectorAdd(tempvec, start, tempvec);
    fire_airstrike(ent->owner, tempvec, targetdir, 300, 430, 200, 450);
	VectorSet(tempvec, 40, 40, 0);
	VectorAdd(tempvec, start, tempvec);
    fire_airstrike(ent->owner, tempvec, targetdir, 600, 240, 320, 480);

	//fire_shell(ent, start, targetdir, 250, ((rand()%500)+900), 300, 75); 	
	
	safe_cprintf(ent->owner, PRINT_HIGH, "Artillery fire confirmed, sir!\n");

	ent->think = G_FreeEdict;
	ent->nextthink = level.time +.1;

	ent->owner->client->airstrike = NULL;

	ent->owner->client->arty_time_restrict = level.time + arty_time->value; // delay for user defined minutes
}
示例#27
0
void CG_AddTrailToScene( trailJunc_t *trail, int iteration, int numJuncs )
{
	int		k, i, n, l, numOutVerts;
	polyVert_t	mid;
	float	mod[4];
	float	sInc, s;
	trailJunc_t	*j, *jNext;
	vec3_t	fwd, up, p, v;
	// clipping vars
	#define	TRAIL_FADE_CLOSE_DIST	64.0
	#define	TRAIL_FADE_FAR_SCALE	4.0
	vec3_t	viewProj;
	float	viewDist, fadeAlpha;

	// add spark shader at head position
	if (trail->flags & TJFL_SPARKHEADFLARE) {
		j = trail;
		VectorCopy( j->pos, p );
		VectorMA (p, -j->width*2, vup, p);	
		VectorMA (p, -j->width*2, vright, p);	
		VectorCopy (p, verts[0].xyz);	
		verts[0].st[0] = 0;	
		verts[0].st[1] = 0;	
		verts[0].modulate[0] = 255;	
		verts[0].modulate[1] = 255;	
		verts[0].modulate[2] = 255;	
		verts[0].modulate[3] = (unsigned char)(j->alpha*255.0);

		VectorCopy( j->pos, p );
		VectorMA (p, -j->width*2, vup, p);	
		VectorMA (p, j->width*2, vright, p);	
		VectorCopy (p, verts[1].xyz);	
		verts[1].st[0] = 0;	
		verts[1].st[1] = 1;	
		verts[1].modulate[0] = 255;	
		verts[1].modulate[1] = 255;	
		verts[1].modulate[2] = 255;	
		verts[1].modulate[3] = (unsigned char)(j->alpha*255.0);	

		VectorCopy( j->pos, p );
		VectorMA (p, j->width*2, vup, p);	
		VectorMA (p, j->width*2, vright, p);	
		VectorCopy (p, verts[2].xyz);	
		verts[2].st[0] = 1;	
		verts[2].st[1] = 1;	
		verts[2].modulate[0] = 255;	
		verts[2].modulate[1] = 255;	
		verts[2].modulate[2] = 255;	
		verts[2].modulate[3] = (unsigned char)(j->alpha*255.0);	

		VectorCopy( j->pos, p );
		VectorMA (p,  j->width*2, vup, p);	
		VectorMA (p, -j->width*2, vright, p);	
		VectorCopy (p, verts[3].xyz);	
		verts[3].st[0] = 1;	
		verts[3].st[1] = 0;	
		verts[3].modulate[0] = 255;	
		verts[3].modulate[1] = 255;	
		verts[3].modulate[2] = 255;	
		verts[3].modulate[3] = (unsigned char)(j->alpha*255.0);	

		trap_R_AddPolyToScene( cgs.media.sparkFlareShader, 4, verts );
	}

//	if (trail->flags & TJFL_CROSSOVER && iteration < 1) {
//		iteration = 1;
//	}

	sInc = 0;
	
	if (!numJuncs) {
		// first count the number of juncs in the trail
		j = trail;
		numJuncs = 0;
		sInc = 0;
		while (j) {
			numJuncs++;

			// check for a dead next junc
			if (!j->inuse && j->nextJunc && !j->nextJunc->inuse) {
				CG_KillTrail( j );
			} else if (j->nextJunc && j->nextJunc->freed) {
				// not sure how this can happen, but it does, and causes infinite loops
				j->nextJunc = NULL;
			}

			if (j->nextJunc)
				sInc += VectorDistance( j->nextJunc->pos, j->pos );

			j = j->nextJunc;
		}
	}

	if (numJuncs < 2) {
		return;
	}

	s = 0;
	if (trail->sType == STYPE_STRETCH) {
		//sInc = ((1.0 - 0.1) / (float)(numJuncs));	// hack, the end of funnel shows a bit of the start (looping)
		s = 0.05;
		//s = 0.05;
	} else if (trail->sType == STYPE_REPEAT) {
		s = trail->sTex;
	}

	// now traverse the list
	j = trail;
	jNext = j->nextJunc;
	i = 0;
	while (jNext) {

		// first get the directional vectors to the next junc
		VectorSubtract( jNext->pos, j->pos, fwd );
		GetPerpendicularViewVector( cg.refdef.vieworg, j->pos, jNext->pos, up );

		// if it's a crossover, draw it twice
		if (j->flags & TJFL_CROSSOVER) {
			if (iteration > 0) {
				ProjectPointOntoVector( cg.refdef.vieworg, j->pos, jNext->pos, viewProj );
				VectorSubtract( cg.refdef.vieworg, viewProj, v );
				VectorNormalize( v );

				if (iteration == 1) {
					VectorMA( up, 0.3, v, up );
				} else {
					VectorMA( up, -0.3, v, up );
				}
				VectorNormalize( up );
			}
		}
		// do fading when moving towards the projection point onto the trail segment vector
		else if (!(j->flags & TJFL_NOCULL) && (j->widthEnd > 4 || jNext->widthEnd > 4)) {
			ProjectPointOntoVector( cg.refdef.vieworg, j->pos, jNext->pos, viewProj );
			viewDist = Distance( viewProj, cg.refdef.vieworg );
			if (viewDist < (TRAIL_FADE_CLOSE_DIST * TRAIL_FADE_FAR_SCALE)) {
				if (viewDist < TRAIL_FADE_CLOSE_DIST) {
					fadeAlpha = 0.0;
				} else {
					fadeAlpha = (viewDist - TRAIL_FADE_CLOSE_DIST) / (TRAIL_FADE_CLOSE_DIST * TRAIL_FADE_FAR_SCALE);
				}
				if (fadeAlpha < j->alpha) {
					j->alpha = fadeAlpha;
				}
				if (fadeAlpha < jNext->alpha) {
					jNext->alpha = fadeAlpha;
				}
			}
		}

		// now output the QUAD for this segment

		// 1 ----
		VectorMA( j->pos, 0.5*j->width, up, p );
		VectorCopy( p, verts[i].xyz );
		verts[i].st[0] = s;
		verts[i].st[1] = 1.0;
		for (k=0; k<3; k++)
			verts[i].modulate[k] = (unsigned char)(j->color[k]*255.0);
		verts[i].modulate[3] = (unsigned char)(j->alpha*255.0);

		// blend this with the previous junc
		if (j != trail) {
			VectorAdd( verts[i].xyz, verts[i-1].xyz, verts[i].xyz );
			VectorScale( verts[i].xyz, 0.5, verts[i].xyz );
			VectorCopy( verts[i].xyz, verts[i-1].xyz );
		} else if (j->flags & TJFL_FADEIN) {
			verts[i].modulate[3] = 0;	// fade in
		}

		i++;

		// 2 ----
		VectorMA( p, -1*j->width, up, p );
		VectorCopy( p, verts[i].xyz );
		verts[i].st[0] = s;
		verts[i].st[1] = 0.0;
		for (k=0; k<3; k++)
			verts[i].modulate[k] = (unsigned char)(j->color[k]*255.0);
		verts[i].modulate[3] = (unsigned char)(j->alpha*255.0);

		// blend this with the previous junc
		if (j != trail) {
			VectorAdd( verts[i].xyz, verts[i-3].xyz, verts[i].xyz );
			VectorScale( verts[i].xyz, 0.5, verts[i].xyz );
			VectorCopy( verts[i].xyz, verts[i-3].xyz );
		} else if (j->flags & TJFL_FADEIN) {
			verts[i].modulate[3] = 0;	// fade in
		}

		i++;

		if (trail->sType == STYPE_REPEAT)
			s = jNext->sTex;
		else {
			//s += sInc;
			s += VectorDistance( j->pos, jNext->pos ) / sInc;
			if (s > 1.0) s = 1.0;
		}

		// 3 ----
		VectorMA( jNext->pos, -0.5*jNext->width, up, p );
		VectorCopy( p, verts[i].xyz );
		verts[i].st[0] = s;
		verts[i].st[1] = 0.0;
		for (k=0; k<3; k++)
			verts[i].modulate[k] = (unsigned char)(jNext->color[k]*255.0);
		verts[i].modulate[3] = (unsigned char)(jNext->alpha*255.0);
		i++;

		// 4 ----
		VectorMA( p, jNext->width, up, p );
		VectorCopy( p, verts[i].xyz );
		verts[i].st[0] = s;
		verts[i].st[1] = 1.0;
		for (k=0; k<3; k++)
			verts[i].modulate[k] = (unsigned char)(jNext->color[k]*255.0);
		verts[i].modulate[3] = (unsigned char)(jNext->alpha*255.0);
		i++;

		if (i+4 > MAX_TRAIL_VERTS)
			break;

		j = jNext;
		jNext = j->nextJunc;
	}

	if (trail->flags & TJFL_FIXDISTORT) {
		// build the list of outVerts, by dividing up the QUAD's into 4 Tri's each, so as to allow
		//	any shaped (convex) Quad without bilinear distortion
		for (k=0, numOutVerts=0; k<i; k+=4) {
			VectorCopy(verts[k].xyz, mid.xyz);
			mid.st[0] = verts[k].st[0];
			mid.st[1] = verts[k].st[1];
			for (l=0; l<4; l++) {
				mod[l] = (float)verts[k].modulate[l];
			}
			for (n=1; n<4; n++) {
				VectorAdd( verts[k+n].xyz, mid.xyz, mid.xyz );
				mid.st[0] += verts[k+n].st[0];
				mid.st[1] += verts[k+n].st[1];
				for (l=0; l<4; l++) {
					mod[l] += (float)verts[k+n].modulate[l];
				}
			}
			VectorScale( mid.xyz, 0.25, mid.xyz );
			mid.st[0] *= 0.25;
			mid.st[1] *= 0.25;
			for (l=0; l<4; l++) {
				mid.modulate[l] = (unsigned char)(mod[l]/4.0);
			}

			// now output the tri's
			for (n=0; n<4; n++) {
				outVerts[numOutVerts++] = verts[k+n];
				outVerts[numOutVerts++] = mid;
				if (n<3) {
					outVerts[numOutVerts++] = verts[k+n+1];
				} else {
					outVerts[numOutVerts++] = verts[k];
				}
			}
			
		}

		if (!(trail->flags & TJFL_NOPOLYMERGE)) {
			trap_R_AddPolysToScene( trail->shader, 3, &outVerts[0], numOutVerts/3 );
		} else {
			int k;
			for (k=0; k<numOutVerts/3; k++) {
				trap_R_AddPolyToScene( trail->shader, 3, &outVerts[k*3] );
			}
		}
	}
	else
	{
		// send the polygons
		// FIXME: is it possible to send a GL_STRIP here? We are actually sending 2x the verts we really need to
		if (!(trail->flags & TJFL_NOPOLYMERGE)) {
			trap_R_AddPolysToScene( trail->shader, 4, &verts[0], i/4 );
		} else {
			int k;
			for (k=0; k<i/4; k++) {
				trap_R_AddPolyToScene( trail->shader, 4, &verts[k*4] );
			}
		}
	}

	// do we need to make another pass?
	if (trail->flags & TJFL_CROSSOVER) {
		if (iteration < 2) {
			CG_AddTrailToScene( trail, iteration + 1, numJuncs );
		}
	}

}
示例#28
0
/*
==============
TDM_GetPlayerIdView
==============
Find the best player for the id view and return a configstring index that contains their info.
*/
int TDM_GetPlayerIdView (edict_t *ent)
{
    edict_t		*ignore;
    edict_t		*target;
    vec3_t		forward;
    trace_t		tr;
    vec3_t		start;
    vec3_t		mins = {-4,-4,-4};
    vec3_t		maxs = {4,4,4};
    qboolean	ignoreConfigStringUpdate;
    int			i;
    int			powerarmor;
    qboolean	show_health_info;

    ignoreConfigStringUpdate = false;

    if (ent->client->chase_target)
    {
        target = ent->client->chase_target->client->resp.last_id_client;
    }
    else
    {
        int	tracemask;

        VectorCopy (ent->s.origin, start);
        start[2] += ent->viewheight;

        AngleVectors (ent->client->v_angle, forward, NULL, NULL);

        VectorScale (forward, 4096, forward);
        VectorAdd (ent->s.origin, forward, forward);

        ignore = ent;

        target = NULL;

        tracemask = CONTENTS_SOLID|CONTENTS_MONSTER|MASK_WATER;

        //find best player through tracing
        for (i = 0; i < 10; i++)
        {
            tr = gi.trace (start, mins, maxs, forward, ignore, tracemask);

            //hit transparent water
            if (tr.ent == world && tr.surface && (tr.surface->flags & (SURF_TRANS33|SURF_TRANS66)))
            {
                tracemask &= ~MASK_WATER;
                VectorCopy (tr.endpos, start);
                continue;
            }

            if (tr.ent == world || tr.fraction == 1.0f)
                break;

            //we hit something that's a player and it's alive and on our team!
            //note, we trace twice so we hit water planes
            if (tr.ent && tr.ent->client && tr.ent->health > 0 && visible (tr.ent, ent, CONTENTS_SOLID | MASK_WATER))
            {
                target = tr.ent;
                break;
            }
            else
            {
                VectorCopy (tr.endpos, start);
                ignore = tr.ent;
            }
        }

        //if trace was unsuccessful, try guessing based on angles
        if (!target)
        {
            edict_t		*who, *best;
            vec3_t		dir;
            float		distance, bdistance = 0.0f;
            float		bd = 0.0f, d;

            AngleVectors (ent->client->v_angle, forward, NULL, NULL);
            best = NULL;

            for (who = g_edicts + 1; who <= g_edicts + game.maxclients; who++)
            {
                if (!who->inuse)
                    continue;

                if (who->health <= 0)
                    continue;

                if (who == ent)
                    continue;

                VectorSubtract (who->s.origin, ent->s.origin, dir);
                distance = VectorLength (dir);

                VectorNormalize (dir);
                d = DotProduct (forward, dir);

                //note, we trace twice so we hit water planes
                if (d > bd && visible (ent, who, CONTENTS_SOLID | MASK_WATER) && visible (who, ent, CONTENTS_SOLID | MASK_WATER))
                {
                    bdistance = distance;
                    bd = d;
                    best = who;
                }
            }

            if (best)
            {
                if (!best->client->pers.team)
                    TDM_Error ("TDM_GetPlayerIdView: Got a spectator via DotProduct with %d health (%s)", best->health, best->client->pers.netname);
                //allow variable slop based on proximity
                if ((bdistance < 150 && bd > 0.50f) || (bdistance < 250 && bd > 0.90f) || (bdistance < 600 && bd > 0.96f) || bd > 0.98f)
                    target = best;
            }
        }
        else if (!target->client->pers.team)
            TDM_Error ("TDM_GetPlayerIdView: Got a spectator via trace with %d health (%s)", target->health, target->client->pers.netname);
    }

    if (!target)
        return 0;

    show_health_info = false;

    if (ent->client->pers.team == target->client->pers.team)
    {
        //same team, show health info
        show_health_info = true;
    }
    else if (ent->client->pers.team == TEAM_SPEC)
    {
        /*if (!ent->client->chase_target)
        {
        	//free floating camera, DON'T show health info
        	show_health_info = false;
        }
        else */
        if (ent->client->chase_target && ent->client->chase_target->client->pers.team == target->client->pers.team)
        {
            //viewing someone on the same team as our chase target, show health info
            show_health_info = true;
        }
    }

    //check for power armor
    if (target->client->inventory[ITEM_ITEM_POWER_SCREEN] > 0 || target->client->inventory[ITEM_ITEM_POWER_SHIELD] > 0)
        powerarmor = target->client->inventory[ITEM_AMMO_CELLS];
    else
        powerarmor = -1;

    //don't spam configstring if they haven't changed since last time
    if (ent->client->resp.last_id_client == target &&
            ent->client->resp.last_id_health == target->health &&
            ent->client->resp.last_id_armor == TDM_GetArmorValue (target) &&
            ent->client->resp.last_id_powerarmor == powerarmor)
        ignoreConfigStringUpdate = true;

    ent->client->resp.last_id_client = target;
    ent->client->resp.last_id_health = target->health;
    ent->client->resp.last_id_armor = TDM_GetArmorValue (target);
    ent->client->resp.last_id_powerarmor = powerarmor;

    if (!ignoreConfigStringUpdate)
    {
        char	*string;

        if (show_health_info)
        {
            char	buff[16];

            //show power armor if they have it
            if (powerarmor != -1)
                sprintf (buff, " P:%d", powerarmor);
            else
                buff[0] = '\0';

            if (ent->client->pers.config.id_highlight)
                string = TDM_SetColorText (va ("%16s H:%d A:%d%s",
                                               target->client->pers.netname,
                                               target->health,
                                               TDM_GetArmorValue (target),
                                               buff));
            else
                string = va ("%16s H:%d A:%d%s",
                             target->client->pers.netname,
                             target->health,
                             TDM_GetArmorValue (target),
                             buff);
        }
        else
        {
            if (ent->client->pers.config.id_highlight)
                string = TDM_SetColorText (va ("%16s", target->client->pers.netname));
            else
                string = va ("%16s", target->client->pers.netname);
        }

        gi.WriteByte (svc_configstring);
        gi.WriteShort (CS_TDM_ID_VIEW);
        gi.WriteString (string);
        gi.unicast (ent, false);
    }

    return target - g_edicts;
}
示例#29
0
/*QUAKED func_explosive (0 .5 .8) ? Trigger_Spawn ANIMATED ANIMATED_FAST
Any brush that you want to explode or break apart.  If you want an
ex0plosion, set dmg and it will do a radius explosion of that amount
at the center of the bursh.

If targeted it will not be shootable.

health defaults to 100.

mass defaults to 75.  This determines how much debris is emitted when
it explodes.  You get one large chunk per 100 of mass (up to 8) and
one small chunk per 25 of mass (up to 16).  So 800 gives the most.
*/
void
func_explosive_explode (edict_t * self, edict_t * inflictor,
			edict_t * attacker, int damage, vec3_t point)
{
  vec3_t origin;
  vec3_t chunkorigin;
  vec3_t size;
  int count;
  int mass;

  // bmodel origins are (0 0 0), we need to adjust that here
  VectorScale (self->size, 0.5, size);
  VectorAdd (self->absmin, size, origin);
  VectorCopy (origin, self->s.origin);

  self->takedamage = DAMAGE_NO;

  if (self->dmg)
    T_RadiusDamage (self, attacker, self->dmg, NULL, self->dmg + 40,
		    MOD_EXPLOSIVE);

  VectorSubtract (self->s.origin, inflictor->s.origin, self->velocity);
  VectorNormalize (self->velocity);
  VectorScale (self->velocity, 150, self->velocity);

  // start chunks towards the center
  VectorScale (size, 0.5, size);

  mass = self->mass;
  if (!mass)
    mass = 75;

  // big chunks
  if (mass >= 100)
    {
      count = mass / 100;
      if (count > 8)
	count = 8;
      while (count--)
	{
	  chunkorigin[0] = origin[0] + crandom () * size[0];
	  chunkorigin[1] = origin[1] + crandom () * size[1];
	  chunkorigin[2] = origin[2] + crandom () * size[2];
	  ThrowDebris (self, "models/objects/debris1/tris.md2", 1,
		       chunkorigin);
	}
    }

  // small chunks
  count = mass / 25;
  if (count > 16)
    count = 16;
  while (count--)
    {
      chunkorigin[0] = origin[0] + crandom () * size[0];
      chunkorigin[1] = origin[1] + crandom () * size[1];
      chunkorigin[2] = origin[2] + crandom () * size[2];
      ThrowDebris (self, "models/objects/debris2/tris.md2", 2, chunkorigin);
    }

  G_UseTargets (self, attacker);

  if (self->dmg)
    BecomeExplosion1 (self);
  else
    G_FreeEdict (self);
}
示例#30
0
/*
================
AddSkyPolygon
================
*/
static void AddSkyPolygon( int nump, vec3_t vecs ) {
	int i,j;
	vec3_t v, av;
	float s, t, dv;
	int axis;
	float   *vp;
	// s = [0]/[2], t = [1]/[2]
	static int vec_to_st[6][3] =
	{
		{-2,3,1},
		{2,3,-1},

		{1,3,2},
		{-1,3,-2},

		{-2,-1,3},
		{-2,1,-3}

		//	{-1,2,3},
		//	{1,2,-3}
	};

	// decide which face it maps to
	VectorCopy( vec3_origin, v );
	for ( i = 0, vp = vecs ; i < nump ; i++, vp += 3 )
	{
		VectorAdd( vp, v, v );
	}
	av[0] = Q_fabs( v[0] );
	av[1] = Q_fabs( v[1] );
	av[2] = Q_fabs( v[2] );
	if ( av[0] > av[1] && av[0] > av[2] ) {
		if ( v[0] < 0 ) {
			axis = 1;
		} else {
			axis = 0;
		}
	} else if ( av[1] > av[2] && av[1] > av[0] )     {
		if ( v[1] < 0 ) {
			axis = 3;
		} else {
			axis = 2;
		}
	} else
	{
		if ( v[2] < 0 ) {
			axis = 5;
		} else {
			axis = 4;
		}
	}

	// project new texture coords
	for ( i = 0 ; i < nump ; i++, vecs += 3 )
	{
		j = vec_to_st[axis][2];
		if ( j > 0 ) {
			dv = vecs[j - 1];
		} else {
			dv = -vecs[-j - 1];
		}
		if ( dv < 0.001 ) {
			continue;   // don't divide by zero
		}
		j = vec_to_st[axis][0];
		if ( j < 0 ) {
			s = -vecs[-j - 1] / dv;
		} else {
			s = vecs[j - 1] / dv;
		}
		j = vec_to_st[axis][1];
		if ( j < 0 ) {
			t = -vecs[-j - 1] / dv;
		} else {
			t = vecs[j - 1] / dv;
		}

		if ( s < sky_mins[0][axis] ) {
			sky_mins[0][axis] = s;
		}
		if ( t < sky_mins[1][axis] ) {
			sky_mins[1][axis] = t;
		}
		if ( s > sky_maxs[0][axis] ) {
			sky_maxs[0][axis] = s;
		}
		if ( t > sky_maxs[1][axis] ) {
			sky_maxs[1][axis] = t;
		}
	}
}