Esempio n. 1
0
/**
 * @brief Sorts the spawns so that the furthest from the flag are at the beginning.
 */
static int32_t G_CreateTeamSpawnPoints_CompareFunc(gconstpointer a, gconstpointer b, gpointer user_data) {

	g_entity_t *flag = (g_entity_t *) user_data;
	
	const g_entity_t *ap = (const g_entity_t *) a;
	const g_entity_t *bp = (const g_entity_t *) b;

	return Sign(VectorDistanceSquared(flag->s.origin, bp->s.origin) - VectorDistanceSquared(flag->s.origin, ap->s.origin));
}
Esempio n. 2
0
void CG_AddParticleToScene(cparticle_t *p, vec3_t org) {

	vec3_t     point;
	polyVert_t verts[4];
	float      width;
	float      height;
	float      time, time2;
	float      ratio;
	float      invratio;
	vec3_t     color;
	polyVert_t TRIverts[3];
	vec3_t     rright2, rup2;

	if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY
	    || p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) {   // create a front facing polygon
		if (p->type != P_WEATHER_FLURRY) {
			if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) {
				if (org[2] > p->end) {
					p->time = cg.time;
					VectorCopy(org, p->org);   // Ridah, fixes rare snow flakes that flicker on the ground

					p->org[2] = (p->start + crandom() * 4);


					if (p->type == P_BUBBLE_TURBULENT) {
						p->vel[0] = crandom() * 4;
						p->vel[1] = crandom() * 4;
					}

				}
			} else {
				if (org[2] < p->end) {
					p->time = cg.time;
					VectorCopy(org, p->org);   // Ridah, fixes rare snow flakes that flicker on the ground

					while (p->org[2] < p->end) {
						p->org[2] += (p->start - p->end);
					}


					if (p->type == P_WEATHER_TURBULENT) {
						p->vel[0] = crandom() * 16;
						p->vel[1] = crandom() * 16;
					}

				}
			}


			// Rafael snow pvs check
			if (!p->link) {
				return;
			}

			p->alpha = 1;
		}

		// Ridah, had to do this or MAX_POLYS is being exceeded in village1.bsp
		if (VectorDistanceSquared(cg.snap->ps.origin, org) > SQR(1024)) {
			return;
		}
		// done.

		if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) {
			VectorMA(org, -p->height, vup, point);
			VectorMA(point, -p->width, vright, point);
			VectorCopy(point, 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] = 255 * p->alpha;

			VectorMA(org, -p->height, vup, point);
			VectorMA(point, p->width, vright, point);
			VectorCopy(point, 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] = 255 * p->alpha;

			VectorMA(org, p->height, vup, point);
			VectorMA(point, p->width, vright, point);
			VectorCopy(point, 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] = 255 * p->alpha;

			VectorMA(org, p->height, vup, point);
			VectorMA(point, -p->width, vright, point);
			VectorCopy(point, 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] = 255 * p->alpha;
		} else {
			VectorMA(org, -p->height, vup, point);
			VectorMA(point, -p->width, vright, point);
			VectorCopy(point, TRIverts[0].xyz);
			TRIverts[0].st[0]       = 1;
			TRIverts[0].st[1]       = 0;
			TRIverts[0].modulate[0] = 255;
			TRIverts[0].modulate[1] = 255;
			TRIverts[0].modulate[2] = 255;
			TRIverts[0].modulate[3] = 255 * p->alpha;

			VectorMA(org, p->height, vup, point);
			VectorMA(point, -p->width, vright, point);
			VectorCopy(point, TRIverts[1].xyz);
			TRIverts[1].st[0]       = 0;
			TRIverts[1].st[1]       = 0;
			TRIverts[1].modulate[0] = 255;
			TRIverts[1].modulate[1] = 255;
			TRIverts[1].modulate[2] = 255;
			TRIverts[1].modulate[3] = 255 * p->alpha;

			VectorMA(org, p->height, vup, point);
			VectorMA(point, p->width, vright, point);
			VectorCopy(point, TRIverts[2].xyz);
			TRIverts[2].st[0]       = 0;
			TRIverts[2].st[1]       = 1;
			TRIverts[2].modulate[0] = 255;
			TRIverts[2].modulate[1] = 255;
			TRIverts[2].modulate[2] = 255;
			TRIverts[2].modulate[3] = 255 * p->alpha;
		}

	} else if (p->type == P_SPRITE) {
		vec3_t rr, ru;
		vec3_t rotate_ang;

		VectorSet(color, 1.0, 1.0, 1.0);
		time  = cg.time - p->time;
		time2 = p->endtime - p->time;
		ratio = time / time2;

		width  = p->width + (ratio * (p->endwidth - p->width));
		height = p->height + (ratio * (p->endheight - p->height));

		if (p->roll) {
			vectoangles(cg.refdef_current->viewaxis[0], rotate_ang);
			rotate_ang[ROLL] += p->roll;
			AngleVectors(rotate_ang, NULL, rr, ru);
		}

		if (p->roll) {
			VectorMA(org, -height, ru, point);
			VectorMA(point, -width, rr, point);
		} else {
			VectorMA(org, -height, vup, point);
			VectorMA(point, -width, vright, point);
		}
		VectorCopy(point, 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] = 255;

		if (p->roll) {
			VectorMA(point, 2 * height, ru, point);
		} else {
			VectorMA(point, 2 * height, vup, point);
		}
		VectorCopy(point, 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] = 255;

		if (p->roll) {
			VectorMA(point, 2 * width, rr, point);
		} else {
			VectorMA(point, 2 * width, vright, point);
		}
		VectorCopy(point, 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] = 255;

		if (p->roll) {
			VectorMA(point, -2 * height, ru, point);
		} else {
			VectorMA(point, -2 * height, vup, point);
		}
		VectorCopy(point, 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] = 255;
	} else if (p->type == P_SMOKE || p->type == P_SMOKE_IMPACT) {         // create a front rotating facing polygon
		if (p->type == P_SMOKE_IMPACT && VectorDistanceSquared(cg.snap->ps.origin, org) > SQR(1024)) {
			return;
		}

		if (p->color == MUSTARD) {
			VectorSet(color, 0.42, 0.33, 0.19);
		} else if (p->color == BLOODRED) {
			VectorSet(color, 0.22, 0, 0);
		} else if (p->color == ZOMBIE) {
			VectorSet(color, 0.4, 0.28, 0.23);
		} else if (p->color == GREY75) {
			float len;
			float greyit;
			float val;
			len = Distance(cg.snap->ps.origin, org);
			if (!len) {
				len = 1;
			}

			val    = 4096 / len;
			greyit = 0.25 * val;
			if (greyit > 0.5) {
				greyit = 0.5;
			}

			VectorSet(color, greyit, greyit, greyit);
		} else {
			VectorSet(color, 1.0, 1.0, 1.0);
		}

		time  = cg.time - p->time;
		time2 = p->endtime - p->time;
		ratio = time / time2;

		if (cg.time > p->startfade) {
			invratio = 1 - ((cg.time - p->startfade) / (p->endtime - p->startfade));

			if (p->color == EMISIVEFADE) {
				float fval;
				fval = (invratio * invratio);
				if (fval < 0) {
					fval = 0;
				}
				VectorSet(color, fval, fval, fval);
			}
			invratio *= p->alpha;
		} else {
			invratio = 1 * p->alpha;
		}

		if (cgs.glconfig.hardwareType == GLHW_RAGEPRO) {
			invratio = 1;
		}

		if (invratio > 1) {
			invratio = 1;
		}

		width  = p->width + (ratio * (p->endwidth - p->width));
		height = p->height + (ratio * (p->endheight - p->height));

		{
			vec3_t temp;

			vectoangles(rforward, temp);
			p->accumroll += p->roll;
			temp[ROLL]   += p->accumroll * 0.1;
			AngleVectors(temp, NULL, rright2, rup2);
		}

		if (p->rotate) {
			VectorMA(org, -height, rup2, point);
			VectorMA(point, -width, rright2, point);
		} else {
			VectorMA(org, -p->height, vup, point);
			VectorMA(point, -p->width, vright, point);
		}
		VectorCopy(point, verts[0].xyz);
		verts[0].st[0]       = 0;
		verts[0].st[1]       = 0;
		verts[0].modulate[0] = 255 * color[0];
		verts[0].modulate[1] = 255 * color[1];
		verts[0].modulate[2] = 255 * color[2];
		verts[0].modulate[3] = 255 * invratio;

		if (p->rotate) {
			VectorMA(org, -height, rup2, point);
			VectorMA(point, width, rright2, point);
		} else {
			VectorMA(org, -p->height, vup, point);
			VectorMA(point, p->width, vright, point);
		}
		VectorCopy(point, verts[1].xyz);
		verts[1].st[0]       = 0;
		verts[1].st[1]       = 1;
		verts[1].modulate[0] = 255 * color[0];
		verts[1].modulate[1] = 255 * color[1];
		verts[1].modulate[2] = 255 * color[2];
		verts[1].modulate[3] = 255 * invratio;

		if (p->rotate) {
			VectorMA(org, height, rup2, point);
			VectorMA(point, width, rright2, point);
		} else {
			VectorMA(org, p->height, vup, point);
			VectorMA(point, p->width, vright, point);
		}
		VectorCopy(point, verts[2].xyz);
		verts[2].st[0]       = 1;
		verts[2].st[1]       = 1;
		verts[2].modulate[0] = 255 * color[0];
		verts[2].modulate[1] = 255 * color[1];
		verts[2].modulate[2] = 255 * color[2];
		verts[2].modulate[3] = 255 * invratio;

		if (p->rotate) {
			VectorMA(org, height, rup2, point);
			VectorMA(point, -width, rright2, point);
		} else {
			VectorMA(org, p->height, vup, point);
			VectorMA(point, -p->width, vright, point);
		}
		VectorCopy(point, verts[3].xyz);
		verts[3].st[0]       = 1;
		verts[3].st[1]       = 0;
		verts[3].modulate[0] = 255 * color[0];
		verts[3].modulate[1] = 255 * color[1];
		verts[3].modulate[2] = 255 * color[2];
		verts[3].modulate[3] = 255  * invratio;

	} else if (p->type == P_FLAT_SCALEUP) {
		float width, height;
		float sinR, cosR;

		if (p->color == BLOODRED) {
			VectorSet(color, 1, 1, 1);
		} else {
			VectorSet(color, 0.5, 0.5, 0.5);
		}

		time  = cg.time - p->time;
		time2 = p->endtime - p->time;
		ratio = time / time2;

		width  = p->width + (ratio * (p->endwidth - p->width));
		height = p->height + (ratio * (p->endheight - p->height));

		if (width > p->endwidth) {
			width = p->endwidth;
		}

		if (height > p->endheight) {
			height = p->endheight;
		}

		sinR = height * sin(DEG2RAD(p->roll)) * ROOT_2;
		cosR = width * cos(DEG2RAD(p->roll)) * ROOT_2;

		VectorCopy(org, verts[0].xyz);
		verts[0].xyz[0]     -= sinR;
		verts[0].xyz[1]     -= cosR;
		verts[0].st[0]       = 0;
		verts[0].st[1]       = 0;
		verts[0].modulate[0] = 255 * color[0];
		verts[0].modulate[1] = 255 * color[1];
		verts[0].modulate[2] = 255 * color[2];
		verts[0].modulate[3] = 255;

		VectorCopy(org, verts[1].xyz);
		verts[1].xyz[0]     -= cosR;
		verts[1].xyz[1]     += sinR;
		verts[1].st[0]       = 0;
		verts[1].st[1]       = 1;
		verts[1].modulate[0] = verts[0].modulate[0];
		verts[1].modulate[1] = verts[0].modulate[1];
		verts[1].modulate[2] = verts[0].modulate[2];
		verts[1].modulate[3] = verts[0].modulate[3];

		VectorCopy(org, verts[2].xyz);
		verts[2].xyz[0]     += sinR;
		verts[2].xyz[1]     += cosR;
		verts[2].st[0]       = 1;
		verts[2].st[1]       = 1;
		verts[2].modulate[0] = verts[0].modulate[0];
		verts[2].modulate[1] = verts[0].modulate[1];
		verts[2].modulate[2] = verts[0].modulate[2];
		verts[2].modulate[3] = verts[0].modulate[3];

		VectorCopy(org, verts[3].xyz);
		verts[3].xyz[0]     += cosR;
		verts[3].xyz[1]     -= sinR;
		verts[3].st[0]       = 1;
		verts[3].st[1]       = 0;
		verts[3].modulate[0] = verts[0].modulate[0];
		verts[3].modulate[1] = verts[0].modulate[1];
		verts[3].modulate[2] = verts[0].modulate[2];
		verts[3].modulate[3] = verts[0].modulate[3];
	} else if (p->type == P_FLAT) {

		VectorCopy(org, verts[0].xyz);
		verts[0].xyz[0]     -= p->height;
		verts[0].xyz[1]     -= p->width;
		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] = 255;

		VectorCopy(org, verts[1].xyz);
		verts[1].xyz[0]     -= p->height;
		verts[1].xyz[1]     += p->width;
		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] = 255;

		VectorCopy(org, verts[2].xyz);
		verts[2].xyz[0]     += p->height;
		verts[2].xyz[1]     += p->width;
		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] = 255;

		VectorCopy(org, verts[3].xyz);
		verts[3].xyz[0]     += p->height;
		verts[3].xyz[1]     -= p->width;
		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] = 255;

	}
	// Ridah
	else if (p->type == P_ANIM || p->type == P_DLIGHT_ANIM) {    // ydnar
		vec3_t rr, ru;
		vec3_t rotate_ang;
		int    i, j;

		time  = cg.time - p->time;
		time2 = p->endtime - p->time;
		ratio = time / time2;
		if (ratio >= 1.0) {
			ratio = 0.9999;
		} else if (ratio < 0.0) {
			// rain - make sure that ratio isn't negative or
			// we'll walk out of bounds when j is calculated below
			ratio = 0.0001;
		}

		width  = p->width + (ratio * (p->endwidth - p->width));
		height = p->height + (ratio * (p->endheight - p->height));

		// ydnar: add dlight if necessary
		if (p->type == P_DLIGHT_ANIM) {
			// fixme: support arbitrary color
			trap_R_AddLightToScene(org, 320,    //%	1.5 * (width > height ? width : height),
			                       1.25 * (1.0 - ratio), 1.0, 0.95, 0.85, 0, 0);
		}

		// if we are "inside" this sprite, don't draw
		if (VectorDistanceSquared(cg.snap->ps.origin, org) < SQR(width / 1.5f)) {
			return;
		}

		i          = p->shaderAnim;
		j          = (int)floor(ratio * shaderAnimCounts[p->shaderAnim]);
		p->pshader = shaderAnims[i][j];

		// JPW NERVE more particle testing
		if (cg_fxflags & 1) {
			p->roll          = 0;
			p->pshader       = getTestShader();
			rotate_ang[ROLL] = 90;
		}
		// jpw

		if (p->roll) {
			vectoangles(cg.refdef_current->viewaxis[0], rotate_ang);
			rotate_ang[ROLL] += p->roll;
			AngleVectors(rotate_ang, NULL, rr, ru);
		}

		if (p->roll) {
			VectorMA(org, -height, ru, point);
			VectorMA(point, -width, rr, point);
		} else {
			VectorMA(org, -height, vup, point);
			VectorMA(point, -width, vright, point);
		}
		VectorCopy(point, 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] = 255;

		if (p->roll) {
			VectorMA(point, 2 * height, ru, point);
		} else {
			VectorMA(point, 2 * height, vup, point);
		}
		VectorCopy(point, 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] = 255;

		if (p->roll) {
			VectorMA(point, 2 * width, rr, point);
		} else {
			VectorMA(point, 2 * width, vright, point);
		}
		VectorCopy(point, 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] = 255;

		if (p->roll) {
			VectorMA(point, -2 * height, ru, point);
		} else {
			VectorMA(point, -2 * height, vup, point);
		}
		VectorCopy(point, 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] = 255;
	}
	// done.

	if (!cg_wolfparticles.integer) {
		return;
	}

	if (!p->pshader) {
		return;
	}

	if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY) {
		trap_R_AddPolyToScene(p->pshader, 3, TRIverts);
	} else {
		trap_R_AddPolyToScene(p->pshader, 4, verts);
	}

}
Esempio n. 3
0
/**
 * @brief Creates team spawns if the map doesn't have one. Also creates flags, although
 * chances are they will be in crap positions.
 */
