Ejemplo n.º 1
0
Archivo: bot.c Proyecto: icanhas/yantar
/*
 * BotImport_DebugLineShow
 */
static void
BotImport_DebugLineShow(int line, Vec3 start, Vec3 end, int color)
{
	Vec3	points[4], dir, cross, up = {0, 0, 1};
	float	dot;

	copyv3(start, points[0]);
	copyv3(start, points[1]);
	/* points[1][2] -= 2; */
	copyv3(end, points[2]);
	/* points[2][2] -= 2; */
	copyv3(end, points[3]);


	subv3(end, start, dir);
	normv3(dir);
	dot = dotv3(dir, up);
	if(dot > 0.99 || dot < -0.99) setv3(cross, 1, 0, 0);
	else crossv3(dir, up, cross);

	normv3(cross);

	saddv3(points[0], 2, cross, points[0]);
	saddv3(points[1], -2, cross, points[1]);
	saddv3(points[2], -2, cross, points[2]);
	saddv3(points[3], 2, cross, points[3]);

	BotImport_DebugPolygonShow(line, color, 4, points);
}
Ejemplo n.º 2
0
/* exclude meas of eclipsing satellite (block IIA) ---------------------------*/
static void testeclipse(const obsd_t *obs, int n, const nav_t *nav, double *rs)
{
    double rsun[3],esun[3],r,ang,erpv[5]={0},cosa;
    int i,j;
    const char *type;
    
    trace(3,"testeclipse:\n");
    
    /* unit vector of sun direction (ecef) */
    sunmoonpos(gpst2utc(obs[0].time),erpv,rsun,NULL,NULL);
    normv3(rsun,esun);
    
    for (i=0;i<n;i++) {
        type=nav->pcvs[obs[i].sat-1].type;
        
        if ((r=norm(rs+i*6,3))<=0.0) continue;
#if 1
        /* only block IIA */
        if (*type&&!strstr(type,"BLOCK IIA")) continue;
#endif
        /* sun-earth-satellite angle */
        cosa=dot(rs+i*6,esun,3)/r;
        cosa=cosa<-1.0?-1.0:(cosa>1.0?1.0:cosa);
        ang=acos(cosa);
        
        /* test eclipse */
        if (ang<PI/2.0||r*sin(ang)>RE_WGS84) continue;
        
        trace(2,"eclipsing sat excluded %s sat=%2d\n",time_str(obs[0].time,0),
              obs[i].sat);
        
        for (j=0;j<3;j++) rs[j+i*6]=0.0;
    }
}
Ejemplo n.º 3
0
/* satellite antenna phase center variation ----------------------------------*/
static void satantpcv(const double *rs, const double *rr, const pcv_t *pcv,
                      double *dant)
{
    double ru[3],rz[3],eu[3],ez[3],nadir,cosa;
    int i;
    
    for (i=0;i<3;i++) {
        ru[i]=rr[i]-rs[i];
        rz[i]=-rs[i];
    }
    if (!normv3(ru,eu)||!normv3(rz,ez)) return;
    
    cosa=dot(eu,ez,3);
    cosa=cosa<-1.0?-1.0:(cosa>1.0?1.0:cosa);
    nadir=acos(cosa);
    
    antmodel_s(pcv,nadir,dant);
}
Ejemplo n.º 4
0
void
weapon_grenadelauncher_fire(Gentity *ent)
{
	Gentity *m;
	
	normv3(forward);
	m = fire_grenade(ent, muzzle, forward);
	m->damage *= s_quadFactor;
	m->splashDamage *= s_quadFactor;
}
Ejemplo n.º 5
0
void
weapon_proxlauncher_fire(Gentity *ent)
{
	Gentity       *m;

	/* extra vertical velocity */
	forward[2] += 0.2f;
	normv3(forward);
	m = fire_prox(ent, muzzle, forward);
	m->damage *= s_quadFactor;
	m->splashDamage *= s_quadFactor;
}
Ejemplo n.º 6
0
void
G_BounceProjectile(Vec3 start, Vec3 impact, Vec3 dir, Vec3 endout)
{
	Vec3	v, newv;
	float	dot;

	subv3(impact, start, v);
	dot = dotv3(v, dir);
	saddv3(v, -2*dot, dir, newv);
	normv3(newv);
	saddv3(impact, 8192, newv, endout);
}
Ejemplo n.º 7
0
Archivo: sky.c Proyecto: icanhas/yantar
void
R_InitSkyTexCoords(float heightCloud)
{
	int i, s, t;
	float radiusWorld = 4096;
	float p;
	float sRad, tRad;
	Vec3	skyVec;
	Vec3	v;

	/* init zfar so MakeSkyVec works even though
	 * a world hasn't been bounded */
	backEnd.viewParms.zFar = 1024;

	for(i = 0; i < 6; i++){
		for(t = 0; t <= SKY_SUBDIVISIONS; t++)
			for(s = 0; s <= SKY_SUBDIVISIONS; s++){
				/* compute vector from view origin to sky side integral point */
				MakeSkyVec((s - HALF_SKY_SUBDIVISIONS) / ( float )HALF_SKY_SUBDIVISIONS,
					(t - HALF_SKY_SUBDIVISIONS) / ( float )HALF_SKY_SUBDIVISIONS,
					i,
					NULL,
					skyVec);

				/* compute parametric value 'p' that intersects with cloud layer */
				p = (1.0f / (2 * dotv3(skyVec, skyVec))) *
				    (-2 * skyVec[2] * radiusWorld +
				     2 * sqrt(SQR(skyVec[2]) * SQR(radiusWorld) +
					     2 * SQR(skyVec[0]) * radiusWorld * heightCloud +
					     SQR(skyVec[0]) * SQR(heightCloud) +
					     2 * SQR(skyVec[1]) * radiusWorld * heightCloud +
					     SQR(skyVec[1]) * SQR(heightCloud) +
					     2 * SQR(skyVec[2]) * radiusWorld * heightCloud +
					     SQR(skyVec[2]) * SQR(heightCloud)));

				s_cloudTexP[i][t][s] = p;

				/* compute intersection point based on p */
				scalev3(skyVec, p, v);
				v[2] += radiusWorld;

				/* compute vector from world origin to intersection point 'v' */
				normv3(v);

				sRad = Q_acos(v[0]);
				tRad = Q_acos(v[1]);

				s_cloudTexCoords[i][t][s][0] = sRad;
				s_cloudTexCoords[i][t][s][1] = tRad;
			}
	}
}
Ejemplo n.º 8
0
/* satellite antenna phase center offset ---------------------------------------
* compute satellite antenna phase center offset in ecef
* args   : gtime_t time       I   time (gpst)
*          double *rs         I   satellite position and velocity (ecef)
*                                 {x,y,z,vx,vy,vz} (m|m/s)
*          pcv_t  *pcv        I   satellite antenna parameter
*          double *dant       I   satellite antenna phase center offset (ecef)
*                                 {dx,dy,dz} (m)
* return : none
*-----------------------------------------------------------------------------*/
extern void satantoff(gtime_t time, const double *rs, const pcv_t *pcv,
                      double *dant)
{
    double ex[3],ey[3],ez[3],es[3],r[3],rsun[3],gmst;
    int i;
    
    trace(4,"satantoff: time=%s\n",time_str(time,3));
    
    /* sun position in ecef */
    sunmoonpos(gpst2utc(time),NULL,rsun,NULL,&gmst);
    
    /* unit vectors of satellite fixed coordinates */
    for (i=0;i<3;i++) r[i]=-rs[i];
    if (!normv3(r,ez)) return;
    for (i=0;i<3;i++) r[i]=rsun[i]-rs[i];
    if (!normv3(r,es)) return;
    cross3(ez,es,r);
    if (!normv3(r,ey)) return;
    cross3(ey,ez,ex);
    
    for (i=0;i<3;i++) { /* use L1 value */
        dant[i]=pcv->off[0][0]*ex[i]+pcv->off[0][1]*ey[i]+pcv->off[0][2]*ez[i];
    }
}
Ejemplo n.º 9
0
Archivo: dma.c Proyecto: icanhas/yantar
/* Used for spatializing s_channels */
static void
S_SpatializeOrigin(Vec3 origin, int master_vol, int *left_vol, int *right_vol)
{
    Scalar	dot;
    Scalar	dist;
    Scalar	lscale, rscale, scale;
    Vec3	source_vec;
    Vec3	vec;
    const float dist_mult = SOUND_ATTENUATE;

    /* calculate stereo seperation and distance attenuation */
    subv3(origin, listener_origin, source_vec);
    dist = normv3(source_vec);
    dist -= SOUND_FULLVOLUME;
    if(dist < 0)
        dist = 0;	/* close enough to be at full volume */
    dist *= dist_mult;	/* different attenuation levels */
    rotv3(source_vec, listener_axis, vec);
    dot = -vec[1];

    if(dma.channels == 1) {	/* no attenuation = no spatialization */
        rscale	= 1.0;
        lscale	= 1.0;
    } else {
        rscale	= 0.5 * (1.0 + dot);
        lscale	= 0.5 * (1.0 - dot);
        if(rscale < 0)
            rscale = 0;
        if(lscale < 0)
            lscale = 0;
    }

    /* add in distance effect */
    scale = (1.0 - dist) * rscale;
    *right_vol = (master_vol * scale);
    if(*right_vol < 0)
        *right_vol = 0;

    scale = (1.0 - dist) * lscale;
    *left_vol = (master_vol * scale);
    if(*left_vol < 0)
        *left_vol = 0;
}
Ejemplo n.º 10
0
/*
 * R_SetupEntityLighting
 *
 * Calculates all the lighting values that will be used
 * by the Calc_* functions
 */
