mirror of
https://github.com/ReactionQuake3/reaction.git
synced 2024-11-11 07:42:15 +00:00
New TNG spawning system :)
This commit is contained in:
parent
500d26beac
commit
c114cae764
8 changed files with 328 additions and 12 deletions
|
@ -5,6 +5,9 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log$
|
||||
// Revision 1.81 2002/06/19 18:13:57 jbravo
|
||||
// New TNG spawning system :)
|
||||
//
|
||||
// Revision 1.80 2002/06/16 20:06:14 jbravo
|
||||
// Reindented all the source files with "indent -kr -ut -i8 -l120 -lc120 -sob -bad -bap"
|
||||
//
|
||||
|
@ -1319,6 +1322,7 @@ qboolean BG_CanItemBeGrabbed(int gametype, const entityState_t * ent, const play
|
|||
#define DF_NO_FALLING 8
|
||||
#define DF_FIXED_FOV 16
|
||||
#define DF_NO_FOOTSTEPS 32
|
||||
#define DF_SPAWN_FARTHEST 512
|
||||
|
||||
// content masks
|
||||
#define MASK_ALL (-1)
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log$
|
||||
// Revision 1.80 2002/06/19 18:13:57 jbravo
|
||||
// New TNG spawning system :)
|
||||
//
|
||||
// Revision 1.79 2002/06/18 06:15:30 niceass
|
||||
// m4 kick now smooth
|
||||
//
|
||||
|
@ -140,8 +143,6 @@
|
|||
// Copyright (C) 1999-2000 Id Software, Inc.
|
||||
//
|
||||
#include "g_local.h"
|
||||
// JBravo: need TP functions
|
||||
#include "g_teamplay.h"
|
||||
#include "zcam.h"
|
||||
|
||||
//Elder: moved kick to g_weapon.c where it belongs
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log$
|
||||
// Revision 1.96 2002/06/19 18:13:57 jbravo
|
||||
// New TNG spawning system :)
|
||||
//
|
||||
// Revision 1.95 2002/06/17 00:23:59 slicer
|
||||
// Lasersight problem fixed
|
||||
//
|
||||
|
@ -332,7 +335,8 @@ SelectNearestDeathmatchSpawnPoint
|
|||
Find the spot that we DON'T want to use
|
||||
================
|
||||
*/
|
||||
#define MAX_SPAWN_POINTS 128
|
||||
// Moved to g_local.h
|
||||
//#define MAX_SPAWN_POINTS 128
|
||||
gentity_t *SelectNearestDeathmatchSpawnPoint(vec3_t from)
|
||||
{
|
||||
gentity_t *spot;
|
||||
|
@ -364,7 +368,8 @@ SelectRandomDeathmatchSpawnPoint
|
|||
go to a random point that doesn't telefrag
|
||||
================
|
||||
*/
|
||||
#define MAX_SPAWN_POINTS 128
|
||||
// Moved to g_local.h
|
||||
//#define MAX_SPAWN_POINTS 128
|
||||
gentity_t *SelectRandomDeathmatchSpawnPoint(void)
|
||||
{
|
||||
gentity_t *spot;
|
||||
|
@ -1563,7 +1568,7 @@ void ClientSpawn(gentity_t * ent)
|
|||
client = ent->client;
|
||||
|
||||
// JBravo: Check if team spawnpoints have been located. If not find a spot for each team ala AQ2.
|
||||
if (g_gametype.integer == GT_TEAMPLAY) {
|
||||
/* if (g_gametype.integer == GT_TEAMPLAY) {
|
||||
if (!level.spawnPointsLocated) {
|
||||
client->pers.initialSpawn = qfalse;
|
||||
do {
|
||||
|
@ -1582,7 +1587,7 @@ void ClientSpawn(gentity_t * ent)
|
|||
level.team2spawn_angles);
|
||||
level.spawnPointsLocated = qtrue;
|
||||
}
|
||||
}
|
||||
} */
|
||||
// End JBravo.
|
||||
|
||||
// find a spawn point
|
||||
|
@ -1604,16 +1609,21 @@ void ClientSpawn(gentity_t * ent)
|
|||
client->pers.teamState.state, spawn_origin, spawn_angles);
|
||||
// JBravo: If we are in Teamplay mode, use the teamspawnpoints.
|
||||
} else if (g_gametype.integer == GT_TEAMPLAY) {
|
||||
|
||||
// Freud: Assign the spawns from the spawning system (g_teamplay.c)
|
||||
level.team1spawnpoint = level.teamplay_spawns[0];
|
||||
level.team2spawnpoint = level.teamplay_spawns[1];
|
||||
|
||||
if (client->sess.sessionTeam == TEAM_RED) {
|
||||
client->sess.spawnPoint = level.team1spawnpoint;
|
||||
spawnPoint = level.team1spawnpoint;
|
||||
VectorCopy(level.team1spawn_angles, spawn_angles);
|
||||
VectorCopy(level.team1spawn_origin, spawn_origin);
|
||||
VectorCopy(level.team1spawnpoint->s.angles, spawn_angles);
|
||||
VectorCopy(level.team1spawnpoint->s.origin, spawn_origin);
|
||||
} else {
|
||||
client->sess.spawnPoint = level.team2spawnpoint;
|
||||
spawnPoint = level.team2spawnpoint;
|
||||
VectorCopy(level.team2spawn_angles, spawn_angles);
|
||||
VectorCopy(level.team2spawn_origin, spawn_origin);
|
||||
VectorCopy(level.team2spawnpoint->s.angles, spawn_angles);
|
||||
VectorCopy(level.team2spawnpoint->s.origin, spawn_origin);
|
||||
}
|
||||
// End JBravo.
|
||||
} else {
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log$
|
||||
// Revision 1.97 2002/06/19 18:13:57 jbravo
|
||||
// New TNG spawning system :)
|
||||
//
|
||||
// Revision 1.96 2002/06/18 09:22:16 niceass
|
||||
// file exist function
|
||||
//
|
||||
|
@ -213,6 +216,8 @@
|
|||
|
||||
// JBravo: Max number of killed enemys to track
|
||||
#define RQ3_MAXKILLS 5
|
||||
#define MAX_TEAMS 2
|
||||
#define MAX_SPAWN_POINTS 128
|
||||
|
||||
// Blaze: How long someone bleeds for
|
||||
// Elder: This doesn't work the same as Q2 because clients and servers can
|
||||
|
@ -748,6 +753,16 @@ typedef struct {
|
|||
//Slicer:
|
||||
int team1gender;
|
||||
int team2gender;
|
||||
|
||||
// Freud: spawning system
|
||||
int randteam;
|
||||
int num_used_farteamplay_spawns[MAX_TEAMS];
|
||||
int num_potential_spawns[MAX_TEAMS];
|
||||
gentity_t *teamplay_spawns[MAX_TEAMS];
|
||||
qboolean teams_assigned[MAX_TEAMS];
|
||||
gentity_t *potential_spawns[MAX_TEAMS][MAX_SPAWN_POINTS];
|
||||
gentity_t *used_farteamplay_spawns[MAX_TEAMS][MAX_SPAWN_POINTS];
|
||||
|
||||
} level_locals_t;
|
||||
|
||||
//
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log$
|
||||
// Revision 1.91 2002/06/19 18:13:57 jbravo
|
||||
// New TNG spawning system :)
|
||||
//
|
||||
// Revision 1.90 2002/06/19 05:21:43 niceass
|
||||
// scoreboard stuff
|
||||
//
|
||||
|
@ -981,6 +984,8 @@ void G_InitGame(int levelTime, int randomSeed, int restart)
|
|||
level.team_game_going = 0;
|
||||
level.team_round_going = 0;
|
||||
level.fps = trap_Cvar_VariableIntegerValue("sv_fps");
|
||||
level.num_potential_spawns[0] = 0;
|
||||
level.num_potential_spawns[1] = 0;
|
||||
}
|
||||
// Slicer: reset matchmode vars
|
||||
if (g_RQ3_matchmode.integer && g_gametype.integer == GT_TEAMPLAY) {
|
||||
|
@ -998,7 +1003,6 @@ void G_InitGame(int levelTime, int randomSeed, int restart)
|
|||
}
|
||||
|
||||
G_RemapTeamShaders();
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log$
|
||||
// Revision 1.13 2002/06/19 18:13:57 jbravo
|
||||
// New TNG spawning system :)
|
||||
//
|
||||
// Revision 1.12 2002/06/18 03:57:38 jbravo
|
||||
// Committing for aasimon. Callvote nextmap removed and replaced with cyclemap for .ini
|
||||
//
|
||||
|
@ -40,7 +43,6 @@
|
|||
// this file holds commands that can be executed by the server console, but not remote clients
|
||||
|
||||
#include "g_local.h"
|
||||
#include "g_teamplay.h"
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log$
|
||||
// Revision 1.109 2002/06/19 18:13:57 jbravo
|
||||
// New TNG spawning system :)
|
||||
//
|
||||
// Revision 1.108 2002/06/17 03:30:33 jbravo
|
||||
// More color fixes
|
||||
//
|
||||
|
@ -353,6 +356,8 @@
|
|||
#include "g_local.h"
|
||||
#include "zcam.h"
|
||||
|
||||
void RQ3_SetupTeamSpawnPoints (void);
|
||||
|
||||
gitem_t *BG_FindItemForHoldable(holdable_t pw);
|
||||
char *ConcatArgs(int start);
|
||||
int touch[MAX_GENTITIES];
|
||||
|
@ -853,6 +858,7 @@ void SpawnPlayers()
|
|||
int clientNum, i;
|
||||
|
||||
level.spawnPointsLocated = qfalse;
|
||||
RQ3_SetupTeamSpawnPoints ();
|
||||
for (i = 0; i < level.maxclients; i++) {
|
||||
player = &g_entities[i];
|
||||
|
||||
|
@ -2286,3 +2292,267 @@ void Cmd_Playerlist_f(gentity_t * ent)
|
|||
trap_SendServerCommand(ent - g_entities, va("print \"%i - %s^7\n\"", i, other->client->pers.netname));
|
||||
}
|
||||
}
|
||||
|
||||
// Freud: RQ3_compare_spawn_distances
|
||||
//
|
||||
// Sorting mechanism for spawn point distances feeded to qsort
|
||||
int QDECL RQ3_compare_spawn_distances (const void *sd1, const void *sd2)
|
||||
{
|
||||
if (((spawn_distances_t *) sd1)->distance < ((spawn_distances_t *) sd2)->distance)
|
||||
return -1;
|
||||
else if (((spawn_distances_t *) sd1)->distance > ((spawn_distances_t *) sd2)->distance)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Freud: SpawnPointDistance
|
||||
//
|
||||
// Returns the distance between two spawn points (or any entities, actually...)
|
||||
float
|
||||
RQ3_SpawnPointDistance (gentity_t * spot1, gentity_t * spot2)
|
||||
{
|
||||
vec3_t v;
|
||||
VectorSubtract (spot1->s.origin, spot2->s.origin, v);
|
||||
return VectorLength (v);
|
||||
}
|
||||
|
||||
// RQ3_GetSpawnPoints ()
|
||||
//
|
||||
// Called whenever no spawn points are available.
|
||||
void RQ3_GetSpawnPoints ()
|
||||
{
|
||||
gentity_t *spot;
|
||||
int x, spawns;
|
||||
|
||||
spot = NULL;
|
||||
|
||||
// The team that is called with SetupRandomTeamplaySpawnPoint
|
||||
level.randteam = rand() % MAX_TEAMS;
|
||||
|
||||
// Reset the spawns for each team
|
||||
for (x = 0;x < MAX_TEAMS;x++) {
|
||||
level.num_potential_spawns[x] = 0;
|
||||
level.num_used_farteamplay_spawns[x] = 0;
|
||||
}
|
||||
|
||||
spawns = 0;
|
||||
|
||||
// Read spawn points from the map
|
||||
while ((spot = G_Find (spot, FOFS (classname), "info_player_deathmatch")) != NULL) {
|
||||
spawns++;
|
||||
for (x = 0;x < MAX_TEAMS;x++) {
|
||||
level.potential_spawns[x][level.num_potential_spawns[x]] = spot;
|
||||
level.num_potential_spawns[x]++;
|
||||
}
|
||||
}
|
||||
G_Printf("%i spawns read from map\n", spawns);
|
||||
}
|
||||
|
||||
// Freud: RQ3_SelectRandomTeamplaySpawnPoint
|
||||
//
|
||||
// Selects a random spawns point from potential team spawns.
|
||||
qboolean RQ3_SelectRandomTeamplaySpawnPoint (int team)
|
||||
{
|
||||
int spawn_point, y, ok, i, z;
|
||||
float distance;
|
||||
gentity_t *spot;
|
||||
|
||||
spot = NULL;
|
||||
|
||||
i = 0;
|
||||
ok = qfalse;
|
||||
|
||||
// Done with potential spawns, re-reading and re-assigning
|
||||
if (level.num_potential_spawns[team] < 1)
|
||||
{
|
||||
RQ3_GetSpawnPoints ();
|
||||
RQ3_SetupTeamSpawnPoints ();
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
// Randomizing from potential spawn points
|
||||
spawn_point = rand() % level.num_potential_spawns[team];
|
||||
|
||||
// decrementing potential spawns counter
|
||||
level.num_potential_spawns[team]--;
|
||||
|
||||
while ((ok == qfalse) && (i < MAX_TEAMS))
|
||||
{
|
||||
ok = qtrue;
|
||||
for (y = 0; y < MAX_TEAMS; y++)
|
||||
{
|
||||
if (level.teams_assigned[y] == qtrue)
|
||||
{
|
||||
distance = RQ3_SpawnPointDistance (level.potential_spawns[team][spawn_point],
|
||||
level.teamplay_spawns[y]);
|
||||
|
||||
if (distance == 0)
|
||||
{
|
||||
ok = qfalse;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ok == qfalse)
|
||||
{
|
||||
spawn_point++;
|
||||
if (spawn_point == level.num_potential_spawns[team])
|
||||
{
|
||||
spawn_point = 0;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
// Assigning the spawn point to the team
|
||||
level.teamplay_spawns[team] = level.potential_spawns[team][spawn_point];
|
||||
level.teams_assigned[team] = qtrue;
|
||||
|
||||
// Removing used spawn point from potential_spawns
|
||||
for (z = spawn_point;z < level.num_potential_spawns[team];z++)
|
||||
{
|
||||
level.potential_spawns[team][z] = level.potential_spawns[team][z + 1];
|
||||
}
|
||||
|
||||
if (i == MAX_TEAMS)
|
||||
{
|
||||
G_Printf("Arrrggh: More teams than potential spawnpoints!\n");
|
||||
|
||||
if ((spot = G_Find (spot, FOFS (classname), "info_player_start")) != NULL)
|
||||
{
|
||||
G_Printf("Well, guess I'm using info_player_start\n");
|
||||
level.teamplay_spawns[team] = spot;
|
||||
}
|
||||
else
|
||||
return qfalse;
|
||||
}
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
// Freud: RQ3_SelectFarTeamplaySpawnPoint
|
||||
//
|
||||
// Selects farthest teamplay spawn point(s) from available spawns.
|
||||
qboolean RQ3_SelectFarTeamplaySpawnPoint (int team)
|
||||
{
|
||||
int u, x, y, z;
|
||||
int spawn_to_use, preferred_spawn_points, num_already_used;
|
||||
int total_good_spawn_points, num_usable;
|
||||
|
||||
float closest_spawn_distance, distance;
|
||||
gentity_t *usable_spawns[MAX_SPAWN_POINTS];
|
||||
qboolean used;
|
||||
|
||||
spawn_distances_t spawn_distances[MAX_SPAWN_POINTS];
|
||||
|
||||
num_already_used = 0;
|
||||
|
||||
// Reset the spawn_distances structure
|
||||
for (x = 0; x < MAX_SPAWN_POINTS; x++) {
|
||||
memset(&spawn_distances[x], 0 , sizeof(spawn_distances[x]));
|
||||
}
|
||||
|
||||
//
|
||||
for (x = 0; x < level.num_potential_spawns[team]; x++)
|
||||
{
|
||||
closest_spawn_distance = 2000000000;
|
||||
|
||||
for (y = 0; y < MAX_TEAMS; y++)
|
||||
{
|
||||
if (level.teams_assigned[y] == qtrue)
|
||||
{
|
||||
distance = RQ3_SpawnPointDistance (level.potential_spawns[team][x], level.teamplay_spawns[y]);
|
||||
|
||||
if (distance < closest_spawn_distance)
|
||||
{
|
||||
closest_spawn_distance = distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (closest_spawn_distance == 0)
|
||||
num_already_used++;
|
||||
|
||||
spawn_distances[x].s = level.potential_spawns[team][x];
|
||||
spawn_distances[x].distance = closest_spawn_distance;
|
||||
}
|
||||
|
||||
// Sort the farthest spawn points to the end of the array
|
||||
qsort (spawn_distances, MAX_SPAWN_POINTS,
|
||||
sizeof (spawn_distances_t), RQ3_compare_spawn_distances);
|
||||
|
||||
total_good_spawn_points = level.num_potential_spawns[team] - num_already_used;
|
||||
|
||||
// Support Spawn farthest and the old AQ system for spawn possibilities
|
||||
if (g_dmflags.integer & DF_SPAWN_FARTHEST || total_good_spawn_points <= 4)
|
||||
preferred_spawn_points = 1;
|
||||
else if (total_good_spawn_points <= 10)
|
||||
preferred_spawn_points = 2;
|
||||
else
|
||||
preferred_spawn_points = 3;
|
||||
|
||||
num_usable = 0;
|
||||
|
||||
// Now lets go through the spawn points and see if they have been used up.
|
||||
for (z = 0;z < preferred_spawn_points;z++)
|
||||
{
|
||||
used = qfalse;
|
||||
for (u = 0; u < level.num_used_farteamplay_spawns[team]; u++)
|
||||
{
|
||||
if (level.used_farteamplay_spawns[team][u] == spawn_distances[MAX_SPAWN_POINTS - z - 1].s) {
|
||||
used = qtrue;
|
||||
}
|
||||
|
||||
}
|
||||
if (used == qfalse)
|
||||
{
|
||||
usable_spawns[num_usable] = spawn_distances[MAX_SPAWN_POINTS-z-1].s;
|
||||
num_usable++;
|
||||
}
|
||||
}
|
||||
|
||||
// Can't use any of the far spawn points, let's go through the whole thing again.
|
||||
if (num_usable < 1)
|
||||
{
|
||||
RQ3_SetupTeamSpawnPoints();
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
// Randomize through the usable spawns.
|
||||
spawn_to_use = rand() % num_usable;
|
||||
|
||||
// Marking the spawn as used.
|
||||
level.used_farteamplay_spawns[team][level.num_used_farteamplay_spawns[team]] = usable_spawns[spawn_to_use];
|
||||
level.num_used_farteamplay_spawns[team]++;
|
||||
|
||||
// Setting the team to assigned and assigning the spawn point.
|
||||
level.teams_assigned[team] = qtrue;
|
||||
level.teamplay_spawns[team] = usable_spawns[spawn_to_use];
|
||||
|
||||
if (!level.teamplay_spawns[team]) {
|
||||
G_Printf("Argh, Invalid Far Spawn\n");
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
// Freud: RQ3_SetupTeamSpawnPoints
|
||||
//
|
||||
// Call this for assigning the spawn points to the teams
|
||||
void RQ3_SetupTeamSpawnPoints()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_TEAMS; i++) {
|
||||
level.teamplay_spawns[i] = NULL;
|
||||
level.teams_assigned[i] = qfalse;
|
||||
}
|
||||
|
||||
if (RQ3_SelectRandomTeamplaySpawnPoint (level.randteam) == qfalse)
|
||||
return;
|
||||
|
||||
// If we ever decide to have more teams then 2.. :)
|
||||
for (i = 0;i < MAX_TEAMS;i++)
|
||||
if (i != level.randteam && RQ3_SelectFarTeamplaySpawnPoint (i) == qfalse)
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Log$
|
||||
// Revision 1.19 2002/06/19 18:13:57 jbravo
|
||||
// New TNG spawning system :)
|
||||
//
|
||||
// Revision 1.18 2002/06/16 20:06:14 jbravo
|
||||
// Reindented all the source files with "indent -kr -ut -i8 -l120 -lc120 -sob -bad -bap"
|
||||
//
|
||||
|
@ -74,6 +77,12 @@
|
|||
//Slicer TeamName Size.
|
||||
#define TEAM_NAME_SIZE 30
|
||||
|
||||
typedef struct {
|
||||
float distance;
|
||||
gentity_t *s;
|
||||
} spawn_distances_t;
|
||||
|
||||
|
||||
void CheckTeamRules();
|
||||
void StartLCA();
|
||||
void ContinueLCA();
|
||||
|
@ -109,3 +118,4 @@ void Cmd_Ignorenum_f(gentity_t * ent);
|
|||
void Cmd_Ignoreclear_f(gentity_t * ent);
|
||||
void Cmd_Playerlist_f(gentity_t * ent);
|
||||
int IsInIgnoreList(gentity_t * source, gentity_t * subject);
|
||||
void RQ3_GetSpawnPoints (void);
|
||||
|
|
Loading…
Reference in a new issue