static void G_CreateTeamSpawnPoints(GSList **dm_spawns, GSList **team_red_spawns, GSList **team_blue_spawns) {

	// find our flags
	g_entity_t *red_flag, *blue_flag;
	g_entity_t *reused_spawns[2] = { NULL, NULL };
	
	red_flag = g_team_red->flag_entity;
	blue_flag = g_team_blue->flag_entity;

	if (!!red_flag != !!blue_flag) {
		gi.Error("Make sure you have both flags in your map!\n");
	} else if (!red_flag) {
		// no flag in map, so let's make one by repurposing the furthest spawn points

		if (g_slist_length(*dm_spawns) < 4) {
			return; // not enough points to make a flag
		}

		vec_t furthest_dist = 0;

		for (GSList *pa = *dm_spawns; pa; pa = pa->next) {
			for (GSList *pb = *dm_spawns; pb; pb = pb->next) {

				if (pa == pb) {
					continue;
				}
				
				g_entity_t *pae = (g_entity_t *) pa->data;
				g_entity_t *pab = (g_entity_t *) pb->data;

				if ((reused_spawns[0] == pae && reused_spawns[1] == pab) ||
					(reused_spawns[0] == pab && reused_spawns[1] == pae)) {
					continue;
				}

				vec3_t line;
				VectorSubtract(pae->s.origin, pab->s.origin, line);
				line[2] /= 10.0; // don't consider Z as heavily as X/Y

				const vec_t dist = VectorLengthSquared(line);

				if (dist > furthest_dist) {

					reused_spawns[0] = pae;
					reused_spawns[1] = pab;
					furthest_dist = dist;
				}
			}
		}

		if (!reused_spawns[0] || !reused_spawns[1] || !furthest_dist) {
			return; // error in finding furthest points
		}
		
		red_flag = G_AllocEntity_(g_team_red->flag);
		blue_flag = G_AllocEntity_(g_team_blue->flag);

		const uint8_t r = Randomr(0, 2);

		VectorCopy(reused_spawns[r]->s.origin, red_flag->s.origin);
		VectorCopy(reused_spawns[r ^ 1]->s.origin, blue_flag->s.origin);
		
		G_SpawnItem(red_flag, g_media.items.flags[TEAM_RED]);
		G_SpawnItem(blue_flag, g_media.items.flags[TEAM_BLUE]);
		
		g_team_red->flag_entity = red_flag;
		g_team_blue->flag_entity = blue_flag;
	}

	for (GSList *point = *dm_spawns; point; point = point->next) {

		g_entity_t *p = (g_entity_t *) point->data;

		if (p == reused_spawns[0] || p == reused_spawns[1]) {
			continue;
		}

		const vec_t dist_to_red = VectorDistanceSquared(red_flag->s.origin, p->s.origin);
		const vec_t dist_to_blue = VectorDistanceSquared(blue_flag->s.origin, p->s.origin);

		if (dist_to_red < dist_to_blue) {
			*team_red_spawns = g_slist_prepend(*team_red_spawns, p);
		} else {
			*team_blue_spawns = g_slist_prepend(*team_blue_spawns, p);
		}
	}

	if (g_slist_length(*team_red_spawns) == g_slist_length(*team_blue_spawns)) {
		return; // best case scenario
	}
	
	// unmatched spawns, we need to move some
	*team_red_spawns = g_slist_sort_with_data(*team_red_spawns, G_CreateTeamSpawnPoints_CompareFunc, red_flag);
	*team_blue_spawns = g_slist_sort_with_data(*team_blue_spawns, G_CreateTeamSpawnPoints_CompareFunc, blue_flag);
		
	int32_t num_red_spawns = (int32_t) g_slist_length(*team_red_spawns);
	int32_t num_blue_spawns = (int32_t) g_slist_length(*team_blue_spawns);
	int32_t diff = abs(num_red_spawns - num_blue_spawns);

	GSList **from, **to;

	if (num_red_spawns > num_blue_spawns) {
		from = team_red_spawns;
		to = team_blue_spawns;
	} else {
		from = team_blue_spawns;
		to = team_red_spawns;
	}

	// odd number of points, make one neutral
	if (diff & 1) {
		g_entity_t *point = (g_entity_t *) ((*from)->data);

		*to = g_slist_prepend(*to, point);
	}

	int32_t num_move = diff - 1;
	
	// move spawns to the other team
	while (num_move) {

		g_entity_t *point = (g_entity_t *) ((*from)->data);

		*from = g_slist_remove(*from, point);
		*to = g_slist_prepend(*to, point);

		num_move--;
	}
}
Esempio n. 4
0
/**
 * @brief CG_AddParticleToScene
 * @param[in,out] p
 * @param[in] org
 * @param alpha - unused
 */