void
R_SetupEntityLighting(const trRefdef_t *refdef, trRefEntity_t *ent)
{
	int i;
	dlight_t	*dl;
	float		power;
	Vec3		dir;
	float		d;
	Vec3		lightDir;
	Vec3		lightOrigin;

	/* lighting calculations */
	if(ent->lightingCalculated){
		return;
	}
	ent->lightingCalculated = qtrue;

	/*
	 * trace a sample point down to find ambient light
	 *  */
	if(ent->e.renderfx & RF_LIGHTING_ORIGIN){
		/* seperate lightOrigins are needed so an object that is
		 * sinking into the ground can still be lit, and so
		 * multi-part models can be lit identically */
		copyv3(ent->e.lightingOrigin, lightOrigin);
	}else{
		copyv3(ent->e.origin, lightOrigin);
	}

	/* if NOWORLDMODEL, only use dynamic lights (menu system, etc) */
	if(!(refdef->rdflags & RDF_NOWORLDMODEL)
	   && tr.world->lightGridData){
		R_SetupEntityLightingGrid(ent);
	}else{
		ent->ambientLight[0] = ent->ambientLight[1] =
					       ent->ambientLight[2] = tr.identityLight * 150;
		ent->directedLight[0] = ent->directedLight[1] =
						ent->directedLight[2] = tr.identityLight * 150;
		copyv3(tr.sunDirection, ent->lightDir);
	}

	/* bonus items and view weapons have a fixed minimum add */
	if(1 /* ent->e.renderfx & RF_MINLIGHT */){
		/* give everything a minimum light add */
		ent->ambientLight[0]	+= tr.identityLight * 32;
		ent->ambientLight[1]	+= tr.identityLight * 32;
		ent->ambientLight[2]	+= tr.identityLight * 32;
	}

	/*
	 * modify the light by dynamic lights
	 *  */
	d = lenv3(ent->directedLight);
	scalev3(ent->lightDir, d, lightDir);

	for(i = 0; i < refdef->num_dlights; i++){
		dl = &refdef->dlights[i];
		subv3(dl->origin, lightOrigin, dir);
		d = normv3(dir);

		power = DLIGHT_AT_RADIUS * (dl->radius * dl->radius);
		if(d < DLIGHT_MINIMUM_RADIUS){
			d = DLIGHT_MINIMUM_RADIUS;
		}
		d = power / (d * d);

		saddv3(ent->directedLight, d, dl->color, ent->directedLight);
		saddv3(lightDir, d, dir, lightDir);
	}

	/* clamp ambient */
	for(i = 0; i < 3; i++)
		if(ent->ambientLight[i] > tr.identityLightByte){
			ent->ambientLight[i] = tr.identityLightByte;
		}

	if(r_debugLight->integer){
		LogLight(ent);
	}

	/* save out the byte packet version */
	((byte*)&ent->ambientLightInt)[0]	= ri.ftol(ent->ambientLight[0]);
	((byte*)&ent->ambientLightInt)[1]	= ri.ftol(ent->ambientLight[1]);
	((byte*)&ent->ambientLightInt)[2]	= ri.ftol(ent->ambientLight[2]);
	((byte*)&ent->ambientLightInt)[3]	= 0xff;

	/* transform the direction to local space */
	normv3(lightDir);
	ent->lightDir[0]	= dotv3(lightDir, ent->e.axis[0]);
	ent->lightDir[1]	= dotv3(lightDir, ent->e.axis[1]);
	ent->lightDir[2]	= dotv3(lightDir, ent->e.axis[2]);
}
Ejemplo n.º 11
0
/*
 * R_SubdividePatchToGrid
 */
