jkxr/Projects/Android/jni/OpenJK/codemp/ui/ui_force.c

1358 lines
32 KiB
C

/*
===========================================================================
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2013 - 2015, OpenJK contributors
This file is part of the OpenJK source code.
OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/
/*
=======================================================================
FORCE INTERFACE
=======================================================================
*/
// use this to get a demo build without an explicit demo build, i.e. to get the demo ui files to build
#include "ui_local.h"
#include "qcommon/qfiles.h"
#include "ui_force.h"
int uiForceSide = FORCE_LIGHTSIDE;
int uiJediNonJedi = -1;
int uiForceRank = FORCE_MASTERY_JEDI_KNIGHT;
int uiMaxRank = MAX_FORCE_RANK;
int uiMaxPoints = 20;
int uiForceUsed = 0;
int uiForceAvailable=0;
extern const char *UI_TeamName(int team);
qboolean gTouchedForce = qfalse;
void Menu_ShowItemByName(menuDef_t *menu, const char *p, qboolean bShow);
qboolean uiForcePowersDisabled[NUM_FORCE_POWERS] = {
qfalse,//FP_HEAL,//instant
qfalse,//FP_LEVITATION,//hold/duration
qfalse,//FP_SPEED,//duration
qfalse,//FP_PUSH,//hold/duration
qfalse,//FP_PULL,//hold/duration
qfalse,//FP_TELEPATHY,//instant
qfalse,//FP_GRIP,//hold/duration
qfalse,//FP_LIGHTNING,//hold/duration
qfalse,//FP_RAGE,//duration
qfalse,//FP_PROTECT,
qfalse,//FP_ABSORB,
qfalse,//FP_TEAM_HEAL,
qfalse,//FP_TEAM_FORCE,
qfalse,//FP_DRAIN,
qfalse,//FP_SEE,
qfalse,//FP_SABER_OFFENSE,
qfalse,//FP_SABER_DEFENSE,
qfalse//FP_SABERTHROW,
};
int uiForcePowersRank[NUM_FORCE_POWERS] = {
0,//FP_HEAL = 0,//instant
1,//FP_LEVITATION,//hold/duration, this one defaults to 1 (gives a free point)
0,//FP_SPEED,//duration
0,//FP_PUSH,//hold/duration
0,//FP_PULL,//hold/duration
0,//FP_TELEPATHY,//instant
0,//FP_GRIP,//hold/duration
0,//FP_LIGHTNING,//hold/duration
0,//FP_RAGE,//duration
0,//FP_PROTECT,
0,//FP_ABSORB,
0,//FP_TEAM_HEAL,
0,//FP_TEAM_FORCE,
0,//FP_DRAIN,
0,//FP_SEE,
1,//FP_SABER_OFFENSE, //default to 1 point in attack
1,//FP_SABER_DEFENSE, //defualt to 1 point in defense
0//FP_SABERTHROW,
};
int uiForcePowerDarkLight[NUM_FORCE_POWERS] = //0 == neutral
{ //nothing should be usable at rank 0..
FORCE_LIGHTSIDE,//FP_HEAL,//instant
0,//FP_LEVITATION,//hold/duration
0,//FP_SPEED,//duration
0,//FP_PUSH,//hold/duration
0,//FP_PULL,//hold/duration
FORCE_LIGHTSIDE,//FP_TELEPATHY,//instant
FORCE_DARKSIDE,//FP_GRIP,//hold/duration
FORCE_DARKSIDE,//FP_LIGHTNING,//hold/duration
FORCE_DARKSIDE,//FP_RAGE,//duration
FORCE_LIGHTSIDE,//FP_PROTECT,//duration
FORCE_LIGHTSIDE,//FP_ABSORB,//duration
FORCE_LIGHTSIDE,//FP_TEAM_HEAL,//instant
FORCE_DARKSIDE,//FP_TEAM_FORCE,//instant
FORCE_DARKSIDE,//FP_DRAIN,//hold/duration
0,//FP_SEE,//duration
0,//FP_SABER_OFFENSE,
0,//FP_SABER_DEFENSE,
0//FP_SABERTHROW,
//NUM_FORCE_POWERS
};
int uiForceStarShaders[NUM_FORCE_STAR_IMAGES][2];
int uiSaberColorShaders[NUM_SABER_COLORS];
void UI_InitForceShaders(void)
{
uiForceStarShaders[0][0] = trap->R_RegisterShaderNoMip("forcestar0");
uiForceStarShaders[0][1] = trap->R_RegisterShaderNoMip("forcestar0");
uiForceStarShaders[1][0] = trap->R_RegisterShaderNoMip("forcecircle1");
uiForceStarShaders[1][1] = trap->R_RegisterShaderNoMip("forcestar1");
uiForceStarShaders[2][0] = trap->R_RegisterShaderNoMip("forcecircle2");
uiForceStarShaders[2][1] = trap->R_RegisterShaderNoMip("forcestar2");
uiForceStarShaders[3][0] = trap->R_RegisterShaderNoMip("forcecircle3");
uiForceStarShaders[3][1] = trap->R_RegisterShaderNoMip("forcestar3");
uiForceStarShaders[4][0] = trap->R_RegisterShaderNoMip("forcecircle4");
uiForceStarShaders[4][1] = trap->R_RegisterShaderNoMip("forcestar4");
uiForceStarShaders[5][0] = trap->R_RegisterShaderNoMip("forcecircle5");
uiForceStarShaders[5][1] = trap->R_RegisterShaderNoMip("forcestar5");
uiForceStarShaders[6][0] = trap->R_RegisterShaderNoMip("forcecircle6");
uiForceStarShaders[6][1] = trap->R_RegisterShaderNoMip("forcestar6");
uiForceStarShaders[7][0] = trap->R_RegisterShaderNoMip("forcecircle7");
uiForceStarShaders[7][1] = trap->R_RegisterShaderNoMip("forcestar7");
uiForceStarShaders[8][0] = trap->R_RegisterShaderNoMip("forcecircle8");
uiForceStarShaders[8][1] = trap->R_RegisterShaderNoMip("forcestar8");
uiSaberColorShaders[SABER_RED] = trap->R_RegisterShaderNoMip("menu/art/saber_red");
uiSaberColorShaders[SABER_ORANGE] = trap->R_RegisterShaderNoMip("menu/art/saber_orange");
uiSaberColorShaders[SABER_YELLOW] = trap->R_RegisterShaderNoMip("menu/art/saber_yellow");
uiSaberColorShaders[SABER_GREEN] = trap->R_RegisterShaderNoMip("menu/art/saber_green");
uiSaberColorShaders[SABER_BLUE] = trap->R_RegisterShaderNoMip("menu/art/saber_blue");
uiSaberColorShaders[SABER_PURPLE] = trap->R_RegisterShaderNoMip("menu/art/saber_purple");
}
// Draw the stars spent on the current force power
void UI_DrawForceStars(rectDef_t *rect, float scale, vec4_t color, int textStyle, int forceindex, int val, int min, int max)
{
int i,pad = 4;
int xPos,width = 16;
int starcolor;
if (val < min || val > max)
{
val = min;
}
if (1) // if (val)
{
xPos = rect->x;
for (i=FORCE_LEVEL_1;i<=max;i++)
{
starcolor = bgForcePowerCost[forceindex][i];
if (uiForcePowersDisabled[forceindex])
{
vec4_t grColor = {0.2f, 0.2f, 0.2f, 1.0f};
trap->R_SetColor(grColor);
}
if (val >= i)
{ // Draw a star.
UI_DrawHandlePic( xPos, rect->y+6, width, width, uiForceStarShaders[starcolor][1] );
}
else
{ // Draw a circle.
UI_DrawHandlePic( xPos, rect->y+6, width, width, uiForceStarShaders[starcolor][0] );
}
if (uiForcePowersDisabled[forceindex])
{
trap->R_SetColor(NULL);
}
xPos += width + pad;
}
}
}
// Set the client's force power layout.
void UI_UpdateClientForcePowers(const char *teamArg)
{
trap->Cvar_Set( "forcepowers", va("%i-%i-%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i",
uiForceRank, uiForceSide, uiForcePowersRank[0], uiForcePowersRank[1],
uiForcePowersRank[2], uiForcePowersRank[3], uiForcePowersRank[4],
uiForcePowersRank[5], uiForcePowersRank[6], uiForcePowersRank[7],
uiForcePowersRank[8], uiForcePowersRank[9], uiForcePowersRank[10],
uiForcePowersRank[11], uiForcePowersRank[12], uiForcePowersRank[13],
uiForcePowersRank[14], uiForcePowersRank[15], uiForcePowersRank[16],
uiForcePowersRank[17]) );
if (gTouchedForce)
{
if (teamArg && teamArg[0])
{
trap->Cmd_ExecuteText( EXEC_APPEND, va("forcechanged \"%s\"\n", teamArg) );
}
else
{
trap->Cmd_ExecuteText( EXEC_APPEND, "forcechanged\n" );
}
}
gTouchedForce = qfalse;
}
int UI_TranslateFCFIndex(int index)
{
if (uiForceSide == FORCE_LIGHTSIDE)
{
return index-uiInfo.forceConfigLightIndexBegin;
}
return index-uiInfo.forceConfigDarkIndexBegin;
}
void UI_SaveForceTemplate()
{
char *selectedName = UI_Cvar_VariableString("ui_SaveFCF");
char fcfString[512];
char forceStringValue[4];
fileHandle_t f;
int strPlace = 0;
int forcePlace = 0;
int i = 0;
qboolean foundFeederItem = qfalse;
if (!selectedName || !selectedName[0])
{
Com_Printf("You did not provide a name for the template.\n");
return;
}
if (uiForceSide == FORCE_LIGHTSIDE)
{ //write it into the light side folder
trap->FS_Open(va("forcecfg/light/%s.fcf", selectedName), &f, FS_WRITE);
}
else
{ //if it isn't light it must be dark
trap->FS_Open(va("forcecfg/dark/%s.fcf", selectedName), &f, FS_WRITE);
}
if (!f)
{
Com_Printf("There was an error writing the template file (read-only?).\n");
return;
}
Com_sprintf(fcfString, sizeof(fcfString), "%i-%i-", uiForceRank, uiForceSide);
strPlace = strlen(fcfString);
while (forcePlace < NUM_FORCE_POWERS)
{
Com_sprintf(forceStringValue, sizeof(forceStringValue), "%i", uiForcePowersRank[forcePlace]);
//Just use the force digit even if multiple digits. Shouldn't be longer than 1.
fcfString[strPlace] = forceStringValue[0];
strPlace++;
forcePlace++;
}
fcfString[strPlace] = '\n';
fcfString[strPlace+1] = 0;
trap->FS_Write(fcfString, strlen(fcfString), f);
trap->FS_Close(f);
Com_Printf("Template saved as \"%s\".\n", selectedName);
//Now, update the FCF list
UI_LoadForceConfig_List();
//Then, scroll through and select the template for the file we just saved
while (i < uiInfo.forceConfigCount)
{
if (!Q_stricmp(uiInfo.forceConfigNames[i], selectedName))
{
if ((uiForceSide == FORCE_LIGHTSIDE && uiInfo.forceConfigSide[i]) ||
(uiForceSide == FORCE_DARKSIDE && !uiInfo.forceConfigSide[i]))
{
Menu_SetFeederSelection(NULL, FEEDER_FORCECFG, UI_TranslateFCFIndex(i), NULL);
foundFeederItem = qtrue;
}
}
i++;
}
//Else, go back to 0
if (!foundFeederItem)
{
Menu_SetFeederSelection(NULL, FEEDER_FORCECFG, 0, NULL);
}
}
//
extern qboolean UI_TrueJediEnabled( void );
void UpdateForceUsed()
{
int curpower, currank;
menuDef_t *menu;
// Currently we don't make a distinction between those that wish to play Jedi of lower than maximum skill.
uiForceRank = uiMaxRank;
uiForceUsed = 0;
uiForceAvailable = forceMasteryPoints[uiForceRank];
// Make sure that we have one freebie in jump.
if (uiForcePowersRank[FP_LEVITATION]<1)
{
uiForcePowersRank[FP_LEVITATION]=1;
}
if ( UI_TrueJediEnabled() )
{//true jedi mode is set
if ( uiJediNonJedi == -1 )
{
int x = 0;
qboolean clear = qfalse, update = qfalse;
uiJediNonJedi = FORCE_NONJEDI;
while ( x < NUM_FORCE_POWERS )
{//if any force power is set, we must be a jedi
if ( x == FP_LEVITATION || x == FP_SABER_OFFENSE )
{
if ( uiForcePowersRank[x] > 1 )
{
uiJediNonJedi = FORCE_JEDI;
break;
}
else if ( uiForcePowersRank[x] > 0 )
{
clear = qtrue;
}
}
else if ( uiForcePowersRank[x] > 0 )
{
uiJediNonJedi = FORCE_JEDI;
break;
}
x++;
}
if ( uiJediNonJedi == FORCE_JEDI )
{
if ( uiForcePowersRank[FP_SABER_OFFENSE] < 1 )
{
uiForcePowersRank[FP_SABER_OFFENSE]=1;
update = qtrue;
}
}
else if ( clear )
{
x = 0;
while ( x < NUM_FORCE_POWERS )
{//clear all force
uiForcePowersRank[x] = 0;
x++;
}
update = qtrue;
}
if ( update )
{
int myTeam;
myTeam = (int)(trap->Cvar_VariableValue("ui_myteam"));
if ( myTeam != TEAM_SPECTATOR )
{
UI_UpdateClientForcePowers(UI_TeamName(myTeam));//will cause him to respawn, if it's been 5 seconds since last one
}
else
{
UI_UpdateClientForcePowers(NULL);//just update powers
}
}
}
}
menu = Menus_FindByName("ingame_playerforce");
// Set the cost of the saberattack according to whether its free.
if (ui_freeSaber.integer)
{ // Make saber free
bgForcePowerCost[FP_SABER_OFFENSE][FORCE_LEVEL_1] = 0;
bgForcePowerCost[FP_SABER_DEFENSE][FORCE_LEVEL_1] = 0;
// Make sure that we have one freebie in saber if applicable.
if (uiForcePowersRank[FP_SABER_OFFENSE]<1)
{
uiForcePowersRank[FP_SABER_OFFENSE]=1;
}
if (uiForcePowersRank[FP_SABER_DEFENSE]<1)
{
uiForcePowersRank[FP_SABER_DEFENSE]=1;
}
if (menu)
{
Menu_ShowItemByName(menu, "setFP_SABER_DEFENSE", qtrue);
Menu_ShowItemByName(menu, "setfp_saberthrow", qtrue);
Menu_ShowItemByName(menu, "effectentry", qtrue);
Menu_ShowItemByName(menu, "effectfield", qtrue);
Menu_ShowItemByName(menu, "nosaber", qfalse);
}
}
else
{ // Make saber normal cost
bgForcePowerCost[FP_SABER_OFFENSE][FORCE_LEVEL_1] = 1;
bgForcePowerCost[FP_SABER_DEFENSE][FORCE_LEVEL_1] = 1;
// Also, check if there is no saberattack. If there isn't, there had better not be any defense or throw!
if (uiForcePowersRank[FP_SABER_OFFENSE]<1)
{
uiForcePowersRank[FP_SABER_DEFENSE]=0;
uiForcePowersRank[FP_SABERTHROW]=0;
if (menu)
{
Menu_ShowItemByName(menu, "setfp_saberdefend", qfalse);
Menu_ShowItemByName(menu, "setfp_saberthrow", qfalse);
Menu_ShowItemByName(menu, "effectentry", qfalse);
Menu_ShowItemByName(menu, "effectfield", qfalse);
Menu_ShowItemByName(menu, "nosaber", qtrue);
}
}
else
{
if (menu)
{
Menu_ShowItemByName(menu, "setfp_saberdefend", qtrue);
Menu_ShowItemByName(menu, "setfp_saberthrow", qtrue);
Menu_ShowItemByName(menu, "effectentry", qtrue);
Menu_ShowItemByName(menu, "effectfield", qtrue);
Menu_ShowItemByName(menu, "nosaber", qfalse);
}
}
}
// Make sure that we're still legal.
for (curpower=0;curpower<NUM_FORCE_POWERS;curpower++)
{ // Make sure that our ranks are within legal limits.
if (uiForcePowersRank[curpower]<0)
uiForcePowersRank[curpower]=0;
else if (uiForcePowersRank[curpower]>=NUM_FORCE_POWER_LEVELS)
uiForcePowersRank[curpower]=(NUM_FORCE_POWER_LEVELS-1);
for (currank=FORCE_LEVEL_1;currank<=uiForcePowersRank[curpower];currank++)
{ // Check on this force power
if (uiForcePowersRank[curpower]>0)
{ // Do not charge the player for the one freebie in jump, or if there is one in saber.
if ( (curpower == FP_LEVITATION && currank == FORCE_LEVEL_1) ||
(curpower == FP_SABER_OFFENSE && currank == FORCE_LEVEL_1 && ui_freeSaber.integer) ||
(curpower == FP_SABER_DEFENSE && currank == FORCE_LEVEL_1 && ui_freeSaber.integer) )
{
// Do nothing (written this way for clarity)
}
else
{ // Check if we can accrue the cost of this power.
if (bgForcePowerCost[curpower][currank] > uiForceAvailable)
{ // We can't afford this power. Break to the next one.
// Remove this power from the player's roster.
uiForcePowersRank[curpower] = currank-1;
break;
}
else
{ // Sure we can afford it.
uiForceUsed += bgForcePowerCost[curpower][currank];
uiForceAvailable -= bgForcePowerCost[curpower][currank];
}
}
}
}
}
}
//Mostly parts of other functions merged into one another.
//Puts the current UI stuff into a string, legalizes it, and then reads it back out.
void UI_ReadLegalForce(void)
{
char fcfString[512];
char forceStringValue[4];
int strPlace = 0;
int forcePlace = 0;
int i = 0;
char singleBuf[64];
char info[MAX_INFO_VALUE];
int c = 0;
int iBuf = 0;
int forcePowerRank = 0;
int currank = 0;
int forceTeam = 0;
qboolean updateForceLater = qfalse;
//First, stick them into a string.
Com_sprintf(fcfString, sizeof(fcfString), "%i-%i-", uiForceRank, uiForceSide);
strPlace = strlen(fcfString);
while (forcePlace < NUM_FORCE_POWERS)
{
Com_sprintf(forceStringValue, sizeof(forceStringValue), "%i", uiForcePowersRank[forcePlace]);
//Just use the force digit even if multiple digits. Shouldn't be longer than 1.
fcfString[strPlace] = forceStringValue[0];
strPlace++;
forcePlace++;
}
fcfString[strPlace] = '\n';
fcfString[strPlace+1] = 0;
info[0] = '\0';
trap->GetConfigString(CS_SERVERINFO, info, sizeof(info));
if (atoi( Info_ValueForKey( info, "g_forceBasedTeams" ) ))
{
switch((int)(trap->Cvar_VariableValue("ui_myteam")))
{
case TEAM_RED:
forceTeam = FORCE_DARKSIDE;
break;
case TEAM_BLUE:
forceTeam = FORCE_LIGHTSIDE;
break;
default:
break;
}
}
//Second, legalize them.
if (!BG_LegalizedForcePowers(fcfString, sizeof (fcfString), uiMaxRank, ui_freeSaber.integer, forceTeam, atoi( Info_ValueForKey( info, "g_gametype" )), 0))
{ //if they were illegal, we should refresh them.
updateForceLater = qtrue;
}
//Lastly, put them back into the UI storage from the legalized string
i = 0;
while (fcfString[i] && fcfString[i] != '-')
{
singleBuf[c] = fcfString[i];
c++;
i++;
}
singleBuf[c] = 0;
c = 0;
i++;
iBuf = atoi(singleBuf);
if (iBuf > uiMaxRank || iBuf < 0)
{ //this force config uses a rank level higher than our currently restricted level.. so we can't use it
//FIXME: Print a message indicating this to the user
// return;
}
uiForceRank = iBuf;
while (fcfString[i] && fcfString[i] != '-')
{
singleBuf[c] = fcfString[i];
c++;
i++;
}
singleBuf[c] = 0;
c = 0;
i++;
uiForceSide = atoi(singleBuf);
if (uiForceSide != FORCE_LIGHTSIDE &&
uiForceSide != FORCE_DARKSIDE)
{
uiForceSide = FORCE_LIGHTSIDE;
return;
}
//clear out the existing powers
while (c < NUM_FORCE_POWERS)
{
uiForcePowersRank[c] = 0;
c++;
}
uiForceUsed = 0;
uiForceAvailable = forceMasteryPoints[uiForceRank];
gTouchedForce = qtrue;
for (c=0;fcfString[i]&&c<NUM_FORCE_POWERS;c++,i++)
{
singleBuf[0] = fcfString[i];
singleBuf[1] = 0;
iBuf = atoi(singleBuf); // So, that means that Force Power "c" wants to be set to rank "iBuf".
if (iBuf < 0)
{
iBuf = 0;
}
forcePowerRank = iBuf;
if (forcePowerRank > FORCE_LEVEL_3 || forcePowerRank < 0)
{ //err.. not correct
continue; // skip this power
}
if (uiForcePowerDarkLight[c] && uiForcePowerDarkLight[c] != uiForceSide)
{ //Apparently the user has crafted a force config that has powers that don't fit with the config's side.
continue; // skip this power
}
// Accrue cost for each assigned rank for this power.
for (currank=FORCE_LEVEL_1;currank<=forcePowerRank;currank++)
{
if (bgForcePowerCost[c][currank] > uiForceAvailable)
{ // Break out, we can't afford any more power.
break;
}
// Pay for this rank of this power.
uiForceUsed += bgForcePowerCost[c][currank];
uiForceAvailable -= bgForcePowerCost[c][currank];
uiForcePowersRank[c]++;
}
}
if (uiForcePowersRank[FP_LEVITATION] < 1)
{
uiForcePowersRank[FP_LEVITATION]=1;
}
if (uiForcePowersRank[FP_SABER_OFFENSE] < 1 && ui_freeSaber.integer)
{
uiForcePowersRank[FP_SABER_OFFENSE]=1;
}
if (uiForcePowersRank[FP_SABER_DEFENSE] < 1 && ui_freeSaber.integer)
{
uiForcePowersRank[FP_SABER_DEFENSE]=1;
}
UpdateForceUsed();
if (updateForceLater)
{
gTouchedForce = qtrue;
UI_UpdateClientForcePowers(NULL);
}
}
void UI_UpdateForcePowers()
{
char *forcePowers = UI_Cvar_VariableString("forcepowers");
char readBuf[256];
int i = 0, i_f = 0, i_r = 0;
uiForceSide = 0;
if (forcePowers && forcePowers[0])
{
while (forcePowers[i])
{
i_r = 0;
while (forcePowers[i] && forcePowers[i] != '-' && i_r < 255)
{
readBuf[i_r] = forcePowers[i];
i_r++;
i++;
}
readBuf[i_r] = '\0';
if (i_r >= 255 || !forcePowers[i] || forcePowers[i] != '-')
{
uiForceSide = 0;
goto validitycheck;
}
uiForceRank = atoi(readBuf);
i_r = 0;
if (uiForceRank > uiMaxRank)
{
uiForceRank = uiMaxRank;
}
i++;
while (forcePowers[i] && forcePowers[i] != '-' && i_r < 255)
{
readBuf[i_r] = forcePowers[i];
i_r++;
i++;
}
readBuf[i_r] = '\0';
if (i_r >= 255 || !forcePowers[i] || forcePowers[i] != '-')
{
uiForceSide = 0;
goto validitycheck;
}
uiForceSide = atoi(readBuf);
i_r = 0;
i++;
i_f = FP_HEAL;
while (forcePowers[i] && i_f < NUM_FORCE_POWERS)
{
readBuf[0] = forcePowers[i];
readBuf[1] = '\0';
uiForcePowersRank[i_f] = atoi(readBuf);
if (i_f == FP_LEVITATION &&
uiForcePowersRank[i_f] < 1)
{
uiForcePowersRank[i_f] = 1;
}
if (i_f == FP_SABER_OFFENSE &&
uiForcePowersRank[i_f] < 1 &&
ui_freeSaber.integer)
{
uiForcePowersRank[i_f] = 1;
}
if (i_f == FP_SABER_DEFENSE &&
uiForcePowersRank[i_f] < 1 &&
ui_freeSaber.integer)
{
uiForcePowersRank[i_f] = 1;
}
i_f++;
i++;
}
if (i_f < NUM_FORCE_POWERS)
{ //info for all the powers wasn't there..
uiForceSide = 0;
goto validitycheck;
}
i++;
}
}
validitycheck:
if (!uiForceSide)
{
uiForceSide = 1;
uiForceRank = 1;
i = 0;
while (i < NUM_FORCE_POWERS)
{
if (i == FP_LEVITATION)
{
uiForcePowersRank[i] = 1;
}
else if (i == FP_SABER_OFFENSE && ui_freeSaber.integer)
{
uiForcePowersRank[i] = 1;
}
else if (i == FP_SABER_DEFENSE && ui_freeSaber.integer)
{
uiForcePowersRank[i] = 1;
}
else
{
uiForcePowersRank[i] = 0;
}
i++;
}
UI_UpdateClientForcePowers(NULL);
}
UpdateForceUsed();
}
extern int uiSkinColor;
extern int uiHoldSkinColor;
qboolean UI_SkinColor_HandleKey(int flags, float *special, int key, int num, int min, int max, int type)
{
if (key == A_MOUSE1 || key == A_MOUSE2 || key == A_ENTER || key == A_KP_ENTER)
{
int i = num;
if (key == A_MOUSE2)
{
i--;
}
else
{
i++;
}
if (i < min)
{
i = max;
}
else if (i > max)
{
i = min;
}
num = i;
uiSkinColor = num;
uiHoldSkinColor = uiSkinColor;
UI_FeederSelection(FEEDER_Q3HEADS, uiInfo.q3SelectedHead, NULL);
return qtrue;
}
return qfalse;
}
qboolean UI_ForceSide_HandleKey(int flags, float *special, int key, int num, int min, int max, int type)
{
char info[MAX_INFO_VALUE];
info[0] = '\0';
trap->GetConfigString(CS_SERVERINFO, info, sizeof(info));
if (atoi( Info_ValueForKey( info, "g_forceBasedTeams" ) ))
{
switch((int)(trap->Cvar_VariableValue("ui_myteam")))
{
case TEAM_RED:
return qfalse;
case TEAM_BLUE:
return qfalse;
default:
break;
}
}
if (key == A_MOUSE1 || key == A_MOUSE2 || key == A_ENTER || key == A_KP_ENTER)
{
int i = num;
int x = 0;
//update the feeder item selection, it might be different depending on side
Menu_SetFeederSelection(NULL, FEEDER_FORCECFG, 0, NULL);
if (key == A_MOUSE2)
{
i--;
}
else
{
i++;
}
if (i < min)
{
i = max;
}
else if (i > max)
{
i = min;
}
num = i;
uiForceSide = num;
// Resetting power ranks based on if light or dark side is chosen
while (x < NUM_FORCE_POWERS)
{
if (uiForcePowerDarkLight[x] && uiForceSide != uiForcePowerDarkLight[x])
{
uiForcePowersRank[x] = 0;
}
x++;
}
UpdateForceUsed();
gTouchedForce = qtrue;
return qtrue;
}
return qfalse;
}
qboolean UI_JediNonJedi_HandleKey(int flags, float *special, int key, int num, int min, int max, int type)
{
char info[MAX_INFO_VALUE];
info[0] = '\0';
trap->GetConfigString(CS_SERVERINFO, info, sizeof(info));
if ( !UI_TrueJediEnabled() )
{//true jedi mode is not set
return qfalse;
}
if (key == A_MOUSE1 || key == A_MOUSE2 || key == A_ENTER || key == A_KP_ENTER)
{
int i = num;
int x = 0;
if (key == A_MOUSE2)
{
i--;
}
else
{
i++;
}
if (i < min)
{
i = max;
}
else if (i > max)
{
i = min;
}
num = i;
uiJediNonJedi = num;
// Resetting power ranks based on if light or dark side is chosen
if ( !num )
{//not a jedi?
int myTeam = (int)(trap->Cvar_VariableValue("ui_myteam"));
while ( x < NUM_FORCE_POWERS )
{//clear all force powers
uiForcePowersRank[x] = 0;
x++;
}
if ( myTeam != TEAM_SPECTATOR )
{
UI_UpdateClientForcePowers(UI_TeamName(myTeam));//will cause him to respawn, if it's been 5 seconds since last one
}
else
{
UI_UpdateClientForcePowers(NULL);//just update powers
}
}
else if ( num )
{//a jedi, set the minimums, hopefuly they know to set the rest!
if ( uiForcePowersRank[FP_LEVITATION] < FORCE_LEVEL_1 )
{//force jump 1 minimum
uiForcePowersRank[FP_LEVITATION] = FORCE_LEVEL_1;
}
if ( uiForcePowersRank[FP_SABER_OFFENSE] < FORCE_LEVEL_1 )
{//saber attack 1, minimum
uiForcePowersRank[FP_SABER_OFFENSE] = FORCE_LEVEL_1;
}
}
UpdateForceUsed();
gTouchedForce = qtrue;
return qtrue;
}
return qfalse;
}
qboolean UI_ForceMaxRank_HandleKey(int flags, float *special, int key, int num, int min, int max, int type)
{
if (key == A_MOUSE1 || key == A_MOUSE2 || key == A_ENTER || key == A_KP_ENTER)
{
int i = num;
if (key == A_MOUSE2)
{
i--;
}
else
{
i++;
}
if (i < min)
{
i = max;
}
else if (i > max)
{
i = min;
}
num = i;
uiMaxRank = num;
trap->Cvar_Set( "g_maxForceRank", va("%i", num));
// The update force used will remove overallocated powers automatically.
UpdateForceUsed();
gTouchedForce = qtrue;
return qtrue;
}
return qfalse;
}
// This function will either raise or lower a power by one rank.
qboolean UI_ForcePowerRank_HandleKey(int flags, float *special, int key, int num, int min, int max, int type)
{
qboolean raising;
if (key == A_MOUSE1 || key == A_MOUSE2 || key == A_ENTER || key == A_KP_ENTER || key == A_BACKSPACE)
{
int forcepower, rank;
//this will give us the index as long as UI_FORCE_RANK is always one below the first force rank index
forcepower = (type-UI_FORCE_RANK)-1;
//the power is disabled on the server
if (uiForcePowersDisabled[forcepower])
{
return qtrue;
}
// If we are not on the same side as a power, or if we are not of any rank at all.
if (uiForcePowerDarkLight[forcepower] && uiForceSide != uiForcePowerDarkLight[forcepower])
{
return qtrue;
}
else if (forcepower == FP_SABER_DEFENSE || forcepower == FP_SABERTHROW)
{ // Saberdefend and saberthrow can't be bought if there is no saberattack
if (uiForcePowersRank[FP_SABER_OFFENSE] < 1)
{
return qtrue;
}
}
if (type == UI_FORCE_RANK_LEVITATION)
{
min += 1;
}
if (type == UI_FORCE_RANK_SABERATTACK && ui_freeSaber.integer)
{
min += 1;
}
if (type == UI_FORCE_RANK_SABERDEFEND && ui_freeSaber.integer)
{
min += 1;
}
if (key == A_MOUSE2 || key == A_BACKSPACE)
{ // Lower a point.
if (uiForcePowersRank[forcepower]<=min)
{
return qtrue;
}
raising = qfalse;
}
else
{ // Raise a point.
if (uiForcePowersRank[forcepower]>=max)
{
return qtrue;
}
raising = qtrue;
}
if (raising)
{ // Check if we can accrue the cost of this power.
rank = uiForcePowersRank[forcepower]+1;
if (bgForcePowerCost[forcepower][rank] > uiForceAvailable)
{ // We can't afford this power. Abandon ship.
return qtrue;
}
else
{ // Sure we can afford it.
uiForceUsed += bgForcePowerCost[forcepower][rank];
uiForceAvailable -= bgForcePowerCost[forcepower][rank];
uiForcePowersRank[forcepower]=rank;
}
}
else
{ // Lower the point.
rank = uiForcePowersRank[forcepower];
uiForceUsed -= bgForcePowerCost[forcepower][rank];
uiForceAvailable += bgForcePowerCost[forcepower][rank];
uiForcePowersRank[forcepower]--;
}
UpdateForceUsed();
gTouchedForce = qtrue;
return qtrue;
}
return qfalse;
}
int gCustRank = 0;
int gCustSide = 0;
int gCustPowersRank[NUM_FORCE_POWERS] = {
0,//FP_HEAL = 0,//instant
1,//FP_LEVITATION,//hold/duration, this one defaults to 1 (gives a free point)
0,//FP_SPEED,//duration
0,//FP_PUSH,//hold/duration
0,//FP_PULL,//hold/duration
0,//FP_TELEPATHY,//instant
0,//FP_GRIP,//hold/duration
0,//FP_LIGHTNING,//hold/duration
0,//FP_RAGE,//duration
0,//FP_PROTECT,
0,//FP_ABSORB,
0,//FP_TEAM_HEAL,
0,//FP_TEAM_FORCE,
0,//FP_DRAIN,
0,//FP_SEE,
0,//FP_SABER_OFFENSE,
0,//FP_SABER_DEFENSE,
0//FP_SABERTHROW,
};
/*
=================
UI_ForceConfigHandle
=================
*/
void UI_ForceConfigHandle( int oldindex, int newindex )
{
fileHandle_t f;
int len = 0;
int i = 0;
int c = 0;
int iBuf = 0, forcePowerRank, currank;
char fcfBuffer[8192];
char singleBuf[64];
char info[MAX_INFO_VALUE];
int forceTeam = 0;
if (oldindex == 0)
{ //switching out from custom config, so first shove the current values into the custom storage
i = 0;
while (i < NUM_FORCE_POWERS)
{
gCustPowersRank[i] = uiForcePowersRank[i];
i++;
}
gCustRank = uiForceRank;
gCustSide = uiForceSide;
}
if (newindex == 0)
{ //switching back to custom, shove the values back in from the custom storage
i = 0;
uiForceUsed = 0;
gTouchedForce = qtrue;
while (i < NUM_FORCE_POWERS)
{
uiForcePowersRank[i] = gCustPowersRank[i];
uiForceUsed += uiForcePowersRank[i];
i++;
}
uiForceRank = gCustRank;
uiForceSide = gCustSide;
UpdateForceUsed();
return;
}
//If we made it here, we want to load in a new config
if (uiForceSide == FORCE_LIGHTSIDE)
{ //we should only be displaying lightside configs, so.. look in the light folder
newindex += uiInfo.forceConfigLightIndexBegin;
if (newindex >= uiInfo.forceConfigCount)
return;
len = trap->FS_Open(va("forcecfg/light/%s.fcf", uiInfo.forceConfigNames[newindex]), &f, FS_READ);
}
else
{ //else dark
newindex += uiInfo.forceConfigDarkIndexBegin;
if (newindex >= uiInfo.forceConfigCount || newindex > uiInfo.forceConfigLightIndexBegin)
{ //dark gets read in before light
return;
}
len = trap->FS_Open(va("forcecfg/dark/%s.fcf", uiInfo.forceConfigNames[newindex]), &f, FS_READ);
}
if (len <= 0)
{ //This should not have happened. But, before we quit out, attempt searching the other light/dark folder for the file.
if (uiForceSide == FORCE_LIGHTSIDE)
len = trap->FS_Open(va("forcecfg/dark/%s.fcf", uiInfo.forceConfigNames[newindex]), &f, FS_READ);
else
len = trap->FS_Open(va("forcecfg/light/%s.fcf", uiInfo.forceConfigNames[newindex]), &f, FS_READ);
if (len <= 0)
{ //still failure? Oh well.
return;
}
}
if (len >= 8192)
{
trap->FS_Close( f );
return;
}
trap->FS_Read(fcfBuffer, len, f);
fcfBuffer[len] = 0;
trap->FS_Close(f);
i = 0;
info[0] = '\0';
trap->GetConfigString(CS_SERVERINFO, info, sizeof(info));
if (atoi( Info_ValueForKey( info, "g_forceBasedTeams" ) ))
{
switch((int)(trap->Cvar_VariableValue("ui_myteam")))
{
case TEAM_RED:
forceTeam = FORCE_DARKSIDE;
break;
case TEAM_BLUE:
forceTeam = FORCE_LIGHTSIDE;
break;
default:
break;
}
}
BG_LegalizedForcePowers(fcfBuffer, sizeof (fcfBuffer), uiMaxRank, ui_freeSaber.integer, forceTeam, atoi( Info_ValueForKey( info, "g_gametype" )), 0);
//legalize the config based on the max rank
//now that we're done with the handle, it's time to parse our force data out of the string
//we store strings in rank-side-xxxxxxxxx format (where the x's are individual force power levels)
while (fcfBuffer[i] && fcfBuffer[i] != '-')
{
singleBuf[c] = fcfBuffer[i];
c++;
i++;
}
singleBuf[c] = 0;
c = 0;
i++;
iBuf = atoi(singleBuf);
if (iBuf > uiMaxRank || iBuf < 0)
{ //this force config uses a rank level higher than our currently restricted level.. so we can't use it
//FIXME: Print a message indicating this to the user
return;
}
uiForceRank = iBuf;
while (fcfBuffer[i] && fcfBuffer[i] != '-')
{
singleBuf[c] = fcfBuffer[i];
c++;
i++;
}
singleBuf[c] = 0;
c = 0;
i++;
uiForceSide = atoi(singleBuf);
if (uiForceSide != FORCE_LIGHTSIDE &&
uiForceSide != FORCE_DARKSIDE)
{
uiForceSide = FORCE_LIGHTSIDE;
return;
}
//clear out the existing powers
while (c < NUM_FORCE_POWERS)
{
/*
if (c==FP_LEVITATION)
{
uiForcePowersRank[c]=1;
}
else if (c==FP_SABER_OFFENSE && ui_freeSaber.integer)
{
uiForcePowersRank[c]=1;
}
else if (c==FP_SABER_DEFENSE && ui_freeSaber.integer)
{
uiForcePowersRank[c]=1;
}
else
{
uiForcePowersRank[c] = 0;
}
*/
//rww - don't need to do these checks. Just trust whatever the saber config says.
uiForcePowersRank[c] = 0;
c++;
}
uiForceUsed = 0;
uiForceAvailable = forceMasteryPoints[uiForceRank];
gTouchedForce = qtrue;
for (c=0;fcfBuffer[i]&&c<NUM_FORCE_POWERS;c++,i++)
{
singleBuf[0] = fcfBuffer[i];
singleBuf[1] = 0;
iBuf = atoi(singleBuf); // So, that means that Force Power "c" wants to be set to rank "iBuf".
if (iBuf < 0)
{
iBuf = 0;
}
forcePowerRank = iBuf;
if (forcePowerRank > FORCE_LEVEL_3 || forcePowerRank < 0)
{ //err.. not correct
continue; // skip this power
}
if (uiForcePowerDarkLight[c] && uiForcePowerDarkLight[c] != uiForceSide)
{ //Apparently the user has crafted a force config that has powers that don't fit with the config's side.
continue; // skip this power
}
// Accrue cost for each assigned rank for this power.
for (currank=FORCE_LEVEL_1;currank<=forcePowerRank;currank++)
{
if (bgForcePowerCost[c][currank] > uiForceAvailable)
{ // Break out, we can't afford any more power.
break;
}
// Pay for this rank of this power.
uiForceUsed += bgForcePowerCost[c][currank];
uiForceAvailable -= bgForcePowerCost[c][currank];
uiForcePowersRank[c]++;
}
}
if (uiForcePowersRank[FP_LEVITATION] < 1)
{
uiForcePowersRank[FP_LEVITATION]=1;
}
if (uiForcePowersRank[FP_SABER_OFFENSE] < 1 && ui_freeSaber.integer)
{
uiForcePowersRank[FP_SABER_OFFENSE]=1;
}
if (uiForcePowersRank[FP_SABER_DEFENSE] < 1 && ui_freeSaber.integer)
{
uiForcePowersRank[FP_SABER_DEFENSE]=1;
}
UpdateForceUsed();
}