static float ProjectRadius(float r, vec3_t location) { float pr; float dist; float c; vec3_t p; float projected[4];
/* * ====================================================================== * * SHOTGUN * * ====================================================================== */ // DEFAULT_SHOTGUN_SPREAD and DEFAULT_SHOTGUN_COUNT are in bg_public.h, because // client predicts same spreads #define DEFAULT_SHOTGUN_DAMAGE 10 bool ShotgunPellet(vec3_t start, vec3_t end, gentity_t *ent) { trace_t tr; int damage, i, passent; gentity_t *traceEnt; vec3_t tr_start, tr_end; passent = ent->s.number; VectorCopy(start, tr_start); VectorCopy(end, tr_end); for (i = 0; i < 10; i++) { trap_Trace(&tr, tr_start, NULL, NULL, tr_end, passent, MASK_SHOT); traceEnt = &g_entities[tr.entityNum]; // send bullet impact if (tr.surfaceFlags & SURF_NOIMPACT) { return(false); } if (traceEnt->takedamage) { damage = DEFAULT_SHOTGUN_DAMAGE * s_quadFactor; G_Damage(traceEnt, ent, ent, forward, tr.endpos, damage, 0, MOD_SHOTGUN); if (LogAccuracyHit(traceEnt, ent)) { return(true); } } return(false); } return(false); }
//============================================================================= /* * ================= * fire_rocket * ================= */ gentity_t *fire_rocket(gentity_t *self, vec3_t start, vec3_t dir) { gentity_t *bolt; VectorNormalize(dir); bolt = G_Spawn(); bolt->classname = "rocket"; bolt->nextthink = level.time + 15000; bolt->think = G_ExplodeMissile; bolt->s.eType = ET_MISSILE; bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN; bolt->s.weapon = WP_ROCKET_LAUNCHER; bolt->r.ownerNum = self->s.number; bolt->parent = self; bolt->damage = 100; bolt->splashDamage = 100; bolt->splashRadius = 120; bolt->methodOfDeath = MOD_ROCKET; bolt->splashMethodOfDeath = MOD_ROCKET_SPLASH; bolt->clipmask = MASK_SHOT; bolt->target_ent = NULL; bolt->s.pos.trType = TR_LINEAR; bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME; // move a bit on the very first frame VectorCopy(start, bolt->s.pos.trBase); VectorScale(dir, 900, bolt->s.pos.trDelta); SnapVector(bolt->s.pos.trDelta); // save net bandwidth VectorCopy(start, bolt->r.currentOrigin); return(bolt); }
// this should match CG_ShotgunPattern void ShotgunPattern(vec3_t origin, vec3_t origin2, int seed, gentity_t *ent) { int i; float r, u; vec3_t end; vec3_t forward, right, up; int oldScore; bool hitClient = false; // derive the right and up vectors from the forward vector, because // the client won't have any other information VectorNormalize2(origin2, forward); PerpendicularVector(right, forward); CrossProduct(forward, right, up); oldScore = ent->client->ps.persistant[PERS_SCORE]; // generate the "random" spread pattern for (i = 0; i < DEFAULT_SHOTGUN_COUNT; i++) { r = Q_crandom(&seed) * DEFAULT_SHOTGUN_SPREAD * 16; u = Q_crandom(&seed) * DEFAULT_SHOTGUN_SPREAD * 16; VectorMA(origin, 8192 * 16, forward, end); VectorMA(end, r, right, end); VectorMA(end, u, up, end); if (ShotgunPellet(origin, end, ent) && !hitClient) { hitClient = true; ent->client->accuracy_hits++; } } }
//calculates collision with given entity bool AAS_EntityCollision(int entnum, vec3_t start, vec3_t boxmins, vec3_t boxmaxs, vec3_t end, int contentmask, bsp_trace_t *trace);
} //end of the function AAS_DebugLine //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void AAS_PermanentLine(vec3_t start, vec3_t end, int color) { int line; line = botimport.DebugLineCreate(); botimport.DebugLineShow(line, start, end, color); } //end of the function AAS_PermenentLine
/* * ================= * fire_grapple * ================= */ gentity_t *fire_grapple(gentity_t *self, vec3_t start, vec3_t dir) { gentity_t *hook; VectorNormalize(dir); hook = G_Spawn(); hook->classname = "hook"; hook->nextthink = level.time + 10000; hook->think = Weapon_HookFree; hook->s.eType = ET_MISSILE; hook->r.svFlags = SVF_USE_CURRENT_ORIGIN; hook->s.weapon = WP_GRAPPLING_HOOK; hook->r.ownerNum = self->s.number; hook->methodOfDeath = MOD_GRAPPLE; hook->clipmask = MASK_SHOT; hook->parent = self; hook->target_ent = NULL; hook->s.pos.trType = TR_LINEAR; hook->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME; // move a bit on the very first frame hook->s.otherEntityNum = self->s.number; // use to match beam in client VectorCopy(start, hook->s.pos.trBase); VectorScale(dir, 800, hook->s.pos.trDelta); SnapVector(hook->s.pos.trDelta); // save net bandwidth VectorCopy(start, hook->r.currentOrigin); self->client->hook = hook; return(hook); }
} //end of the function EA_Move //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void EA_View(int client, vec3_t viewangles) { bot_input_t *bi; bi = &botinputs[client]; VectorCopy(viewangles, bi->viewangles); } //end of the function EA_View
/* * =============== * CalcMuzzlePointOrigin * * set muzzle location relative to pivoting eye * =============== */ void CalcMuzzlePointOrigin(gentity_t *ent, vec3_t origin, vec3_t forward, vec3_t right, vec3_t up, vec3_t muzzlePoint) { VectorCopy(ent->s.pos.trBase, muzzlePoint); muzzlePoint[2] += ent->client->ps.viewheight; VectorMA(muzzlePoint, 14, forward, muzzlePoint); // snap to integer coordinates for more efficient network bandwidth usage SnapVector(muzzlePoint); }
/* * ================== * CG_BubbleTrail * * Bullets shot underwater * ================== */ void CG_BubbleTrail(vec3_t start, vec3_t end, float spacing) { vec3_t move; vec3_t vec; float len; int i; if (cg_noProjectileTrail.integer) { return; } VectorCopy(start, move); VectorSubtract(end, start, vec); len = VectorNormalize(vec); // advance a random amount first i = rand() % (int)spacing; VectorMA(move, i, vec, move); VectorScale(vec, spacing, vec); for ( ; i < len; i += spacing) { localEntity_t *le; refEntity_t * re; le = CG_AllocLocalEntity(); le->leFlags = LEF_PUFF_DONT_SCALE; le->leType = LE_MOVE_SCALE_FADE; le->startTime = cg.time; le->endTime = cg.time + 1000 + random() * 250; le->lifeRate = 1.0 / (le->endTime - le->startTime); re = &le->refEntity; re->shaderTime = cg.time / 1000.0f; re->reType = RT_SPRITE; re->rotation = 0; re->radius = 3; re->customShader = cgs.media.waterBubbleShader; re->shaderRGBA[0] = 0xff; re->shaderRGBA[1] = 0xff; re->shaderRGBA[2] = 0xff; re->shaderRGBA[3] = 0xff; le->color[3] = 1.0; le->pos.trType = TR_LINEAR; le->pos.trTime = cg.time; VectorCopy(move, le->pos.trBase); le->pos.trDelta[0] = crandom() * 5; le->pos.trDelta[1] = crandom() * 5; le->pos.trDelta[2] = crandom() * 5 + 6; VectorAdd(move, vec, move); } }
/* * ================ * G_BounceProjectile * ================ */ void G_BounceProjectile(vec3_t start, vec3_t impact, vec3_t dir, vec3_t endout) { vec3_t v, newv; float dot; VectorSubtract(impact, start, v); dot = DotProduct(v, dir); VectorMA(v, -2 * dot, dir, newv); VectorNormalize(newv); VectorMA(impact, 8192, newv, endout); }
/* * ============ * ScorePlum * ============ */ void ScorePlum(gentity_t *ent, vec3_t origin, int score) { gentity_t *plum; plum = G_TempEntity(origin, EV_SCOREPLUM); // only send this temp entity to a single client plum->r.svFlags |= SVF_SINGLECLIENT; plum->r.singleClient = ent->s.number; // plum->s.otherEntityNum = ent->s.number; plum->s.time = score; }
/* * ================================================================================= * * TELEPORTERS * * ================================================================================= */ void TeleportPlayer(gentity_t *player, vec3_t origin, vec3_t angles) { gentity_t *tent; // use temp events at source and destination to prevent the effect // from getting dropped by a second player event if (player->client->sess.sessionTeam != TEAM_SPECTATOR) { tent = G_TempEntity(player->client->ps.origin, EV_PLAYER_TELEPORT_OUT); tent->s.clientNum = player->s.clientNum; tent = G_TempEntity(origin, EV_PLAYER_TELEPORT_IN); tent->s.clientNum = player->s.clientNum; } // unlink to make sure it can't possibly interfere with G_KillBox trap_UnlinkEntity(player); VectorCopy(origin, player->client->ps.origin); player->client->ps.origin[2] += 1; // spit the player out AngleVectors(angles, player->client->ps.velocity, NULL, NULL); VectorScale(player->client->ps.velocity, 400, player->client->ps.velocity); player->client->ps.pm_time = 160; // hold time player->client->ps.pm_flags |= PMF_TIME_KNOCKBACK; // toggle the teleport bit so the client knows to not lerp player->client->ps.eFlags ^= EF_TELEPORT_BIT; // set angles SetClientViewAngle(player, angles); // kill anything at the destination if (player->client->sess.sessionTeam != TEAM_SPECTATOR) { G_KillBox(player); } // save results of pmove BG_PlayerStateToEntityState(&player->client->ps, &player->s, true); // use the precise origin for linking VectorCopy(player->client->ps.origin, player->r.currentOrigin); if (player->client->sess.sessionTeam != TEAM_SPECTATOR) { trap_LinkEntity(player); } }
} //end of the function AAS_PermenentLine //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void AAS_DrawPermanentCross(vec3_t origin, float size, int color) { int i, debugline; vec3_t start, end; for (i = 0; i < 3; i++) { VectorCopy(origin, start); start[i] += size; VectorCopy(origin, end); end[i] -= size; AAS_DebugLine(start, end, color); debugline = botimport.DebugLineCreate(); botimport.DebugLineShow(debugline, start, end, color); } //end for } //end of the function AAS_DrawPermanentCross
/* * ====================================================================== * * MACHINEGUN * * ====================================================================== */ /* * ====================== * SnapVectorTowards * * Round a vector to integers for more efficient network * transmission, but make sure that it rounds towards a given point * rather than blindly truncating. This prevents it from truncating * into a wall. * ====================== */ void SnapVectorTowards(vec3_t v, vec3_t to) { int i; for (i = 0; i < 3; i++) { if (to[i] <= v[i]) { v[i] = (int)v[i]; } else { v[i] = (int)v[i] + 1; } } }
} //end of the function EA_MoveRight //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void EA_Move(int client, vec3_t dir, float speed) { bot_input_t *bi; bi = &botinputs[client]; VectorCopy(dir, bi->dir); //cap speed if (speed > MAX_USERMOVE) { speed = MAX_USERMOVE; } else if (speed < -MAX_USERMOVE) { speed = -MAX_USERMOVE; } bi->speed = speed; } //end of the function EA_Move
//====================================================================== /* * ================ * LaunchItem * * Spawns an item and tosses it forward * ================ */ gentity_t *LaunchItem(gitem_t *item, vec3_t origin, vec3_t velocity) { gentity_t *dropped; dropped = G_Spawn(); dropped->s.eType = ET_ITEM; dropped->s.modelindex = item - bg_itemlist; // store item number in modelindex dropped->s.modelindex2 = 1; // This is non-zero is it's a dropped item dropped->classname = item->classname; dropped->item = item; VectorSet(dropped->r.mins, -ITEM_RADIUS, -ITEM_RADIUS, -ITEM_RADIUS); VectorSet(dropped->r.maxs, ITEM_RADIUS, ITEM_RADIUS, ITEM_RADIUS); dropped->r.contents = CONTENTS_TRIGGER; dropped->touch = Touch_Item; G_SetOrigin(dropped, origin); dropped->s.pos.trType = TR_GRAVITY; dropped->s.pos.trTime = level.time; VectorCopy(velocity, dropped->s.pos.trDelta); dropped->s.eFlags |= EF_BOUNCE_HALF; if (g_gametype.integer == GT_CTF && item->giType == IT_TEAM) // Special case for CTF flags { dropped->think = Team_DroppedFlagThink; dropped->nextthink = level.time + 30000; Team_CheckDroppedItem(dropped); } else // auto-remove after 30 seconds { dropped->think = G_FreeEntity; dropped->nextthink = level.time + 30000; } dropped->flags = FL_DROPPED_ITEM; trap_LinkEntity(dropped); return(dropped); }
} //end of the function AAS_ClearShownDebugLines //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void AAS_DebugLine(vec3_t start, vec3_t end, int color) { int line; for (line = 0; line < MAX_DEBUGLINES; line++) { if (!debuglines[line]) { debuglines[line] = botimport.DebugLineCreate(); debuglinevisible[line] = false; numdebuglines++; } //end if if (!debuglinevisible[line]) { botimport.DebugLineShow(debuglines[line], start, end, color); debuglinevisible[line] = true; return; } //end else } //end for } //end of the function AAS_DebugLine
/* * ============ * AddScore * * Adds score to both the client and his team * ============ */ void AddScore(gentity_t *ent, vec3_t origin, int score) { if (!ent->client) { return; } // no scoring during pre-match warmup if (level.warmupTime) { return; } // show score plum ScorePlum(ent, origin, score); // ent->client->ps.persistant[PERS_SCORE] += score; if (g_gametype.integer == GT_TEAM) { level.teamScores[ent->client->ps.persistant[PERS_TEAM]] += score; } CalculateRanks(); }
//returns the contents at the given point int AAS_PointContents(vec3_t point);
//returns true when p2 is in the PVS of p1 bool AAS_inPVS(vec3_t p1, vec3_t p2);
//returns true when p2 is in the PHS of p1 bool AAS_inPHS(vec3_t p1, vec3_t p2);
//creates a list with entities totally or partly within the given box int AAS_BoxEntities(vec3_t absmins, vec3_t absmaxs, int *list, int maxcount);
} //end of the function AAS_DrawPermanentCross //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void AAS_DrawPlaneCross(vec3_t point, vec3_t normal, float dist, int type, int color) { int n0, n1, n2, j, line, lines[2];
//get a vector for the BSP epair key int AAS_VectorForBSPEpairKey(int ent, char *key, vec3_t v);
// if origin is NULL, the sound will be dynamically sourced from the entity void S_StartSound(vec3_t origin, int entnum, int entchannel, sfxHandle_t sfx);
/* * ============== * RB_AddQuadStampExt * ============== */ void RB_AddQuadStampExt(vec3_t origin, vec3_t left, vec3_t up, byte *color, float s1, float t1, float s2, float t2) { vec3_t normal; int ndx; RB_CHECKOVERFLOW(4, 6); ndx = tess.numVertexes; // triangle indexes for a simple quad tess.indexes[tess.numIndexes] = ndx; tess.indexes[tess.numIndexes + 1] = ndx + 1; tess.indexes[tess.numIndexes + 2] = ndx + 3; tess.indexes[tess.numIndexes + 3] = ndx + 3; tess.indexes[tess.numIndexes + 4] = ndx + 1; tess.indexes[tess.numIndexes + 5] = ndx + 2; tess.xyz[ndx][0] = origin[0] + left[0] + up[0]; tess.xyz[ndx][1] = origin[1] + left[1] + up[1]; tess.xyz[ndx][2] = origin[2] + left[2] + up[2]; tess.xyz[ndx + 1][0] = origin[0] - left[0] + up[0]; tess.xyz[ndx + 1][1] = origin[1] - left[1] + up[1]; tess.xyz[ndx + 1][2] = origin[2] - left[2] + up[2]; tess.xyz[ndx + 2][0] = origin[0] - left[0] - up[0]; tess.xyz[ndx + 2][1] = origin[1] - left[1] - up[1]; tess.xyz[ndx + 2][2] = origin[2] - left[2] - up[2]; tess.xyz[ndx + 3][0] = origin[0] + left[0] - up[0]; tess.xyz[ndx + 3][1] = origin[1] + left[1] - up[1]; tess.xyz[ndx + 3][2] = origin[2] + left[2] - up[2]; // constant normal all the way around VectorSubtract(vec3_origin, backEnd.viewParms.or.axis[0], normal); tess.normal[ndx][0] = tess.normal[ndx + 1][0] = tess.normal[ndx + 2][0] = tess.normal[ndx + 3][0] = normal[0]; tess.normal[ndx][1] = tess.normal[ndx + 1][1] = tess.normal[ndx + 2][1] = tess.normal[ndx + 3][1] = normal[1]; tess.normal[ndx][2] = tess.normal[ndx + 1][2] = tess.normal[ndx + 2][2] = tess.normal[ndx + 3][2] = normal[2]; // standard square texture coordinates tess.texCoords[ndx][0][0] = tess.texCoords[ndx][1][0] = s1; tess.texCoords[ndx][0][1] = tess.texCoords[ndx][1][1] = t1; tess.texCoords[ndx + 1][0][0] = tess.texCoords[ndx + 1][1][0] = s2; tess.texCoords[ndx + 1][0][1] = tess.texCoords[ndx + 1][1][1] = t1; tess.texCoords[ndx + 2][0][0] = tess.texCoords[ndx + 2][1][0] = s2; tess.texCoords[ndx + 2][0][1] = tess.texCoords[ndx + 2][1][1] = t2; tess.texCoords[ndx + 3][0][0] = tess.texCoords[ndx + 3][1][0] = s1; tess.texCoords[ndx + 3][0][1] = tess.texCoords[ndx + 3][1][1] = t2; // constant color all the way around // should this be identity and let the shader specify from entity? *( unsigned int * )&tess.vertexColors[ndx] = *( unsigned int * )&tess.vertexColors[ndx + 1] = *( unsigned int * )&tess.vertexColors[ndx + 2] = *( unsigned int * )&tess.vertexColors[ndx + 3] = *( unsigned int * )color; tess.numVertexes += 4; tess.numIndexes += 6; }
public eval_t(int address) { this.address = address; vector = new vec3_t(this); }
// #define MAX_EPAIRKEY 128 //trace through the world bsp_trace_t AAS_Trace(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int passent, int contentmask);
/* * ============== * RB_AddQuadStamp * ============== */ void RB_AddQuadStamp(vec3_t origin, vec3_t left, vec3_t up, byte *color) { RB_AddQuadStampExt(origin, left, up, color, 0, 0, 1, 1); }
//gets the mins, maxs and origin of a BSP model void AAS_BSPModelMinsMaxsOrigin(int modelnum, vec3_t angles, vec3_t mins, vec3_t maxs, vec3_t origin);