srfGridMesh_t *
R_SubdividePatchToGrid(int width, int height,
		       Drawvert points[MAX_PATCH_SIZE*MAX_PATCH_SIZE])
{
	int i, j, k, l;
	drawVert_t_cleared(prev);
	drawVert_t_cleared(next);
	drawVert_t_cleared(mid);
	float len, maxLen;
	int dir;
	int t;
	Drawvert	ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
	float		errorTable[2][MAX_GRID_SIZE];

	for(i = 0; i < width; i++)
		for(j = 0; j < height; j++)
			ctrl[j][i] = points[j*width+i];

	for(dir = 0; dir < 2; dir++){

		for(j = 0; j < MAX_GRID_SIZE; j++)
			errorTable[dir][j] = 0;

		/* horizontal subdivisions */
		for(j = 0; j + 2 < width; j += 2){
			/* check subdivided midpoints against control points */

			/* FIXME: also check midpoints of adjacent patches against the control points
			 * this would basically stitch all patches in the same LOD group together. */

			maxLen = 0;
			for(i = 0; i < height; i++){
				Vec3	midxyz;
				Vec3	midxyz2;
				Vec3	dir;
				Vec3	projected;
				float	d;

				/* calculate the point on the curve */
				for(l = 0; l < 3; l++)
					midxyz[l] = (ctrl[i][j].xyz[l] + ctrl[i][j+1].xyz[l] * 2
						     + ctrl[i][j+2].xyz[l]) * 0.25f;

				/* see how far off the line it is
				 * using dist-from-line will not account for internal
				 * texture warping, but it gives a lot less polygons than
				 * dist-from-midpoint */
				subv3(midxyz, ctrl[i][j].xyz, midxyz);
				subv3(ctrl[i][j+2].xyz, ctrl[i][j].xyz, dir);
				normv3(dir);

				d = dotv3(midxyz, dir);
				scalev3(dir, d, projected);
				subv3(midxyz, projected, midxyz2);
				len = lensqrv3(midxyz2);	/* we will do the sqrt later */
				if(len > maxLen){
					maxLen = len;
				}
			}

			maxLen = sqrt(maxLen);

			/* if all the points are on the lines, remove the entire columns */
			if(maxLen < 0.1f){
				errorTable[dir][j+1] = 999;
				continue;
			}

			/* see if we want to insert subdivided columns */
			if(width + 2 > MAX_GRID_SIZE){
				errorTable[dir][j+1] = 1.0f/maxLen;
				continue;	/* can't subdivide any more */
			}

			if(maxLen <= r_subdivisions->value){
				errorTable[dir][j+1] = 1.0f/maxLen;
				continue;	/* didn't need subdivision */
			}

			errorTable[dir][j+2] = 1.0f/maxLen;

			/* insert two columns and replace the peak */
			width += 2;
			for(i = 0; i < height; i++){
				LerpDrawVert(&ctrl[i][j], &ctrl[i][j+1], &prev);
				LerpDrawVert(&ctrl[i][j+1], &ctrl[i][j+2], &next);
				LerpDrawVert(&prev, &next, &mid);

				for(k = width - 1; k > j + 3; k--)
					ctrl[i][k] = ctrl[i][k-2];
				ctrl[i][j + 1]	= prev;
				ctrl[i][j + 2]	= mid;
				ctrl[i][j + 3]	= next;
			}

			/* back up and recheck this set again, it may need more subdivision */
			j -= 2;

		}

		Transpose(width, height, ctrl);
		t = width;
		width	= height;
		height	= t;
	}


	/* put all the aproximating points on the curve */
	PutPointsOnCurve(ctrl, width, height);

	/* cull out any rows or columns that are colinear */
	for(i = 1; i < width-1; i++){
		if(errorTable[0][i] != 999){
			continue;
		}
		for(j = i+1; j < width; j++){
			for(k = 0; k < height; k++)
				ctrl[k][j-1] = ctrl[k][j];
			errorTable[0][j-1] = errorTable[0][j];
		}
		width--;
	}

	for(i = 1; i < height-1; i++){
		if(errorTable[1][i] != 999){
			continue;
		}
		for(j = i+1; j < height; j++){
			for(k = 0; k < width; k++)
				ctrl[j-1][k] = ctrl[j][k];
			errorTable[1][j-1] = errorTable[1][j];
		}
		height--;
	}

#if 1
	/* flip for longest tristrips as an optimization
	 * the results should be visually identical with or
	 * without this step */
	if(height > width){
		Transpose(width, height, ctrl);
		InvertErrorTable(errorTable, width, height);
		t = width;
		width	= height;
		height	= t;
		InvertCtrl(width, height, ctrl);
	}
#endif

	/* calculate normals */
	MakeMeshNormals(width, height, ctrl);

	return R_CreateSurfaceGridMesh(width, height, ctrl, errorTable);
}
Ejemplo n.º 12
0
static int
Pickup_Powerup(Gentity *ent, Gentity *other)
{
	int	quantity;
	int	i;
	Gclient *client;

	if(!other->client->ps.powerups[ent->item->tag])
		/* round timing to seconds to make multiple powerup timers
		 * count in sync */
		other->client->ps.powerups[ent->item->tag] =
			level.time - (level.time % 1000);

	if(ent->count)
		quantity = ent->count;
	else
		quantity = ent->item->quantity;

	other->client->ps.powerups[ent->item->tag] += quantity * 1000;

	/* give any nearby players a "denied" anti-reward */
	for(i = 0; i < level.maxclients; i++){
		Vec3	delta;
		float	len;
		Vec3	forward;
		Trace tr;

		client = &level.clients[i];
		if(client == other->client)
			continue;
		if(client->pers.connected == CON_DISCONNECTED)
			continue;
		if(client->ps.stats[STAT_HEALTH] <= 0)
			continue;

		/* if same team in team game, no sound
		 * cannot use OnSameTeam as it expects to g_entities, not clients */
		if(g_gametype.integer >= GT_TEAM &&
		   other->client->sess.team == client->sess.team)
			continue;

		/* if too far away, no sound */
		subv3(ent->s.traj.base, client->ps.origin, delta);
		len = normv3(delta);
		if(len > 192)
			continue;

		/* if not facing, no sound */
		anglev3s(client->ps.viewangles, forward, NULL, NULL);
		if(dotv3(delta, forward) < 0.4)
			continue;

		/* if not line of sight, no sound */
		trap_Trace(&tr, client->ps.origin, NULL, NULL, ent->s.traj.base,
			ENTITYNUM_NONE,
			CONTENTS_SOLID);
		if(tr.fraction != 1.0)
			continue;

		/* anti-reward */
		client->ps.persistant[PERS_PLAYEREVENTS] ^=
			PLAYEREVENT_DENIEDREWARD;
	}
	return RESPAWN_POWERUP;
}
Ejemplo n.º 13
0
/* satellite position and clock with ssr correction --------------------------*/
static int satpos_ssr(gtime_t time, gtime_t teph, int sat, const nav_t *nav,
                      int opt, double *rs, double *dts, double *var, int *svh)
{
    const ssr_t *ssr;
    eph_t *eph;
    double t1,t2,t3,er[3],ea[3],ec[3],rc[3],deph[3],dclk,dant[3]={0},tk;
    int i,sys;
    
    trace(4,"satpos_ssr: time=%s sat=%2d\n",time_str(time,3),sat);
    
    ssr=nav->ssr+sat-1;
    
    if (!ssr->t0[0].time) {
        trace(2,"no ssr orbit correction: %s sat=%2d\n",time_str(time,0),sat);
        return 0;
    }
    if (!ssr->t0[1].time) {
        trace(2,"no ssr clock correction: %s sat=%2d\n",time_str(time,0),sat);
        return 0;
    }
    /* inconsistency between orbit and clock correction */
    if (ssr->iod[0]!=ssr->iod[1]) {
        trace(2,"inconsist ssr correction: %s sat=%2d iod=%d %d\n",
              time_str(time,0),sat,ssr->iod[0],ssr->iod[1]);
        *svh=-1;
        return 0;
    }
    t1=timediff(time,ssr->t0[0]);
    t2=timediff(time,ssr->t0[1]);
    t3=timediff(time,ssr->t0[2]);
    
    /* ssr orbit and clock correction (ref [4]) */
    if (fabs(t1)>MAXAGESSR||fabs(t2)>MAXAGESSR) {
        trace(2,"age of ssr error: %s sat=%2d t=%.0f %.0f\n",time_str(time,0),
              sat,t1,t2);
        *svh=-1;
        return 0;
    }
    if (ssr->udi[0]>=1.0) t1-=ssr->udi[0]/2.0;
    if (ssr->udi[1]>=1.0) t2-=ssr->udi[0]/2.0;
    
    for (i=0;i<3;i++) deph[i]=ssr->deph[i]+ssr->ddeph[i]*t1;
    dclk=ssr->dclk[0]+ssr->dclk[1]*t2+ssr->dclk[2]*t2*t2;
    
    /* ssr highrate clock correction (ref [4]) */
    if (ssr->iod[0]==ssr->iod[2]&&ssr->t0[2].time&&fabs(t3)<MAXAGESSR_HRCLK) {
        dclk+=ssr->hrclk;
    }
    if (norm(deph,3)>MAXECORSSR||fabs(dclk)>MAXCCORSSR) {
        trace(3,"invalid ssr correction: %s deph=%.1f dclk=%.1f\n",
              time_str(time,0),norm(deph,3),dclk);
        *svh=-1;
        return 0;
    }
    /* satellite postion and clock by broadcast ephemeris */
    if (!ephpos(time,teph,sat,nav,ssr->iode,rs,dts,var,svh)) return 0;
    
    /* satellite clock for gps, galileo and qzss */
    sys=satsys(sat,NULL);
    if (sys==SYS_GPS||sys==SYS_GAL||sys==SYS_QZS||sys==SYS_CMP) {
        if (!(eph=seleph(teph,sat,ssr->iode,nav))) return 0;
        
        /* satellite clock by clock parameters */
        tk=timediff(time,eph->toc);
        dts[0]=eph->f0+eph->f1*tk+eph->f2*tk*tk;
        dts[1]=eph->f1+2.0*eph->f2*tk;
        
        /* relativity correction */
        dts[0]-=2.0*dot(rs,rs+3,3)/CLIGHT/CLIGHT;
    }
    /* radial-along-cross directions in ecef */
    if (!normv3(rs+3,ea)) return 0;
    cross3(rs,rs+3,rc);
    if (!normv3(rc,ec)) {
        *svh=-1;
        return 0;
    }
    cross3(ea,ec,er);
    
    /* satellite antenna offset correction */
    if (opt) {
        satantoff(time,rs,sat,nav,dant);
    }
    for (i=0;i<3;i++) {
        rs[i]+=-(er[i]*deph[0]+ea[i]*deph[1]+ec[i]*deph[2])+dant[i];
    }
    /* t_corr = t_sv - (dts(brdc) + dclk(ssr) / CLIGHT) (ref [10] eq.3.12-7) */
    dts[0]+=dclk/CLIGHT;
    
    /* variance by ssr ura */
    *var=var_urassr(ssr->ura);
    
    trace(5,"satpos_ssr: %s sat=%2d deph=%6.3f %6.3f %6.3f er=%6.3f %6.3f %6.3f dclk=%6.3f var=%6.3f\n",
          time_str(time,2),sat,deph[0],deph[1],deph[2],er[0],er[1],er[2],dclk,*var);
    
    return 1;
}
Ejemplo n.º 14
0
static void
KamikazeShockWave(Vec3 origin, Gentity *attacker, float damage, float push,
		  float radius)
{
	float dist;
	Gentity       *ent;
	int entityList[MAX_GENTITIES];
	int numListedEntities;
	Vec3 mins, maxs;
	Vec3 v;
	Vec3 dir;
	int i, e;

	if(radius < 1)
		radius = 1;

	for(i = 0; i < 3; i++){
		mins[i] = origin[i] - radius;
		maxs[i] = origin[i] + radius;
	}

	numListedEntities = trap_EntitiesInBox(mins, maxs, entityList,
		MAX_GENTITIES);

	for(e = 0; e < numListedEntities; e++){
		ent = &g_entities[entityList[ e ]];

		/* dont hit things we have already hit */
		if(ent->kamikazeShockTime > level.time)
			continue;

		/* find the distance from the edge of the bounding box */
		for(i = 0; i < 3; i++){
			if(origin[i] < ent->r.absmin[i])
				v[i] = ent->r.absmin[i] - origin[i];
			else if(origin[i] > ent->r.absmax[i])
				v[i] = origin[i] - ent->r.absmax[i];
			else
				v[i] = 0;
		}

		dist = lenv3(v);
		if(dist >= radius)
			continue;

/*		if( CanDamage (ent, origin) ) { */
		subv3 (ent->r.currentOrigin, origin, dir);
		dir[2] += 24;
		G_Damage(ent, NULL, attacker, dir, origin, damage,
			DAMAGE_RADIUS|DAMAGE_NO_TEAM_PROTECTION,
			MOD_KAMIKAZE);
		dir[2] = 0;
		normv3(dir);
		if(ent->client){
			ent->client->ps.velocity[0] = dir[0] * push;
			ent->client->ps.velocity[1] = dir[1] * push;
			ent->client->ps.velocity[2] = 100;
		}
		ent->kamikazeShockTime = level.time + 3000;
/*		} */
	}
}
Ejemplo n.º 15
0
qbool
PM_SlideMove(Pmove *pm, Pml *pml, qbool gravity)
{
	int i, j, k, bumpcount, numbumps, numplanes;
	Vec3	dir;
	float	d, time_left, into;
	Vec3	planes[MAX_CLIP_PLANES];
	Vec3	primal_velocity, clipVelocity;
	Trace trace;
	Vec3	end, endVelocity, endClipVelocity;

	numbumps = 4;

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

	if(gravity){
		copyv3(pm->ps->velocity, endVelocity);
		endVelocity[2] -= pm->ps->gravity * pml->frametime;
		pm->ps->velocity[2] = (pm->ps->velocity[2] + endVelocity[2]) * 0.5f;
		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;
		copyv3(pml->groundTrace.plane.normal, planes[0]);
	}else
		numplanes = 0;

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

	for(bumpcount=0; bumpcount < numbumps; bumpcount++){
		/* calculate position we are trying to move to */
		saddv3(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 */
			copyv3 (trace.endpos, pm->ps->origin);

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

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

		time_left -= time_left * trace.fraction;

		if(numplanes >= MAX_CLIP_PLANES){
			/* this shouldn't really happen */
			clearv3(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(dotv3(trace.plane.normal, planes[i]) > 0.99f){
				addv3(trace.plane.normal, pm->ps->velocity,
					pm->ps->velocity);
				break;
			}
		if(i < numplanes)
			continue;
		copyv3 (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 = dotv3(pm->ps->velocity, planes[i]);
			if(into >= 0.1f)
				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(dotv3(clipVelocity, planes[j]) >= 0.1f)
					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(dotv3(clipVelocity, planes[i]) >= 0)
					continue;

				/* slide the original velocity along the crease */
				crossv3 (planes[i], planes[j], dir);
				normv3(dir);
				d = dotv3(dir, pm->ps->velocity);
				scalev3(dir, d, clipVelocity);

				crossv3 (planes[i], planes[j], dir);
				normv3(dir);
				d = dotv3(dir, endVelocity);
				scalev3(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(dotv3(clipVelocity,
						   planes[k]) >= 0.1f)
						continue;	/* move doesn't interact with the plane */

					/* stop dead at a triple plane interaction */
					clearv3(pm->ps->velocity);
					return qtrue;
				}
			}

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

	if(gravity)
		copyv3(endVelocity, pm->ps->velocity);

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

	return (bumpcount != 0);
}