Skip to content

Commit

Permalink
mod: fix spawn pt have bad player count, refs #506
Browse files Browse the repository at this point in the history
* Fixed incorrect player counts at spawn points on the command map.
* Rewrote player counter and spawn point update code.
  Should be more reliable now. It handles both invalid auto spawns
  and player selected spawns, and tries to resolve to nearest
  available team spawn point.
* Added 'listspawnpt' client command to print available map spawns.
* Added additional prints to 'setspawnpt' command.
* Removed unnecessary stuff and function calls.
  • Loading branch information
isRyven committed Aug 6, 2019
1 parent 44eb46d commit 2d024da
Show file tree
Hide file tree
Showing 10 changed files with 288 additions and 162 deletions.
21 changes: 20 additions & 1 deletion src/cgame/cg_consolecmds.c
Expand Up @@ -1847,6 +1847,24 @@ static void CG_PrintObjectiveInfo_f(void)
CG_Printf("^2%i from %i objectives defined\n", i, MAX_OID_TRIGGERS);
}

static void CG_ListSpawnPoints_f()
{
int i;
CG_Printf("^2Spawn Points\n");
for (i = 0; i < cg.spawnCount; i++)
{
// inactive
if (cg.spawnTeams[i] & 256)
{
CG_Printf("^9[%2i] %s %-26s\n", i, ((cg.spawnTeams[i] & 0xF) == TEAM_AXIS) ? "X" : "A", cg.spawnPoints[i]);
}
else
{
CG_Printf("^7[^2%2i^7] %s ^o%-26s\n", i, (cg.spawnTeams[i] == TEAM_AXIS) ? "^1X" : "^4A", cg.spawnPoints[i]);
}
}
}

static consoleCommand_t commands[] =
{
{ "testgun", CG_TestGun_f },
Expand Down Expand Up @@ -1965,7 +1983,8 @@ static consoleCommand_t commands[] =
#endif
// objective info list for mappers/scripters (and players? - we might extend it)
{ "oinfo", CG_PrintObjectiveInfo_f },
{ "resetmaxspeed", CG_ResetMaxSpeed_f }
{ "resetmaxspeed", CG_ResetMaxSpeed_f },
{ "listspawnpt", CG_ListSpawnPoints_f }
};

