1094 lines
24 KiB
C
1094 lines
24 KiB
C
// Copyright (C) 2000-2002 Raven Software, Inc.
|
|
//
|
|
/*****************************************************************************
|
|
* name: cg_siege.c
|
|
*
|
|
* desc: Clientgame-side module for Siege gametype.
|
|
*
|
|
* $Author: osman $
|
|
* $Revision: 1.5 $
|
|
*
|
|
*****************************************************************************/
|
|
#include "cg_local.h"
|
|
#include "bg_saga.h"
|
|
|
|
int cgSiegeRoundState = 0;
|
|
int cgSiegeRoundTime = 0;
|
|
|
|
static char team1[512];
|
|
static char team2[512];
|
|
|
|
int team1Timed = 0;
|
|
int team2Timed = 0;
|
|
|
|
int cgSiegeTeam1PlShader = 0;
|
|
int cgSiegeTeam2PlShader = 0;
|
|
|
|
static char cgParseObjectives[MAX_SIEGE_INFO_SIZE];
|
|
|
|
extern void CG_LoadCISounds(clientInfo_t *ci, qboolean modelloaded); //cg_players.c
|
|
|
|
void CG_DrawSiegeMessage( const char *str, int objectiveScreen );
|
|
void CG_DrawSiegeMessageNonMenu( const char *str );
|
|
void CG_SiegeBriefingDisplay(int team, int dontshow);
|
|
|
|
void CG_PrecacheSiegeObjectiveAssetsForTeam(int myTeam)
|
|
{
|
|
char teamstr[64];
|
|
char objstr[256];
|
|
char foundobjective[MAX_SIEGE_INFO_SIZE];
|
|
|
|
if (!siege_valid)
|
|
{
|
|
CG_Error("Siege data does not exist on client!\n");
|
|
return;
|
|
}
|
|
|
|
if (myTeam == SIEGETEAM_TEAM1)
|
|
{
|
|
Com_sprintf(teamstr, sizeof(teamstr), team1);
|
|
}
|
|
else
|
|
{
|
|
Com_sprintf(teamstr, sizeof(teamstr), team2);
|
|
}
|
|
|
|
if (BG_SiegeGetValueGroup(siege_info, teamstr, cgParseObjectives))
|
|
{
|
|
int i = 1;
|
|
while (i < 32)
|
|
{ //eh, just try 32 I guess
|
|
Com_sprintf(objstr, sizeof(objstr), "Objective%i", i);
|
|
|
|
if (BG_SiegeGetValueGroup(cgParseObjectives, objstr, foundobjective))
|
|
{
|
|
char str[MAX_QPATH];
|
|
|
|
if (BG_SiegeGetPairedValue(foundobjective, "sound_team1", str))
|
|
{
|
|
trap_S_RegisterSound(str);
|
|
}
|
|
if (BG_SiegeGetPairedValue(foundobjective, "sound_team2", str))
|
|
{
|
|
trap_S_RegisterSound(str);
|
|
}
|
|
if (BG_SiegeGetPairedValue(foundobjective, "objgfx", str))
|
|
{
|
|
trap_R_RegisterShaderNoMip(str);
|
|
}
|
|
if (BG_SiegeGetPairedValue(foundobjective, "mapicon", str))
|
|
{
|
|
trap_R_RegisterShaderNoMip(str);
|
|
}
|
|
if (BG_SiegeGetPairedValue(foundobjective, "litmapicon", str))
|
|
{
|
|
trap_R_RegisterShaderNoMip(str);
|
|
}
|
|
if (BG_SiegeGetPairedValue(foundobjective, "donemapicon", str))
|
|
{
|
|
trap_R_RegisterShaderNoMip(str);
|
|
}
|
|
}
|
|
else
|
|
{ //no more
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CG_PrecachePlayersForSiegeTeam(int team)
|
|
{
|
|
siegeTeam_t *stm;
|
|
int i = 0;
|
|
|
|
stm = BG_SiegeFindThemeForTeam(team);
|
|
|
|
if (!stm)
|
|
{ //invalid team/no theme for team?
|
|
return;
|
|
}
|
|
|
|
while (i < stm->numClasses)
|
|
{
|
|
siegeClass_t *scl = stm->classes[i];
|
|
|
|
if (scl->forcedModel[0])
|
|
{
|
|
clientInfo_t fake;
|
|
|
|
memset(&fake, 0, sizeof(fake));
|
|
strcpy(fake.modelName, scl->forcedModel);
|
|
|
|
trap_R_RegisterModel(va("models/players/%s/model.glm", scl->forcedModel));
|
|
if (scl->forcedSkin[0])
|
|
{
|
|
trap_R_RegisterSkin(va("models/players/%s/model_%s.skin", scl->forcedModel, scl->forcedSkin));
|
|
strcpy(fake.skinName, scl->forcedSkin);
|
|
}
|
|
else
|
|
{
|
|
strcpy(fake.skinName, "default");
|
|
}
|
|
|
|
//precache the sounds for the model...
|
|
CG_LoadCISounds(&fake, qtrue);
|
|
}
|
|
|
|
i++;
|
|
}
|
|
}
|
|
|
|
void CG_InitSiegeMode(void)
|
|
{
|
|
char levelname[MAX_QPATH];
|
|
char btime[1024];
|
|
char teams[2048];
|
|
char teamInfo[MAX_SIEGE_INFO_SIZE];
|
|
int len = 0;
|
|
int i = 0;
|
|
int j = 0;
|
|
siegeClass_t *cl;
|
|
siegeTeam_t *sTeam;
|
|
fileHandle_t f;
|
|
char teamIcon[128];
|
|
|
|
if (cgs.gametype != GT_SIEGE)
|
|
{
|
|
goto failure;
|
|
}
|
|
|
|
Com_sprintf(levelname, sizeof(levelname), "%s\0", cgs.mapname);
|
|
|
|
i = strlen(levelname)-1;
|
|
|
|
while (i > 0 && levelname[i] && levelname[i] != '.')
|
|
{
|
|
i--;
|
|
}
|
|
|
|
if (!i)
|
|
{
|
|
goto failure;
|
|
}
|
|
|
|
levelname[i] = '\0'; //kill the ".bsp"
|
|
|
|
Com_sprintf(levelname, sizeof(levelname), "%s.siege\0", levelname);
|
|
|
|
if (!levelname || !levelname[0])
|
|
{
|
|
goto failure;
|
|
}
|
|
|
|
len = trap_FS_FOpenFile(levelname, &f, FS_READ);
|
|
|
|
if (!f || len >= MAX_SIEGE_INFO_SIZE)
|
|
{
|
|
goto failure;
|
|
}
|
|
|
|
trap_FS_Read(siege_info, len, f);
|
|
|
|
trap_FS_FCloseFile(f);
|
|
|
|
siege_valid = 1;
|
|
|
|
if (BG_SiegeGetValueGroup(siege_info, "Teams", teams))
|
|
{
|
|
char buf[1024];
|
|
|
|
trap_Cvar_VariableStringBuffer("cg_siegeTeam1", buf, 1024);
|
|
if (buf[0] && Q_stricmp(buf, "none"))
|
|
{
|
|
strcpy(team1, buf);
|
|
}
|
|
else
|
|
{
|
|
BG_SiegeGetPairedValue(teams, "team1", team1);
|
|
}
|
|
|
|
if (team1[0] == '@')
|
|
{ //it's a damn stringed reference.
|
|
char b[256];
|
|
trap_SP_GetStringTextString(team1+1, b, 256);
|
|
trap_Cvar_Set("cg_siegeTeam1Name", b);
|
|
}
|
|
else
|
|
{
|
|
trap_Cvar_Set("cg_siegeTeam1Name", team1);
|
|
}
|
|
|
|
trap_Cvar_VariableStringBuffer("cg_siegeTeam2", buf, 1024);
|
|
if (buf[0] && Q_stricmp(buf, "none"))
|
|
{
|
|
strcpy(team2, buf);
|
|
}
|
|
else
|
|
{
|
|
BG_SiegeGetPairedValue(teams, "team2", team2);
|
|
}
|
|
|
|
if (team2[0] == '@')
|
|
{ //it's a damn stringed reference.
|
|
char b[256];
|
|
trap_SP_GetStringTextString(team2+1, b, 256);
|
|
trap_Cvar_Set("cg_siegeTeam2Name", b);
|
|
}
|
|
else
|
|
{
|
|
trap_Cvar_Set("cg_siegeTeam2Name", team2);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CG_Error("Siege teams not defined");
|
|
}
|
|
|
|
if (BG_SiegeGetValueGroup(siege_info, team1, teamInfo))
|
|
{
|
|
if (BG_SiegeGetPairedValue(teamInfo, "TeamIcon", teamIcon))
|
|
{
|
|
trap_Cvar_Set( "team1_icon", teamIcon);
|
|
}
|
|
|
|
if (BG_SiegeGetPairedValue(teamInfo, "Timed", btime))
|
|
{
|
|
team1Timed = atoi(btime)*1000;
|
|
CG_SetSiegeTimerCvar ( team1Timed );
|
|
}
|
|
else
|
|
{
|
|
team1Timed = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CG_Error("No team entry for '%s'\n", team1);
|
|
}
|
|
|
|
if (BG_SiegeGetPairedValue(siege_info, "mapgraphic", teamInfo))
|
|
{
|
|
trap_Cvar_Set("siege_mapgraphic", teamInfo);
|
|
}
|
|
else
|
|
{
|
|
trap_Cvar_Set("siege_mapgraphic", "gfx/mplevels/siege1_hoth");
|
|
}
|
|
|
|
if (BG_SiegeGetPairedValue(siege_info, "missionname", teamInfo))
|
|
{
|
|
trap_Cvar_Set("siege_missionname", teamInfo);
|
|
}
|
|
else
|
|
{
|
|
trap_Cvar_Set("siege_missionname", " ");
|
|
}
|
|
|
|
if (BG_SiegeGetValueGroup(siege_info, team2, teamInfo))
|
|
{
|
|
if (BG_SiegeGetPairedValue(teamInfo, "TeamIcon", teamIcon))
|
|
{
|
|
trap_Cvar_Set( "team2_icon", teamIcon);
|
|
}
|
|
|
|
if (BG_SiegeGetPairedValue(teamInfo, "Timed", btime))
|
|
{
|
|
team2Timed = atoi(btime)*1000;
|
|
CG_SetSiegeTimerCvar ( team2Timed );
|
|
}
|
|
else
|
|
{
|
|
team2Timed = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CG_Error("No team entry for '%s'\n", team2);
|
|
}
|
|
|
|
//Load the player class types
|
|
BG_SiegeLoadClasses(NULL);
|
|
|
|
if (!bgNumSiegeClasses)
|
|
{ //We didn't find any?!
|
|
CG_Error("Couldn't find any player classes for Siege");
|
|
}
|
|
|
|
//Now load the teams since we have class data.
|
|
BG_SiegeLoadTeams();
|
|
|
|
if (!bgNumSiegeTeams)
|
|
{ //React same as with classes.
|
|
CG_Error("Couldn't find any player teams for Siege");
|
|
}
|
|
|
|
//Get and set the team themes for each team. This will control which classes can be
|
|
//used on each team.
|
|
if (BG_SiegeGetValueGroup(siege_info, team1, teamInfo))
|
|
{
|
|
if (BG_SiegeGetPairedValue(teamInfo, "UseTeam", btime))
|
|
{
|
|
BG_SiegeSetTeamTheme(SIEGETEAM_TEAM1, btime);
|
|
}
|
|
if (BG_SiegeGetPairedValue(teamInfo, "FriendlyShader", btime))
|
|
{
|
|
cgSiegeTeam1PlShader = trap_R_RegisterShaderNoMip(btime);
|
|
}
|
|
else
|
|
{
|
|
cgSiegeTeam1PlShader = 0;
|
|
}
|
|
}
|
|
if (BG_SiegeGetValueGroup(siege_info, team2, teamInfo))
|
|
{
|
|
if (BG_SiegeGetPairedValue(teamInfo, "UseTeam", btime))
|
|
{
|
|
BG_SiegeSetTeamTheme(SIEGETEAM_TEAM2, btime);
|
|
}
|
|
if (BG_SiegeGetPairedValue(teamInfo, "FriendlyShader", btime))
|
|
{
|
|
cgSiegeTeam2PlShader = trap_R_RegisterShaderNoMip(btime);
|
|
}
|
|
else
|
|
{
|
|
cgSiegeTeam2PlShader = 0;
|
|
}
|
|
}
|
|
|
|
//Now go through the classes used by the loaded teams and try to precache
|
|
//any forced models or forced skins.
|
|
i = SIEGETEAM_TEAM1;
|
|
|
|
while (i <= SIEGETEAM_TEAM2)
|
|
{
|
|
j = 0;
|
|
sTeam = BG_SiegeFindThemeForTeam(i);
|
|
|
|
if (!sTeam)
|
|
{
|
|
i++;
|
|
continue;
|
|
}
|
|
|
|
//Get custom team shaders while we're at it.
|
|
if (i == SIEGETEAM_TEAM1)
|
|
{
|
|
cgSiegeTeam1PlShader = sTeam->friendlyShader;
|
|
}
|
|
else if (i == SIEGETEAM_TEAM2)
|
|
{
|
|
cgSiegeTeam2PlShader = sTeam->friendlyShader;
|
|
}
|
|
|
|
while (j < sTeam->numClasses)
|
|
{
|
|
cl = sTeam->classes[j];
|
|
|
|
if (cl->forcedModel[0])
|
|
{ //This class has a forced model, so precache it.
|
|
trap_R_RegisterModel(va("models/players/%s/model.glm", cl->forcedModel));
|
|
|
|
if (cl->forcedSkin[0])
|
|
{ //also has a forced skin, precache it.
|
|
char *useSkinName;
|
|
|
|
if (strchr(cl->forcedSkin, '|'))
|
|
{//three part skin
|
|
useSkinName = va("models/players/%s/|%s", cl->forcedModel, cl->forcedSkin);
|
|
}
|
|
else
|
|
{
|
|
useSkinName = va("models/players/%s/model_%s.skin", cl->forcedModel, cl->forcedSkin);
|
|
}
|
|
|
|
trap_R_RegisterSkin(useSkinName);
|
|
}
|
|
}
|
|
|
|
j++;
|
|
}
|
|
i++;
|
|
}
|
|
|
|
//precache saber data for classes that use sabers on both teams
|
|
BG_PrecacheSabersForSiegeTeam(SIEGETEAM_TEAM1);
|
|
BG_PrecacheSabersForSiegeTeam(SIEGETEAM_TEAM2);
|
|
|
|
CG_PrecachePlayersForSiegeTeam(SIEGETEAM_TEAM1);
|
|
CG_PrecachePlayersForSiegeTeam(SIEGETEAM_TEAM2);
|
|
|
|
CG_PrecachePlayersForSiegeTeam(SIEGETEAM_TEAM1);
|
|
CG_PrecachePlayersForSiegeTeam(SIEGETEAM_TEAM2);
|
|
|
|
CG_PrecacheSiegeObjectiveAssetsForTeam(SIEGETEAM_TEAM1);
|
|
CG_PrecacheSiegeObjectiveAssetsForTeam(SIEGETEAM_TEAM2);
|
|
|
|
return;
|
|
failure:
|
|
siege_valid = 0;
|
|
}
|
|
|
|
static char CGAME_INLINE *CG_SiegeObjectiveBuffer(int team, int objective)
|
|
{
|
|
static char buf[8192];
|
|
char teamstr[1024];
|
|
|
|
if (team == SIEGETEAM_TEAM1)
|
|
{
|
|
Com_sprintf(teamstr, sizeof(teamstr), team1);
|
|
}
|
|
else
|
|
{
|
|
Com_sprintf(teamstr, sizeof(teamstr), team2);
|
|
}
|
|
|
|
if (BG_SiegeGetValueGroup(siege_info, teamstr, cgParseObjectives))
|
|
{ //found the team group
|
|
if (BG_SiegeGetValueGroup(cgParseObjectives, va("Objective%i", objective), buf))
|
|
{ //found the objective group
|
|
return buf;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void CG_ParseSiegeObjectiveStatus(const char *str)
|
|
{
|
|
int i = 0;
|
|
int team = SIEGETEAM_TEAM1;
|
|
char *cvarName;
|
|
char *s;
|
|
int objectiveNum = 0;
|
|
|
|
if (!str || !str[0])
|
|
{
|
|
return;
|
|
}
|
|
|
|
while (str[i])
|
|
{
|
|
if (str[i] == '|')
|
|
{ //switch over to team2, this is the next section
|
|
team = SIEGETEAM_TEAM2;
|
|
objectiveNum = 0;
|
|
}
|
|
else if (str[i] == '-')
|
|
{
|
|
objectiveNum++;
|
|
i++;
|
|
|
|
cvarName = va("team%i_objective%i", team, objectiveNum);
|
|
if (str[i] == '1')
|
|
{ //it's completed
|
|
trap_Cvar_Set(cvarName, "1");
|
|
}
|
|
else
|
|
{ //otherwise assume it is not
|
|
trap_Cvar_Set(cvarName, "0");
|
|
}
|
|
|
|
s = CG_SiegeObjectiveBuffer(team, objectiveNum);
|
|
if (s && s[0])
|
|
{ //now set the description and graphic cvars to by read by the menu
|
|
char buffer[8192];
|
|
|
|
cvarName = va("team%i_objective%i_longdesc", team, objectiveNum);
|
|
if (BG_SiegeGetPairedValue(s, "objdesc", buffer))
|
|
{
|
|
trap_Cvar_Set(cvarName, buffer);
|
|
}
|
|
else
|
|
{
|
|
trap_Cvar_Set(cvarName, "UNSPECIFIED");
|
|
}
|
|
|
|
cvarName = va("team%i_objective%i_gfx", team, objectiveNum);
|
|
if (BG_SiegeGetPairedValue(s, "objgfx", buffer))
|
|
{
|
|
trap_Cvar_Set(cvarName, buffer);
|
|
}
|
|
else
|
|
{
|
|
trap_Cvar_Set(cvarName, "UNSPECIFIED");
|
|
}
|
|
|
|
cvarName = va("team%i_objective%i_mapicon", team, objectiveNum);
|
|
if (BG_SiegeGetPairedValue(s, "mapicon", buffer))
|
|
{
|
|
trap_Cvar_Set(cvarName, buffer);
|
|
}
|
|
else
|
|
{
|
|
trap_Cvar_Set(cvarName, "UNSPECIFIED");
|
|
}
|
|
|
|
cvarName = va("team%i_objective%i_litmapicon", team, objectiveNum);
|
|
if (BG_SiegeGetPairedValue(s, "litmapicon", buffer))
|
|
{
|
|
trap_Cvar_Set(cvarName, buffer);
|
|
}
|
|
else
|
|
{
|
|
trap_Cvar_Set(cvarName, "UNSPECIFIED");
|
|
}
|
|
|
|
cvarName = va("team%i_objective%i_donemapicon", team, objectiveNum);
|
|
if (BG_SiegeGetPairedValue(s, "donemapicon", buffer))
|
|
{
|
|
trap_Cvar_Set(cvarName, buffer);
|
|
}
|
|
else
|
|
{
|
|
trap_Cvar_Set(cvarName, "UNSPECIFIED");
|
|
}
|
|
|
|
cvarName = va("team%i_objective%i_mappos", team, objectiveNum);
|
|
if (BG_SiegeGetPairedValue(s, "mappos", buffer))
|
|
{
|
|
trap_Cvar_Set(cvarName, buffer);
|
|
}
|
|
else
|
|
{
|
|
trap_Cvar_Set(cvarName, "0 0 32 32");
|
|
}
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
|
|
if (cg.predictedPlayerState.persistant[PERS_TEAM] != TEAM_SPECTATOR)
|
|
{ //update menu cvars
|
|
CG_SiegeBriefingDisplay(cg.predictedPlayerState.persistant[PERS_TEAM], 1);
|
|
}
|
|
}
|
|
|
|
void CG_SiegeRoundOver(centity_t *ent, int won)
|
|
{
|
|
int myTeam;
|
|
char teamstr[64];
|
|
char appstring[1024];
|
|
char soundstr[1024];
|
|
int success = 0;
|
|
playerState_t *ps = NULL;
|
|
|
|
if (!siege_valid)
|
|
{
|
|
CG_Error("ERROR: Siege data does not exist on client!\n");
|
|
return;
|
|
}
|
|
|
|
if (cg.snap)
|
|
{ //this should always be true, if it isn't though use the predicted ps as a fallback
|
|
ps = &cg.snap->ps;
|
|
}
|
|
else
|
|
{
|
|
ps = &cg.predictedPlayerState;
|
|
}
|
|
|
|
if (!ps)
|
|
{
|
|
assert(0);
|
|
return;
|
|
}
|
|
|
|
myTeam = ps->persistant[PERS_TEAM];
|
|
|
|
if (myTeam == TEAM_SPECTATOR)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (myTeam == SIEGETEAM_TEAM1)
|
|
{
|
|
Com_sprintf(teamstr, sizeof(teamstr), team1);
|
|
}
|
|
else
|
|
{
|
|
Com_sprintf(teamstr, sizeof(teamstr), team2);
|
|
}
|
|
|
|
if (BG_SiegeGetValueGroup(siege_info, teamstr, cgParseObjectives))
|
|
{
|
|
if (won == myTeam)
|
|
{
|
|
success = BG_SiegeGetPairedValue(cgParseObjectives, "wonround", appstring);
|
|
}
|
|
else
|
|
{
|
|
success = BG_SiegeGetPairedValue(cgParseObjectives, "lostround", appstring);
|
|
}
|
|
|
|
if (success)
|
|
{
|
|
CG_DrawSiegeMessage(appstring, 0);
|
|
}
|
|
|
|
appstring[0] = 0;
|
|
soundstr[0] = 0;
|
|
|
|
if (myTeam == won)
|
|
{
|
|
Com_sprintf(teamstr, sizeof(teamstr), "roundover_sound_wewon");
|
|
}
|
|
else
|
|
{
|
|
Com_sprintf(teamstr, sizeof(teamstr), "roundover_sound_welost");
|
|
}
|
|
|
|
if (BG_SiegeGetPairedValue(cgParseObjectives, teamstr, appstring))
|
|
{
|
|
Com_sprintf(soundstr, sizeof(soundstr), appstring);
|
|
}
|
|
/*
|
|
else
|
|
{
|
|
if (myTeam != won)
|
|
{
|
|
Com_sprintf(soundstr, sizeof(soundstr), DEFAULT_LOSE_ROUND);
|
|
}
|
|
else
|
|
{
|
|
Com_sprintf(soundstr, sizeof(soundstr), DEFAULT_WIN_ROUND);
|
|
}
|
|
}
|
|
*/
|
|
|
|
if (soundstr[0])
|
|
{
|
|
trap_S_StartLocalSound(trap_S_RegisterSound(soundstr), CHAN_ANNOUNCER);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CG_SiegeGetObjectiveDescription(int team, int objective, char *buffer)
|
|
{
|
|
char teamstr[1024];
|
|
char objectiveStr[8192];
|
|
|
|
buffer[0] = 0; //set to 0 ahead of time in case we fail to find the objective group/name
|
|
|
|
if (team == SIEGETEAM_TEAM1)
|
|
{
|
|
Com_sprintf(teamstr, sizeof(teamstr), team1);
|
|
}
|
|
else
|
|
{
|
|
Com_sprintf(teamstr, sizeof(teamstr), team2);
|
|
}
|
|
|
|
if (BG_SiegeGetValueGroup(siege_info, teamstr, cgParseObjectives))
|
|
{ //found the team group
|
|
if (BG_SiegeGetValueGroup(cgParseObjectives, va("Objective%i", objective), objectiveStr))
|
|
{ //found the objective group
|
|
//Parse the name right into the buffer.
|
|
BG_SiegeGetPairedValue(objectiveStr, "goalname", buffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
int CG_SiegeGetObjectiveFinal(int team, int objective )
|
|
{
|
|
char finalStr[64];
|
|
char teamstr[1024];
|
|
char objectiveStr[8192];
|
|
|
|
if (team == SIEGETEAM_TEAM1)
|
|
{
|
|
Com_sprintf(teamstr, sizeof(teamstr), team1);
|
|
}
|
|
else
|
|
{
|
|
Com_sprintf(teamstr, sizeof(teamstr), team2);
|
|
}
|
|
|
|
if (BG_SiegeGetValueGroup(siege_info, teamstr, cgParseObjectives))
|
|
{ //found the team group
|
|
if (BG_SiegeGetValueGroup(cgParseObjectives, va("Objective%i", objective), objectiveStr))
|
|
{ //found the objective group
|
|
//Parse the name right into the buffer.
|
|
BG_SiegeGetPairedValue(objectiveStr, "final", finalStr);
|
|
return (atoi( finalStr ));
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void CG_SiegeBriefingDisplay(int team, int dontshow)
|
|
{
|
|
char teamstr[64];
|
|
char briefing[8192];
|
|
char properValue[1024];
|
|
char objectiveDesc[1024];
|
|
int i = 1;
|
|
int useTeam = team;
|
|
qboolean primary = qfalse;
|
|
|
|
if (!siege_valid)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (team == TEAM_SPECTATOR)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (team == SIEGETEAM_TEAM1)
|
|
{
|
|
Com_sprintf(teamstr, sizeof(teamstr), team1);
|
|
}
|
|
else
|
|
{
|
|
Com_sprintf(teamstr, sizeof(teamstr), team2);
|
|
}
|
|
|
|
if (useTeam != SIEGETEAM_TEAM1 && useTeam != SIEGETEAM_TEAM2)
|
|
{ //This shouldn't be happening. But just fall back to team 2 anyway.
|
|
useTeam = SIEGETEAM_TEAM2;
|
|
}
|
|
|
|
trap_Cvar_Set(va("siege_primobj_inuse"), "0");
|
|
|
|
while (i < 16)
|
|
{ //do up to 16 objectives I suppose
|
|
//Get the value for this objective on this team
|
|
//Now set the cvar for the menu to display.
|
|
|
|
//primary = (CG_SiegeGetObjectiveFinal(useTeam, i)>-1)?qtrue:qfalse;
|
|
primary = (CG_SiegeGetObjectiveFinal(useTeam, i)>0)?qtrue:qfalse;
|
|
|
|
properValue[0] = 0;
|
|
trap_Cvar_VariableStringBuffer(va("team%i_objective%i", useTeam, i), properValue, 1024);
|
|
if (primary)
|
|
{
|
|
trap_Cvar_Set(va("siege_primobj"), properValue);
|
|
}
|
|
else
|
|
{
|
|
trap_Cvar_Set(va("siege_objective%i", i), properValue);
|
|
}
|
|
|
|
//Now set the long desc cvar for the menu to display.
|
|
properValue[0] = 0;
|
|
trap_Cvar_VariableStringBuffer(va("team%i_objective%i_longdesc", useTeam, i), properValue, 1024);
|
|
if (primary)
|
|
{
|
|
trap_Cvar_Set(va("siege_primobj_longdesc"), properValue);
|
|
}
|
|
else
|
|
{
|
|
trap_Cvar_Set(va("siege_objective%i_longdesc", i), properValue);
|
|
}
|
|
|
|
//Now set the gfx cvar for the menu to display.
|
|
properValue[0] = 0;
|
|
trap_Cvar_VariableStringBuffer(va("team%i_objective%i_gfx", useTeam, i), properValue, 1024);
|
|
if (primary)
|
|
{
|
|
trap_Cvar_Set(va("siege_primobj_gfx"), properValue);
|
|
}
|
|
else
|
|
{
|
|
trap_Cvar_Set(va("siege_objective%i_gfx", i), properValue);
|
|
}
|
|
|
|
//Now set the mapicon cvar for the menu to display.
|
|
properValue[0] = 0;
|
|
trap_Cvar_VariableStringBuffer(va("team%i_objective%i_mapicon", useTeam, i), properValue, 1024);
|
|
if (primary)
|
|
{
|
|
trap_Cvar_Set(va("siege_primobj_mapicon"), properValue);
|
|
}
|
|
else
|
|
{
|
|
trap_Cvar_Set(va("siege_objective%i_mapicon", i), properValue);
|
|
}
|
|
|
|
//Now set the mappos cvar for the menu to display.
|
|
properValue[0] = 0;
|
|
trap_Cvar_VariableStringBuffer(va("team%i_objective%i_mappos", useTeam, i), properValue, 1024);
|
|
if (primary)
|
|
{
|
|
trap_Cvar_Set(va("siege_primobj_mappos"), properValue);
|
|
}
|
|
else
|
|
{
|
|
trap_Cvar_Set(va("siege_objective%i_mappos", i), properValue);
|
|
}
|
|
|
|
//Now set the description cvar for the objective
|
|
CG_SiegeGetObjectiveDescription(useTeam, i, objectiveDesc);
|
|
|
|
if (objectiveDesc[0])
|
|
{ //found a valid objective description
|
|
if ( primary )
|
|
{
|
|
trap_Cvar_Set(va("siege_primobj_desc"), objectiveDesc);
|
|
//this one is marked not in use because it gets primobj
|
|
trap_Cvar_Set(va("siege_objective%i_inuse", i), "0");
|
|
trap_Cvar_Set(va("siege_primobj_inuse"), "1");
|
|
|
|
trap_Cvar_Set(va("team%i_objective%i_inuse", useTeam, i), "1");
|
|
|
|
}
|
|
else
|
|
{
|
|
trap_Cvar_Set(va("siege_objective%i_desc", i), objectiveDesc);
|
|
trap_Cvar_Set(va("siege_objective%i_inuse", i), "2");
|
|
trap_Cvar_Set(va("team%i_objective%i_inuse", useTeam, i), "2");
|
|
|
|
}
|
|
}
|
|
else
|
|
{ //didn't find one, so set the "inuse" cvar to 0 for the objective and mark it non-complete.
|
|
trap_Cvar_Set(va("siege_objective%i_inuse", i), "0");
|
|
trap_Cvar_Set(va("siege_objective%i", i), "0");
|
|
trap_Cvar_Set(va("team%i_objective%i_inuse", useTeam, i), "0");
|
|
trap_Cvar_Set(va("team%i_objective%i", useTeam, i), "0");
|
|
|
|
trap_Cvar_Set(va("siege_objective%i_mappos", i), "");
|
|
trap_Cvar_Set(va("team%i_objective%i_mappos", useTeam, i), "");
|
|
trap_Cvar_Set(va("siege_objective%i_gfx", i), "");
|
|
trap_Cvar_Set(va("team%i_objective%i_gfx", useTeam, i), "");
|
|
trap_Cvar_Set(va("siege_objective%i_mapicon", i), "");
|
|
trap_Cvar_Set(va("team%i_objective%i_mapicon", useTeam, i), "");
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
if (dontshow)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (BG_SiegeGetValueGroup(siege_info, teamstr, cgParseObjectives))
|
|
{
|
|
if (BG_SiegeGetPairedValue(cgParseObjectives, "briefing", briefing))
|
|
{
|
|
CG_DrawSiegeMessage(briefing, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CG_SiegeObjectiveCompleted(centity_t *ent, int won, int objectivenum)
|
|
{
|
|
int myTeam;
|
|
char teamstr[64];
|
|
char objstr[256];
|
|
char foundobjective[MAX_SIEGE_INFO_SIZE];
|
|
char appstring[1024];
|
|
char soundstr[1024];
|
|
int success = 0;
|
|
playerState_t *ps = NULL;
|
|
|
|
if (!siege_valid)
|
|
{
|
|
CG_Error("Siege data does not exist on client!\n");
|
|
return;
|
|
}
|
|
|
|
if (cg.snap)
|
|
{ //this should always be true, if it isn't though use the predicted ps as a fallback
|
|
ps = &cg.snap->ps;
|
|
}
|
|
else
|
|
{
|
|
ps = &cg.predictedPlayerState;
|
|
}
|
|
|
|
if (!ps)
|
|
{
|
|
assert(0);
|
|
return;
|
|
}
|
|
|
|
myTeam = ps->persistant[PERS_TEAM];
|
|
|
|
if (myTeam == TEAM_SPECTATOR)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (won == SIEGETEAM_TEAM1)
|
|
{
|
|
Com_sprintf(teamstr, sizeof(teamstr), team1);
|
|
}
|
|
else
|
|
{
|
|
Com_sprintf(teamstr, sizeof(teamstr), team2);
|
|
}
|
|
|
|
if (BG_SiegeGetValueGroup(siege_info, teamstr, cgParseObjectives))
|
|
{
|
|
Com_sprintf(objstr, sizeof(objstr), "Objective%i", objectivenum);
|
|
|
|
if (BG_SiegeGetValueGroup(cgParseObjectives, objstr, foundobjective))
|
|
{
|
|
if (myTeam == SIEGETEAM_TEAM1)
|
|
{
|
|
success = BG_SiegeGetPairedValue(foundobjective, "message_team1", appstring);
|
|
}
|
|
else
|
|
{
|
|
success = BG_SiegeGetPairedValue(foundobjective, "message_team2", appstring);
|
|
}
|
|
|
|
if (success)
|
|
{
|
|
CG_DrawSiegeMessageNonMenu(appstring);
|
|
}
|
|
|
|
appstring[0] = 0;
|
|
soundstr[0] = 0;
|
|
|
|
if (myTeam == SIEGETEAM_TEAM1)
|
|
{
|
|
Com_sprintf(teamstr, sizeof(teamstr), "sound_team1");
|
|
}
|
|
else
|
|
{
|
|
Com_sprintf(teamstr, sizeof(teamstr), "sound_team2");
|
|
}
|
|
|
|
if (BG_SiegeGetPairedValue(foundobjective, teamstr, appstring))
|
|
{
|
|
Com_sprintf(soundstr, sizeof(soundstr), appstring);
|
|
}
|
|
/*
|
|
else
|
|
{
|
|
if (myTeam != won)
|
|
{
|
|
Com_sprintf(soundstr, sizeof(soundstr), DEFAULT_LOSE_OBJECTIVE);
|
|
}
|
|
else
|
|
{
|
|
Com_sprintf(soundstr, sizeof(soundstr), DEFAULT_WIN_OBJECTIVE);
|
|
}
|
|
}
|
|
*/
|
|
|
|
if (soundstr[0])
|
|
{
|
|
trap_S_StartLocalSound(trap_S_RegisterSound(soundstr), CHAN_ANNOUNCER);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
siegeExtended_t cg_siegeExtendedData[MAX_CLIENTS];
|
|
|
|
//parse a single extended siege data entry
|
|
void CG_ParseSiegeExtendedDataEntry(const char *conStr)
|
|
{
|
|
char s[MAX_STRING_CHARS];
|
|
char *str = (char *)conStr;
|
|
int argParses = 0;
|
|
int i;
|
|
int maxAmmo = 0, clNum = -1, health = 1, maxhealth = 1, ammo = 1;
|
|
centity_t *cent;
|
|
|
|
if (!conStr || !conStr[0])
|
|
{
|
|
return;
|
|
}
|
|
|
|
while (*str && argParses < 4)
|
|
{
|
|
i = 0;
|
|
while (*str && *str != '|')
|
|
{
|
|
s[i] = *str;
|
|
i++;
|
|
*str++;
|
|
}
|
|
s[i] = 0;
|
|
switch (argParses)
|
|
{
|
|
case 0:
|
|
clNum = atoi(s);
|
|
break;
|
|
case 1:
|
|
health = atoi(s);
|
|
break;
|
|
case 2:
|
|
maxhealth = atoi(s);
|
|
break;
|
|
case 3:
|
|
ammo = atoi(s);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
argParses++;
|
|
str++;
|
|
}
|
|
|
|
if (clNum < 0 || clNum >= MAX_CLIENTS)
|
|
{
|
|
return;
|
|
}
|
|
|
|
cg_siegeExtendedData[clNum].health = health;
|
|
cg_siegeExtendedData[clNum].maxhealth = maxhealth;
|
|
cg_siegeExtendedData[clNum].ammo = ammo;
|
|
|
|
cent = &cg_entities[clNum];
|
|
|
|
maxAmmo = ammoData[weaponData[cent->currentState.weapon].ammoIndex].max;
|
|
if ( (cent->currentState.eFlags & EF_DOUBLE_AMMO) )
|
|
{
|
|
maxAmmo *= 2.0f;
|
|
}
|
|
if (ammo >= 0 && ammo <= maxAmmo )
|
|
{ //assure the weapon number is valid and not over max
|
|
//keep the weapon so if it changes before our next ext data update we'll know
|
|
//that the ammo is not applicable.
|
|
cg_siegeExtendedData[clNum].weapon = cent->currentState.weapon;
|
|
}
|
|
else
|
|
{ //not valid? Oh well, just invalidate the weapon too then so we don't display ammo
|
|
cg_siegeExtendedData[clNum].weapon = -1;
|
|
}
|
|
|
|
cg_siegeExtendedData[clNum].lastUpdated = cg.time;
|
|
}
|
|
|
|
//parse incoming siege data, see counterpart in g_saga.c
|
|
void CG_ParseSiegeExtendedData(void)
|
|
{
|
|
int numEntries = trap_Argc();
|
|
int i = 0;
|
|
|
|
if (numEntries < 1)
|
|
{
|
|
assert(!"Bad numEntries for sxd");
|
|
return;
|
|
}
|
|
|
|
while (i < numEntries)
|
|
{
|
|
CG_ParseSiegeExtendedDataEntry(CG_Argv(i+1));
|
|
i++;
|
|
}
|
|
}
|
|
|
|
void CG_SetSiegeTimerCvar ( int msec )
|
|
{
|
|
int seconds;
|
|
int mins;
|
|
int tens;
|
|
|
|
seconds = msec / 1000;
|
|
mins = seconds / 60;
|
|
seconds -= mins * 60;
|
|
tens = seconds / 10;
|
|
seconds -= tens * 10;
|
|
|
|
trap_Cvar_Set("ui_siegeTimer", va( "%i:%i%i", mins, tens, seconds ) );
|
|
}
|