/** * @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)); }
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); } }
/** * @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--; } }
/** * @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); } }
/* ================ 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; }