/**
Expand Down
7 changes: 3 additions & 4 deletions src/game/g_client.c
Expand Up @@ -642,7 +642,7 @@ void CopyToBodyQue(gentity_t *ent)
BODY_TEAM(body) = ent->client->sess.sessionTeam;
BODY_CLASS(body) = ent->client->sess.playerType;
BODY_CHARACTER(body) = ent->client->pers.characterIndex;
BODY_VALUE(body) = 0;
BODY_VALUE(body) = 0;

//if ( ent->client->ps.eFlags & EF_PANTSED ){
// body->s.time2 = 1;
Expand Down Expand Up @@ -2738,8 +2738,6 @@ void ClientSpawn(gentity_t *ent, qboolean revived, qboolean teamChange, qboolean
int savedTeam;
int savedDeathTime;

G_UpdateSpawnCounts();

client->pers.lastSpawnTime = level.time;
client->pers.lastBattleSenseBonusTime = level.timeCurrent;
client->pers.lastHQMineReportTime = level.timeCurrent;
Expand Down Expand Up @@ -2770,6 +2768,7 @@ void ClientSpawn(gentity_t *ent, qboolean revived, qboolean teamChange, qboolean
}
else
{
G_UpdateSpawnPointStatePlayerCounts();
// let's just be sure it does the right thing at all times. (well maybe not the right thing, but at least not the bad thing!)
//if( client->sess.sessionTeam == TEAM_SPECTATOR || client->sess.sessionTeam == TEAM_FREE ) {
if (client->sess.sessionTeam != TEAM_AXIS && client->sess.sessionTeam != TEAM_ALLIES)
Expand All @@ -2778,7 +2777,7 @@ void ClientSpawn(gentity_t *ent, qboolean revived, qboolean teamChange, qboolean
}
else
{
spawnPoint = SelectCTFSpawnPoint(client->sess.sessionTeam, client->pers.teamState.state, spawn_origin, spawn_angles, client->sess.spawnObjectiveIndex);
spawnPoint = SelectCTFSpawnPoint(client->sess.sessionTeam, client->pers.teamState.state, spawn_origin, spawn_angles, client->sess.userSpawnPointValue);
}
}

Expand Down
119 changes: 44 additions & 75 deletions src/game/g_cmds.c
Expand Up @@ -1530,8 +1530,6 @@ qboolean SetTeam(gentity_t *ent, const char *s, qboolean force, weapon_t w1, wea
// G_deleteStats(clientNum);
//}

G_UpdateSpawnCounts();

if (g_gamestate.integer == GS_PLAYING && (client->sess.sessionTeam == TEAM_AXIS || client->sess.sessionTeam == TEAM_ALLIES))
{
if (g_gametype.integer == GT_WOLF_LMS && level.numTeamClients[0] > 0 && level.numTeamClients[1] > 0)
Expand Down Expand Up @@ -4162,69 +4160,6 @@ void Cmd_Activate2_f(gentity_t *ent)
}
}

/**
* @brief G_UpdateSpawnCounts
*/
void G_UpdateSpawnCounts(void)
{
int i, j;
char cs[MAX_STRING_CHARS];
int current, count, team;

for (i = 0; i < level.numspawntargets; i++)
{
trap_GetConfigstring(CS_MULTI_SPAWNTARGETS + i, cs, sizeof(cs));

current = atoi(Info_ValueForKey(cs, "c"));
team = atoi(Info_ValueForKey(cs, "t")) & ~256;

count = 0;
for (j = 0; j < level.numConnectedClients; j++)
{
gclient_t *client = &level.clients[level.sortedClients[j]];

if (client->sess.sessionTeam != TEAM_AXIS && client->sess.sessionTeam != TEAM_ALLIES)
{
continue;
}

if (client->sess.sessionTeam == team && client->sess.spawnObjectiveIndex == i + 1)
{
count++;
continue;
}

if (client->sess.spawnObjectiveIndex == 0)
{
if (client->sess.sessionTeam == TEAM_AXIS)
{
if (level.axisAutoSpawn == i)
{
count++;
continue;
}
}
else
{
if (level.alliesAutoSpawn == i)
{
count++;
continue;
}
}
}
}

if (count == current)
{
continue;
}

Info_SetValueForKey(cs, "c", va("%i", count));
trap_SetConfigstring(CS_MULTI_SPAWNTARGETS + i, cs);
}
}

/**
* @brief SetPlayerSpawn
* @param[in,out] ent
Expand All @@ -4233,15 +4168,39 @@ void G_UpdateSpawnCounts(void)
*/
void SetPlayerSpawn(gentity_t *ent, int spawn, qboolean update)
{
ent->client->sess.spawnObjectiveIndex = spawn;
if (ent->client->sess.spawnObjectiveIndex >= MAX_MULTI_SPAWNTARGETS || ent->client->sess.spawnObjectiveIndex < 0)
int resolvedSpawnPoint;
int targetSpawnPoint;
spawnPointState_t *spawnPointState;
spawnPointState_t *targetSpawnPointState;
ent->client->sess.userSpawnPointValue = spawn;
if (ent->client->sess.sessionTeam != TEAM_ALLIES && ent->client->sess.sessionTeam != TEAM_AXIS)
{
trap_SendServerCommand((int)(ent - g_entities), "print \"^3Warning! To select spawn points you should be in game.\n\"");
return;
}
if (spawn < 0 || spawn > level.numSpawnPoints)
{
ent->client->sess.spawnObjectiveIndex = 0;
trap_SendServerCommand((int)(ent - g_entities), "print \"^3Warning! Spawn point is out of bounds. Selecting 'Auto Pick'.\n\"");
trap_SendServerCommand((int)(ent - g_entities), "print \" ^3Use '/listspawnpt' command to list available spawn points.\n\"");
ent->client->sess.userSpawnPointValue = 0;
}

if (update)
{
G_UpdateSpawnCounts();
G_UpdateSpawnPointStatePlayerCounts();
}

resolvedSpawnPoint = Com_Clamp(0, (level.numSpawnPoints - 1), ent->client->sess.resolvedSpawnPointIndex);
targetSpawnPoint = Com_Clamp(0, (level.numSpawnPoints - 1), (ent->client->sess.userSpawnPointValue - 1));
spawnPointState = &level.spawnPointStates[resolvedSpawnPoint];
if (spawn > 0 && targetSpawnPoint != resolvedSpawnPoint)
{
targetSpawnPointState = &level.spawnPointStates[targetSpawnPoint];
trap_SendServerCommand((int)(ent - g_entities), va("print \"^9Spawning at '^2%s^9', near the selected '^2%s^9'.\n\"", spawnPointState->description, targetSpawnPointState->description));
}
else
{
trap_SendServerCommand((int)(ent - g_entities), va("print \"^9Spawning at '^2%s^9'.\n\"", spawnPointState->description));
}
}