void CG_AddParticleToScene(cparticle_t *p, vec3_t org, float alpha)
{
	polyVert_t verts[4];
	polyVert_t TRIverts[3];

	switch (p->type)
	{
	case P_WEATHER:
	case P_WEATHER_TURBULENT:
	case P_WEATHER_FLURRY:
	case P_BUBBLE:
	case P_BUBBLE_TURBULENT:  // create a front facing polygon
	{
		if (p->type != P_WEATHER_FLURRY)
		{
			if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT)
			{
				if (org[2] > p->end)
				{
					p->time = cg.time;
					VectorCopy(org, p->org);   // fixes rare snow flakes that flicker on the ground

					p->org[2] = (p->start + crandom() * 4);

					if (p->type == P_BUBBLE_TURBULENT)
					{
						p->vel[0] = crandom() * 4;
						p->vel[1] = crandom() * 4;
					}
				}
			}
			else
			{
				if (org[2] < p->end)
				{
					p->time = cg.time;
					VectorCopy(org, p->org);   // fixes rare snow flakes that flicker on the ground

					while (p->org[2] < p->end)
					{
						p->org[2] += (p->start - p->end);
					}

					if (p->type == P_WEATHER_TURBULENT)
					{
						p->vel[0] = crandom() * 16;
						p->vel[1] = crandom() * 16;
					}
				}
			}

			// snow pvs check
			if (!p->link)
			{
				return;
			}

			p->alpha = 1;
		}

		// had to do this or MAX_POLYS is being exceeded in village1.bsp
		if (VectorDistanceSquared(cg.snap->ps.origin, org) > Square(1024))
		{
			return;
		}

		if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT)
		{
			vec3_t point;

			VectorMA(org, -p->height, vup, point);
			VectorMA(point, -p->width, vright, point);
			VectorCopy(point, 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] = (byte)(255 * p->alpha);

			VectorMA(org, -p->height, vup, point);
			VectorMA(point, p->width, vright, point);
			VectorCopy(point, 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] = (byte)(255 * p->alpha);

			VectorMA(org, p->height, vup, point);
			VectorMA(point, p->width, vright, point);
			VectorCopy(point, 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] = (byte)(255 * p->alpha);

			VectorMA(org, p->height, vup, point);
			VectorMA(point, -p->width, vright, point);
			VectorCopy(point, 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] = (byte)(255 * p->alpha);
		}
		else
		{
			vec3_t point;

			VectorMA(org, -p->height, vup, point);
			VectorMA(point, -p->width, vright, point);
			VectorCopy(point, TRIverts[0].xyz);
			TRIverts[0].st[0]       = 1;
			TRIverts[0].st[1]       = 0;
			TRIverts[0].modulate[0] = 255;
			TRIverts[0].modulate[1] = 255;
			TRIverts[0].modulate[2] = 255;
			TRIverts[0].modulate[3] = (byte)(255 * p->alpha);

			VectorMA(org, p->height, vup, point);
			VectorMA(point, -p->width, vright, point);
			VectorCopy(point, TRIverts[1].xyz);
			TRIverts[1].st[0]       = 0;
			TRIverts[1].st[1]       = 0;
			TRIverts[1].modulate[0] = 255;
			TRIverts[1].modulate[1] = 255;
			TRIverts[1].modulate[2] = 255;
			TRIverts[1].modulate[3] = (byte)(255 * p->alpha);

			VectorMA(org, p->height, vup, point);
			VectorMA(point, p->width, vright, point);
			VectorCopy(point, TRIverts[2].xyz);
			TRIverts[2].st[0]       = 0;
			TRIverts[2].st[1]       = 1;
			TRIverts[2].modulate[0] = 255;
			TRIverts[2].modulate[1] = 255;
			TRIverts[2].modulate[2] = 255;
			TRIverts[2].modulate[3] = (byte)(255 * p->alpha);
		}
	}
	break;
	case P_SPRITE:
	{
		vec3_t point, rr, ru, rotate_ang;
		float  time   = cg.time - p->time;
		float  time2  = p->endtime - p->time;
		float  ratio  = time / time2;
		float  width  = p->width + (ratio * (p->endwidth - p->width));
		float  height = p->height + (ratio * (p->endheight - p->height));

		if (p->roll)
		{
			vectoangles(cg.refdef_current->viewaxis[0], rotate_ang);
			rotate_ang[ROLL] += p->roll;
			AngleVectors(rotate_ang, NULL, rr, ru);
		}

		if (p->roll)
		{
			VectorMA(org, -height, ru, point);
			VectorMA(point, -width, rr, point);
		}
		else
		{
			VectorMA(org, -height, vup, point);
			VectorMA(point, -width, vright, point);
		}
		VectorCopy(point, 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] = 255;

		if (p->roll)
		{
			VectorMA(point, 2 * height, ru, point);
		}
		else
		{
			VectorMA(point, 2 * height, vup, point);
		}
		VectorCopy(point, 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] = 255;

		if (p->roll)
		{
			VectorMA(point, 2 * width, rr, point);
		}
		else
		{
			VectorMA(point, 2 * width, vright, point);
		}
		VectorCopy(point, 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] = 255;

		if (p->roll)
		{
			VectorMA(point, -2 * height, ru, point);
		}
		else
		{
			VectorMA(point, -2 * height, vup, point);
		}
		VectorCopy(point, 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] = 255;
	}
	break;
	case P_SMOKE:
	case P_SMOKE_IMPACT: // create a front rotating facing polygon
	{
		vec3_t point, rup2, rright2, color;
		float  invratio, time, time2, ratio, width, height;

		if (p->type == P_SMOKE_IMPACT && VectorDistanceSquared(cg.snap->ps.origin, org) > Square(1024))
		{
			return;
		}

		if (p->color == MUSTARD)
		{
			VectorSet(color, 0.42f, 0.33f, 0.19f);
		}
		else if (p->color == BLOODRED)
		{
			VectorSet(color, 0.22f, 0, 0);
		}
		else if (p->color == ZOMBIE)
		{
			VectorSet(color, 0.4f, 0.28f, 0.23f);
		}
		else if (p->color == GREY75)
		{
			float len, greyit;

			len = Distance(cg.snap->ps.origin, org);
			if (len == 0.f)
			{
				len = 1;
			}

			//val    = 4096 / len;
			greyit = 0.25f * (4096 / len);
			if (greyit > 0.5f)
			{
				greyit = 0.5f;
			}

			VectorSet(color, greyit, greyit, greyit);
		}
		else
		{
			VectorSet(color, 1.0f, 1.0f, 1.0f);
		}

		time  = cg.time - p->time;
		time2 = p->endtime - p->time;
		ratio = time / time2;

		if (cg.time > p->startfade)
		{
			invratio = 1 - ((cg.time - p->startfade) / (p->endtime - p->startfade));

			if (p->color == EMISIVEFADE)
			{
				float fval = invratio * invratio;

				if (fval < 0)
				{
					fval = 0;
				}
				VectorSet(color, fval, fval, fval);
			}
			invratio *= p->alpha;
		}
		else
		{
			invratio = 1 * p->alpha;
		}

		if (invratio > 1)
		{
			invratio = 1;
		}

		width  = p->width + (ratio * (p->endwidth - p->width));
		height = p->height + (ratio * (p->endheight - p->height));

		//if (p->type != P_SMOKE_IMPACT)
		{
			vec3_t temp;

			vectoangles(rforward, temp);
			p->accumroll += p->roll;
			temp[ROLL]   += p->accumroll * 0.1;
			//temp[ROLL] += p->roll * 0.1;
			AngleVectors(temp, NULL, rright2, rup2);
		}
		//else
		//{
		//VectorCopy (rright, rright2);
		//VectorCopy (rup, rup2);
		//}

		if (p->rotate)
		{
			VectorMA(org, -height, rup2, point);
			VectorMA(point, -width, rright2, point);
		}
		else
		{
			VectorMA(org, -p->height, vup, point);
			VectorMA(point, -p->width, vright, point);
		}
		VectorCopy(point, verts[0].xyz);
		verts[0].st[0]       = 0;
		verts[0].st[1]       = 0;
		verts[0].modulate[0] = (byte)(255 * color[0]);
		verts[0].modulate[1] = (byte)(255 * color[1]);
		verts[0].modulate[2] = (byte)(255 * color[2]);
		verts[0].modulate[3] = (byte)(255 * invratio);

		if (p->rotate)
		{
			VectorMA(org, -height, rup2, point);
			VectorMA(point, width, rright2, point);
		}
		else
		{
			VectorMA(org, -p->height, vup, point);
			VectorMA(point, p->width, vright, point);
		}
		VectorCopy(point, verts[1].xyz);
		verts[1].st[0]       = 0;
		verts[1].st[1]       = 1;
		verts[1].modulate[0] = (byte)(255 * color[0]);
		verts[1].modulate[1] = (byte)(255 * color[1]);
		verts[1].modulate[2] = (byte)(255 * color[2]);
		verts[1].modulate[3] = (byte)(255 * invratio);

		if (p->rotate)
		{
			VectorMA(org, height, rup2, point);
			VectorMA(point, width, rright2, point);
		}
		else
		{
			VectorMA(org, p->height, vup, point);
			VectorMA(point, p->width, vright, point);
		}
		VectorCopy(point, verts[2].xyz);
		verts[2].st[0]       = 1;
		verts[2].st[1]       = 1;
		verts[2].modulate[0] = (byte)(255 * color[0]);
		verts[2].modulate[1] = (byte)(255 * color[1]);
		verts[2].modulate[2] = (byte)(255 * color[2]);
		verts[2].modulate[3] = (byte)(255 * invratio);

		if (p->rotate)
		{
			VectorMA(org, height, rup2, point);
			VectorMA(point, -width, rright2, point);
		}
		else
		{
			VectorMA(org, p->height, vup, point);
			VectorMA(point, -p->width, vright, point);
		}
		VectorCopy(point, verts[3].xyz);
		verts[3].st[0]       = 1;
		verts[3].st[1]       = 0;
		verts[3].modulate[0] = (byte)(255 * color[0]);
		verts[3].modulate[1] = (byte)(255 * color[1]);
		verts[3].modulate[2] = (byte)(255 * color[2]);
		verts[3].modulate[3] = (byte)(255 * invratio);

	}
	break;
	case P_BLEED:
	{
		vec3_t point, rr, ru, rotate_ang;
		float  alpha = p->alpha;

		if (p->roll)
		{
			vectoangles(cg.refdef_current->viewaxis[0], rotate_ang);
			rotate_ang[ROLL] += p->roll;
			AngleVectors(rotate_ang, NULL, rr, ru);
		}
		else
		{
			VectorCopy(vup, ru);
			VectorCopy(vright, rr);
		}

		VectorMA(org, -p->height, ru, point);
		VectorMA(point, -p->width, rr, point);
		VectorCopy(point, verts[0].xyz);
		verts[0].st[0]       = 0;
		verts[0].st[1]       = 0;
		verts[0].modulate[0] = 111;
		verts[0].modulate[1] = 19;
		verts[0].modulate[2] = 9;
		verts[0].modulate[3] = (byte)(255 * alpha);

		VectorMA(org, -p->height, ru, point);
		VectorMA(point, p->width, rr, point);
		VectorCopy(point, verts[1].xyz);
		verts[1].st[0]       = 0;
		verts[1].st[1]       = 1;
		verts[1].modulate[0] = 111;
		verts[1].modulate[1] = 19;
		verts[1].modulate[2] = 9;
		verts[1].modulate[3] = (byte)(255 * alpha);

		VectorMA(org, p->height, ru, point);
		VectorMA(point, p->width, rr, point);
		VectorCopy(point, verts[2].xyz);
		verts[2].st[0]       = 1;
		verts[2].st[1]       = 1;
		verts[2].modulate[0] = 111;
		verts[2].modulate[1] = 19;
		verts[2].modulate[2] = 9;
		verts[2].modulate[3] = (byte)(255 * alpha);

		VectorMA(org, p->height, ru, point);
		VectorMA(point, -p->width, rr, point);
		VectorCopy(point, verts[3].xyz);
		verts[3].st[0]       = 1;
		verts[3].st[1]       = 0;
		verts[3].modulate[0] = 111;
		verts[3].modulate[1] = 19;
		verts[3].modulate[2] = 9;
		verts[3].modulate[3] = (byte)(255 * alpha);
	}
	break;
	case P_FLAT_SCALEUP:
	{
		vec3_t color;
		float  width, height;
		float  sinR, cosR;
		float  time  = cg.time - p->time;
		float  time2 = p->endtime - p->time;
		float  ratio = time / time2;

		if (p->color == BLOODRED)
		{
			VectorSet(color, 1, 1, 1);
		}
		else
		{
			VectorSet(color, 0.5f, 0.5f, 0.5f);
		}

		width  = p->width + (ratio * (p->endwidth - p->width));
		height = p->height + (ratio * (p->endheight - p->height));

		if (width > p->endwidth)
		{
			width = p->endwidth;
		}

		if (height > p->endheight)
		{
			height = p->endheight;
		}

		sinR = height * (float)(sin(DEG2RAD(p->roll)) * M_SQRT2);
		cosR = width * (float)(cos(DEG2RAD(p->roll)) * M_SQRT2);

		VectorCopy(org, verts[0].xyz);
		verts[0].xyz[0]     -= sinR;
		verts[0].xyz[1]     -= cosR;
		verts[0].st[0]       = 0;
		verts[0].st[1]       = 0;
		verts[0].modulate[0] = (byte)(255 * color[0]);
		verts[0].modulate[1] = (byte)(255 * color[1]);
		verts[0].modulate[2] = (byte)(255 * color[2]);
		verts[0].modulate[3] = 255;

		VectorCopy(org, verts[1].xyz);
		verts[1].xyz[0]     -= cosR;
		verts[1].xyz[1]     += sinR;
		verts[1].st[0]       = 0;
		verts[1].st[1]       = 1;
		verts[1].modulate[0] = verts[0].modulate[0];
		verts[1].modulate[1] = verts[0].modulate[1];
		verts[1].modulate[2] = verts[0].modulate[2];
		verts[1].modulate[3] = verts[0].modulate[3];

		VectorCopy(org, verts[2].xyz);
		verts[2].xyz[0]     += sinR;
		verts[2].xyz[1]     += cosR;
		verts[2].st[0]       = 1;
		verts[2].st[1]       = 1;
		verts[2].modulate[0] = verts[0].modulate[0];
		verts[2].modulate[1] = verts[0].modulate[1];
		verts[2].modulate[2] = verts[0].modulate[2];
		verts[2].modulate[3] = verts[0].modulate[3];

		VectorCopy(org, verts[3].xyz);
		verts[3].xyz[0]     += cosR;
		verts[3].xyz[1]     -= sinR;
		verts[3].st[0]       = 1;
		verts[3].st[1]       = 0;
		verts[3].modulate[0] = verts[0].modulate[0];
		verts[3].modulate[1] = verts[0].modulate[1];
		verts[3].modulate[2] = verts[0].modulate[2];
		verts[3].modulate[3] = verts[0].modulate[3];
	}
	break;
	case P_FLAT:
	{
		VectorCopy(org, verts[0].xyz);
		verts[0].xyz[0]     -= p->height;
		verts[0].xyz[1]     -= p->width;
		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] = 255;

		VectorCopy(org, verts[1].xyz);
		verts[1].xyz[0]     -= p->height;
		verts[1].xyz[1]     += p->width;
		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] = 255;

		VectorCopy(org, verts[2].xyz);
		verts[2].xyz[0]     += p->height;
		verts[2].xyz[1]     += p->width;
		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] = 255;

		VectorCopy(org, verts[3].xyz);
		verts[3].xyz[0]     += p->height;
		verts[3].xyz[1]     -= p->width;
		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] = 255;
	}
	break;
	case P_ANIM:
	case P_DLIGHT_ANIM:
	{
		vec3_t point, rr, ru, rotate_ang;
		float  width, height;
		float  time = cg.time - p->time;
		float  time2 = p->endtime - p->time;
		float  ratio = time / time2;
		int    i, j;

		if (ratio >= 1)
		{
			ratio = 0.9999f;
		}
		else if (ratio < 0)
		{
			// make sure that ratio isn't negative or
			// we'll walk out of bounds when j is calculated below
			ratio = 0.0001f;
		}

		width  = p->width + (ratio * (p->endwidth - p->width));
		height = p->height + (ratio * (p->endheight - p->height));

		// add dlight if necessary
		if (p->type == P_DLIGHT_ANIM)
		{
			// fixme: support arbitrary color
			trap_R_AddLightToScene(org, 320,        //%	1.5 * (width > height ? width : height),
			                       1.25f * (1.0f - ratio), 1.0f, 0.95f, 0.85f, 0, 0);
		}

		// if we are "inside" this sprite, don't draw
		if (VectorDistanceSquared(cg.snap->ps.origin, org) < Square(width / 1.5f))
		{
			return;
		}

		i          = p->shaderAnim;
		j          = (int)floor((double)ratio * shaderAnimCounts[p->shaderAnim]);
		p->pshader = shaderAnims[i][j];

		if (p->roll)
		{
			vectoangles(cg.refdef_current->viewaxis[0], rotate_ang);
			rotate_ang[ROLL] += p->roll;
			AngleVectors(rotate_ang, NULL, rr, ru);
		}

		if (p->roll)
		{
			VectorMA(org, -height, ru, point);
			VectorMA(point, -width, rr, point);
		}
		else
		{
			VectorMA(org, -height, vup, point);
			VectorMA(point, -width, vright, point);
		}
		VectorCopy(point, 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] = 255;

		if (p->roll)
		{
			VectorMA(point, 2 * height, ru, point);
		}
		else
		{
			VectorMA(point, 2 * height, vup, point);
		}
		VectorCopy(point, 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] = 255;

		if (p->roll)
		{
			VectorMA(point, 2 * width, rr, point);
		}
		else
		{
			VectorMA(point, 2 * width, vright, point);
		}
		VectorCopy(point, 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] = 255;

		if (p->roll)
		{
			VectorMA(point, -2 * height, ru, point);
		}
		else
		{
			VectorMA(point, -2 * height, vup, point);
		}
		VectorCopy(point, 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] = 255;
	}
	break;
	default:
		break;
	}

	if (!cg_wolfparticles.integer)
	{
		return;
	}

	if (!p->pshader)
	{
		CG_Printf("CG_AddParticleToScene type %d p->pshader == ZERO\n", p->type);
		return;
	}

	if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY)
	{
		trap_R_AddPolyToScene(p->pshader, 3, TRIverts);
	}
	else
	{
		trap_R_AddPolyToScene(p->pshader, 4, verts);
	}
}
Esempio n. 5
0
/*
================
Bot_ScriptInitBot
================
*/
qboolean Bot_ScriptInitBot(int entnum)
{
	gentity_t      *ent, *trav;
	bot_state_t    *bs;
	char            userinfo[MAX_INFO_STRING];
	bot_script_global_data_t *bsgd;
	char           *token, *p, *pBackup;
	int             i, val = 0;
	int             weapons[2];
	gitem_t        *item = NULL;
	char           *name;

	//
	bs = &botstates[entnum];
	if(!bs->inuse)
	{
		return qfalse;
	}
	if(bs->script.data)
	{
		return qtrue;
	}
	// set starting defaults
	bs->script.status.eventIndex = -1;
	bs->script.data = NULL;
	//
	ent = BotGetEntity(bs->entitynum);
	trap_GetUserinfo(bs->entitynum, userinfo, sizeof(userinfo));
	name = Info_ValueForKey(userinfo, "scriptName");
	if(!name || !name[0])
	{
		return qfalse;
	}

	// find the script data for this bot
	bsgd = botCharacterScriptData;
	for(i = 0; i < numScriptCharacters; i++, bsgd++)
	{
		if(Q_stricmp(name, bsgd->name) != 0)
		{
			continue;
		}
		// check params
		p = bsgd->params;
		//
		// eliminate them with each condition not met
		while(qtrue)
		{
			token = COM_ParseExt(&p, qfalse);
			if(!token || !token[0])
			{
				// we're done, we found a match
				break;
			}
			//
			if(token[0] != '/')
			{
				G_Error("BotScript, line %i: condition identifier expected, '%s' found\n", bsgd->lineNum, token);
			}
			//
			if(!Q_stricmp(token, "/team"))
			{
				token = COM_ParseExt(&p, qfalse);
				if(!token || !token[0] || token[0] == '/')
				{
					G_Error("BotScript, line %i: unexpected end of /team parameter", bsgd->lineNum);
				}
				//
				if(!Q_stricmp(token, "axis"))
				{
					val = TEAM_AXIS;
				}
				else if(!Q_stricmp(token, "allies"))
				{
					val = TEAM_ALLIES;
				}
				else
				{
					G_Error("BotScript, line %i: unknown team \"%s\"", bsgd->lineNum, token);
				}
				// eliminate player
				if(bs->mpTeam != val)
				{
					break;
				}
			}
			else
				//
			if(!Q_stricmp(token, "/class"))
			{
				token = COM_ParseExt(&p, qfalse);
				if(!token || !token[0] || token[0] == '/')
				{
					G_Error("BotScript, line %i: unexpected end of /class parameter", bsgd->lineNum);
				}
				//
				val = Team_ClassForString(token);
				if(val < 0)
				{
					G_Error("BotScript, line %i: unknown class \"%s\"", bsgd->lineNum, token);
				}
				if(bs->mpClass != val)
				{
					break;
				}
			}
			else
				//
			if(!Q_stricmp(token, "/weapon"))
			{
				memset(weapons, 0, sizeof(weapons));
				// for each weapon
				while(qtrue)
				{
					// read the weapon
					token = COM_ParseExt(&p, qfalse);
					if(!token || !token[0] || token[0] == '/')
					{
						G_Error("BotScript, line %i: unexpected end of /weapon parameter", bsgd->lineNum);
					}
					//
					if((item = BG_FindItem(token)))
					{
						if(!item->giTag)
						{
							G_Error("BotScript, line %i: unknown weapon \"%s\"", bsgd->lineNum, token);
						}
						COM_BitSet(weapons, item->giTag);
					}
					else
					{
						G_Error("BotScript, line %i: unknown weapon \"%s\"", bsgd->lineNum, token);
					}
					//
					pBackup = p;
					token = COM_ParseExt(&p, qfalse);
					if(Q_stricmp(token, "or") != 0)
					{
						// not OR, so drop out of here
						p = pBackup;
						break;
					}
				}
				if(!(ent->client->ps.weapons[0] & weapons[0]) && !(ent->client->ps.weapons[1] & weapons[1]))
				{
					break;
				}
			}
			else
				//
			if(!Q_stricmp(token, "/within_range"))
			{
				// targetname
				token = COM_ParseExt(&p, qfalse);
				if(!token || !token[0] || token[0] == '/')
				{
					G_Error("BotScript, line %i: unexpected end of /within_range parameter", bsgd->lineNum);
				}
				trav = G_FindByTargetname(NULL, token);
				if(!trav)
				{
					G_Error("BotScript, line %i: unknown spawn point \"%s\"", bsgd->lineNum, token);
				}
				// range
				token = COM_ParseExt(&p, qfalse);
				if(!token || !token[0] || token[0] == '/')
				{
					G_Error("BotScript, line %i: range expected, not found", bsgd->lineNum);
				}
				//
				// eliminate players
				if(VectorDistanceSquared(ent->r.currentOrigin, trav->s.origin) > SQR(atof(token)))
				{
					break;
				}
			}
		}
		//
		// if there is a NOT a valid token waiting, then we passed all checks
		if(!token[0])
		{
			break;
		}
	}
	//
	if(i < numScriptCharacters)
	{
		// we found a script for this character
		bs->script.data = bsgd->data;
		return qtrue;
	}
	//
	return qfalse;
}