Expand All @@ -4251,11 +4210,14 @@ void SetPlayerSpawn(gentity_t *ent, int spawn, qboolean update)
*/
void Cmd_SetSpawnPoint_f(gentity_t *ent)
{
char arg[MAX_TOKEN_CHARS];
int val, i;
char arg[MAX_TOKEN_CHARS];
int val, i;
spawnPointState_t *spawnPointState;

if (trap_Argc() != 2)
{
trap_SendServerCommand((int)(ent - g_entities), "print \"^3Warning! Spawn point number expected.\n\"");
trap_SendServerCommand((int)(ent - g_entities), "print \" ^3Use '/listspawnpt' command to list available spawn points.\n\"");
return;
}

Expand All @@ -4269,13 +4231,20 @@ void Cmd_SetSpawnPoint_f(gentity_t *ent)

for (i = 0; i < level.numLimboCams; i++)
{
int x = (g_entities[level.limboCams[i].targetEnt].count - CS_MULTI_SPAWNTARGETS) + 1;

if (level.limboCams[i].spawn && x == val)
int targetSpawnPoint = g_entities[level.limboCams[i].targetEnt].count - CS_MULTI_SPAWNTARGETS;
if (level.limboCams[i].spawn && (targetSpawnPoint + 1) == val)
{
spawnPointState = &level.spawnPointStates[targetSpawnPoint];
// don't allow checking opposite team's spawn camp
if (ent->client &&
ent->client->sess.sessionTeam != TEAM_SPECTATOR &&
ent->client->sess.sessionTeam != spawnPointState->team)
{
break;
}
VectorCopy(level.limboCams[i].origin, ent->s.origin2);
ent->r.svFlags |= SVF_SELF_PORTAL_EXCLUSIVE;
trap_SendServerCommand(ent - g_entities, va("portalcampos %i %i %i %i %i %i %i %i", val - 1, (int)level.limboCams[i].origin[0], (int)level.limboCams[i].origin[1], (int)level.limboCams[i].origin[2], (int)level.limboCams[i].angles[0], (int)level.limboCams[i].angles[1], (int)level.limboCams[i].angles[2], level.limboCams[i].hasEnt ? level.limboCams[i].targetEnt : -1));
trap_SendServerCommand((int)(ent - g_entities), va("portalcampos %i %i %i %i %i %i %i %i", val - 1, (int)level.limboCams[i].origin[0], (int)level.limboCams[i].origin[1], (int)level.limboCams[i].origin[2], (int)level.limboCams[i].angles[0], (int)level.limboCams[i].angles[1], (int)level.limboCams[i].angles[2], level.limboCams[i].hasEnt ? level.limboCams[i].targetEnt : -1));
break;
}
}
Expand Down
20 changes: 15 additions & 5 deletions src/game/g_local.h
Expand Up @@ -632,7 +632,8 @@ typedef struct
int playerType; ///< for GT_WOLF
weapon_t playerWeapon; ///< for GT_WOLF
weapon_t playerWeapon2; ///< secondary weapon
int spawnObjectiveIndex; ///< index of objective to spawn nearest to (returned from UI)
int userSpawnPointValue; ///< index of objective to spawn nearest to (returned from UI)
int resolvedSpawnPointIndex; ///< most possible objective to spawn nearest to
int latchPlayerType; ///< for GT_WOLF not archived
weapon_t latchPlayerWeapon; ///< for GT_WOLF not archived
weapon_t latchPlayerWeapon2; ///< secondary weapon
Expand Down Expand Up @@ -1113,6 +1114,15 @@ typedef struct database_s
} database_t;
#endif

typedef struct spawnPointState_s
{
vec3_t origin;
team_t team;
int playerCount;
int isActive;
char description[128];
} spawnPointState_t;

/**
* @struct level_locals_s
* @typedef level_locals_t
Expand Down Expand Up @@ -1182,8 +1192,8 @@ typedef struct level_locals_s
int bodyQueIndex; ///< dead bodies
gentity_t *bodyQue[BODY_QUEUE_SIZE];

vec3_t spawntargets[MAX_MULTI_SPAWNTARGETS]; ///< coordinates of spawn targets
int numspawntargets; ////< # spawntargets in this map
int numSpawnPoints; ////< number of spawn points in this map
spawnPointState_t spawnPointStates[MAX_MULTI_SPAWNTARGETS];

/// entity scripting
char *scriptEntity;
Expand Down Expand Up @@ -1681,7 +1691,6 @@ qboolean ReadyToConstruct(gentity_t *ent, gentity_t *constructible, qboolean upd
// g_team.c
qboolean OnSameTeam(gentity_t *ent1, gentity_t *ent2);
//int Team_ClassForString(const char *string); // Unused
void reset_numobjectives(void);

// g_mem.c
void *G_Alloc(unsigned int size);
Expand Down Expand Up @@ -2585,7 +2594,8 @@ void G_MakeReady(gentity_t *ent);
void G_MakeUnready(gentity_t *ent);

void SetPlayerSpawn(gentity_t *ent, int spawn, qboolean update);
void G_UpdateSpawnCounts(void);
void G_UpdateSpawnPointState(gentity_t *ent);
void G_UpdateSpawnPointStatePlayerCounts();

void G_SetConfigStringValue(int num, const char *key, const char *value);
void G_GlobalClientEvent(entity_event_t event, int param, int client);
Expand Down
2 changes: 1 addition & 1 deletion src/game/g_lua.c
Expand Up @@ -1013,7 +1013,7 @@ static const gentity_field_t gclient_fields[] =
_et_gclient_addfield(sess.playerType, FIELD_INT, 0),
_et_gclient_addfield(sess.playerWeapon, FIELD_INT, 0),
_et_gclient_addfield(sess.playerWeapon2, FIELD_INT, 0),
_et_gclient_addfield(sess.spawnObjectiveIndex, FIELD_INT, 0),
_et_gclient_addfield(sess.userSpawnPointValue, FIELD_INT, 0),
_et_gclient_addfield(sess.latchPlayerType, FIELD_INT, 0),
_et_gclient_addfield(sess.latchPlayerWeapon, FIELD_INT, 0),
_et_gclient_addfield(sess.latchPlayerWeapon2, FIELD_INT, 0),
Expand Down
4 changes: 2 additions & 2 deletions src/game/g_main.c
Expand Up @@ -2330,7 +2330,8 @@ void G_InitGame(int levelTime, int randomSeed, int restart, int legacyServer, in

for (i = 0; i < level.numConnectedClients; i++)
{
level.clients[level.sortedClients[i]].sess.spawnObjectiveIndex = 0;
level.clients[level.sortedClients[i]].sess.userSpawnPointValue = 0;
level.clients[level.sortedClients[i]].sess.resolvedSpawnPointIndex = 0;
}

// init the anim scripting
Expand Down Expand Up @@ -2545,7 +2546,6 @@ void G_InitGame(int levelTime, int randomSeed, int restart, int legacyServer, in
// Clear out spawn target config strings
trap_GetConfigstring(CS_MULTI_INFO, cs, sizeof(cs));
Info_SetValueForKey(cs, "s", "0"); // numspawntargets
reset_numobjectives();
trap_SetConfigstring(CS_MULTI_INFO, cs);

for (i = CS_MULTI_SPAWNTARGETS; i < CS_MULTI_SPAWNTARGETS + MAX_MULTI_SPAWNTARGETS; i++)
Expand Down
10 changes: 5 additions & 5 deletions src/game/g_script_actions.c
Expand Up @@ -212,7 +212,7 @@ qboolean G_ScriptAction_SetAutoSpawn(gentity_t *ent, char *params)

*pTeamAutoSpawn = tent->count - CS_MULTI_SPAWNTARGETS;

G_UpdateSpawnCounts();
G_UpdateSpawnPointStatePlayerCounts();

return qtrue;
}
Expand Down Expand Up @@ -252,7 +252,7 @@ qboolean G_ScriptAction_ChangeModel(gentity_t *ent, char *params)
qboolean G_ScriptAction_ShaderRemap(gentity_t *ent, char *params)
{
char *pString = params, *token;
float f = level.time * 0.001f;
float f = level.time * 0.001f;
char oldShader[MAX_QPATH];
char newShader[MAX_QPATH];

Expand Down Expand Up @@ -2004,7 +2004,7 @@ qboolean G_ScriptAction_MusicPlay(gentity_t *ent, char *params)
*/
qboolean G_ScriptAction_MusicStop(gentity_t *ent, char *params)
{
char *pString = params, *token;
char *pString = params, *token;
int fadeoutTime = 0;

token = COM_ParseExt(&pString, qfalse);
Expand Down Expand Up @@ -2049,7 +2049,7 @@ qboolean G_ScriptAction_MusicQueue(gentity_t *ent, char *params)
*/
qboolean G_ScriptAction_MusicFade(gentity_t *ent, char *params)
{
char *pString = params, *token;
char *pString = params, *token;
int fadeoutTime = 0;
float targetVol = 0.0;

Expand Down Expand Up @@ -2932,7 +2932,7 @@ qboolean G_ScriptAction_Print(gentity_t *ent, char *params)
// Default to printing whole string
char *printThis = params;

char *pString = params, *token;
char *pString = params, *token;
int printLevel = 0;

if (!params || !params[0])
Expand Down
6 changes: 3 additions & 3 deletions src/game/g_session.c
Expand Up @@ -113,7 +113,7 @@ void G_WriteClientSessionData(gclient_t *client, qboolean restart)
client->sess.ignoreClients[0],
client->sess.ignoreClients[1],
client->pers.enterTime,
restart ? client->sess.spawnObjectiveIndex : 0,
restart ? client->sess.userSpawnPointValue : 0,
client->sess.uci
);

Expand Down Expand Up @@ -322,7 +322,7 @@ void G_ReadSessionData(gclient_t *client)
&client->sess.ignoreClients[0],
&client->sess.ignoreClients[1],
&client->pers.enterTime,
&client->sess.spawnObjectiveIndex,
&client->sess.userSpawnPointValue,
&client->sess.uci
);

Expand Down Expand Up @@ -415,7 +415,7 @@ void G_InitSessionData(gclient_t *client, const char *userinfo)
sess->latchPlayerWeapon = sess->playerWeapon = WP_NONE;
sess->latchPlayerWeapon2 = sess->playerWeapon2 = WP_NONE;

sess->spawnObjectiveIndex = 0;
sess->userSpawnPointValue = 0;

Com_Memset(sess->ignoreClients, 0, sizeof(sess->ignoreClients));

Expand Down

0 comments on commit 2d024da

Please sign in to comment.