/* =========================================================================== Copyright (C) 1999 - 2005, Id Software, Inc. 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 . =========================================================================== */ /* ======================================================================= USER INTERFACE MAIN ======================================================================= */ #include #include #include "../server/exe_headers.h" #include "ui_local.h" #include "menudef.h" #include "ui_shared.h" #include "../ghoul2/G2.h" #include "../game/bg_public.h" #include "../game/anims.h" extern stringID_table_t animTable [MAX_ANIMATIONS+1]; #include "../qcommon/stringed_ingame.h" #include "../qcommon/stv_version.h" #include "../qcommon/q_shared.h" extern qboolean ItemParse_model_g2anim_go( itemDef_t *item, const char *animName ); extern qboolean ItemParse_asset_model_go( itemDef_t *item, const char *name ); extern qboolean ItemParse_model_g2skin_go( itemDef_t *item, const char *skinName ); extern qboolean UI_SaberModelForSaber( const char *saberName, char *saberModel ); extern qboolean UI_SaberSkinForSaber( const char *saberName, char *saberSkin ); extern void UI_SaberAttachToChar( itemDef_t *item ); extern qboolean PC_Script_Parse(const char **out); #define LISTBUFSIZE 10240 static struct { char listBuf[LISTBUFSIZE]; // The list of file names read in // For scrolling through file names int currentLine; // Index to currentSaveFileComments[] currently highlighted int saveFileCnt; // Number of save files read in int awaitingSave; // Flag to see if user wants to overwrite a game. char *savegameMap; int savegameFromFlag; } s_savegame; #define MAX_SAVELOADFILES 1000 #define MAX_SAVELOADNAME 32 #ifdef JK2_MODE byte screenShotBuf[SG_SCR_WIDTH * SG_SCR_HEIGHT * 4]; #endif typedef struct { char *currentSaveFileName; // file name of savegame char currentSaveFileComments[iSG_COMMENT_SIZE]; // file comment char currentSaveFileDateTimeString[iSG_COMMENT_SIZE]; // file time and date time_t currentSaveFileDateTime; char currentSaveFileMap[MAX_TOKEN_CHARS]; // map save game is from } savedata_t; static savedata_t s_savedata[MAX_SAVELOADFILES]; void UI_SetActiveMenu( const char* menuname,const char *menuID ); void ReadSaveDirectory (void); void Item_RunScript(itemDef_t *item, const char *s); qboolean Item_SetFocus(itemDef_t *item, float x, float y); qboolean Asset_Parse(char **buffer); menuDef_t *Menus_FindByName(const char *p); void Menus_HideItems(const char *menuName); int Text_Height(const char *text, float scale, int iFontIndex ); int Text_Width(const char *text, float scale, int iFontIndex ); void _UI_DrawTopBottom(float x, float y, float w, float h, float size); void _UI_DrawSides(float x, float y, float w, float h, float size); void UI_CheckVid1Data(const char *menuTo,const char *warningMenuName); void UI_GetVideoSetup ( void ); void UI_UpdateVideoSetup ( void ); static void UI_UpdateCharacterCvars ( void ); static void UI_GetCharacterCvars ( void ); static void UI_UpdateSaberCvars ( void ); static void UI_GetSaberCvars ( void ); static void UI_ResetSaberCvars ( void ); static void UI_InitAllocForcePowers ( const char *forceName ); static void UI_AffectForcePowerLevel ( const char *forceName ); static void UI_ShowForceLevelDesc ( const char *forceName ); static void UI_ResetForceLevels ( void ); static void UI_ClearWeapons ( void ); static void UI_GiveWeapon ( const int weaponIndex ); static void UI_EquipWeapon ( const int weaponIndex ); static void UI_LoadMissionSelectMenu( const char *cvarName ); static void UI_AddWeaponSelection ( const int weaponIndex, const int ammoIndex, const int ammoAmount, const char *iconItemName,const char *litIconItemName, const char *hexBackground, const char *soundfile ); static void UI_AddThrowWeaponSelection ( const int weaponIndex, const int ammoIndex, const int ammoAmount, const char *iconItemName,const char *litIconItemName, const char *hexBackground, const char *soundfile ); static void UI_RemoveWeaponSelection ( const int weaponIndex ); static void UI_RemoveThrowWeaponSelection ( void ); static void UI_HighLightWeaponSelection ( const int selectionslot ); static void UI_NormalWeaponSelection ( const int selectionslot ); static void UI_NormalThrowSelection ( void ); static void UI_HighLightThrowSelection( void ); static void UI_ClearInventory ( void ); static void UI_GiveInventory ( const int itemIndex, const int amount ); static void UI_ForcePowerWeaponsButton(qboolean activeFlag); static void UI_UpdateCharacterSkin( void ); static void UI_UpdateCharacter( qboolean changedModel ); static void UI_UpdateSaberType( void ); static void UI_UpdateSaberHilt( qboolean secondSaber ); //static void UI_UpdateSaberColor( qboolean secondSaber ); static void UI_InitWeaponSelect( void ); static void UI_WeaponHelpActive( void ); #ifndef JK2_MODE static void UI_UpdateFightingStyle ( void ); static void UI_UpdateFightingStyleChoices ( void ); static void UI_CalcForceStatus(void); #endif // !JK2_MODE static void UI_DecrementForcePowerLevel( void ); static void UI_DecrementCurrentForcePower ( void ); static void UI_ShutdownForceHelp( void ); static void UI_ForceHelpActive( void ); #ifndef JK2_MODE static void UI_DemoSetForceLevels( void ); #endif // !JK2_MODE static void UI_RecordForceLevels( void ); static void UI_RecordWeapons( void ); static void UI_ResetCharacterListBoxes( void ); void UI_LoadMenus(const char *menuFile, qboolean reset); static void UI_OwnerDraw(float x, float y, float w, float h, float text_x, float text_y, int ownerDraw, int ownerDrawFlags, int align, float special, float scale, vec4_t color, qhandle_t shader, int textStyle, int iFontIndex); static qboolean UI_OwnerDrawVisible(int flags); int UI_OwnerDrawWidth(int ownerDraw, float scale); static void UI_Update(const char *name); void UI_UpdateCvars( void ); void UI_ResetDefaults( void ); void UI_AdjustSaveGameListBox( int currentLine ); void Menus_CloseByName(const char *p); // Movedata Sounds enum { MDS_NONE = 0, MDS_FORCE_JUMP, MDS_ROLL, MDS_SABER, MDS_MOVE_SOUNDS_MAX }; enum { MD_ACROBATICS = 0, MD_SINGLE_FAST, MD_SINGLE_MEDIUM, MD_SINGLE_STRONG, MD_DUAL_SABERS, MD_SABER_STAFF, MD_MOVE_TITLE_MAX }; // Some hard coded badness // At some point maybe this should be externalized to a .dat file const char *datapadMoveTitleData[MD_MOVE_TITLE_MAX] = { "@MENUS_ACROBATICS", "@MENUS_SINGLE_FAST", "@MENUS_SINGLE_MEDIUM", "@MENUS_SINGLE_STRONG", "@MENUS_DUAL_SABERS", "@MENUS_SABER_STAFF", }; const char *datapadMoveTitleBaseAnims[MD_MOVE_TITLE_MAX] = { "BOTH_RUN1", "BOTH_SABERFAST_STANCE", "BOTH_STAND2", "BOTH_SABERSLOW_STANCE", "BOTH_SABERDUAL_STANCE", "BOTH_SABERSTAFF_STANCE", }; #define MAX_MOVES 16 typedef struct { const char *title; const char *desc; const char *anim; short sound; } datpadmovedata_t; static datpadmovedata_t datapadMoveData[MD_MOVE_TITLE_MAX][MAX_MOVES] = { { // Acrobatics { "@MENUS_FORCE_JUMP1", "@MENUS_FORCE_JUMP1_DESC", "BOTH_FORCEJUMP1", MDS_FORCE_JUMP }, { "@MENUS_FORCE_FLIP", "@MENUS_FORCE_FLIP_DESC", "BOTH_FLIP_F", MDS_FORCE_JUMP }, { "@MENUS_ROLL", "@MENUS_ROLL_DESC", "BOTH_ROLL_F", MDS_ROLL }, { "@MENUS_BACKFLIP_OFF_WALL", "@MENUS_BACKFLIP_OFF_WALL_DESC", "BOTH_WALL_FLIP_BACK1", MDS_FORCE_JUMP }, { "@MENUS_SIDEFLIP_OFF_WALL", "@MENUS_SIDEFLIP_OFF_WALL_DESC", "BOTH_WALL_FLIP_RIGHT", MDS_FORCE_JUMP }, { "@MENUS_WALL_RUN", "@MENUS_WALL_RUN_DESC", "BOTH_WALL_RUN_RIGHT", MDS_FORCE_JUMP }, { "@MENUS_LONG_JUMP", "@MENUS_LONG_JUMP_DESC", "BOTH_FORCELONGLEAP_START", MDS_FORCE_JUMP }, { "@MENUS_WALL_GRAB_JUMP", "@MENUS_WALL_GRAB_JUMP_DESC", "BOTH_FORCEWALLREBOUND_FORWARD",MDS_FORCE_JUMP }, { "@MENUS_RUN_UP_WALL_BACKFLIP", "@MENUS_RUN_UP_WALL_BACKFLIP_DESC", "BOTH_FORCEWALLRUNFLIP_START", MDS_FORCE_JUMP }, { "@MENUS_JUMPUP_FROM_KNOCKDOWN", "@MENUS_JUMPUP_FROM_KNOCKDOWN_DESC","BOTH_KNOCKDOWN3", MDS_NONE }, { "@MENUS_JUMPKICK_FROM_KNOCKDOWN", "@MENUS_JUMPKICK_FROM_KNOCKDOWN_DESC","BOTH_KNOCKDOWN2", MDS_NONE }, { "@MENUS_ROLL_FROM_KNOCKDOWN", "@MENUS_ROLL_FROM_KNOCKDOWN_DESC", "BOTH_KNOCKDOWN1", MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, }, { //Single Saber, Fast Style { "@MENUS_STAB_BACK", "@MENUS_STAB_BACK_DESC", "BOTH_A2_STABBACK1", MDS_SABER }, { "@MENUS_LUNGE_ATTACK", "@MENUS_LUNGE_ATTACK_DESC", "BOTH_LUNGE2_B__T_", MDS_SABER }, { "@MENUS_FORCE_PULL_IMPALE", "@MENUS_FORCE_PULL_IMPALE_DESC", "BOTH_PULL_IMPALE_STAB", MDS_SABER }, { "@MENUS_FAST_ATTACK_KATA", "@MENUS_FAST_ATTACK_KATA_DESC", "BOTH_A1_SPECIAL", MDS_SABER }, { "@MENUS_ATTACK_ENEMYONGROUND", "@MENUS_ATTACK_ENEMYONGROUND_DESC", "BOTH_STABDOWN", MDS_FORCE_JUMP }, { "@MENUS_CARTWHEEL", "@MENUS_CARTWHEEL_DESC", "BOTH_ARIAL_RIGHT", MDS_FORCE_JUMP }, { "@MENUS_BOTH_ROLL_STAB", "@MENUS_BOTH_ROLL_STAB2_DESC", "BOTH_ROLL_STAB", MDS_SABER }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, }, { //Single Saber, Medium Style { "@MENUS_SLASH_BACK", "@MENUS_SLASH_BACK_DESC", "BOTH_ATTACK_BACK", MDS_SABER }, { "@MENUS_FLIP_ATTACK", "@MENUS_FLIP_ATTACK_DESC", "BOTH_JUMPFLIPSLASHDOWN1", MDS_FORCE_JUMP }, { "@MENUS_FORCE_PULL_SLASH", "@MENUS_FORCE_PULL_SLASH_DESC", "BOTH_PULL_IMPALE_SWING", MDS_SABER }, { "@MENUS_MEDIUM_ATTACK_KATA", "@MENUS_MEDIUM_ATTACK_KATA_DESC", "BOTH_A2_SPECIAL", MDS_SABER }, { "@MENUS_ATTACK_ENEMYONGROUND", "@MENUS_ATTACK_ENEMYONGROUND_DESC", "BOTH_STABDOWN", MDS_FORCE_JUMP }, { "@MENUS_CARTWHEEL", "@MENUS_CARTWHEEL_DESC", "BOTH_ARIAL_RIGHT", MDS_FORCE_JUMP }, { "@MENUS_BOTH_ROLL_STAB", "@MENUS_BOTH_ROLL_STAB2_DESC", "BOTH_ROLL_STAB", MDS_SABER }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, }, { //Single Saber, Strong Style { "@MENUS_SLASH_BACK", "@MENUS_SLASH_BACK_DESC", "BOTH_ATTACK_BACK", MDS_SABER }, { "@MENUS_JUMP_ATTACK", "@MENUS_JUMP_ATTACK_DESC", "BOTH_FORCELEAP2_T__B_", MDS_FORCE_JUMP }, { "@MENUS_FORCE_PULL_SLASH", "@MENUS_FORCE_PULL_SLASH_DESC", "BOTH_PULL_IMPALE_SWING", MDS_SABER }, { "@MENUS_STRONG_ATTACK_KATA", "@MENUS_STRONG_ATTACK_KATA_DESC", "BOTH_A3_SPECIAL", MDS_SABER }, { "@MENUS_ATTACK_ENEMYONGROUND", "@MENUS_ATTACK_ENEMYONGROUND_DESC", "BOTH_STABDOWN", MDS_FORCE_JUMP }, { "@MENUS_CARTWHEEL", "@MENUS_CARTWHEEL_DESC", "BOTH_ARIAL_RIGHT", MDS_FORCE_JUMP }, { "@MENUS_BOTH_ROLL_STAB", "@MENUS_BOTH_ROLL_STAB2_DESC", "BOTH_ROLL_STAB", MDS_SABER }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, }, { //Dual Sabers { "@MENUS_SLASH_BACK", "@MENUS_SLASH_BACK_DESC", "BOTH_ATTACK_BACK", MDS_SABER }, { "@MENUS_FLIP_FORWARD_ATTACK", "@MENUS_FLIP_FORWARD_ATTACK_DESC", "BOTH_JUMPATTACK6", MDS_FORCE_JUMP }, { "@MENUS_DUAL_SABERS_TWIRL", "@MENUS_DUAL_SABERS_TWIRL_DESC", "BOTH_SPINATTACK6", MDS_SABER }, { "@MENUS_ATTACK_ENEMYONGROUND", "@MENUS_ATTACK_ENEMYONGROUND_DESC", "BOTH_STABDOWN_DUAL", MDS_FORCE_JUMP }, { "@MENUS_DUAL_SABER_BARRIER", "@MENUS_DUAL_SABER_BARRIER_DESC", "BOTH_A6_SABERPROTECT", MDS_SABER }, { "@MENUS_DUAL_STAB_FRONT_BACK", "@MENUS_DUAL_STAB_FRONT_BACK_DESC", "BOTH_A6_FB", MDS_SABER }, { "@MENUS_DUAL_STAB_LEFT_RIGHT", "@MENUS_DUAL_STAB_LEFT_RIGHT_DESC", "BOTH_A6_LR", MDS_SABER }, { "@MENUS_CARTWHEEL", "@MENUS_CARTWHEEL_DESC", "BOTH_ARIAL_RIGHT", MDS_FORCE_JUMP }, { "@MENUS_BOTH_ROLL_STAB", "@MENUS_BOTH_ROLL_STAB_DESC", "BOTH_ROLL_STAB", MDS_SABER }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, }, { // Saber Staff { "@MENUS_STAB_BACK", "@MENUS_STAB_BACK_DESC", "BOTH_A2_STABBACK1", MDS_SABER }, { "@MENUS_BACK_FLIP_ATTACK", "@MENUS_BACK_FLIP_ATTACK_DESC", "BOTH_JUMPATTACK7", MDS_FORCE_JUMP }, { "@MENUS_SABER_STAFF_TWIRL", "@MENUS_SABER_STAFF_TWIRL_DESC", "BOTH_SPINATTACK7", MDS_SABER }, { "@MENUS_ATTACK_ENEMYONGROUND", "@MENUS_ATTACK_ENEMYONGROUND_DESC", "BOTH_STABDOWN_STAFF", MDS_FORCE_JUMP }, { "@MENUS_SPINNING_KATA", "@MENUS_SPINNING_KATA_DESC", "BOTH_A7_SOULCAL", MDS_SABER }, { "@MENUS_KICK1", "@MENUS_KICK1_DESC", "BOTH_A7_KICK_F", MDS_FORCE_JUMP }, { "@MENUS_JUMP_KICK", "@MENUS_JUMP_KICK_DESC", "BOTH_A7_KICK_F_AIR", MDS_FORCE_JUMP }, { "@MENUS_SPLIT_KICK", "@MENUS_SPLIT_KICK_DESC", "BOTH_A7_KICK_RL", MDS_FORCE_JUMP }, { "@MENUS_SPIN_KICK", "@MENUS_SPIN_KICK_DESC", "BOTH_A7_KICK_S", MDS_FORCE_JUMP }, { "@MENUS_FLIP_KICK", "@MENUS_FLIP_KICK_DESC", "BOTH_A7_KICK_BF", MDS_FORCE_JUMP }, { "@MENUS_BUTTERFLY_ATTACK", "@MENUS_BUTTERFLY_ATTACK_DESC", "BOTH_BUTTERFLY_FR1", MDS_SABER }, { "@MENUS_BOTH_ROLL_STAB", "@MENUS_BOTH_ROLL_STAB2_DESC", "BOTH_ROLL_STAB", MDS_SABER }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, { NULL, NULL, 0, MDS_NONE }, } }; static int gamecodetoui[] = {4,2,3,0,5,1,6}; uiInfo_t uiInfo; static void UI_RegisterCvars( void ); void UI_Load(void); static int UI_GetScreenshotFormatForString( const char *str ) { if ( !Q_stricmp(str, "jpg") || !Q_stricmp(str, "jpeg") ) return SSF_JPEG; else if ( !Q_stricmp(str, "tga") ) return SSF_TGA; else if ( !Q_stricmp(str, "png") ) return SSF_PNG; else return -1; } static const char *UI_GetScreenshotFormatString( int format ) { switch ( format ) { default: case SSF_JPEG: return "jpg"; case SSF_TGA: return "tga"; case SSF_PNG: return "png"; } } typedef struct cvarTable_s { vmCvar_t *vmCvar; const char *cvarName; const char *defaultString; void (*update)( void ); uint32_t cvarFlags; } cvarTable_t; vmCvar_t ui_menuFiles; vmCvar_t ui_hudFiles; vmCvar_t ui_char_anim; vmCvar_t ui_char_model; vmCvar_t ui_char_skin_head; vmCvar_t ui_char_skin_torso; vmCvar_t ui_char_skin_legs; vmCvar_t ui_saber_type; vmCvar_t ui_saber; vmCvar_t ui_saber2; vmCvar_t ui_saber_color; vmCvar_t ui_saber2_color; vmCvar_t ui_char_color_red; vmCvar_t ui_char_color_green; vmCvar_t ui_char_color_blue; vmCvar_t ui_PrecacheModels; vmCvar_t ui_screenshotType; static void UI_UpdateScreenshot( void ) { qboolean changed = qfalse; // check some things if ( ui_screenshotType.string[0] && isalpha( ui_screenshotType.string[0] ) ) { int ssf = UI_GetScreenshotFormatForString( ui_screenshotType.string ); if ( ssf == -1 ) { ui.Printf( "UI Screenshot Format Type '%s' unrecognised, defaulting to JPEG\n", ui_screenshotType.string ); uiInfo.uiDC.screenshotFormat = SSF_JPEG; changed = qtrue; } else uiInfo.uiDC.screenshotFormat = ssf; } else if ( ui_screenshotType.integer < SSF_JPEG || ui_screenshotType.integer > SSF_PNG ) { ui.Printf( "ui_screenshotType %i is out of range, defaulting to 0 (JPEG)\n", ui_screenshotType.integer ); uiInfo.uiDC.screenshotFormat = SSF_JPEG; changed = qtrue; } else { uiInfo.uiDC.screenshotFormat = atoi( ui_screenshotType.string ); changed = qtrue; } if ( changed ) { Cvar_Set( "ui_screenshotType", UI_GetScreenshotFormatString( uiInfo.uiDC.screenshotFormat ) ); Cvar_Update( &ui_screenshotType ); } } static cvarTable_t cvarTable[] = { { &ui_menuFiles, "ui_menuFiles", "ui/menus.txt", NULL, CVAR_ARCHIVE }, #ifdef JK2_MODE { &ui_hudFiles, "cg_hudFiles", "ui/jk2hud.txt", NULL, CVAR_ARCHIVE}, #else { &ui_hudFiles, "cg_hudFiles", "ui/jahud.txt", NULL, CVAR_ARCHIVE}, #endif { &ui_char_anim, "ui_char_anim", "BOTH_WALK1", NULL, 0}, { &ui_char_model, "ui_char_model", "", NULL, 0}, //these are filled in by the "g_*" versions on load { &ui_char_skin_head, "ui_char_skin_head", "", NULL, 0}, //the "g_*" versions are initialized in UI_Init, ui_atoms.cpp { &ui_char_skin_torso, "ui_char_skin_torso", "", NULL, 0}, { &ui_char_skin_legs, "ui_char_skin_legs", "", NULL, 0}, { &ui_saber_type, "ui_saber_type", "", NULL, 0}, { &ui_saber, "ui_saber", "", NULL, 0}, { &ui_saber2, "ui_saber2", "", NULL, 0}, { &ui_saber_color, "ui_saber_color", "", NULL, 0}, { &ui_saber2_color, "ui_saber2_color", "", NULL, 0}, { &ui_char_color_red, "ui_char_color_red", "", NULL, 0}, { &ui_char_color_green, "ui_char_color_green", "", NULL, 0}, { &ui_char_color_blue, "ui_char_color_blue", "", NULL, 0}, { &ui_PrecacheModels, "ui_PrecacheModels", "1", NULL, CVAR_ARCHIVE}, { &ui_screenshotType, "ui_screenshotType", "jpg", UI_UpdateScreenshot, CVAR_ARCHIVE } }; #define FP_UPDATED_NONE -1 #define NOWEAPON -1 static const size_t cvarTableSize = ARRAY_LEN( cvarTable ); void Text_Paint(float x, float y, float scale, vec4_t color, const char *text, int iMaxPixelWidth, int style, int iFontIndex); int Key_GetCatcher( void ); #define UI_FPS_FRAMES 4 void _UI_Refresh( int realtime ) { static int index; static int previousTimes[UI_FPS_FRAMES]; if ( !( Key_GetCatcher() & KEYCATCH_UI ) ) { return; } extern void SE_CheckForLanguageUpdates(void); SE_CheckForLanguageUpdates(); if ( Menus_AnyFullScreenVisible() ) {//if not in full screen, don't mess with ghoul2 //rww - ghoul2 needs to know what time it is even if the client/server are not running //FIXME: this screws up the game when you go back to the game... re.G2API_SetTime(realtime, 0); re.G2API_SetTime(realtime, 1); } uiInfo.uiDC.frameTime = realtime - uiInfo.uiDC.realTime; uiInfo.uiDC.realTime = realtime; previousTimes[index % UI_FPS_FRAMES] = uiInfo.uiDC.frameTime; index++; if ( index > UI_FPS_FRAMES ) { int i, total; // average multiple frames together to smooth changes out a bit total = 0; for ( i = 0 ; i < UI_FPS_FRAMES ; i++ ) { total += previousTimes[i]; } if ( !total ) { total = 1; } uiInfo.uiDC.FPS = 1000 * UI_FPS_FRAMES / total; } UI_UpdateCvars(); if (Menu_Count() > 0) { // paint all the menus Menu_PaintAll(); // refresh server browser list // UI_DoServerRefresh(); // refresh server status // UI_BuildServerStatus(qfalse); // refresh find player list // UI_BuildFindPlayerList(qfalse); } // draw cursor UI_SetColor( NULL ); if (Menu_Count() > 0) { if (uiInfo.uiDC.cursorShow == qtrue) { UI_DrawHandlePic( uiInfo.uiDC.cursorx, uiInfo.uiDC.cursory, 48, 48, uiInfo.uiDC.Assets.cursor); } } } #define MODSBUFSIZE (MAX_MODS * MAX_QPATH) /* =============== UI_LoadMods =============== */ static void UI_LoadMods() { int numdirs; char dirlist[MODSBUFSIZE]; char *dirptr; char *descptr; int i; int dirlen; uiInfo.modCount = 0; numdirs = FS_GetFileList( "$modlist", "", dirlist, sizeof(dirlist) ); dirptr = dirlist; for( i = 0; i < numdirs; i++ ) { dirlen = strlen( dirptr ) + 1; descptr = dirptr + dirlen; uiInfo.modList[uiInfo.modCount].modName = String_Alloc(dirptr); uiInfo.modList[uiInfo.modCount].modDescr = String_Alloc(descptr); dirptr += dirlen + strlen(descptr) + 1; uiInfo.modCount++; if (uiInfo.modCount >= MAX_MODS) { break; } } } /* ================ vmMain This is the only way control passes into the module. This must be the very first function compiled into the .qvm file ================ */ extern "C" Q_EXPORT intptr_t QDECL vmMain( int command, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, int arg10, int arg11 ) { return 0; } /* ================ Text_PaintChar ================ */ /* static void Text_PaintChar(float x, float y, float width, float height, float scale, float s, float t, float s2, float t2, qhandle_t hShader) { float w, h; w = width * scale; h = height * scale; ui.R_DrawStretchPic((int)x, (int)y, w, h, s, t, s2, t2, hShader ); //make the coords (int) or else the chars bleed } */ /* ================ Text_Paint ================ */ // iMaxPixelWidth is 0 here for no limit (but gets converted to -1), else max printable pixel width relative to start pos // void Text_Paint(float x, float y, float scale, vec4_t color, const char *text, int iMaxPixelWidth, int style, int iFontIndex) { if (iFontIndex == 0) { iFontIndex = uiInfo.uiDC.Assets.qhMediumFont; } // kludge.. convert JK2 menu styles to SOF2 printstring ctrl codes... // int iStyleOR = 0; switch (style) { // case ITEM_TEXTSTYLE_NORMAL: iStyleOR = 0;break; // JK2 normal text // case ITEM_TEXTSTYLE_BLINK: iStyleOR = STYLE_BLINK;break; // JK2 fast blinking case ITEM_TEXTSTYLE_PULSE: iStyleOR = STYLE_BLINK;break; // JK2 slow pulsing case ITEM_TEXTSTYLE_SHADOWED: iStyleOR = STYLE_DROPSHADOW;break; // JK2 drop shadow ( need a color for this ) case ITEM_TEXTSTYLE_OUTLINED: iStyleOR = STYLE_DROPSHADOW;break; // JK2 drop shadow ( need a color for this ) case ITEM_TEXTSTYLE_OUTLINESHADOWED: iStyleOR = STYLE_DROPSHADOW;break; // JK2 drop shadow ( need a color for this ) case ITEM_TEXTSTYLE_SHADOWEDMORE: iStyleOR = STYLE_DROPSHADOW;break; // JK2 drop shadow ( need a color for this ) } ui.R_Font_DrawString( x, // int ox y, // int oy text, // const char *text color, // paletteRGBA_c c iStyleOR | iFontIndex, // const int iFontHandle !iMaxPixelWidth?-1:iMaxPixelWidth, // iMaxPixelWidth (-1 = none) scale // const float scale = 1.0f ); } /* ================ Text_PaintWithCursor ================ */ // iMaxPixelWidth is 0 here for no-limit void Text_PaintWithCursor(float x, float y, float scale, vec4_t color, const char *text, int cursorPos, char cursor, int iMaxPixelWidth, int style, int iFontIndex) { Text_Paint(x, y, scale, color, text, iMaxPixelWidth, style, iFontIndex); // now print the cursor as well... // char sTemp[1024]; int iCopyCount = iMaxPixelWidth > 0 ? Q_min( (int)strlen( text ), iMaxPixelWidth ) : (int)strlen( text ); iCopyCount = Q_min(iCopyCount, cursorPos); iCopyCount = Q_min(iCopyCount,(int)sizeof(sTemp)); // copy text into temp buffer for pixel measure... // strncpy(sTemp,text,iCopyCount); sTemp[iCopyCount] = '\0'; int iNextXpos = ui.R_Font_StrLenPixels(sTemp, iFontIndex, scale ); Text_Paint(x+iNextXpos, y, scale, color, va("%c",cursor), iMaxPixelWidth, style|ITEM_TEXTSTYLE_BLINK, iFontIndex); } const char *UI_FeederItemText(float feederID, int index, int column, qhandle_t *handle) { *handle = -1; if (feederID == FEEDER_SAVEGAMES) { if (column==0) { return s_savedata[index].currentSaveFileComments; } else { return s_savedata[index].currentSaveFileDateTimeString; } } else if (feederID == FEEDER_MOVES) { return datapadMoveData[uiInfo.movesTitleIndex][index].title; } else if (feederID == FEEDER_MOVES_TITLES) { return datapadMoveTitleData[index]; } else if (feederID == FEEDER_PLAYER_SPECIES) { if (index >= 0 && index < uiInfo.playerSpeciesCount) { return uiInfo.playerSpecies[index].Name; } } else if (feederID == FEEDER_LANGUAGES) { #ifdef JK2_MODE // FIXME return NULL; #else return SE_GetLanguageName( index ); #endif } else if (feederID == FEEDER_PLAYER_SKIN_HEAD) { if (index >= 0 && index < uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinHeadCount) { *handle = ui.R_RegisterShaderNoMip(va("models/players/%s/icon_%s.jpg", uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].Name, uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinHead[index].name)); return uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinHead[index].name; } } else if (feederID == FEEDER_PLAYER_SKIN_TORSO) { if (index >= 0 && index < uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinTorsoCount) { *handle = ui.R_RegisterShaderNoMip(va("models/players/%s/icon_%s.jpg", uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].Name, uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinTorso[index].name)); return uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinTorso[index].name; } } else if (feederID == FEEDER_PLAYER_SKIN_LEGS) { if (index >= 0 && index < uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinLegCount) { *handle = ui.R_RegisterShaderNoMip(va("models/players/%s/icon_%s.jpg", uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].Name, uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinLeg[index].name)); return uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinLeg[index].name; } } else if (feederID == FEEDER_COLORCHOICES) { if (index >= 0 && index < uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].ColorCount) { *handle = ui.R_RegisterShaderNoMip( uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].Color[index].shader); return uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].Color[index].shader; } } else if (feederID == FEEDER_MODS) { if (index >= 0 && index < uiInfo.modCount) { if (uiInfo.modList[index].modDescr && *uiInfo.modList[index].modDescr) { return uiInfo.modList[index].modDescr; } else { return uiInfo.modList[index].modName; } } } return ""; } qhandle_t UI_FeederItemImage(float feederID, int index) { if (feederID == FEEDER_PLAYER_SKIN_HEAD) { if (index >= 0 && index < uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinHeadCount) { //return uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinHeadIcons[index]; return ui.R_RegisterShaderNoMip(va("models/players/%s/icon_%s.jpg", uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].Name, uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinHead[index].name)); } } else if (feederID == FEEDER_PLAYER_SKIN_TORSO) { if (index >= 0 && index < uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinTorsoCount) { //return uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinTorsoIcons[index]; return ui.R_RegisterShaderNoMip(va("models/players/%s/icon_%s.jpg", uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].Name, uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinTorso[index].name)); } } else if (feederID == FEEDER_PLAYER_SKIN_LEGS) { if (index >= 0 && index < uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinLegCount) { //return uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinLegIcons[index]; return ui.R_RegisterShaderNoMip(va("models/players/%s/icon_%s.jpg", uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].Name, uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinLeg[index].name)); } } else if (feederID == FEEDER_COLORCHOICES) { if (index >= 0 && index < uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].ColorCount) { return ui.R_RegisterShaderNoMip( uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].Color[index].shader); } } /* else if (feederID == FEEDER_ALLMAPS || feederID == FEEDER_MAPS) { int actual; UI_SelectedMap(index, &actual); index = actual; if (index >= 0 && index < uiInfo.mapCount) { if (uiInfo.mapList[index].levelShot == -1) { uiInfo.mapList[index].levelShot = trap_R_RegisterShaderNoMip(uiInfo.mapList[index].imageName); } return uiInfo.mapList[index].levelShot; } } */ return 0; } /* ================= CreateNextSaveName ================= */ static int CreateNextSaveName(char *fileName) { int i; // Loop through all the save games and look for the first open name for (i=0;i0) && ((s_savegame.currentLine+1) == s_savegame.saveFileCnt) ) { s_savegame.currentLine--; // yeah this is a pretty bad hack // adjust cursor position of listbox so correct item is highlighted UI_AdjustSaveGameListBox( s_savegame.currentLine ); } // ReadSaveDirectory(); //refresh s_savegame.saveFileCnt = -1; //force a refresh at drawtime } } else if (Q_stricmp(name, "savegame") == 0) { // Create a new save game char fileName[MAX_SAVELOADNAME]; CreateNextSaveName(fileName); // Save description line const char *serverInfo = sv.configstrings[CS_SERVERINFO]; const char *mapName = Info_ValueForKey( serverInfo, "mapname" ); ui.SG_StoreSaveGameComment(mapName); ui.Cmd_ExecuteText( EXEC_APPEND, va("save %s\n", fileName)); s_savegame.saveFileCnt = -1; //force a refresh the next time around } else if (Q_stricmp(name, "LoadMods") == 0) { UI_LoadMods(); } else if (Q_stricmp(name, "RunMod") == 0) { if (uiInfo.modList[uiInfo.modIndex].modName) { Cvar_Set( "fs_game", uiInfo.modList[uiInfo.modIndex].modName); extern void FS_Restart( void ); FS_Restart(); Cbuf_ExecuteText( EXEC_APPEND, "vid_restart;" ); } } else if (Q_stricmp(name, "Quit") == 0) { if (showCredits) { showCredits = false; Menus_CloseAll(); Menus_OpenByName( "credits" ); } else { Cbuf_ExecuteText( EXEC_NOW, "quit"); } } else if (Q_stricmp(name, "Controls") == 0) { Cvar_Set( "cl_paused", "1" ); trap_Key_SetCatcher( KEYCATCH_UI ); Menus_CloseAll(); Menus_ActivateByName("setup_menu2"); } else if (Q_stricmp(name, "Leave") == 0) { Cbuf_ExecuteText( EXEC_APPEND, "disconnect\n" ); trap_Key_SetCatcher( KEYCATCH_UI ); Menus_CloseAll(); //Menus_ActivateByName("mainMenu"); } else if (Q_stricmp(name, "getvideosetup") == 0) { UI_GetVideoSetup ( ); } else if (Q_stricmp(name, "updatevideosetup") == 0) { UI_UpdateVideoSetup ( ); } else if (Q_stricmp(name, "nextDataPadForcePower") == 0) { ui.Cmd_ExecuteText( EXEC_APPEND, "dpforcenext\n"); } else if (Q_stricmp(name, "prevDataPadForcePower") == 0) { ui.Cmd_ExecuteText( EXEC_APPEND, "dpforceprev\n"); } else if (Q_stricmp(name, "nextDataPadWeapon") == 0) { ui.Cmd_ExecuteText( EXEC_APPEND, "dpweapnext\n"); } else if (Q_stricmp(name, "prevDataPadWeapon") == 0) { ui.Cmd_ExecuteText( EXEC_APPEND, "dpweapprev\n"); } else if (Q_stricmp(name, "nextDataPadInventory") == 0) { ui.Cmd_ExecuteText( EXEC_APPEND, "dpinvnext\n"); } else if (Q_stricmp(name, "prevDataPadInventory") == 0) { ui.Cmd_ExecuteText( EXEC_APPEND, "dpinvprev\n"); } else if (Q_stricmp(name, "checkvid1data") == 0) // Warn user data has changed before leaving screen? { String_Parse(args, &menuName); String_Parse(args, &warningMenuName); UI_CheckVid1Data(menuName,warningMenuName); } else if (Q_stricmp(name, "startgame") == 0) { Menus_CloseAll(); #ifdef JK2_MODE ui.Cmd_ExecuteText( EXEC_APPEND, "map kejim_post\n" ); #else ui.Cmd_ExecuteText( EXEC_APPEND, "map yavin1\n"); #endif } else if (Q_stricmp(name, "startmap") == 0) { Menus_CloseAll(); String_Parse(args, &mapName); ui.Cmd_ExecuteText( EXEC_APPEND, va("maptransition %s\n",mapName)); } else if (Q_stricmp(name, "closeingame") == 0) { trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI ); trap_Key_ClearStates(); Cvar_Set( "cl_paused", "0" ); Menus_CloseAll(); if (1 == Cvar_VariableIntegerValue("ui_missionfailed")) { Menus_ActivateByName("missionfailed_menu"); ui.Key_SetCatcher( KEYCATCH_UI ); } else { Menus_ActivateByName("mainhud"); } } else if (Q_stricmp(name, "closedatapad") == 0) { trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI ); trap_Key_ClearStates(); Cvar_Set( "cl_paused", "0" ); Menus_CloseAll(); Menus_ActivateByName("mainhud"); Cvar_Set( "cg_updatedDataPadForcePower1", "0" ); Cvar_Set( "cg_updatedDataPadForcePower2", "0" ); Cvar_Set( "cg_updatedDataPadForcePower3", "0" ); Cvar_Set( "cg_updatedDataPadObjective", "0" ); } else if (Q_stricmp(name, "closesabermenu") == 0) { // if we're in the saber menu when creating a character, close this down if( !Cvar_VariableIntegerValue( "saber_menu" ) ) { Menus_CloseByName( "saberMenu" ); Menus_OpenByName( "characterMenu" ); } } else if (Q_stricmp(name, "clearmouseover") == 0) { itemDef_t *item; menuDef_t *menu = Menu_GetFocused(); if (menu) { const char *itemName; String_Parse(args, &itemName); item = (itemDef_s *) Menu_FindItemByName((menuDef_t *) menu, itemName); if (item) { item->window.flags &= ~WINDOW_MOUSEOVER; } } } else if (Q_stricmp(name, "setMovesListDefault") == 0) { uiInfo.movesTitleIndex = 2; } else if (Q_stricmp(name, "resetMovesDesc") == 0) { menuDef_t *menu = Menu_GetFocused(); itemDef_t *item; if (menu) { item = (itemDef_s *) Menu_FindItemByName(menu, "item_desc"); if (item) { listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData; if( listPtr ) { listPtr->cursorPos = 0; listPtr->startPos = 0; } item->cursorPos = 0; } } } else if (Q_stricmp(name, "resetMovesList") == 0) { menuDef_t *menu; menu = Menus_FindByName("datapadMovesMenu"); //update saber models if (menu) { itemDef_t *item; item = (itemDef_s *) Menu_FindItemByName((menuDef_t *) menu, "character"); if (item) { UI_SaberAttachToChar( item ); } } Cvar_Set( "ui_move_desc", " " ); } // else if (Q_stricmp(name, "setanisotropicmax") == 0) // { // r_ext_texture_filter_anisotropic->value; // } else if (Q_stricmp(name, "setMoveCharacter") == 0) { itemDef_t *item; menuDef_t *menu; modelDef_t *modelPtr; char skin[MAX_QPATH]; UI_GetCharacterCvars(); UI_GetSaberCvars(); uiInfo.movesTitleIndex = 0; menu = Menus_FindByName("datapadMovesMenu"); if (menu) { item = (itemDef_s *) Menu_FindItemByName((menuDef_t *) menu, "character"); if (item) { modelPtr = (modelDef_t*)item->typeData; if (modelPtr) { uiInfo.movesBaseAnim = datapadMoveTitleBaseAnims[uiInfo.movesTitleIndex]; ItemParse_model_g2anim_go( item, uiInfo.movesBaseAnim ); uiInfo.moveAnimTime = 0 ; DC->g2hilev_SetAnim(&item->ghoul2[0], "model_root", modelPtr->g2anim, qtrue); Com_sprintf( skin, sizeof( skin ), "models/players/%s/|%s|%s|%s", Cvar_VariableString ( "g_char_model"), Cvar_VariableString ( "g_char_skin_head"), Cvar_VariableString ( "g_char_skin_torso"), Cvar_VariableString ( "g_char_skin_legs") ); ItemParse_model_g2skin_go( item, skin ); UI_SaberAttachToChar( item ); } } } } else if (Q_stricmp(name, "glCustom") == 0) { Cvar_Set("ui_r_glCustom", "4"); } else if (Q_stricmp(name, "character") == 0) { UI_UpdateCharacter( qfalse ); } else if (Q_stricmp(name, "characterchanged") == 0) { UI_UpdateCharacter( qtrue ); } else if (Q_stricmp(name, "char_skin") == 0) { UI_UpdateCharacterSkin(); } else if (Q_stricmp(name, "saber_type") == 0) { UI_UpdateSaberType(); } else if (Q_stricmp(name, "saber_hilt") == 0) { UI_UpdateSaberHilt( qfalse ); } else if (Q_stricmp(name, "saber_color") == 0) { // UI_UpdateSaberColor( qfalse ); } else if (Q_stricmp(name, "saber2_hilt") == 0) { UI_UpdateSaberHilt( qtrue ); } else if (Q_stricmp(name, "saber2_color") == 0) { // UI_UpdateSaberColor( qtrue ); } else if (Q_stricmp(name, "updatecharcvars") == 0) { UI_UpdateCharacterCvars(); } else if (Q_stricmp(name, "getcharcvars") == 0) { UI_GetCharacterCvars(); } else if (Q_stricmp(name, "updatesabercvars") == 0) { UI_UpdateSaberCvars(); } else if (Q_stricmp(name, "getsabercvars") == 0) { UI_GetSaberCvars(); } else if (Q_stricmp(name, "resetsabercvardefaults") == 0) { // NOTE : ONLY do this if saber menu is set properly (ie. first time we enter this menu) if( !Cvar_VariableIntegerValue( "saber_menu" ) ) { UI_ResetSaberCvars(); } } #ifndef JK2_MODE else if (Q_stricmp(name, "updatefightingstylechoices") == 0) { UI_UpdateFightingStyleChoices(); } #endif // !JK2_MODE else if (Q_stricmp(name, "initallocforcepower") == 0) { const char *forceName; String_Parse(args, &forceName); UI_InitAllocForcePowers(forceName); } else if (Q_stricmp(name, "affectforcepowerlevel") == 0) { const char *forceName; String_Parse(args, &forceName); UI_AffectForcePowerLevel(forceName); } else if (Q_stricmp(name, "decrementcurrentforcepower") == 0) { UI_DecrementCurrentForcePower(); } else if (Q_stricmp(name, "shutdownforcehelp") == 0) { UI_ShutdownForceHelp(); } else if (Q_stricmp(name, "forcehelpactive") == 0) { UI_ForceHelpActive(); } #ifndef JK2_MODE else if (Q_stricmp(name, "demosetforcelevels") == 0) { UI_DemoSetForceLevels(); } #endif // !JK2_MODE else if (Q_stricmp(name, "recordforcelevels") == 0) { UI_RecordForceLevels(); } else if (Q_stricmp(name, "recordweapons") == 0) { UI_RecordWeapons(); } else if (Q_stricmp(name, "showforceleveldesc") == 0) { const char *forceName; String_Parse(args, &forceName); UI_ShowForceLevelDesc(forceName); } else if (Q_stricmp(name, "resetforcelevels") == 0) { UI_ResetForceLevels(); } else if (Q_stricmp(name, "weaponhelpactive") == 0) { UI_WeaponHelpActive(); } // initialize weapon selection screen else if (Q_stricmp(name, "initweaponselect") == 0) { UI_InitWeaponSelect(); } else if (Q_stricmp(name, "clearweapons") == 0) { UI_ClearWeapons(); } else if (Q_stricmp(name, "stopgamesounds") == 0) { trap_S_StopSounds(); } else if (Q_stricmp(name, "loadmissionselectmenu") == 0) { const char *cvarName; String_Parse(args, &cvarName); if (cvarName) { UI_LoadMissionSelectMenu(cvarName); } } #ifndef JK2_MODE else if (Q_stricmp(name, "calcforcestatus") == 0) { UI_CalcForceStatus(); } #endif // !JK2_MODE else if (Q_stricmp(name, "giveweapon") == 0) { const char *weaponIndex; String_Parse(args, &weaponIndex); UI_GiveWeapon(atoi(weaponIndex)); } else if (Q_stricmp(name, "equipweapon") == 0) { const char *weaponIndex; String_Parse(args, &weaponIndex); UI_EquipWeapon(atoi(weaponIndex)); } else if (Q_stricmp(name, "addweaponselection") == 0) { const char *weaponIndex; String_Parse(args, &weaponIndex); if (!weaponIndex) { return qfalse; } const char *ammoIndex; String_Parse(args, &ammoIndex); if (!ammoIndex) { return qfalse; } const char *ammoAmount; String_Parse(args, &ammoAmount); if (!ammoAmount) { return qfalse; } const char *itemName; String_Parse(args, &itemName); if (!itemName) { return qfalse; } const char *litItemName; String_Parse(args, &litItemName); if (!litItemName) { return qfalse; } const char *backgroundName; String_Parse(args, &backgroundName); if (!backgroundName) { return qfalse; } const char *soundfile = NULL; String_Parse(args, &soundfile); UI_AddWeaponSelection(atoi(weaponIndex),atoi(ammoIndex),atoi(ammoAmount),itemName,litItemName, backgroundName, soundfile); } else if (Q_stricmp(name, "addthrowweaponselection") == 0) { const char *weaponIndex; String_Parse(args, &weaponIndex); if (!weaponIndex) { return qfalse; } const char *ammoIndex; String_Parse(args, &ammoIndex); if (!ammoIndex) { return qfalse; } const char *ammoAmount; String_Parse(args, &ammoAmount); if (!ammoAmount) { return qfalse; } const char *itemName; String_Parse(args, &itemName); if (!itemName) { return qfalse; } const char *litItemName; String_Parse(args, &litItemName); if (!litItemName) { return qfalse; } const char *backgroundName; String_Parse(args, &backgroundName); if (!backgroundName) { return qfalse; } const char *soundfile; String_Parse(args, &soundfile); UI_AddThrowWeaponSelection(atoi(weaponIndex),atoi(ammoIndex),atoi(ammoAmount),itemName,litItemName,backgroundName, soundfile); } else if (Q_stricmp(name, "removeweaponselection") == 0) { const char *weaponIndex; String_Parse(args, &weaponIndex); if (weaponIndex) { UI_RemoveWeaponSelection(atoi(weaponIndex)); } } else if (Q_stricmp(name, "removethrowweaponselection") == 0) { UI_RemoveThrowWeaponSelection(); } else if (Q_stricmp(name, "normalthrowselection") == 0) { UI_NormalThrowSelection(); } else if (Q_stricmp(name, "highlightthrowselection") == 0) { UI_HighLightThrowSelection(); } else if (Q_stricmp(name, "normalweaponselection") == 0) { const char *slotIndex; String_Parse(args, &slotIndex); if (!slotIndex) { return qfalse; } UI_NormalWeaponSelection(atoi(slotIndex)); } else if (Q_stricmp(name, "highlightweaponselection") == 0) { const char *slotIndex; String_Parse(args, &slotIndex); if (!slotIndex) { return qfalse; } UI_HighLightWeaponSelection(atoi(slotIndex)); } else if (Q_stricmp(name, "clearinventory") == 0) { UI_ClearInventory(); } else if (Q_stricmp(name, "giveinventory") == 0) { const char *inventoryIndex,*amount; String_Parse(args, &inventoryIndex); String_Parse(args, &amount); UI_GiveInventory(atoi(inventoryIndex),atoi(amount)); } #ifndef JK2_MODE else if (Q_stricmp(name, "updatefightingstyle") == 0) { UI_UpdateFightingStyle(); } #endif // !JK2_MODE else if (Q_stricmp(name, "update") == 0) { if (String_Parse(args, &name2)) { UI_Update(name2); } else { Com_Printf("update missing cmd\n"); } } else if (Q_stricmp(name, "load_quick") == 0) { #ifdef JK2_MODE ui.Cmd_ExecuteText(EXEC_APPEND,"load quik\n"); #else ui.Cmd_ExecuteText(EXEC_APPEND,"load quick\n"); #endif } else if (Q_stricmp(name, "load_auto") == 0) { ui.Cmd_ExecuteText(EXEC_APPEND,"load *respawn\n"); //death menu, might load a saved game instead if they just loaded on this map } else if (Q_stricmp(name, "decrementforcepowerlevel") == 0) { UI_DecrementForcePowerLevel(); } else if (Q_stricmp(name, "getmousepitch") == 0) { Cvar_Set("ui_mousePitch", (trap_Cvar_VariableValue("m_pitch") >= 0) ? "0" : "1"); } else if (Q_stricmp(name, "resetcharacterlistboxes") == 0) { UI_ResetCharacterListBoxes(); } else if ( Q_stricmp( name, "LaunchMP" ) == 0 ) { // TODO for MAC_PORT, will only be valid for non-JK2 mode } else { Com_Printf("unknown UI script %s\n", name); } } return qtrue; } /* ================= UI_GetValue ================= */ static float UI_GetValue(int ownerDraw) { return 0; } //Force Warnings enum { FW_VERY_LIGHT = 0, FW_SEMI_LIGHT, FW_NEUTRAL, FW_SEMI_DARK, FW_VERY_DARK }; const char *lukeForceStatusSounds[] = { "sound/chars/luke/misc/MLUK_03.mp3", // Very Light "sound/chars/luke/misc/MLUK_04.mp3", // Semi Light "sound/chars/luke/misc/MLUK_05.mp3", // Neutral "sound/chars/luke/misc/MLUK_01.mp3", // Semi dark "sound/chars/luke/misc/MLUK_02.mp3", // Very dark }; const char *kyleForceStatusSounds[] = { "sound/chars/kyle/misc/MKYK_05.mp3", // Very Light "sound/chars/kyle/misc/MKYK_04.mp3", // Semi Light "sound/chars/kyle/misc/MKYK_03.mp3", // Neutral "sound/chars/kyle/misc/MKYK_01.mp3", // Semi dark "sound/chars/kyle/misc/MKYK_02.mp3", // Very dark }; #ifndef JK2_MODE static void UI_CalcForceStatus(void) { float lightSide,darkSide,total; short who, index=FW_VERY_LIGHT; qboolean lukeFlag=qtrue; float percent; client_t* cl = &svs.clients[0]; // 0 because only ever us as a player char value[256]; if (!cl) { return; } playerState_t* pState = cl->gentity->client; if (!cl->gentity || !cl->gentity->client) { return; } memset(value, 0, sizeof(value)); lightSide = pState->forcePowerLevel[FP_HEAL] + pState->forcePowerLevel[FP_TELEPATHY] + pState->forcePowerLevel[FP_PROTECT] + pState->forcePowerLevel[FP_ABSORB]; darkSide = pState->forcePowerLevel[FP_GRIP] + pState->forcePowerLevel[FP_LIGHTNING] + pState->forcePowerLevel[FP_RAGE] + pState->forcePowerLevel[FP_DRAIN]; total = lightSide + darkSide; percent = lightSide / total; who = Q_irand( 0, 100 ); if (percent >= 0.90f) // 90 - 100% { index = FW_VERY_LIGHT; if (who <50) { strcpy(value,"vlk"); // Very light Kyle lukeFlag = qfalse; } else { strcpy(value,"vll"); // Very light Luke } } else if (percent > 0.60f ) { index = FW_SEMI_LIGHT; if ( who<50 ) { strcpy(value,"slk"); // Semi-light Kyle lukeFlag = qfalse; } else { strcpy(value,"sll"); // Semi-light light Luke } } else if (percent > 0.40f ) { index = FW_NEUTRAL; if ( who<50 ) { strcpy(value,"ntk"); // Neutral Kyle lukeFlag = qfalse; } else { strcpy(value,"ntl"); // Netural Luke } } else if (percent > 0.10f ) { index = FW_SEMI_DARK; if ( who<50 ) { strcpy(value,"sdk"); // Semi-dark Kyle lukeFlag = qfalse; } else { strcpy(value,"sdl"); // Semi-Dark Luke } } else { index = FW_VERY_DARK; if ( who<50 ) { strcpy(value,"vdk"); // Very dark Kyle lukeFlag = qfalse; } else { strcpy(value,"vdl"); // Very Dark Luke } } Cvar_Set("ui_forcestatus", value ); if (lukeFlag) { DC->startLocalSound(DC->registerSound(lukeForceStatusSounds[index], qfalse), CHAN_VOICE ); } else { DC->startLocalSound(DC->registerSound(kyleForceStatusSounds[index], qfalse), CHAN_VOICE ); } } #endif // !JK2_MODE /* ================= UI_StopCinematic ================= */ static void UI_StopCinematic(int handle) { if (handle >= 0) { trap_CIN_StopCinematic(handle); } else { handle = abs(handle); if (handle == UI_MAPCINEMATIC) { // FIXME - BOB do we need this? // if (uiInfo.mapList[ui_currentMap.integer].cinematic >= 0) // { // trap_CIN_StopCinematic(uiInfo.mapList[ui_currentMap.integer].cinematic); // uiInfo.mapList[ui_currentMap.integer].cinematic = -1; // } } else if (handle == UI_NETMAPCINEMATIC) { // FIXME - BOB do we need this? // if (uiInfo.serverStatus.currentServerCinematic >= 0) // { // trap_CIN_StopCinematic(uiInfo.serverStatus.currentServerCinematic); // uiInfo.serverStatus.currentServerCinematic = -1; // } } else if (handle == UI_CLANCINEMATIC) { // FIXME - BOB do we need this? // int i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_teamName")); // if (i >= 0 && i < uiInfo.teamCount) // { // if (uiInfo.teamList[i].cinematic >= 0) // { // trap_CIN_StopCinematic(uiInfo.teamList[i].cinematic); // uiInfo.teamList[i].cinematic = -1; // } // } } } } static void UI_HandleLoadSelection() { Cvar_Set("ui_SelectionOK", va("%d",(s_savegame.currentLine < s_savegame.saveFileCnt)) ); if (s_savegame.currentLine >= s_savegame.saveFileCnt) return; #ifdef JK2_MODE Cvar_Set("ui_gameDesc", s_savedata[s_savegame.currentLine].currentSaveFileComments ); // set comment if (!ui.SG_GetSaveImage(s_savedata[s_savegame.currentLine].currentSaveFileName, &screenShotBuf)) { memset( screenShotBuf,0,(SG_SCR_WIDTH * SG_SCR_HEIGHT * 4)); } #endif } /* ================= UI_FeederCount ================= */ static int UI_FeederCount(float feederID) { if (feederID == FEEDER_SAVEGAMES ) { if (s_savegame.saveFileCnt == -1) { ReadSaveDirectory(); //refresh UI_HandleLoadSelection(); #ifndef JK2_MODE UI_AdjustSaveGameListBox(s_savegame.currentLine); #endif } return s_savegame.saveFileCnt; } // count number of moves for the current title else if (feederID == FEEDER_MOVES) { int count=0,i; for (i=0;itypeData; if (modelPtr) { if (datapadMoveData[uiInfo.movesTitleIndex][index].anim) { ItemParse_model_g2anim_go( item, datapadMoveData[uiInfo.movesTitleIndex][index].anim ); uiInfo.moveAnimTime = DC->g2hilev_SetAnim(&item->ghoul2[0], "model_root", modelPtr->g2anim, qtrue); uiInfo.moveAnimTime += uiInfo.uiDC.realTime; // Play sound for anim if (datapadMoveData[uiInfo.movesTitleIndex][index].sound == MDS_FORCE_JUMP) { DC->startLocalSound(uiInfo.uiDC.Assets.datapadmoveJumpSound, CHAN_LOCAL ); } else if (datapadMoveData[uiInfo.movesTitleIndex][index].sound == MDS_ROLL) { DC->startLocalSound(uiInfo.uiDC.Assets.datapadmoveRollSound, CHAN_LOCAL ); } else if (datapadMoveData[uiInfo.movesTitleIndex][index].sound == MDS_SABER) { // Randomly choose one sound int soundI = Q_irand( 1, 6 ); sfxHandle_t *soundPtr; soundPtr = &uiInfo.uiDC.Assets.datapadmoveSaberSound1; if (soundI == 2) { soundPtr = &uiInfo.uiDC.Assets.datapadmoveSaberSound2; } else if (soundI == 3) { soundPtr = &uiInfo.uiDC.Assets.datapadmoveSaberSound3; } else if (soundI == 4) { soundPtr = &uiInfo.uiDC.Assets.datapadmoveSaberSound4; } else if (soundI == 5) { soundPtr = &uiInfo.uiDC.Assets.datapadmoveSaberSound5; } else if (soundI == 6) { soundPtr = &uiInfo.uiDC.Assets.datapadmoveSaberSound6; } DC->startLocalSound(*soundPtr, CHAN_LOCAL ); } if (datapadMoveData[uiInfo.movesTitleIndex][index].desc) { Cvar_Set( "ui_move_desc", datapadMoveData[uiInfo.movesTitleIndex][index].desc); } Com_sprintf( skin, sizeof( skin ), "models/players/%s/|%s|%s|%s", Cvar_VariableString ( "g_char_model"), Cvar_VariableString ( "g_char_skin_head"), Cvar_VariableString ( "g_char_skin_torso"), Cvar_VariableString ( "g_char_skin_legs") ); ItemParse_model_g2skin_go( item, skin ); } } } } } else if (feederID == FEEDER_MOVES_TITLES) { itemDef_t *item; menuDef_t *menu; modelDef_t *modelPtr; uiInfo.movesTitleIndex = index; uiInfo.movesBaseAnim = datapadMoveTitleBaseAnims[uiInfo.movesTitleIndex]; menu = Menus_FindByName("datapadMovesMenu"); if (menu) { item = (itemDef_s *) Menu_FindItemByName((menuDef_t *) menu, "character"); if (item) { modelPtr = (modelDef_t*)item->typeData; if (modelPtr) { ItemParse_model_g2anim_go( item, uiInfo.movesBaseAnim ); uiInfo.moveAnimTime = DC->g2hilev_SetAnim(&item->ghoul2[0], "model_root", modelPtr->g2anim, qtrue); } } } } else if (feederID == FEEDER_MODS) { uiInfo.modIndex = index; } else if (feederID == FEEDER_PLAYER_SPECIES) { if (index >= 0 && index < uiInfo.playerSpeciesCount) { uiInfo.playerSpeciesIndex = index; } } else if (feederID == FEEDER_LANGUAGES) { uiInfo.languageCountIndex = index; } else if (feederID == FEEDER_PLAYER_SKIN_HEAD) { if (index >= 0 && index < uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinHeadCount) { Cvar_Set("ui_char_skin_head", uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinHead[index].name); } } else if (feederID == FEEDER_PLAYER_SKIN_TORSO) { if (index >= 0 && index < uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinTorsoCount) { Cvar_Set("ui_char_skin_torso", uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinTorso[index].name); } } else if (feederID == FEEDER_PLAYER_SKIN_LEGS) { if (index >= 0 && index < uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinLegCount) { Cvar_Set("ui_char_skin_legs", uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].SkinLeg[index].name); } } else if (feederID == FEEDER_COLORCHOICES) { extern void Item_RunScript(itemDef_t *item, const char *s); //from ui_shared; if (index >= 0 && index < uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].ColorCount) { Item_RunScript(item, uiInfo.playerSpecies[uiInfo.playerSpeciesIndex].Color[index].actionText); } } /* else if (feederID == FEEDER_CINEMATICS) { uiInfo.movieIndex = index; if (uiInfo.previewMovie >= 0) { trap_CIN_StopCinematic(uiInfo.previewMovie); } uiInfo.previewMovie = -1; } else if (feederID == FEEDER_DEMOS) { uiInfo.demoIndex = index; } */ } void Key_KeynumToStringBuf( int keynum, char *buf, int buflen ); void Key_GetBindingBuf( int keynum, char *buf, int buflen ); static qboolean UI_Crosshair_HandleKey(int flags, float *special, int key) { if (key == A_MOUSE1 || key == A_MOUSE2 || key == A_ENTER || key == A_KP_ENTER) { if (key == A_MOUSE2) { uiInfo.currentCrosshair--; } else { uiInfo.currentCrosshair++; } if (uiInfo.currentCrosshair >= NUM_CROSSHAIRS) { uiInfo.currentCrosshair = 0; } else if (uiInfo.currentCrosshair < 0) { uiInfo.currentCrosshair = NUM_CROSSHAIRS - 1; } Cvar_Set("cg_drawCrosshair", va("%d", uiInfo.currentCrosshair)); return qtrue; } return qfalse; } static qboolean UI_OwnerDrawHandleKey(int ownerDraw, int flags, float *special, int key) { switch (ownerDraw) { case UI_CROSSHAIR: UI_Crosshair_HandleKey(flags, special, key); break; default: break; } return qfalse; } //unfortunately we cannot rely on any game/cgame module code to do our animation stuff, //because the ui can be loaded while the game/cgame are not loaded. So we're going to recreate what we need here. #undef MAX_ANIM_FILES #define MAX_ANIM_FILES 4 class ui_animFileSet_t { public: char filename[MAX_QPATH]; animation_t animations[MAX_ANIMATIONS]; }; // ui_animFileSet_t static ui_animFileSet_t ui_knownAnimFileSets[MAX_ANIM_FILES]; int ui_numKnownAnimFileSets; qboolean UI_ParseAnimationFile( const char *af_filename ) { const char *text_p; int len; int i; const char *token; float fps; char text[80000]; int animNum; animation_t *animations = ui_knownAnimFileSets[ui_numKnownAnimFileSets].animations; len = re.GetAnimationCFG(af_filename, text, sizeof(text)); if ( len <= 0 ) { return qfalse; } if ( len >= (int)(sizeof( text ) - 1) ) { Com_Error( ERR_FATAL, "UI_ParseAnimationFile: File %s too long\n (%d > %d)", af_filename, len, sizeof( text ) - 1); return qfalse; } // parse the text text_p = text; //FIXME: have some way of playing anims backwards... negative numFrames? //initialize anim array so that from 0 to MAX_ANIMATIONS, set default values of 0 1 0 100 for(i = 0; i < MAX_ANIMATIONS; i++) { animations[i].firstFrame = 0; animations[i].numFrames = 0; animations[i].loopFrames = -1; animations[i].frameLerp = 100; // animations[i].initialLerp = 100; } // read information for each frame COM_BeginParseSession(); while(1) { token = COM_Parse( &text_p ); if ( !token || !token[0]) { break; } animNum = GetIDForString(animTable, token); if(animNum == -1) { //#ifndef FINAL_BUILD #ifdef _DEBUG if (strcmp(token,"ROOT")) { Com_Printf(S_COLOR_RED"WARNING: Unknown token %s in %s\n", token, af_filename); } #endif while (token[0]) { token = COM_ParseExt( &text_p, qfalse ); //returns empty string when next token is EOL } continue; } token = COM_Parse( &text_p ); if ( !token ) { break; } animations[animNum].firstFrame = atoi( token ); token = COM_Parse( &text_p ); if ( !token ) { break; } animations[animNum].numFrames = atoi( token ); token = COM_Parse( &text_p ); if ( !token ) { break; } animations[animNum].loopFrames = atoi( token ); token = COM_Parse( &text_p ); if ( !token ) { break; } fps = atof( token ); if ( fps == 0 ) { fps = 1;//Don't allow divide by zero error } if ( fps < 0 ) {//backwards animations[animNum].frameLerp = floor(1000.0f / fps); } else { animations[animNum].frameLerp = ceil(1000.0f / fps); } // animations[animNum].initialLerp = ceil(1000.0f / fabs(fps)); } COM_EndParseSession(); return qtrue; } qboolean UI_ParseAnimFileSet( const char *animCFG, int *animFileIndex ) { //Not going to bother parsing the sound config here. char afilename[MAX_QPATH]; char strippedName[MAX_QPATH]; int i; char *slash; Q_strncpyz( strippedName, animCFG, sizeof(strippedName)); slash = strrchr( strippedName, '/' ); if ( slash ) { // truncate modelName to find just the dir not the extension *slash = 0; } //if this anims file was loaded before, don't parse it again, just point to the correct table of info for ( i = 0; i < ui_numKnownAnimFileSets; i++ ) { if ( Q_stricmp(ui_knownAnimFileSets[i].filename, strippedName ) == 0 ) { *animFileIndex = i; return qtrue; } } if ( ui_numKnownAnimFileSets == MAX_ANIM_FILES ) {//TOO MANY! for (i = 0; i < MAX_ANIM_FILES; i++) { Com_Printf("animfile[%d]: %s\n", i, ui_knownAnimFileSets[i].filename); } Com_Error( ERR_FATAL, "UI_ParseAnimFileSet: %d == MAX_ANIM_FILES == %d", ui_numKnownAnimFileSets, MAX_ANIM_FILES); } //Okay, time to parse in a new one Q_strncpyz( ui_knownAnimFileSets[ui_numKnownAnimFileSets].filename, strippedName, sizeof( ui_knownAnimFileSets[ui_numKnownAnimFileSets].filename ) ); // Load and parse animations.cfg file Com_sprintf( afilename, sizeof( afilename ), "%s/animation.cfg", strippedName ); if ( !UI_ParseAnimationFile( afilename ) ) { *animFileIndex = -1; return qfalse; } //set index and increment *animFileIndex = ui_numKnownAnimFileSets++; return qtrue; } int UI_G2SetAnim(CGhoul2Info *ghlInfo, const char *boneName, int animNum, const qboolean freeze) { int animIndex,blendTime; char *GLAName; GLAName = re.G2API_GetGLAName(ghlInfo); if (!GLAName || !GLAName[0]) { return 0; } UI_ParseAnimFileSet(GLAName, &animIndex); if (animIndex != -1) { animation_t *anim = &ui_knownAnimFileSets[animIndex].animations[animNum]; if (anim->numFrames <= 0) { return 0; } int sFrame = anim->firstFrame; int eFrame = anim->firstFrame + anim->numFrames; int flags = BONE_ANIM_OVERRIDE; int time = uiInfo.uiDC.realTime; float animSpeed = (50.0f / anim->frameLerp); blendTime = 150; // Freeze anim if it's not looping, special hack for datapad moves menu if (freeze) { if (anim->loopFrames == -1) { flags = BONE_ANIM_OVERRIDE_FREEZE; } else { flags = BONE_ANIM_OVERRIDE_LOOP; } } else if (anim->loopFrames != -1) { flags = BONE_ANIM_OVERRIDE_LOOP; } flags |= BONE_ANIM_BLEND; blendTime = 150; re.G2API_SetBoneAnim(ghlInfo, boneName, sFrame, eFrame, flags, animSpeed, time, -1, blendTime); return ((anim->frameLerp * (anim->numFrames-2))); } return 0; } static qboolean UI_ParseColorData(char* buf, playerSpeciesInfo_t &species) { const char *token; const char *p; p = buf; COM_BeginParseSession(); species.ColorCount = 0; species.ColorMax = 16; species.Color = (playerColor_t *)malloc(species.ColorMax * sizeof(playerColor_t)); while ( p ) { token = COM_ParseExt( &p, qtrue ); //looking for the shader if ( token[0] == 0 ) { COM_EndParseSession( ); return (qboolean)(species.ColorCount != 0); } if (species.ColorCount >= species.ColorMax) { species.ColorMax *= 2; species.Color = (playerColor_t *)realloc(species.Color, species.ColorMax * sizeof(playerColor_t)); } memset(&species.Color[species.ColorCount], 0, sizeof(playerColor_t)); Q_strncpyz( species.Color[species.ColorCount].shader, token, MAX_QPATH ); token = COM_ParseExt( &p, qtrue ); //looking for action block { if ( token[0] != '{' ) { COM_EndParseSession( ); return qfalse; } token = COM_ParseExt( &p, qtrue ); //looking for action commands while (token[0] != '}') { if ( token[0] == 0) { //EOF COM_EndParseSession( ); return qfalse; } Q_strcat(species.Color[species.ColorCount].actionText, ACTION_BUFFER_SIZE, token); Q_strcat(species.Color[species.ColorCount].actionText, ACTION_BUFFER_SIZE, " "); token = COM_ParseExt( &p, qtrue ); //looking for action commands or final } } species.ColorCount++; //next color please } COM_EndParseSession( ); return qtrue;//never get here } /* ================= bIsImageFile builds path and scans for valid image extentions ================= */ static qboolean IsImageFile(const char* dirptr, const char* skinname, qboolean building) { char fpath[MAX_QPATH]; int f; Com_sprintf(fpath, MAX_QPATH, "models/players/%s/icon_%s.jpg", dirptr, skinname); ui.FS_FOpenFile(fpath, &f, FS_READ); if (!f) { //not there, try png Com_sprintf(fpath, MAX_QPATH, "models/players/%s/icon_%s.png", dirptr, skinname); ui.FS_FOpenFile(fpath, &f, FS_READ); } if (!f) { //not there, try tga Com_sprintf(fpath, MAX_QPATH, "models/players/%s/icon_%s.tga", dirptr, skinname); ui.FS_FOpenFile(fpath, &f, FS_READ); } if (f) { ui.FS_FCloseFile(f); if ( building ) ui.R_RegisterShaderNoMip(fpath); return qtrue; } return qfalse; } static void UI_FreeSpecies( playerSpeciesInfo_t *species ) { free(species->SkinHead); free(species->SkinTorso); free(species->SkinLeg); free(species->Color); memset(species, 0, sizeof(playerSpeciesInfo_t)); } void UI_FreeAllSpecies( void ) { int i; for (i = 0; i < uiInfo.playerSpeciesCount; i++) { UI_FreeSpecies(&uiInfo.playerSpecies[i]); } free(uiInfo.playerSpecies); uiInfo.playerSpeciesCount = 0; uiInfo.playerSpecies = NULL; } /* ================= PlayerModel_BuildList ================= */ static void UI_BuildPlayerModel_List( qboolean inGameLoad ) { static const size_t DIR_LIST_SIZE = 16384; int numdirs; size_t dirListSize = DIR_LIST_SIZE; char stackDirList[8192]; char *dirlist; char* dirptr; int dirlen; int i; const int building = Cvar_VariableIntegerValue("com_buildscript"); dirlist = (char *)malloc(DIR_LIST_SIZE); if ( !dirlist ) { Com_Printf(S_COLOR_YELLOW "WARNING: Failed to allocate %u bytes of memory for player model " "directory list. Using stack allocated buffer of %u bytes instead.", DIR_LIST_SIZE, sizeof(stackDirList)); dirlist = stackDirList; dirListSize = sizeof(stackDirList); } uiInfo.playerSpeciesCount = 0; uiInfo.playerSpeciesIndex = 0; uiInfo.playerSpeciesMax = 8; uiInfo.playerSpecies = (playerSpeciesInfo_t *)malloc(uiInfo.playerSpeciesMax * sizeof(playerSpeciesInfo_t)); // iterate directory of all player models numdirs = ui.FS_GetFileList("models/players", "/", dirlist, dirListSize ); dirptr = dirlist; for (i=0; i buffer(filelen + 1); ui.FS_Read(&buffer[0], filelen, f); ui.FS_FCloseFile(f); buffer[filelen] = 0; //record this species if (uiInfo.playerSpeciesCount >= uiInfo.playerSpeciesMax) { uiInfo.playerSpeciesMax *= 2; uiInfo.playerSpecies = (playerSpeciesInfo_t *)realloc(uiInfo.playerSpecies, uiInfo.playerSpeciesMax*sizeof(playerSpeciesInfo_t)); } species = &uiInfo.playerSpecies[uiInfo.playerSpeciesCount]; memset(species, 0, sizeof(playerSpeciesInfo_t)); Q_strncpyz( species->Name, dirptr, MAX_QPATH ); if (!UI_ParseColorData(buffer.data(),*species)) { ui.Printf( "UI_BuildPlayerModel_List: Errors parsing '%s'\n", fpath ); } species->SkinHeadMax = 8; species->SkinTorsoMax = 8; species->SkinLegMax = 8; species->SkinHead = (skinName_t *)malloc(species->SkinHeadMax * sizeof(skinName_t)); species->SkinTorso = (skinName_t *)malloc(species->SkinTorsoMax * sizeof(skinName_t)); species->SkinLeg = (skinName_t *)malloc(species->SkinLegMax * sizeof(skinName_t)); int j; char skinname[64]; int numfiles; int iSkinParts=0; numfiles = ui.FS_GetFileList( va("models/players/%s",dirptr), ".skin", filelist, sizeof(filelist) ); fileptr = filelist; for (j=0; jSkinHeadCount >= species->SkinHeadMax) { species->SkinHeadMax *= 2; species->SkinHead = (skinName_t *)realloc(species->SkinHead, species->SkinHeadMax*sizeof(skinName_t)); } Q_strncpyz(species->SkinHead[species->SkinHeadCount++].name, skinname, SKIN_LENGTH); iSkinParts |= 1<<0; } else if (Q_stricmpn(skinname,"torso_",6) == 0) { if (species->SkinTorsoCount >= species->SkinTorsoMax) { species->SkinTorsoMax *= 2; species->SkinTorso = (skinName_t *)realloc(species->SkinTorso, species->SkinTorsoMax*sizeof(skinName_t)); } Q_strncpyz(species->SkinTorso[species->SkinTorsoCount++].name, skinname, SKIN_LENGTH); iSkinParts |= 1<<1; } else if (Q_stricmpn(skinname,"lower_",6) == 0) { if (species->SkinLegCount >= species->SkinLegMax) { species->SkinLegMax *= 2; species->SkinLeg = (skinName_t *)realloc(species->SkinLeg, species->SkinLegMax*sizeof(skinName_t)); } Q_strncpyz(species->SkinLeg[species->SkinLegCount++].name, skinname, SKIN_LENGTH); iSkinParts |= 1<<2; } } } if (iSkinParts != 7) { //didn't get a skin for each, then skip this model. UI_FreeSpecies(species); continue; } uiInfo.playerSpeciesCount++; if (!inGameLoad && ui_PrecacheModels.integer) { CGhoul2Info_v ghoul2; Com_sprintf( fpath, sizeof( fpath ), "models/players/%s/model.glm", dirptr ); int g2Model = DC->g2_InitGhoul2Model(ghoul2, fpath, 0, 0, 0, 0, 0); if (g2Model >= 0) { DC->g2_RemoveGhoul2Model( ghoul2, 0 ); } } } } if ( dirlist != stackDirList ) { free(dirlist); } } /* ================ UI_Shutdown ================= */ void UI_Shutdown( void ) { UI_FreeAllSpecies(); } /* ================= UI_Init ================= */ void _UI_Init( qboolean inGameLoad ) { // Get the list of possible languages #ifndef JK2_MODE uiInfo.languageCount = SE_GetNumLanguages(); // this does a dir scan, so use carefully #else // sod it, parse every menu strip file until we find a gap in the sequence... // for (int i=0; i<10; i++) { if (!ui.SP_Register(va("menus%d",i), /*SP_REGISTER_REQUIRED|*/SP_REGISTER_MENU)) break; } //Our special VR locale file - tanks to @MuadDib! ui.SP_Register("menus_vr", /*SP_REGISTER_REQUIRED|*/SP_REGISTER_MENU); #endif uiInfo.inGameLoad = inGameLoad; UI_RegisterCvars(); UI_InitMemory(); // cache redundant calulations trap_GetGlconfig( &uiInfo.uiDC.glconfig ); // for 640x480 virtualized screen uiInfo.uiDC.yscale = uiInfo.uiDC.glconfig.vidHeight * (1.0/480.0); uiInfo.uiDC.xscale = uiInfo.uiDC.glconfig.vidWidth * (1.0/640.0); if ( uiInfo.uiDC.glconfig.vidWidth * 480 > uiInfo.uiDC.glconfig.vidHeight * 640 ) { // wide screen uiInfo.uiDC.bias = 0.5 * ( uiInfo.uiDC.glconfig.vidWidth - ( uiInfo.uiDC.glconfig.vidHeight * (640.0/480.0) ) ); } else { // no wide screen uiInfo.uiDC.bias = 0; } Init_Display(&uiInfo.uiDC); uiInfo.uiDC.drawText = &Text_Paint; uiInfo.uiDC.drawHandlePic = &UI_DrawHandlePic; uiInfo.uiDC.drawRect = &_UI_DrawRect; uiInfo.uiDC.drawSides = &_UI_DrawSides; uiInfo.uiDC.drawTextWithCursor = &Text_PaintWithCursor; uiInfo.uiDC.executeText = &Cbuf_ExecuteText; uiInfo.uiDC.drawTopBottom = &_UI_DrawTopBottom; uiInfo.uiDC.feederCount = &UI_FeederCount; uiInfo.uiDC.feederSelection = &UI_FeederSelection; uiInfo.uiDC.fillRect = &UI_FillRect; uiInfo.uiDC.getBindingBuf = &Key_GetBindingBuf; uiInfo.uiDC.getCVarString = Cvar_VariableStringBuffer; uiInfo.uiDC.getCVarValue = trap_Cvar_VariableValue; uiInfo.uiDC.getOverstrikeMode = &trap_Key_GetOverstrikeMode; uiInfo.uiDC.getValue = &UI_GetValue; uiInfo.uiDC.keynumToStringBuf = &Key_KeynumToStringBuf; uiInfo.uiDC.modelBounds = &trap_R_ModelBounds; uiInfo.uiDC.ownerDrawVisible = &UI_OwnerDrawVisible; uiInfo.uiDC.ownerDrawWidth = &UI_OwnerDrawWidth; uiInfo.uiDC.ownerDrawItem = &UI_OwnerDraw; uiInfo.uiDC.Print = &Com_Printf; uiInfo.uiDC.registerSound = &trap_S_RegisterSound; uiInfo.uiDC.registerModel = ui.R_RegisterModel; uiInfo.uiDC.clearScene = &trap_R_ClearScene; uiInfo.uiDC.addRefEntityToScene = &trap_R_AddRefEntityToScene; uiInfo.uiDC.renderScene = &trap_R_RenderScene; uiInfo.uiDC.runScript = &UI_RunMenuScript; uiInfo.uiDC.deferScript = &UI_DeferMenuScript; uiInfo.uiDC.setBinding = &trap_Key_SetBinding; uiInfo.uiDC.setColor = &UI_SetColor; uiInfo.uiDC.setCVar = Cvar_Set; uiInfo.uiDC.setOverstrikeMode = &trap_Key_SetOverstrikeMode; uiInfo.uiDC.startLocalSound = &trap_S_StartLocalSound; uiInfo.uiDC.stopCinematic = &UI_StopCinematic; uiInfo.uiDC.textHeight = &Text_Height; uiInfo.uiDC.textWidth = &Text_Width; uiInfo.uiDC.feederItemImage = &UI_FeederItemImage; uiInfo.uiDC.feederItemText = &UI_FeederItemText; uiInfo.uiDC.ownerDrawHandleKey = &UI_OwnerDrawHandleKey; uiInfo.uiDC.registerSkin = re.RegisterSkin; uiInfo.uiDC.g2_SetSkin = re.G2API_SetSkin; uiInfo.uiDC.g2_SetBoneAnim = re.G2API_SetBoneAnim; uiInfo.uiDC.g2_RemoveGhoul2Model = re.G2API_RemoveGhoul2Model; uiInfo.uiDC.g2_InitGhoul2Model = re.G2API_InitGhoul2Model; uiInfo.uiDC.g2_CleanGhoul2Models = re.G2API_CleanGhoul2Models; uiInfo.uiDC.g2_AddBolt = re.G2API_AddBolt; uiInfo.uiDC.g2_GetBoltMatrix = re.G2API_GetBoltMatrix; uiInfo.uiDC.g2_GiveMeVectorFromMatrix = re.G2API_GiveMeVectorFromMatrix; uiInfo.uiDC.g2hilev_SetAnim = UI_G2SetAnim; UI_BuildPlayerModel_List(inGameLoad); String_Init(); const char *menuSet = UI_Cvar_VariableString("ui_menuFiles"); if (menuSet == NULL || menuSet[0] == '\0') { menuSet = "ui/menus.txt"; } #ifndef JK2_MODE if (inGameLoad) { UI_LoadMenus("ui/ingame.txt", qtrue); } else #endif { UI_LoadMenus(menuSet, qtrue); } Menus_CloseAll(); uiInfo.uiDC.whiteShader = ui.R_RegisterShaderNoMip( "white" ); AssetCache(); uis.debugMode = qfalse; // sets defaults for ui temp cvars uiInfo.effectsColor = (int)trap_Cvar_VariableValue("color")-1; if (uiInfo.effectsColor < 0) { uiInfo.effectsColor = 0; } uiInfo.effectsColor = gamecodetoui[uiInfo.effectsColor]; uiInfo.currentCrosshair = (int)trap_Cvar_VariableValue("cg_drawCrosshair"); Cvar_Set("ui_mousePitch", (trap_Cvar_VariableValue("m_pitch") >= 0) ? "0" : "1"); Cvar_Set("cg_endcredits", "0"); // Reset value Cvar_Set("ui_missionfailed","0"); // reset uiInfo.forcePowerUpdated = FP_UPDATED_NONE; uiInfo.selectedWeapon1 = NOWEAPON; uiInfo.selectedWeapon2 = NOWEAPON; uiInfo.selectedThrowWeapon = NOWEAPON; uiInfo.uiDC.Assets.nullSound = trap_S_RegisterSound("sound/null", qfalse); #ifndef JK2_MODE //FIXME hack to prevent error in jk2 by disabling trap_S_RegisterSound("sound/interface/weapon_deselect", qfalse); #endif } /* ================= UI_RegisterCvars ================= */ static void UI_RegisterCvars( void ) { size_t i = 0; const cvarTable_t *cv = NULL; for ( i=0, cv=cvarTable; ivmCvar, cv->cvarName, cv->defaultString, cv->cvarFlags ); if ( cv->update ) cv->update(); } } /* ================= UI_ParseMenu ================= */ void UI_ParseMenu(const char *menuFile) { char *buffer,*holdBuffer,*token2; int len; // pc_token_t token; //Com_DPrintf("Parsing menu file: %s\n", menuFile); len = PC_StartParseSession(menuFile,&buffer); holdBuffer = buffer; if (len<=0) { Com_Printf("UI_ParseMenu: Unable to load menu %s\n", menuFile); return; } while ( 1 ) { token2 = PC_ParseExt(); if (!*token2) { break; } /* if ( menuCount == MAX_MENUS ) { PC_ParseWarning("Too many menus!"); break; } */ if ( *token2 == '{') { continue; } else if ( *token2 == '}' ) { break; } else if (Q_stricmp(token2, "assetGlobalDef") == 0) { if (Asset_Parse(&holdBuffer)) { continue; } else { break; } } else if (Q_stricmp(token2, "menudef") == 0) { // start a new menu Menu_New(holdBuffer); continue; } PC_ParseWarning(va("Invalid keyword '%s'",token2)); } PC_EndParseSession(buffer); } /* ================= Load_Menu Load current menu file ================= */ qboolean Load_Menu(const char **holdBuffer) { const char *token2; token2 = COM_ParseExt( holdBuffer, qtrue ); if (!token2[0]) { return qfalse; } if (*token2 != '{') { return qfalse; } while ( 1 ) { token2 = COM_ParseExt( holdBuffer, qtrue ); if ((!token2) || (token2 == 0)) { return qfalse; } if ( *token2 == '}' ) { return qtrue; } //#ifdef _DEBUG // extern void UI_Debug_AddMenuFilePath(const char *); // UI_Debug_AddMenuFilePath(token2); //#endif UI_ParseMenu(token2); } return qfalse; } /* ================= UI_LoadMenus Load all menus based on the files listed in the data file in menuFile (default "ui/menus.txt") ================= */ void UI_LoadMenus(const char *menuFile, qboolean reset) { // pc_token_t token; // int handle; int start; char *buffer; const char *holdBuffer; int len; start = Sys_Milliseconds(); len = ui.FS_ReadFile(menuFile,(void **) &buffer); if (len<1) { Com_Printf( va( S_COLOR_YELLOW "menu file not found: %s, using default\n", menuFile ) ); len = ui.FS_ReadFile("ui/menus.txt",(void **) &buffer); if (len<1) { Com_Error( ERR_FATAL, "%s", va("default menu file not found: ui/menus.txt, unable to continue!\n", menuFile )); return; } } if (reset) { Menu_Reset(); } const char *token2; holdBuffer = buffer; COM_BeginParseSession(); while ( 1 ) { token2 = COM_ParseExt( &holdBuffer, qtrue ); if (!*token2) { break; } if( *token2 == 0 || *token2 == '}') // End of the menus file { break; } if (*token2 == '{') { continue; } else if (Q_stricmp(token2, "loadmenu") == 0) { if (Load_Menu(&holdBuffer)) { continue; } else { break; } } else { Com_Printf("Unknown keyword '%s' in menus file %s\n", token2, menuFile); } } COM_EndParseSession(); Com_Printf("UI menu load time = %d milli seconds\n", Sys_Milliseconds() - start); ui.FS_FreeFile( buffer ); //let go of the buffer } /* ================= UI_Load ================= */ void UI_Load(void) { const char *menuSet; char lastName[1024]; menuDef_t *menu = Menu_GetFocused(); if (menu && menu->window.name) { strcpy(lastName, menu->window.name); } else { lastName[0] = 0; } #ifndef JK2_MODE if (uiInfo.inGameLoad) { menuSet= "ui/ingame.txt"; } else #endif { menuSet= UI_Cvar_VariableString("ui_menuFiles"); } if (menuSet == NULL || menuSet[0] == '\0') { menuSet = "ui/menus.txt"; } String_Init(); UI_LoadMenus(menuSet, qtrue); Menus_CloseAll(); Menus_ActivateByName(lastName); } /* ================= Asset_Parse ================= */ qboolean Asset_Parse(char **buffer) { char *token; const char *tempStr; int pointSize; token = PC_ParseExt(); if (!token) { return qfalse; } if (*token != '{') { return qfalse; } while ( 1 ) { token = PC_ParseExt(); if (!token) { return qfalse; } if (*token == '}') { return qtrue; } // fonts if (Q_stricmp(token, "smallFont") == 0) //legacy, really it only matters which order they are registered { if (PC_ParseString(&tempStr)) { PC_ParseWarning("Bad 1st parameter for keyword 'smallFont'"); return qfalse; } UI_RegisterFont(tempStr); //not used anymore if (PC_ParseInt(&pointSize)) { // PC_ParseWarning("Bad 2nd parameter for keyword 'smallFont'"); } continue; } if (Q_stricmp(token, "mediumFont") == 0) { if (PC_ParseString(&tempStr)) { PC_ParseWarning("Bad 1st parameter for keyword 'font'"); return qfalse; } uiInfo.uiDC.Assets.qhMediumFont = UI_RegisterFont(tempStr); uiInfo.uiDC.Assets.fontRegistered = qtrue; //not used if (PC_ParseInt(&pointSize)) { // PC_ParseWarning("Bad 2nd parameter for keyword 'font'"); } continue; } if (Q_stricmp(token, "bigFont") == 0) //legacy { if (PC_ParseString(&tempStr)) { PC_ParseWarning("Bad 1st parameter for keyword 'bigFont'"); return qfalse; } UI_RegisterFont(tempStr); if (PC_ParseInt(&pointSize)) { // PC_ParseWarning("Bad 2nd parameter for keyword 'bigFont'"); } continue; } #ifdef JK2_MODE if (Q_stricmp(token, "stripedFile") == 0) { if (!PC_ParseStringMem((const char **) &tempStr)) { PC_ParseWarning("Bad 1st parameter for keyword 'stripedFile'"); return qfalse; } char sTemp[1024]; Q_strncpyz( sTemp, tempStr, sizeof(sTemp) ); if (!ui.SP_Register(sTemp, /*SP_REGISTER_REQUIRED|*/SP_REGISTER_MENU)) { PC_ParseWarning(va("(.SP file \"%s\" not found)",sTemp)); //return qfalse; // hmmm... dunno about this, don't want to break scripts for just missing subtitles } else { // extern void AddMenuPackageRetryKey(const char *); // AddMenuPackageRetryKey(sTemp); } continue; } #endif // gradientbar if (Q_stricmp(token, "gradientbar") == 0) { if (PC_ParseString(&tempStr)) { PC_ParseWarning("Bad 1st parameter for keyword 'gradientbar'"); return qfalse; } uiInfo.uiDC.Assets.gradientBar = ui.R_RegisterShaderNoMip(tempStr); continue; } // enterMenuSound if (Q_stricmp(token, "menuEnterSound") == 0) { if (PC_ParseString(&tempStr)) { PC_ParseWarning("Bad 1st parameter for keyword 'menuEnterSound'"); return qfalse; } uiInfo.uiDC.Assets.menuEnterSound = trap_S_RegisterSound( tempStr, qfalse ); continue; } // exitMenuSound if (Q_stricmp(token, "menuExitSound") == 0) { if (PC_ParseString(&tempStr)) { PC_ParseWarning("Bad 1st parameter for keyword 'menuExitSound'"); return qfalse; } uiInfo.uiDC.Assets.menuExitSound = trap_S_RegisterSound( tempStr, qfalse ); continue; } // itemFocusSound if (Q_stricmp(token, "itemFocusSound") == 0) { if (PC_ParseString(&tempStr)) { PC_ParseWarning("Bad 1st parameter for keyword 'itemFocusSound'"); return qfalse; } uiInfo.uiDC.Assets.itemFocusSound = trap_S_RegisterSound( tempStr, qfalse ); continue; } // menuBuzzSound if (Q_stricmp(token, "menuBuzzSound") == 0) { if (PC_ParseString(&tempStr)) { PC_ParseWarning("Bad 1st parameter for keyword 'menuBuzzSound'"); return qfalse; } uiInfo.uiDC.Assets.menuBuzzSound = trap_S_RegisterSound( tempStr, qfalse ); continue; } // Chose a force power from the ingame force allocation screen (the one where you get to allocate a force power point) if (Q_stricmp(token, "forceChosenSound") == 0) { if (PC_ParseString(&tempStr)) { PC_ParseWarning("Bad 1st parameter for keyword 'forceChosenSound'"); return qfalse; } uiInfo.uiDC.Assets.forceChosenSound = trap_S_RegisterSound( tempStr, qfalse ); continue; } // Unchose a force power from the ingame force allocation screen (the one where you get to allocate a force power point) if (Q_stricmp(token, "forceUnchosenSound") == 0) { if (PC_ParseString(&tempStr)) { PC_ParseWarning("Bad 1st parameter for keyword 'forceUnchosenSound'"); return qfalse; } uiInfo.uiDC.Assets.forceUnchosenSound = trap_S_RegisterSound( tempStr, qfalse ); continue; } if (Q_stricmp(token, "datapadmoveRollSound") == 0) { if (PC_ParseString(&tempStr)) { PC_ParseWarning("Bad 1st parameter for keyword 'datapadmoveRollSound'"); return qfalse; } uiInfo.uiDC.Assets.datapadmoveRollSound = trap_S_RegisterSound( tempStr, qfalse ); continue; } if (Q_stricmp(token, "datapadmoveJumpSound") == 0) { if (PC_ParseString(&tempStr)) { PC_ParseWarning("Bad 1st parameter for keyword 'datapadmoveRoll'"); return qfalse; } uiInfo.uiDC.Assets.datapadmoveJumpSound = trap_S_RegisterSound( tempStr, qfalse ); continue; } if (Q_stricmp(token, "datapadmoveSaberSound1") == 0) { if (PC_ParseString(&tempStr)) { PC_ParseWarning("Bad 1st parameter for keyword 'datapadmoveSaberSound1'"); return qfalse; } uiInfo.uiDC.Assets.datapadmoveSaberSound1 = trap_S_RegisterSound( tempStr, qfalse ); continue; } if (Q_stricmp(token, "datapadmoveSaberSound2") == 0) { if (PC_ParseString(&tempStr)) { PC_ParseWarning("Bad 1st parameter for keyword 'datapadmoveSaberSound2'"); return qfalse; } uiInfo.uiDC.Assets.datapadmoveSaberSound2 = trap_S_RegisterSound( tempStr, qfalse ); continue; } if (Q_stricmp(token, "datapadmoveSaberSound3") == 0) { if (PC_ParseString(&tempStr)) { PC_ParseWarning("Bad 1st parameter for keyword 'datapadmoveSaberSound3'"); return qfalse; } uiInfo.uiDC.Assets.datapadmoveSaberSound3 = trap_S_RegisterSound( tempStr, qfalse ); continue; } if (Q_stricmp(token, "datapadmoveSaberSound4") == 0) { if (PC_ParseString(&tempStr)) { PC_ParseWarning("Bad 1st parameter for keyword 'datapadmoveSaberSound4'"); return qfalse; } uiInfo.uiDC.Assets.datapadmoveSaberSound4 = trap_S_RegisterSound( tempStr, qfalse ); continue; } if (Q_stricmp(token, "datapadmoveSaberSound5") == 0) { if (PC_ParseString(&tempStr)) { PC_ParseWarning("Bad 1st parameter for keyword 'datapadmoveSaberSound5'"); return qfalse; } uiInfo.uiDC.Assets.datapadmoveSaberSound5 = trap_S_RegisterSound( tempStr, qfalse ); continue; } if (Q_stricmp(token, "datapadmoveSaberSound6") == 0) { if (PC_ParseString(&tempStr)) { PC_ParseWarning("Bad 1st parameter for keyword 'datapadmoveSaberSound6'"); return qfalse; } uiInfo.uiDC.Assets.datapadmoveSaberSound6 = trap_S_RegisterSound( tempStr, qfalse ); continue; } if (Q_stricmp(token, "cursor") == 0) { if (PC_ParseString(&tempStr)) { PC_ParseWarning("Bad 1st parameter for keyword 'cursor'"); return qfalse; } uiInfo.uiDC.Assets.cursor = ui.R_RegisterShaderNoMip( tempStr); continue; } if (Q_stricmp(token, "fadeClamp") == 0) { if (PC_ParseFloat(&uiInfo.uiDC.Assets.fadeClamp)) { PC_ParseWarning("Bad 1st parameter for keyword 'fadeClamp'"); return qfalse; } continue; } if (Q_stricmp(token, "fadeCycle") == 0) { if (PC_ParseInt(&uiInfo.uiDC.Assets.fadeCycle)) { PC_ParseWarning("Bad 1st parameter for keyword 'fadeCycle'"); return qfalse; } continue; } if (Q_stricmp(token, "fadeAmount") == 0) { if (PC_ParseFloat(&uiInfo.uiDC.Assets.fadeAmount)) { PC_ParseWarning("Bad 1st parameter for keyword 'fadeAmount'"); return qfalse; } continue; } if (Q_stricmp(token, "shadowX") == 0) { if (PC_ParseFloat(&uiInfo.uiDC.Assets.shadowX)) { PC_ParseWarning("Bad 1st parameter for keyword 'shadowX'"); return qfalse; } continue; } if (Q_stricmp(token, "shadowY") == 0) { if (PC_ParseFloat(&uiInfo.uiDC.Assets.shadowY)) { PC_ParseWarning("Bad 1st parameter for keyword 'shadowY'"); return qfalse; } continue; } if (Q_stricmp(token, "shadowColor") == 0) { if (PC_ParseColor(&uiInfo.uiDC.Assets.shadowColor)) { PC_ParseWarning("Bad 1st parameter for keyword 'shadowColor'"); return qfalse; } uiInfo.uiDC.Assets.shadowFadeClamp = uiInfo.uiDC.Assets.shadowColor[3]; continue; } // precaching various sound files used in the menus if (Q_stricmp(token, "precacheSound") == 0) { if (PC_Script_Parse(&tempStr)) { char *soundFile; do { soundFile = COM_ParseExt(&tempStr, qfalse); if (soundFile[0] != 0 && soundFile[0] != ';') { if (!trap_S_RegisterSound( soundFile, qfalse )) { PC_ParseWarning("Can't locate precache sound"); } } } while (soundFile[0]); } continue; } } PC_ParseWarning(va("Invalid keyword '%s'",token)); return qfalse; } /* ================= UI_Update ================= */ static void UI_Update(const char *name) { int val = trap_Cvar_VariableValue(name); if (Q_stricmp(name, "s_khz") == 0) { ui.Cmd_ExecuteText( EXEC_APPEND, "snd_restart\n" ); return; } if (Q_stricmp(name, "ui_SetName") == 0) { Cvar_Set( "name", UI_Cvar_VariableString("ui_Name")); } else if (Q_stricmp(name, "ui_GetName") == 0) { Cvar_Set( "ui_Name", UI_Cvar_VariableString("name")); } else if (Q_stricmp(name, "ui_r_colorbits") == 0) { switch (val) { case 0: Cvar_SetValue( "ui_r_depthbits", 0 ); break; case 16: Cvar_SetValue( "ui_r_depthbits", 16 ); break; case 32: Cvar_SetValue( "ui_r_depthbits", 24 ); break; } } else if (Q_stricmp(name, "ui_r_lodbias") == 0) { switch (val) { case 0: Cvar_SetValue( "ui_r_subdivisions", 4 ); break; case 1: Cvar_SetValue( "ui_r_subdivisions", 12 ); break; case 2: Cvar_SetValue( "ui_r_subdivisions", 20 ); break; } } else if (Q_stricmp(name, "ui_r_glCustom") == 0) { switch (val) { case 0: // high quality Cvar_SetValue( "ui_r_fullScreen", 1 ); Cvar_SetValue( "ui_r_subdivisions", 4 ); Cvar_SetValue( "ui_r_lodbias", 0 ); Cvar_SetValue( "ui_r_colorbits", 32 ); Cvar_SetValue( "ui_r_depthbits", 24 ); Cvar_SetValue( "ui_r_picmip", 0 ); Cvar_SetValue( "ui_r_mode", 4 ); Cvar_SetValue( "ui_r_texturebits", 32 ); Cvar_SetValue( "ui_r_fastSky", 0 ); Cvar_SetValue( "ui_r_inGameVideo", 1 ); //Cvar_SetValue( "ui_cg_shadows", 2 );//stencil Cvar_Set( "ui_r_texturemode", "GL_LINEAR_MIPMAP_LINEAR" ); break; case 1: // normal Cvar_SetValue( "ui_r_fullScreen", 1 ); Cvar_SetValue( "ui_r_subdivisions", 4 ); Cvar_SetValue( "ui_r_lodbias", 0 ); Cvar_SetValue( "ui_r_colorbits", 0 ); Cvar_SetValue( "ui_r_depthbits", 24 ); Cvar_SetValue( "ui_r_picmip", 1 ); Cvar_SetValue( "ui_r_mode", 3 ); Cvar_SetValue( "ui_r_texturebits", 0 ); Cvar_SetValue( "ui_r_fastSky", 0 ); Cvar_SetValue( "ui_r_inGameVideo", 1 ); //Cvar_SetValue( "ui_cg_shadows", 2 ); Cvar_Set( "ui_r_texturemode", "GL_LINEAR_MIPMAP_LINEAR" ); break; case 2: // fast Cvar_SetValue( "ui_r_fullScreen", 1 ); Cvar_SetValue( "ui_r_subdivisions", 12 ); Cvar_SetValue( "ui_r_lodbias", 1 ); Cvar_SetValue( "ui_r_colorbits", 0 ); Cvar_SetValue( "ui_r_depthbits", 0 ); Cvar_SetValue( "ui_r_picmip", 2 ); Cvar_SetValue( "ui_r_mode", 3 ); Cvar_SetValue( "ui_r_texturebits", 0 ); Cvar_SetValue( "ui_r_fastSky", 1 ); Cvar_SetValue( "ui_r_inGameVideo", 0 ); //Cvar_SetValue( "ui_cg_shadows", 1 ); Cvar_Set( "ui_r_texturemode", "GL_LINEAR_MIPMAP_NEAREST" ); break; case 3: // fastest Cvar_SetValue( "ui_r_fullScreen", 1 ); Cvar_SetValue( "ui_r_subdivisions", 20 ); Cvar_SetValue( "ui_r_lodbias", 2 ); Cvar_SetValue( "ui_r_colorbits", 16 ); Cvar_SetValue( "ui_r_depthbits", 16 ); Cvar_SetValue( "ui_r_mode", 3 ); Cvar_SetValue( "ui_r_picmip", 3 ); Cvar_SetValue( "ui_r_texturebits", 16 ); Cvar_SetValue( "ui_r_fastSky", 1 ); Cvar_SetValue( "ui_r_inGameVideo", 0 ); //Cvar_SetValue( "ui_cg_shadows", 0 ); Cvar_Set( "ui_r_texturemode", "GL_LINEAR_MIPMAP_NEAREST" ); break; } } else if (Q_stricmp(name, "ui_mousePitch") == 0) { if (val == 0) { Cvar_SetValue( "m_pitch", 0.022f ); } else { Cvar_SetValue( "m_pitch", -0.022f ); } } else {//failure!! Com_Printf("unknown UI script UPDATE %s\n", name); } } #define ASSET_SCROLLBAR "gfx/menus/scrollbar.tga" #define ASSET_SCROLLBAR_ARROWDOWN "gfx/menus/scrollbar_arrow_dwn_a.tga" #define ASSET_SCROLLBAR_ARROWUP "gfx/menus/scrollbar_arrow_up_a.tga" #define ASSET_SCROLLBAR_ARROWLEFT "gfx/menus/scrollbar_arrow_left.tga" #define ASSET_SCROLLBAR_ARROWRIGHT "gfx/menus/scrollbar_arrow_right.tga" #define ASSET_SCROLL_THUMB "gfx/menus/scrollbar_thumb.tga" /* ================= AssetCache ================= */ void AssetCache(void) { // int n; uiInfo.uiDC.Assets.scrollBar = ui.R_RegisterShaderNoMip( ASSET_SCROLLBAR ); uiInfo.uiDC.Assets.scrollBarArrowDown = ui.R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWDOWN ); uiInfo.uiDC.Assets.scrollBarArrowUp = ui.R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWUP ); uiInfo.uiDC.Assets.scrollBarArrowLeft = ui.R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWLEFT ); uiInfo.uiDC.Assets.scrollBarArrowRight = ui.R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWRIGHT ); uiInfo.uiDC.Assets.scrollBarThumb = ui.R_RegisterShaderNoMip( ASSET_SCROLL_THUMB ); uiInfo.uiDC.Assets.sliderBar = ui.R_RegisterShaderNoMip( "menu/new/slider" ); uiInfo.uiDC.Assets.sliderThumb = ui.R_RegisterShaderNoMip( "menu/new/sliderthumb"); /* for( n = 0; n < NUM_CROSSHAIRS; n++ ) { uiInfo.uiDC.Assets.crosshairShader[n] = ui.R_RegisterShaderNoMip( va("gfx/2d/crosshair%c", 'a' + n ) ); } */ } /* ================ _UI_DrawSides ================= */ void _UI_DrawSides(float x, float y, float w, float h, float size) { size *= uiInfo.uiDC.xscale; trap_R_DrawStretchPic( x, y, size, h, 0, 0, 0, 0, uiInfo.uiDC.whiteShader ); trap_R_DrawStretchPic( x + w - size, y, size, h, 0, 0, 0, 0, uiInfo.uiDC.whiteShader ); } /* ================ _UI_DrawTopBottom ================= */ void _UI_DrawTopBottom(float x, float y, float w, float h, float size) { size *= uiInfo.uiDC.yscale; trap_R_DrawStretchPic( x, y, w, size, 0, 0, 0, 0, uiInfo.uiDC.whiteShader ); trap_R_DrawStretchPic( x, y + h - size, w, size, 0, 0, 0, 0, uiInfo.uiDC.whiteShader ); } /* ================ UI_DrawRect Coordinates are 640*480 virtual values ================= */ void _UI_DrawRect( float x, float y, float width, float height, float size, const float *color ) { trap_R_SetColor( color ); _UI_DrawTopBottom(x, y, width, height, size); _UI_DrawSides(x, y, width, height, size); trap_R_SetColor( NULL ); } /* ================= UI_UpdateCvars ================= */ void UI_UpdateCvars( void ) { size_t i = 0; const cvarTable_t *cv = NULL; for ( i=0, cv=cvarTable; ivmCvar ) { int modCount = cv->vmCvar->modificationCount; Cvar_Update( cv->vmCvar ); if ( cv->vmCvar->modificationCount != modCount ) { if ( cv->update ) cv->update(); } } } } /* ================= UI_DrawEffects ================= */ static void UI_DrawEffects(rectDef_t *rect, float scale, vec4_t color) { UI_DrawHandlePic( rect->x, rect->y - 14, 128, 8, 0/*uiInfo.uiDC.Assets.fxBasePic*/ ); UI_DrawHandlePic( rect->x + uiInfo.effectsColor * 16 + 8, rect->y - 16, 16, 12, 0/*uiInfo.uiDC.Assets.fxPic[uiInfo.effectsColor]*/ ); } /* ================= UI_Version ================= */ static void UI_Version(rectDef_t *rect, float scale, vec4_t color, int iFontIndex) { int width; width = DC->textWidth(Q3_VERSION, scale, 0); DC->drawText(rect->x - width, rect->y, scale, color, Q3_VERSION, 0, ITEM_TEXTSTYLE_SHADOWED, iFontIndex); } /* ================= UI_DrawKeyBindStatus ================= */ static void UI_DrawKeyBindStatus(rectDef_t *rect, float scale, vec4_t color, int textStyle, int iFontIndex) { if (Display_KeyBindPending()) { #ifdef JK2_MODE Text_Paint(rect->x, rect->y, scale, color, ui.SP_GetStringTextString("MENUS_WAITINGFORKEY"), 0, textStyle, iFontIndex); #else Text_Paint(rect->x, rect->y, scale, color, SE_GetString("MENUS_WAITINGFORKEY"), 0, textStyle, iFontIndex); #endif } else { // Text_Paint(rect->x, rect->y, scale, color, ui.SP_GetStringTextString("MENUS_ENTERTOCHANGE"), 0, textStyle, iFontIndex); } } /* ================= UI_DrawKeyBindStatus ================= */ static void UI_DrawGLInfo(rectDef_t *rect, float scale, vec4_t color, int textStyle, int iFontIndex) { #define MAX_LINES 64 char buff[4096]; char * eptr = buff; const char *lines[MAX_LINES]; int y, numLines=0, i=0; y = rect->y; Text_Paint(rect->x, y, scale, color, va("GL_VENDOR: %s",uiInfo.uiDC.glconfig.vendor_string), rect->w, textStyle, iFontIndex); y += 15; Text_Paint(rect->x, y, scale, color, va("GL_VERSION: %s: %s", uiInfo.uiDC.glconfig.version_string,uiInfo.uiDC.glconfig.renderer_string), rect->w, textStyle, iFontIndex); y += 15; Text_Paint(rect->x, y, scale, color, "GL_PIXELFORMAT:", rect->w, textStyle, iFontIndex); y += 15; Text_Paint(rect->x, y, scale, color, va ("Color(%d-bits) Z(%d-bits) stencil(%d-bits)",uiInfo.uiDC.glconfig.colorBits, uiInfo.uiDC.glconfig.depthBits, uiInfo.uiDC.glconfig.stencilBits), rect->w, textStyle, iFontIndex); y += 15; // build null terminated extension strings Q_strncpyz(buff, uiInfo.uiDC.glconfig.extensions_string, sizeof(buff)); int testy=y-16; while ( testy <= rect->y + rect->h && *eptr && (numLines < MAX_LINES) ) { while ( *eptr && *eptr == ' ' ) *eptr++ = '\0'; // track start of valid string if (*eptr && *eptr != ' ') { lines[numLines++] = eptr; testy+=16; } while ( *eptr && *eptr != ' ' ) eptr++; } numLines--; while (i < numLines) { Text_Paint(rect->x, y, scale, color, lines[i++], rect->w, textStyle, iFontIndex); y += 16; } } /* ================= UI_DataPad_Inventory ================= */ /* static void UI_DataPad_Inventory(rectDef_t *rect, float scale, vec4_t color, int iFontIndex) { Text_Paint(rect->x, rect->y, scale, color, "INVENTORY", 0, 1, iFontIndex); } */ /* ================= UI_DataPad_ForcePowers ================= */ /* static void UI_DataPad_ForcePowers(rectDef_t *rect, float scale, vec4_t color, int iFontIndex) { Text_Paint(rect->x, rect->y, scale, color, "FORCE POWERS", 0, 1, iFontIndex); } */ static void UI_DrawCrosshair(rectDef_t *rect, float scale, vec4_t color) { trap_R_SetColor( color ); if (uiInfo.currentCrosshair < 0 || uiInfo.currentCrosshair >= NUM_CROSSHAIRS) { uiInfo.currentCrosshair = 0; } UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.uiDC.Assets.crosshairShader[uiInfo.currentCrosshair]); trap_R_SetColor( NULL ); } #define TC_PLANE_WIDTH 250 #define TC_PLANE_NEAR 90 #define TC_PLANE_FAR 715 #define TC_PLANE_TOP 0 #define TC_PLANE_BOTTOM 1100 #define TC_PLANE_NO_BEVEL 150 #define TC_STOPTIME 81000 static void UI_PatreonCredits(float x, float y, float w, float h, bool useBevel) { static int startTime = cls.realtime; refdef_t refdef; polyVert_t verts[4]; // Set up refdef memset( &refdef, 0, sizeof( refdef )); refdef.rdflags = RDF_NOWORLDMODEL; AxisClear( refdef.viewaxis ); refdef.override_fov = true; refdef.fov_x = 150; refdef.fov_y = 150; refdef.x = (x / 640) * cls.glconfig.vidWidth; refdef.y = ((y - 15) / 480) * cls.glconfig.vidHeight; refdef.width = (w / 640) * cls.glconfig.vidWidth; refdef.height = (h / 480) * cls.glconfig.vidHeight * 2; // deliberately extend off the bottom of the render area // use to set shaderTime for scrolling shaders refdef.time = 0; // Set up the poly verts float fadeDown = 1.0; for ( int i = 0; i < 4; i++ ) { verts[i].modulate[0] = 255*fadeDown; // gold color? verts[i].modulate[1] = 235*fadeDown; verts[i].modulate[2] = 127*fadeDown; verts[i].modulate[3] = 255*fadeDown; } VectorScaleM( verts[2].modulate, 0.1f, verts[2].modulate ); // darken at the top?? VectorScaleM( verts[3].modulate, 0.1f, verts[3].modulate ); float timeoffset = (cls.realtime-startTime)*0.000022f -1; VectorSet( verts[0].xyz, useBevel ? TC_PLANE_NEAR : TC_PLANE_NO_BEVEL, -TC_PLANE_WIDTH, TC_PLANE_TOP ); verts[0].st[0] = 1; verts[0].st[1] = 1 +timeoffset; VectorSet( verts[1].xyz, useBevel ? TC_PLANE_NEAR : TC_PLANE_NO_BEVEL, TC_PLANE_WIDTH, TC_PLANE_TOP ); verts[1].st[0] = 0; verts[1].st[1] = 1 +timeoffset; VectorSet( verts[2].xyz, useBevel ? TC_PLANE_FAR : TC_PLANE_NO_BEVEL, TC_PLANE_WIDTH, TC_PLANE_BOTTOM ); verts[2].st[0] = 0; verts[2].st[1] = 0 +timeoffset; VectorSet( verts[3].xyz, useBevel ? TC_PLANE_FAR : TC_PLANE_NO_BEVEL, -TC_PLANE_WIDTH, TC_PLANE_BOTTOM ); verts[3].st[0] = 1; verts[3].st[1] = 0 +timeoffset; // render it out re.ClearScene(); re.AddPolyToScene( re.RegisterShaderNoMip( "menu/video/beef_crawl" ), 4, verts ); re.RenderScene( &refdef ); } /* ================= UI_OwnerDraw ================= */ static void UI_OwnerDraw(float x, float y, float w, float h, float text_x, float text_y, int ownerDraw, int ownerDrawFlags, int align, float special, float scale, vec4_t color, qhandle_t shader, int textStyle, int iFontIndex) { rectDef_t rect; rect.x = x + text_x; rect.y = y + text_y; rect.w = w; rect.h = h; switch (ownerDraw) { case UI_EFFECTS: UI_DrawEffects(&rect, scale, color); break; case UI_VERSION: UI_Version(&rect, scale, color, iFontIndex); break; case UI_DATAPAD_MISSION: ui.Draw_DataPad(DP_HUD); ui.Draw_DataPad(DP_OBJECTIVES); break; case UI_DATAPAD_WEAPONS: ui.Draw_DataPad(DP_HUD); ui.Draw_DataPad(DP_WEAPONS); break; case UI_DATAPAD_INVENTORY: ui.Draw_DataPad(DP_HUD); ui.Draw_DataPad(DP_INVENTORY); break; case UI_DATAPAD_FORCEPOWERS: ui.Draw_DataPad(DP_HUD); ui.Draw_DataPad(DP_FORCEPOWERS); break; case UI_ALLMAPS_SELECTION://saved game thumbnail int levelshot; levelshot = ui.R_RegisterShaderNoMip( va( "levelshots/%s", s_savedata[s_savegame.currentLine].currentSaveFileMap ) ); #ifdef JK2_MODE if (screenShotBuf[0]) { ui.DrawStretchRaw( x, y, w, h, SG_SCR_WIDTH, SG_SCR_HEIGHT, screenShotBuf, 0, qtrue ); } else #endif if (levelshot) { ui.R_DrawStretchPic( x, y, w, h, 0, 0, 1, 1, levelshot ); } else { UI_DrawHandlePic(x, y, w, h, uis.menuBackShader); } ui.R_Font_DrawString( x, // int ox y+h, // int oy s_savedata[s_savegame.currentLine].currentSaveFileMap, // const char *text color, // paletteRGBA_c c iFontIndex, // const int iFontHandle w,//-1, // iMaxPixelWidth (-1 = none) scale // const float scale = 1.0f ); break; case UI_PREVIEWCINEMATIC: // FIXME BOB - make this work? // UI_DrawPreviewCinematic(&rect, scale, color); break; case UI_CROSSHAIR: UI_DrawCrosshair(&rect, scale, color); break; case UI_GLINFO: UI_DrawGLInfo(&rect,scale, color, textStyle, iFontIndex); break; case UI_KEYBINDSTATUS: UI_DrawKeyBindStatus(&rect,scale, color, textStyle, iFontIndex); break; case UI_PATREON_CREDITS: UI_PatreonCredits(x, y, w, h, true); break; case UI_PATREON_CREDITS_NO_BEVEL: UI_PatreonCredits(x, y, w, h, false); break; default: break; } } /* ================= UI_OwnerDrawVisible ================= */ static qboolean UI_OwnerDrawVisible(int flags) { qboolean vis = qtrue; while (flags) { /* if (flags & UI_SHOW_DEMOAVAILABLE) { if (!uiInfo.demoAvailable) { vis = qfalse; } flags &= ~UI_SHOW_DEMOAVAILABLE; } else */ { flags = 0; } } return vis; } /* ================= Text_Width ================= */ int Text_Width(const char *text, float scale, int iFontIndex) { // temp code until Bob retro-fits all menus to have font specifiers... // if ( iFontIndex == 0 ) { iFontIndex = uiInfo.uiDC.Assets.qhMediumFont; } return ui.R_Font_StrLenPixels(text, iFontIndex, scale); } /* ================= UI_OwnerDrawWidth ================= */ int UI_OwnerDrawWidth(int ownerDraw, float scale) { // int i, h, value; // const char *text; const char *s = NULL; switch (ownerDraw) { case UI_KEYBINDSTATUS: if (Display_KeyBindPending()) { #ifdef JK2_MODE s = ui.SP_GetStringTextString("MENUS_WAITINGFORKEY"); #else s = SE_GetString("MENUS_WAITINGFORKEY"); #endif } else { // s = ui.SP_GetStringTextString("MENUS_ENTERTOCHANGE"); } break; // FIXME BOB // case UI_SERVERREFRESHDATE: // s = UI_Cvar_VariableString(va("ui_lastServerRefresh_%i", ui_netSource.integer)); // break; default: break; } if (s) { return Text_Width(s, scale, 0); } return 0; } /* ================= Text_Height ================= */ int Text_Height(const char *text, float scale, int iFontIndex) { // temp until Bob retro-fits all menu files with font specifiers... // if ( iFontIndex == 0 ) { iFontIndex = uiInfo.uiDC.Assets.qhMediumFont; } return ui.R_Font_HeightPixels(iFontIndex, scale); } /* ================= UI_MouseEvent ================= */ //JLFMOUSE CALLED EACH FRAME IN UI void _UI_MouseEvent( int dx, int dy ) { // update mouse screen position uiInfo.uiDC.cursorx += dx; if (uiInfo.uiDC.cursorx < 0) { uiInfo.uiDC.cursorx = 0; } else if (uiInfo.uiDC.cursorx > SCREEN_WIDTH) { uiInfo.uiDC.cursorx = SCREEN_WIDTH; } uiInfo.uiDC.cursory += dy; if (uiInfo.uiDC.cursory < 0) { uiInfo.uiDC.cursory = 0; } else if (uiInfo.uiDC.cursory > SCREEN_HEIGHT) { uiInfo.uiDC.cursory = SCREEN_HEIGHT; } if (Menu_Count() > 0) { //menuDef_t *menu = Menu_GetFocused(); //Menu_HandleMouseMove(menu, uiInfo.uiDC.cursorx, uiInfo.uiDC.cursory); Display_MouseMove(NULL, uiInfo.uiDC.cursorx, uiInfo.uiDC.cursory); } } /* ================= UI_MouseEventAbs ================= */ //JLFMOUSE CALLED EACH FRAME IN UI const int cursorSize = 48; void _UI_MouseEventAbs( int x, int y ) { // update mouse screen position // allow to hide cursor beyond the screen edges uiInfo.uiDC.cursorx = x; if (uiInfo.uiDC.cursorx < -cursorSize) { uiInfo.uiDC.cursorx = -cursorSize; } else if (uiInfo.uiDC.cursorx > SCREEN_WIDTH + cursorSize) { uiInfo.uiDC.cursorx = SCREEN_WIDTH + cursorSize; } uiInfo.uiDC.cursory = y; if (uiInfo.uiDC.cursory < -cursorSize) { uiInfo.uiDC.cursory = -cursorSize; } else if (uiInfo.uiDC.cursory > SCREEN_HEIGHT + cursorSize) { uiInfo.uiDC.cursory = SCREEN_HEIGHT + cursorSize; } if (Menu_Count() > 0) { //menuDef_t *menu = Menu_GetFocused(); //Menu_HandleMouseMove(menu, uiInfo.uiDC.cursorx, uiInfo.uiDC.cursory); Display_MouseMove(NULL, uiInfo.uiDC.cursorx, uiInfo.uiDC.cursory); } } /* ================= UI_KeyEvent ================= */ void _UI_KeyEvent( int key, qboolean down ) { /* extern qboolean SwallowBadNumLockedKPKey( int iKey ); if (SwallowBadNumLockedKPKey(key)){ return; } */ if (Menu_Count() > 0) { menuDef_t *menu = Menu_GetFocused(); if (menu) { //DemoEnd(); if (key == A_ESCAPE && down && !Menus_AnyFullScreenVisible() && !(menu->window.flags & WINDOW_IGNORE_ESCAPE)) { Menus_CloseAll(); } else { Menu_HandleKey(menu, key, down ); } } else { trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI ); trap_Key_ClearStates(); Cvar_Set( "cl_paused", "0" ); } } } /* ================= UI_Report ================= */ void UI_Report(void) { String_Report(); } /* ================= UI_DataPadMenu ================= */ void UI_DataPadMenu(void) { int newForcePower,newObjective; Menus_CloseByName("mainhud"); newForcePower = (int)trap_Cvar_VariableValue("cg_updatedDataPadForcePower1"); newObjective = (int)trap_Cvar_VariableValue("cg_updatedDataPadObjective"); if (newForcePower) { Menus_ActivateByName("datapadForcePowersMenu"); } else if (newObjective) { Menus_ActivateByName("datapadMissionMenu"); } else { Menus_ActivateByName("datapadMissionMenu"); } ui.Key_SetCatcher( KEYCATCH_UI ); } /* ================= UI_InGameMenu ================= */ void UI_InGameMenu(const char*menuID) { #ifdef JK2_MODE ui.PrecacheScreenshot(); #endif Menus_CloseByName("mainhud"); if (menuID) { Menus_ActivateByName(menuID); } else { Menus_ActivateByName("ingameMainMenu"); } ui.Key_SetCatcher( KEYCATCH_UI ); } qboolean _UI_IsFullscreen( void ) { return Menus_AnyFullScreenVisible(); } /* ======================================================================= MAIN MENU ======================================================================= */ /* =============== UI_MainMenu The main menu only comes up when not in a game, so make sure that the attract loop server is down and that local cinematics are killed =============== */ void UI_MainMenu(void) { char buf[256]; ui.Cvar_Set("sv_killserver", "1"); // let the demo server know it should shut down ui.Key_SetCatcher( KEYCATCH_UI ); menuDef_t *m = Menus_ActivateByName("mainMenu"); if (!m) { //wha? try again UI_LoadMenus("ui/menus.txt",qfalse); } ui.Cvar_VariableStringBuffer("com_errorMessage", buf, sizeof(buf)); if (strlen(buf)) { Menus_ActivateByName("error_popmenu"); } } /* ================= Menu_Cache ================= */ void Menu_Cache( void ) { uis.cursor = ui.R_RegisterShaderNoMip( "menu/new/crosshairb"); // Common menu graphics uis.whiteShader = ui.R_RegisterShader( "white" ); uis.menuBackShader = ui.R_RegisterShaderNoMip( "menu/art/unknownmap" ); } /* ================= UI_UpdateVideoSetup Copies the temporary user interface version of the video cvars into their real counterparts. This is to create a interface which allows you to discard your changes if you did something you didnt want ================= */ void UI_UpdateVideoSetup ( void ) { Cvar_Set ( "r_mode", Cvar_VariableString ( "ui_r_mode" ) ); Cvar_Set ( "r_fullscreen", Cvar_VariableString ( "ui_r_fullscreen" ) ); Cvar_Set ( "r_colorbits", Cvar_VariableString ( "ui_r_colorbits" ) ); Cvar_Set ( "r_lodbias", Cvar_VariableString ( "ui_r_lodbias" ) ); Cvar_Set ( "r_picmip", Cvar_VariableString ( "ui_r_picmip" ) ); Cvar_Set ( "r_texturebits", Cvar_VariableString ( "ui_r_texturebits" ) ); Cvar_Set ( "r_texturemode", Cvar_VariableString ( "ui_r_texturemode" ) ); Cvar_Set ( "r_detailtextures", Cvar_VariableString ( "ui_r_detailtextures" ) ); Cvar_Set ( "r_ext_compress_textures", Cvar_VariableString ( "ui_r_ext_compress_textures" ) ); Cvar_Set ( "r_depthbits", Cvar_VariableString ( "ui_r_depthbits" ) ); Cvar_Set ( "r_subdivisions", Cvar_VariableString ( "ui_r_subdivisions" ) ); Cvar_Set ( "r_fastSky", Cvar_VariableString ( "ui_r_fastSky" ) ); Cvar_Set ( "r_inGameVideo", Cvar_VariableString ( "ui_r_inGameVideo" ) ); Cvar_Set ( "r_allowExtensions", Cvar_VariableString ( "ui_r_allowExtensions" ) ); // Cvar_Set ( "cg_shadows", Cvar_VariableString ( "ui_cg_shadows" ) ); Cvar_Set ( "ui_r_modified", "0" ); Cbuf_ExecuteText( EXEC_APPEND, "vid_restart;" ); } /* ================= UI_GetVideoSetup Retrieves the current actual video settings into the temporary user interface versions of the cvars. ================= */ void UI_GetVideoSetup ( void ) { Cvar_Register ( NULL, "ui_r_glCustom", "4", CVAR_ARCHIVE ); // Make sure the cvars are registered as read only. Cvar_Register ( NULL, "ui_r_mode", "0", CVAR_ROM ); Cvar_Register ( NULL, "ui_r_fullscreen", "0", CVAR_ROM ); Cvar_Register ( NULL, "ui_r_colorbits", "32", CVAR_ROM ); Cvar_Register ( NULL, "ui_r_lodbias", "0", CVAR_ROM ); Cvar_Register ( NULL, "ui_r_picmip", "0", CVAR_ROM ); Cvar_Register ( NULL, "ui_r_texturebits", "0", CVAR_ROM ); Cvar_Register ( NULL, "ui_r_texturemode", "0", CVAR_ROM ); Cvar_Register ( NULL, "ui_r_detailtextures", "1", CVAR_ROM ); Cvar_Register ( NULL, "ui_r_ext_compress_textures", "0", CVAR_ROM ); Cvar_Register ( NULL, "ui_r_depthbits", "24", CVAR_ROM ); Cvar_Register ( NULL, "ui_r_subdivisions", "0", CVAR_ROM ); Cvar_Register ( NULL, "ui_r_fastSky", "0", CVAR_ROM ); Cvar_Register ( NULL, "ui_r_inGameVideo", "0", CVAR_ROM ); Cvar_Register ( NULL, "ui_r_allowExtensions", "0", CVAR_ROM ); // Cvar_Register ( NULL, "ui_cg_shadows", "0", CVAR_ROM ); Cvar_Register ( NULL, "ui_r_modified", "0", CVAR_ROM ); // Copy over the real video cvars into their temporary counterparts Cvar_Set ( "ui_r_mode", Cvar_VariableString ( "r_mode" ) ); Cvar_Set ( "ui_r_colorbits", Cvar_VariableString ( "r_colorbits" ) ); Cvar_Set ( "ui_r_fullscreen", Cvar_VariableString ( "r_fullscreen" ) ); Cvar_Set ( "ui_r_lodbias", Cvar_VariableString ( "r_lodbias" ) ); Cvar_Set ( "ui_r_picmip", Cvar_VariableString ( "r_picmip" ) ); Cvar_Set ( "ui_r_texturebits", Cvar_VariableString ( "r_texturebits" ) ); Cvar_Set ( "ui_r_texturemode", Cvar_VariableString ( "r_texturemode" ) ); Cvar_Set ( "ui_r_detailtextures", Cvar_VariableString ( "r_detailtextures" ) ); Cvar_Set ( "ui_r_ext_compress_textures", Cvar_VariableString ( "r_ext_compress_textures" ) ); Cvar_Set ( "ui_r_depthbits", Cvar_VariableString ( "r_depthbits" ) ); Cvar_Set ( "ui_r_subdivisions", Cvar_VariableString ( "r_subdivisions" ) ); Cvar_Set ( "ui_r_fastSky", Cvar_VariableString ( "r_fastSky" ) ); Cvar_Set ( "ui_r_inGameVideo", Cvar_VariableString ( "r_inGameVideo" ) ); Cvar_Set ( "ui_r_allowExtensions", Cvar_VariableString ( "r_allowExtensions" ) ); // Cvar_Set ( "ui_cg_shadows", Cvar_VariableString ( "cg_shadows" ) ); Cvar_Set ( "ui_r_modified", "0" ); } static void UI_SetSexandSoundForModel(const char* char_model) { int f,i; char soundpath[MAX_QPATH]; qboolean isFemale = qfalse; i = ui.FS_FOpenFile(va("models/players/%s/sounds.cfg", char_model), &f, FS_READ); if ( !f ) {//no? oh bother. Cvar_Reset("snd"); Cvar_Reset("sex"); return; } soundpath[0] = 0; ui.FS_Read(&soundpath, i, f); while (i >= 0 && soundpath[i] != '\n') { if (soundpath[i] == 'f') { isFemale = qtrue; soundpath[i] = 0; } i--; } i = 0; while (soundpath[i] && soundpath[i] != '\r' && soundpath[i] != '\n') { i++; } soundpath[i] = 0; ui.FS_FCloseFile(f); Cvar_Set ( "snd", soundpath); if (isFemale) { Cvar_Set ( "sex", "f"); } else { Cvar_Set ( "sex", "m"); } } static void UI_UpdateCharacterCvars ( void ) { const char *char_model = Cvar_VariableString ( "ui_char_model" ); UI_SetSexandSoundForModel(char_model); Cvar_Set ( "g_char_model", char_model ); Cvar_Set ( "g_char_skin_head", Cvar_VariableString ( "ui_char_skin_head" ) ); Cvar_Set ( "g_char_skin_torso", Cvar_VariableString ( "ui_char_skin_torso" ) ); Cvar_Set ( "g_char_skin_legs", Cvar_VariableString ( "ui_char_skin_legs" ) ); Cvar_Set ( "g_char_color_red", Cvar_VariableString ( "ui_char_color_red" ) ); Cvar_Set ( "g_char_color_green", Cvar_VariableString ( "ui_char_color_green" ) ); Cvar_Set ( "g_char_color_blue", Cvar_VariableString ( "ui_char_color_blue" ) ); } static void UI_GetCharacterCvars ( void ) { Cvar_Set ( "ui_char_skin_head", Cvar_VariableString ( "g_char_skin_head" ) ); Cvar_Set ( "ui_char_skin_torso", Cvar_VariableString ( "g_char_skin_torso" ) ); Cvar_Set ( "ui_char_skin_legs", Cvar_VariableString ( "g_char_skin_legs" ) ); Cvar_Set ( "ui_char_color_red", Cvar_VariableString ( "g_char_color_red" ) ); Cvar_Set ( "ui_char_color_green", Cvar_VariableString ( "g_char_color_green" ) ); Cvar_Set ( "ui_char_color_blue", Cvar_VariableString ( "g_char_color_blue" ) ); const char* model = Cvar_VariableString ( "g_char_model" ); Cvar_Set ( "ui_char_model", model ); for (int i = 0; i < uiInfo.playerSpeciesCount; i++) { if ( !Q_stricmp(model, uiInfo.playerSpecies[i].Name) ) { uiInfo.playerSpeciesIndex = i; } } } static void UI_UpdateSaberCvars ( void ) { Cvar_Set ( "g_saber_type", Cvar_VariableString ( "ui_saber_type" ) ); Cvar_Set ( "g_saber", Cvar_VariableString ( "ui_saber" ) ); Cvar_Set ( "g_saber2", Cvar_VariableString ( "ui_saber2" ) ); Cvar_Set ( "g_saber_color", Cvar_VariableString ( "ui_saber_color" ) ); Cvar_Set ( "g_saber2_color", Cvar_VariableString ( "ui_saber2_color" ) ); } #ifndef JK2_MODE static void UI_UpdateFightingStyleChoices ( void ) { // if (!Q_stricmp("staff",Cvar_VariableString ( "ui_saber_type" ))) { Cvar_Set ( "ui_fightingstylesallowed", "0" ); Cvar_Set ( "ui_newfightingstyle", "4" ); // SS_STAFF } else if (!Q_stricmp("dual",Cvar_VariableString ( "ui_saber_type" ))) { Cvar_Set ( "ui_fightingstylesallowed", "0" ); Cvar_Set ( "ui_newfightingstyle", "3" ); // SS_DUAL } else { // Get player state client_t *cl = &svs.clients[0]; // 0 because only ever us as a player playerState_t *pState; if (cl && cl->gentity && cl->gentity->client) { pState = cl->gentity->client; // Knows Fast style? if (pState->saberStylesKnown & (1<saberStylesKnown & (1<saberStylesKnown & (1<saberStylesKnown & (1<saberStylesKnown & (1<saberStylesKnown & (1<saberAnimLevel == SS_FAST) { Cvar_Set ( "ui_currentfightingstyle", "0" ); // FAST } else if (pState->saberAnimLevel == SS_STRONG) { Cvar_Set ( "ui_currentfightingstyle", "2" ); // STRONG } else { Cvar_Set ( "ui_currentfightingstyle", "1" ); // default MEDIUM } } else // No client so this must be first time { Cvar_Set ( "ui_currentfightingstyle", "1" ); // Default to MEDIUM Cvar_Set ( "ui_fightingstylesallowed", "0" ); // Default to no new styles allowed Cvar_Set ( "ui_newfightingstyle", "1" ); // MEDIUM } } } #endif // !JK2_MODE #define MAX_POWER_ENUMS 16 typedef struct { const char *title; short powerEnum; } powerEnum_t; static powerEnum_t powerEnums[MAX_POWER_ENUMS] = { #ifndef JK2_MODE { "absorb", FP_ABSORB }, #endif // !JK2_MODE { "heal", FP_HEAL }, { "mindtrick", FP_TELEPATHY }, #ifndef JK2_MODE { "protect", FP_PROTECT }, #endif // !JK2_MODE // Core powers { "jump", FP_LEVITATION }, { "pull", FP_PULL }, { "push", FP_PUSH }, #ifndef JK2_MODE { "sense", FP_SEE }, #endif // !JK2_MODE { "speed", FP_SPEED }, { "sabdef", FP_SABER_DEFENSE }, { "saboff", FP_SABER_OFFENSE }, { "sabthrow", FP_SABERTHROW }, // Dark powers #ifndef JK2_MODE { "drain", FP_DRAIN }, #endif // !JK2_MODE { "grip", FP_GRIP }, { "lightning", FP_LIGHTNING }, #ifndef JK2_MODE { "rage", FP_RAGE }, #endif // !JK2_MODE }; // Find the index to the Force Power in powerEnum array static qboolean UI_GetForcePowerIndex ( const char *forceName, short *forcePowerI ) { int i; // Find a match for the forceName passed in for (i=0;igentity->client; forcelevel = pState->forcePowerLevel[powerEnums[forcePowerI].powerEnum]; } else { forcelevel = uiInfo.forcePowerLevel[powerEnums[forcePowerI].powerEnum]; } char itemName[128]; Com_sprintf (itemName, sizeof(itemName), "%s_hexpic", powerEnums[forcePowerI].title); item = (itemDef_s *) Menu_FindItemByName(menu, itemName); if (item) { char itemGraphic[128]; Com_sprintf (itemGraphic, sizeof(itemGraphic), "gfx/menus/hex_pattern_%d",forcelevel >= 4 ? 3 : forcelevel); item->window.background = ui.R_RegisterShaderNoMip(itemGraphic); // If maxed out on power - don't allow update if (forcelevel>=3) { Com_sprintf (itemName, sizeof(itemName), "%s_fbutton", powerEnums[forcePowerI].title); item = (itemDef_s *) Menu_FindItemByName(menu, itemName); if (item) { item->action = 0; //you are bad, no action for you! item->descText = 0; //no desc either! } } } // Set weapons button to inactive UI_ForcePowerWeaponsButton(qfalse); } // Flip flop between being able to see the text showing the Force Point has or hasn't been allocated (Used by Force Power Allocation screen) static void UI_SetPowerTitleText ( qboolean showAllocated ) { menuDef_t *menu; itemDef_t *item; menu = Menu_GetFocused(); // Get current menu if (!menu) { return; } if (showAllocated) { // Show the text saying the force point has been allocated item = (itemDef_s *) Menu_FindItemByName(menu, "allocated_text"); if (item) { item->window.flags |= WINDOW_VISIBLE; } // Hide text saying the force point needs to be allocated item = (itemDef_s *) Menu_FindItemByName(menu, "allocate_text"); if (item) { item->window.flags &= ~WINDOW_VISIBLE; } } else { // Hide the text saying the force point has been allocated item = (itemDef_s *) Menu_FindItemByName(menu, "allocated_text"); if (item) { item->window.flags &= ~WINDOW_VISIBLE; } // Show text saying the force point needs to be allocated item = (itemDef_s *) Menu_FindItemByName(menu, "allocate_text"); if (item) { item->window.flags |= WINDOW_VISIBLE; } } } //. Find weapons button and make active/inactive (Used by Force Power Allocation screen) static void UI_ForcePowerWeaponsButton(qboolean activeFlag) { menuDef_t *menu; menu = Menu_GetFocused(); // Get current menu if (!menu) { return; } // Cheats are on so lets always let us pass if(trap_Cvar_VariableValue("helpUsObi") != 0) activeFlag = qtrue; // Find weaponsbutton itemDef_t *item; item = (itemDef_s *) Menu_FindItemByName(menu, "weaponbutton"); if (item) { // Make it active if (activeFlag) { item->window.flags &= ~WINDOW_INACTIVE; } else { item->window.flags |= WINDOW_INACTIVE; } } } void UI_SetItemColor(itemDef_t *item,const char *itemname,const char *name,vec4_t color); static void UI_SetHexPicLevel( const menuDef_t *menu,const int forcePowerI,const int powerLevel, const qboolean goldFlag ) { char itemName[128]; itemDef_t *item; // Find proper hex picture on menu Com_sprintf (itemName, sizeof(itemName), "%s_hexpic", powerEnums[forcePowerI].title); item = (itemDef_s *) Menu_FindItemByName((menuDef_t *) menu, itemName); // Now give it the proper hex graphic if (item) { char itemGraphic[128]; if (goldFlag) { Com_sprintf (itemGraphic, sizeof(itemGraphic), "gfx/menus/hex_pattern_%d_gold",powerLevel >= 4 ? 3 : powerLevel); } else { Com_sprintf (itemGraphic, sizeof(itemGraphic), "gfx/menus/hex_pattern_%d",powerLevel >= 4 ? 3 : powerLevel); } item->window.background = ui.R_RegisterShaderNoMip(itemGraphic); Com_sprintf (itemName, sizeof(itemName), "%s_fbutton", powerEnums[forcePowerI].title); item = (itemDef_s *) Menu_FindItemByName((menuDef_t *)menu, itemName); if (item) { if (goldFlag) { // Change description text to tell player they can decrement the force point item->descText = "@MENUS_REMOVEFP"; } else { // Change description text to tell player they can increment the force point item->descText = "@MENUS_ADDFP"; } } } } void UI_SetItemVisible(menuDef_t *menu,const char *itemname,qboolean visible); // if this is the first time into the force power allocation screen, show the INSTRUCTION screen static void UI_ForceHelpActive( void ) { int tier_storyinfo = Cvar_VariableIntegerValue( "tier_storyinfo" ); // First time, show instructions if (tier_storyinfo==1) { // Menus_OpenByName("ingameForceHelp"); Menus_ActivateByName("ingameForceHelp"); } } #ifndef JK2_MODE // Set the force levels depending on the level chosen static void UI_DemoSetForceLevels( void ) { menuDef_t *menu; menu = Menu_GetFocused(); // Get current menu if (!menu) { return; } char buffer[MAX_STRING_CHARS]; client_t* cl = &svs.clients[0]; // 0 because only ever us as a player playerState_t* pState = NULL; if( cl ) { pState = cl->gentity->client; } ui.Cvar_VariableStringBuffer( "ui_demo_level", buffer, sizeof(buffer)); if( Q_stricmp( buffer, "t1_sour")==0 ) {// NOTE : always set the uiInfo powers // level 1 in all core powers uiInfo.forcePowerLevel[FP_LEVITATION]=1; uiInfo.forcePowerLevel[FP_SPEED]=1; uiInfo.forcePowerLevel[FP_PUSH]=1; uiInfo.forcePowerLevel[FP_PULL]=1; uiInfo.forcePowerLevel[FP_SEE]=1; uiInfo.forcePowerLevel[FP_SABER_OFFENSE]=1; uiInfo.forcePowerLevel[FP_SABER_DEFENSE]=1; uiInfo.forcePowerLevel[FP_SABERTHROW]=1; // plus these extras uiInfo.forcePowerLevel[FP_HEAL]=1; uiInfo.forcePowerLevel[FP_TELEPATHY]=1; uiInfo.forcePowerLevel[FP_GRIP]=1; // and set the rest to zero uiInfo.forcePowerLevel[FP_ABSORB]=0; uiInfo.forcePowerLevel[FP_PROTECT]=0; uiInfo.forcePowerLevel[FP_DRAIN]=0; uiInfo.forcePowerLevel[FP_LIGHTNING]=0; uiInfo.forcePowerLevel[FP_RAGE]=0; } else { // level 3 in all core powers uiInfo.forcePowerLevel[FP_LEVITATION]=3; uiInfo.forcePowerLevel[FP_SPEED]=3; uiInfo.forcePowerLevel[FP_PUSH]=3; uiInfo.forcePowerLevel[FP_PULL]=3; uiInfo.forcePowerLevel[FP_SEE]=3; uiInfo.forcePowerLevel[FP_SABER_OFFENSE]=3; uiInfo.forcePowerLevel[FP_SABER_DEFENSE]=3; uiInfo.forcePowerLevel[FP_SABERTHROW]=3; // plus these extras uiInfo.forcePowerLevel[FP_HEAL]=1; uiInfo.forcePowerLevel[FP_TELEPATHY]=1; uiInfo.forcePowerLevel[FP_GRIP]=2; uiInfo.forcePowerLevel[FP_LIGHTNING]=1; uiInfo.forcePowerLevel[FP_PROTECT]=1; // and set the rest to zero uiInfo.forcePowerLevel[FP_ABSORB]=0; uiInfo.forcePowerLevel[FP_DRAIN]=0; uiInfo.forcePowerLevel[FP_RAGE]=0; } if (pState) {//i am carrying over from a previous level, so get the increased power! (non-core only) uiInfo.forcePowerLevel[FP_HEAL] = Q_max(pState->forcePowerLevel[FP_HEAL], uiInfo.forcePowerLevel[FP_HEAL]); uiInfo.forcePowerLevel[FP_TELEPATHY]=Q_max(pState->forcePowerLevel[FP_TELEPATHY], uiInfo.forcePowerLevel[FP_TELEPATHY]); uiInfo.forcePowerLevel[FP_GRIP]=Q_max(pState->forcePowerLevel[FP_GRIP], uiInfo.forcePowerLevel[FP_GRIP]); uiInfo.forcePowerLevel[FP_LIGHTNING]=Q_max(pState->forcePowerLevel[FP_LIGHTNING], uiInfo.forcePowerLevel[FP_LIGHTNING]); uiInfo.forcePowerLevel[FP_PROTECT]=Q_max(pState->forcePowerLevel[FP_PROTECT], uiInfo.forcePowerLevel[FP_PROTECT]); uiInfo.forcePowerLevel[FP_ABSORB]=Q_max(pState->forcePowerLevel[FP_ABSORB], uiInfo.forcePowerLevel[FP_ABSORB]); uiInfo.forcePowerLevel[FP_DRAIN]=Q_max(pState->forcePowerLevel[FP_DRAIN], uiInfo.forcePowerLevel[FP_DRAIN]); uiInfo.forcePowerLevel[FP_RAGE]=Q_max(pState->forcePowerLevel[FP_RAGE], uiInfo.forcePowerLevel[FP_RAGE]); } } #endif // !JK2_MODE // record the force levels into a cvar so when restoring player from map transition // the force levels are set up correctly static void UI_RecordForceLevels( void ) { menuDef_t *menu; menu = Menu_GetFocused(); // Get current menu if (!menu) { return; } const char *s2 = ""; int i; for (i=0;i< NUM_FORCE_POWERS; i++) { s2 = va("%s %i",s2, uiInfo.forcePowerLevel[i]); } Cvar_Set( "demo_playerfplvl", s2 ); } // record the weapons into a cvar so when restoring player from map transition // the force levels are set up correctly static void UI_RecordWeapons( void ) { menuDef_t *menu; menu = Menu_GetFocused(); // Get current menu if (!menu) { return; } const char *s2 = ""; int wpns = 0; // always add blaster and saber wpns |= (1<window.flags |= WINDOW_HASFOCUS; if (item->onFocus) { Item_RunScript(item, item->onFocus); } } // In upgrade mode so just turn the deallocate button on else { UI_SetItemVisible(menu,"force_icon",qtrue); UI_SetItemVisible(menu,"force_desc",qtrue); UI_SetItemVisible(menu,"deallocate_fbutton",qtrue); item = (itemDef_s *) Menu_FindItemByName(menu, va("%s_fbutton",powerEnums[uiInfo.forcePowerUpdated].title)); if (item) { item->window.flags |= WINDOW_HASFOCUS; } // Get player state client_t* cl = &svs.clients[0]; // 0 because only ever us as a player if (!cl) // No client, get out { return; } playerState_t* pState = cl->gentity->client; if (uiInfo.forcePowerUpdated == FP_UPDATED_NONE) { return; } // Update level description Com_sprintf ( itemName, sizeof(itemName), "%s_level%ddesc", powerEnums[uiInfo.forcePowerUpdated].title, pState->forcePowerLevel[powerEnums[uiInfo.forcePowerUpdated].powerEnum] ); item = (itemDef_s *) Menu_FindItemByName(menu, itemName); if (item) { item->window.flags |= WINDOW_VISIBLE; } } // If one was a chosen force power, high light it again. if (uiInfo.forcePowerUpdated>FP_UPDATED_NONE) { char itemhexName[128]; char itemiconName[128]; vec4_t color2 = { 1.0f, 1.0f, 1.0f, 1.0f}; Com_sprintf (itemhexName, sizeof(itemhexName), "%s_hexpic", powerEnums[uiInfo.forcePowerUpdated].title); Com_sprintf (itemiconName, sizeof(itemiconName), "%s_iconpic", powerEnums[uiInfo.forcePowerUpdated].title); UI_SetItemColor(item,itemhexName,"forecolor",color2); UI_SetItemColor(item,itemiconName,"forecolor",color2); } else { // Un-grey-out all icons UI_SetItemColor(item,"hexpic","forecolor",color); UI_SetItemColor(item,"iconpic","forecolor",color); } } // Decrement force power level (Used by Force Power Allocation screen) static void UI_DecrementCurrentForcePower ( void ) { menuDef_t *menu; itemDef_t *item; short i; vec4_t color = { 0.65f, 0.65f, 0.65f, 1.0f}; char itemName[128]; menu = Menu_GetFocused(); // Get current menu if (!menu) { return; } // Get player state client_t* cl = &svs.clients[0]; // 0 because only ever us as a player playerState_t* pState = NULL; int forcelevel; if( cl ) { pState = cl->gentity->client; forcelevel = pState->forcePowerLevel[powerEnums[uiInfo.forcePowerUpdated].powerEnum]; } else { forcelevel = uiInfo.forcePowerLevel[powerEnums[uiInfo.forcePowerUpdated].powerEnum]; } if (uiInfo.forcePowerUpdated == FP_UPDATED_NONE) { return; } DC->startLocalSound(uiInfo.uiDC.Assets.forceUnchosenSound, CHAN_AUTO ); if (forcelevel>0) { if( pState ) { pState->forcePowerLevel[powerEnums[uiInfo.forcePowerUpdated].powerEnum]--; // Decrement it forcelevel = pState->forcePowerLevel[powerEnums[uiInfo.forcePowerUpdated].powerEnum]; // Turn off power if level is 0 if (pState->forcePowerLevel[powerEnums[uiInfo.forcePowerUpdated].powerEnum]<1) { pState->forcePowersKnown &= ~( 1 << powerEnums[uiInfo.forcePowerUpdated].powerEnum ); } } else { uiInfo.forcePowerLevel[powerEnums[uiInfo.forcePowerUpdated].powerEnum]--; // Decrement it forcelevel = uiInfo.forcePowerLevel[powerEnums[uiInfo.forcePowerUpdated].powerEnum]; } } UI_SetHexPicLevel( menu,uiInfo.forcePowerUpdated,forcelevel,qfalse ); UI_ShowForceLevelDesc ( powerEnums[uiInfo.forcePowerUpdated].title ); // We just decremented a field so turn all buttons back on // Make it so all buttons can be clicked for (i=0;iwindow.flags |= WINDOW_VISIBLE; } } // Show point has not been allocated UI_SetPowerTitleText( qfalse); // Make weapons button inactive UI_ForcePowerWeaponsButton(qfalse); // Hide the deallocate button item = (itemDef_s *) Menu_FindItemByName(menu, "deallocate_fbutton"); if (item) { item->window.flags &= ~WINDOW_VISIBLE; // // Un-grey-out all icons UI_SetItemColor(item,"hexpic","forecolor",color); UI_SetItemColor(item,"iconpic","forecolor",color); } item = (itemDef_s *) Menu_FindItemByName(menu, va("%s_fbutton",powerEnums[uiInfo.forcePowerUpdated].title)); if (item) { item->window.flags |= WINDOW_HASFOCUS; } uiInfo.forcePowerUpdated = FP_UPDATED_NONE; // It's as if nothing happened. } void Item_MouseEnter(itemDef_t *item, float x, float y); // Try to increment force power level (Used by Force Power Allocation screen) static void UI_AffectForcePowerLevel ( const char *forceName ) { short forcePowerI=0,i; menuDef_t *menu; itemDef_t *item; menu = Menu_GetFocused(); // Get current menu if (!menu) { return; } if (!UI_GetForcePowerIndex ( forceName, &forcePowerI )) { return; } // Get player state client_t* cl = &svs.clients[0]; // 0 because only ever us as a player playerState_t* pState = NULL; int forcelevel; if( cl ) { pState = cl->gentity->client; forcelevel = pState->forcePowerLevel[powerEnums[forcePowerI].powerEnum]; } else { forcelevel = uiInfo.forcePowerLevel[powerEnums[forcePowerI].powerEnum]; } if (forcelevel>2) { // Too big, can't be incremented return; } // Increment power level. DC->startLocalSound(uiInfo.uiDC.Assets.forceChosenSound, CHAN_AUTO ); uiInfo.forcePowerUpdated = forcePowerI; // Remember which power was updated if( pState ) { pState->forcePowerLevel[powerEnums[forcePowerI].powerEnum]++; // Increment it pState->forcePowersKnown |= ( 1 << powerEnums[forcePowerI].powerEnum ); forcelevel = pState->forcePowerLevel[powerEnums[forcePowerI].powerEnum]; } else { uiInfo.forcePowerLevel[powerEnums[forcePowerI].powerEnum]++; // Increment it forcelevel = uiInfo.forcePowerLevel[powerEnums[forcePowerI].powerEnum]; } UI_SetHexPicLevel( menu,uiInfo.forcePowerUpdated,forcelevel,qtrue ); UI_ShowForceLevelDesc ( forceName ); // A field was updated, so make it so others can't be if (uiInfo.forcePowerUpdated>FP_UPDATED_NONE) { vec4_t color = { 0.25f, 0.25f, 0.25f, 1.0f}; char itemName[128]; // Make it so none of the other buttons can be clicked for (i=0;iwindow.flags &= ~WINDOW_VISIBLE; } } // Show point has been allocated UI_SetPowerTitleText ( qtrue ); // Make weapons button active UI_ForcePowerWeaponsButton(qtrue); // Make user_info Cvar_Set ( "ui_forcepower_inc", va("%d",uiInfo.forcePowerUpdated) ); // Just grab an item to hand it to the function. item = (itemDef_s *) Menu_FindItemByName(menu, "deallocate_fbutton"); if (item) { // Show all icons as greyed-out UI_SetItemColor(item,"hexpic","forecolor",color); UI_SetItemColor(item,"iconpic","forecolor",color); item->window.flags |= WINDOW_HASFOCUS; } } } static void UI_DecrementForcePowerLevel( void ) { int forcePowerI = Cvar_VariableIntegerValue( "ui_forcepower_inc" ); // Get player state client_t* cl = &svs.clients[0]; // 0 because only ever us as a player if (!cl) // No client, get out { return; } playerState_t* pState = cl->gentity->client; pState->forcePowerLevel[powerEnums[forcePowerI].powerEnum]--; // Decrement it } // Show force level description that matches current player level (Used by Force Power Allocation screen) static void UI_ShowForceLevelDesc ( const char *forceName ) { short forcePowerI=0; menuDef_t *menu; itemDef_t *item; menu = Menu_GetFocused(); // Get current menu if (!menu) { return; } if (!UI_GetForcePowerIndex ( forceName, &forcePowerI )) { return; } // Get player state client_t* cl = &svs.clients[0]; // 0 because only ever us as a player if (!cl) // No client, get out { return; } playerState_t* pState = cl->gentity->client; char itemName[128]; // Update level description Com_sprintf ( itemName, sizeof(itemName), "%s_level%ddesc", powerEnums[forcePowerI].title, pState->forcePowerLevel[powerEnums[forcePowerI].powerEnum] ); item = (itemDef_s *) Menu_FindItemByName(menu, itemName); if (item) { item->window.flags |= WINDOW_VISIBLE; } } // Reset force level powers screen to what it was before player upgraded them (Used by Force Power Allocation screen) static void UI_ResetForceLevels ( void ) { // What force ppower had the point added to it? if (uiInfo.forcePowerUpdated!=FP_UPDATED_NONE) { // Get player state client_t* cl = &svs.clients[0]; // 0 because only ever us as a player if (!cl) // No client, get out { return; } playerState_t* pState = cl->gentity->client; // Decrement that power pState->forcePowerLevel[powerEnums[uiInfo.forcePowerUpdated].powerEnum]--; menuDef_t *menu; itemDef_t *item; menu = Menu_GetFocused(); // Get current menu if (!menu) { return; } int i; char itemName[128]; // Make it so all buttons can be clicked for (i=0;iwindow.flags |= WINDOW_VISIBLE; } } UI_SetPowerTitleText( qfalse ); Com_sprintf (itemName, sizeof(itemName), "%s_fbutton", powerEnums[uiInfo.forcePowerUpdated].title); item = (itemDef_s *) Menu_FindItemByName(menu, itemName); if (item) { // Change description text to tell player they can increment the force point item->descText = "@MENUS_ADDFP"; } uiInfo.forcePowerUpdated = FP_UPDATED_NONE; } UI_ForcePowerWeaponsButton(qfalse); } #ifndef JK2_MODE // Set the Players known saber style static void UI_UpdateFightingStyle ( void ) { playerState_t *pState; int fightingStyle,saberStyle; fightingStyle = Cvar_VariableIntegerValue( "ui_newfightingstyle" ); if (fightingStyle == 1) { saberStyle = SS_MEDIUM; } else if (fightingStyle == 2) { saberStyle = SS_STRONG; } else if (fightingStyle == 3) { saberStyle = SS_DUAL; } else if (fightingStyle == 4) { saberStyle = SS_STAFF; } else // 0 is Fast { saberStyle = SS_FAST; } // Get player state client_t *cl = &svs.clients[0]; // 0 because only ever us as a player // No client, get out if (cl && cl->gentity && cl->gentity->client) { pState = cl->gentity->client; pState->saberStylesKnown |= (1<typeData; if( listPtr ) { listPtr->cursorPos = 0; } item->cursorPos = 0; } item = (itemDef_s *) Menu_FindItemByName((menuDef_t *) menu, "torsolistbox"); if (item) { listPtr = (listBoxDef_t*)item->typeData; if( listPtr ) { listPtr->cursorPos = 0; } item->cursorPos = 0; } item = (itemDef_s *) Menu_FindItemByName((menuDef_t *) menu, "lowerlistbox"); if (item) { listPtr = (listBoxDef_t*)item->typeData; if( listPtr ) { listPtr->cursorPos = 0; } item->cursorPos = 0; } item = (itemDef_t *) Menu_FindItemByName((menuDef_t *) menu, "colorbox"); if (item) { listPtr = (listBoxDef_t*)item->typeData; if( listPtr ) { listPtr->cursorPos = 0; } item->cursorPos = 0; } } } static void UI_ClearInventory ( void ) { // Get player state client_t* cl = &svs.clients[0]; // 0 because only ever us as a player if (!cl) // No client, get out { return; } if (cl->gentity && cl->gentity->client) { playerState_t* pState = cl->gentity->client; // Clear out inventory for the player int i; for (i=0;iinventory[i] = 0; } } } static void UI_GiveInventory ( const int itemIndex, const int amount ) { // Get player state client_t* cl = &svs.clients[0]; // 0 because only ever us as a player if (!cl) // No client, get out { return; } if (cl->gentity && cl->gentity->client) { playerState_t* pState = cl->gentity->client; if (itemIndex < MAX_INVENTORY) { pState->inventory[itemIndex]=amount; } } } //. Find weapons allocation screen BEGIN button and make active/inactive static void UI_WeaponAllocBeginButton(qboolean activeFlag) { menuDef_t *menu; menu = Menu_GetFocused(); // Get current menu if (!menu) { return; } int weap = Cvar_VariableIntegerValue( "weapon_menu" ); // Find begin button itemDef_t *item; item = Menu_GetMatchingItemByNumber(menu, weap, "beginmission"); if (item) { // Make it active if (activeFlag) { item->window.flags &= ~WINDOW_INACTIVE; } else { item->window.flags |= WINDOW_INACTIVE; } } } // If we have both weapons and the throwable weapon, turn on the begin mission button, // otherwise, turn it off static void UI_WeaponsSelectionsComplete( void ) { // We need two weapons and one throwable if (( uiInfo.selectedWeapon1 != NOWEAPON ) && ( uiInfo.selectedWeapon2 != NOWEAPON ) && ( uiInfo.selectedThrowWeapon != NOWEAPON )) { UI_WeaponAllocBeginButton(qtrue); // Turn it on } else { UI_WeaponAllocBeginButton(qfalse); // Turn it off } } // if this is the first time into the weapon allocation screen, show the INSTRUCTION screen static void UI_WeaponHelpActive( void ) { int tier_storyinfo = Cvar_VariableIntegerValue( "tier_storyinfo" ); menuDef_t *menu; menu = Menu_GetFocused(); // Get current menu if (!menu) { return; } // First time, show instructions if (tier_storyinfo==1) { UI_SetItemVisible(menu,"weapon_button",qfalse); UI_SetItemVisible(menu,"inst_stuff",qtrue); } // just act like normal else { UI_SetItemVisible(menu,"weapon_button",qtrue); UI_SetItemVisible(menu,"inst_stuff",qfalse); } } static void UI_InitWeaponSelect( void ) { UI_WeaponAllocBeginButton(qfalse); uiInfo.selectedWeapon1 = NOWEAPON; uiInfo.selectedWeapon2 = NOWEAPON; uiInfo.selectedThrowWeapon = NOWEAPON; } static void UI_ClearWeapons ( void ) { // Get player state client_t* cl = &svs.clients[0]; // 0 because only ever us as a player if (!cl) // No client, get out { return; } if (cl->gentity && cl->gentity->client) { playerState_t* pState = cl->gentity->client; // Clear out any weapons for the player pState->stats[ STAT_WEAPONS ] = 0; pState->weapon = WP_NONE; } } static void UI_GiveWeapon ( const int weaponIndex ) { // Get player state client_t* cl = &svs.clients[0]; // 0 because only ever us as a player if (!cl) // No client, get out { return; } if (cl->gentity && cl->gentity->client) { playerState_t* pState = cl->gentity->client; if (weaponIndexstats[ STAT_WEAPONS ] |= ( 1 << weaponIndex ); } } } static void UI_EquipWeapon ( const int weaponIndex ) { // Get player state client_t* cl = &svs.clients[0]; // 0 because only ever us as a player if (!cl) // No client, get out { return; } if (cl->gentity && cl->gentity->client) { playerState_t* pState = cl->gentity->client; if (weaponIndexweapon = weaponIndex; //force it to change //CG_ChangeWeapon( wp ); } } } static void UI_LoadMissionSelectMenu( const char *cvarName ) { int holdLevel = (int)trap_Cvar_VariableValue(cvarName); // Figure out which tier menu to load if ((holdLevel > 0) && (holdLevel < 5)) { UI_LoadMenus("ui/tier1.txt",qfalse); Menus_CloseByName("ingameMissionSelect1"); } else if ((holdLevel > 6) && (holdLevel < 10)) { UI_LoadMenus("ui/tier2.txt",qfalse); Menus_CloseByName("ingameMissionSelect2"); } else if ((holdLevel > 11) && (holdLevel < 15)) { UI_LoadMenus("ui/tier3.txt",qfalse); Menus_CloseByName("ingameMissionSelect3"); } } // Update the player weapons with the chosen weapon static void UI_AddWeaponSelection ( const int weaponIndex, const int ammoIndex, const int ammoAmount, const char *iconItemName,const char *litIconItemName, const char *hexBackground, const char *soundfile ) { itemDef_s *item, *iconItem,*litIconItem; menuDef_t *menu; menu = Menu_GetFocused(); // Get current menu if (!menu) { return; } iconItem = (itemDef_s *) Menu_FindItemByName(menu, iconItemName ); litIconItem = (itemDef_s *) Menu_FindItemByName(menu, litIconItemName ); const char *chosenItemName, *chosenButtonName; // has this weapon already been chosen? if (weaponIndex == uiInfo.selectedWeapon1) { UI_RemoveWeaponSelection ( 1 ); return; } else if (weaponIndex == uiInfo.selectedWeapon2) { UI_RemoveWeaponSelection ( 2 ); return; } // See if either slot is empty if ( uiInfo.selectedWeapon1 == NOWEAPON ) { chosenItemName = "chosenweapon1_icon"; chosenButtonName = "chosenweapon1_button"; uiInfo.selectedWeapon1 = weaponIndex; uiInfo.selectedWeapon1AmmoIndex = ammoIndex; memcpy( uiInfo.selectedWeapon1ItemName,hexBackground,sizeof(uiInfo.selectedWeapon1ItemName)); //Save the lit and unlit icons for the selected weapon slot uiInfo.litWeapon1Icon = litIconItem->window.background; uiInfo.unlitWeapon1Icon = iconItem->window.background; uiInfo.weapon1ItemButton = uiInfo.runScriptItem; uiInfo.weapon1ItemButton->descText = "@MENUS_CLICKREMOVE"; } else if ( uiInfo.selectedWeapon2 == NOWEAPON ) { chosenItemName = "chosenweapon2_icon"; chosenButtonName = "chosenweapon2_button"; uiInfo.selectedWeapon2 = weaponIndex; uiInfo.selectedWeapon2AmmoIndex = ammoIndex; memcpy( uiInfo.selectedWeapon2ItemName,hexBackground,sizeof(uiInfo.selectedWeapon2ItemName)); //Save the lit and unlit icons for the selected weapon slot uiInfo.litWeapon2Icon = litIconItem->window.background; uiInfo.unlitWeapon2Icon = iconItem->window.background; uiInfo.weapon2ItemButton = uiInfo.runScriptItem; uiInfo.weapon2ItemButton->descText = "@MENUS_CLICKREMOVE"; } else // Both slots are used, can't add it. { return; } item = (itemDef_s *) Menu_FindItemByName(menu, chosenItemName ); if ((item) && (iconItem)) { item->window.background = iconItem->window.background; item->window.flags |= WINDOW_VISIBLE; } // Turn on chosenweapon button so player can unchoose the weapon item = (itemDef_s *) Menu_FindItemByName(menu, chosenButtonName ); if (item) { item->window.background = iconItem->window.background; item->window.flags |= WINDOW_VISIBLE; } // Switch hex background to be 'on' item = (itemDef_s *) Menu_FindItemByName(menu, hexBackground ); if (item) { item->window.foreColor[0] = 0; item->window.foreColor[1] = 1; item->window.foreColor[2] = 0; item->window.foreColor[3] = 1; } // Get player state client_t* cl = &svs.clients[0]; // 0 because only ever us as a player // NOTE : this UIScript can now be run from outside the game, so don't // return out here, just skip this part if (cl) { // Add weapon if (cl->gentity && cl->gentity->client) { playerState_t* pState = cl->gentity->client; if ((weaponIndex>0) && (weaponIndexstats[ STAT_WEAPONS ] |= ( 1 << weaponIndex ); } // Give them ammo too if ((ammoIndex>0) && (ammoIndexammo[ ammoIndex ] = ammoAmount; } } } if( soundfile ) { DC->startLocalSound(DC->registerSound(soundfile, qfalse), CHAN_LOCAL ); } UI_WeaponsSelectionsComplete(); // Test to see if the mission begin button should turn on or off } // Update the player weapons with the chosen weapon static void UI_RemoveWeaponSelection ( const int weaponSelectionIndex ) { itemDef_s *item; menuDef_t *menu; const char *chosenItemName, *chosenButtonName,*background; int ammoIndex,weaponIndex; menu = Menu_GetFocused(); // Get current menu // Which item has it? if ( weaponSelectionIndex == 1 ) { chosenItemName = "chosenweapon1_icon"; chosenButtonName = "chosenweapon1_button"; background = uiInfo.selectedWeapon1ItemName; ammoIndex = uiInfo.selectedWeapon1AmmoIndex; weaponIndex = uiInfo.selectedWeapon1; if (uiInfo.weapon1ItemButton) { uiInfo.weapon1ItemButton->descText = "@MENUS_CLICKSELECT"; uiInfo.weapon1ItemButton = NULL; } } else if ( weaponSelectionIndex == 2 ) { chosenItemName = "chosenweapon2_icon"; chosenButtonName = "chosenweapon2_button"; background = uiInfo.selectedWeapon2ItemName; ammoIndex = uiInfo.selectedWeapon2AmmoIndex; weaponIndex = uiInfo.selectedWeapon2; if (uiInfo.weapon2ItemButton) { uiInfo.weapon2ItemButton->descText = "@MENUS_CLICKSELECT"; uiInfo.weapon2ItemButton = NULL; } } else { return; } // Reset background of upper icon item = (itemDef_s *) Menu_FindItemByName( menu, background ); if ( item ) { item->window.foreColor[0] = 0.0f; item->window.foreColor[1] = 0.5f; item->window.foreColor[2] = 0.0f; item->window.foreColor[3] = 1.0f; } // Hide it icon item = (itemDef_s *) Menu_FindItemByName( menu, chosenItemName ); if ( item ) { item->window.flags &= ~WINDOW_VISIBLE; } // Hide button item = (itemDef_s *) Menu_FindItemByName( menu, chosenButtonName ); if ( item ) { item->window.flags &= ~WINDOW_VISIBLE; } // Get player state client_t* cl = &svs.clients[0]; // 0 because only ever us as a player // NOTE : this UIScript can now be run from outside the game, so don't // return out here, just skip this part if (cl) // No client, get out { // Remove weapon if (cl->gentity && cl->gentity->client) { playerState_t* pState = cl->gentity->client; if ((weaponIndex>0) && (weaponIndexstats[ STAT_WEAPONS ] &= ~( 1 << weaponIndex ); } // Remove ammo too if ((ammoIndex>0) && (ammoIndexammo[ ammoIndex ] = 0; } } } } // Now do a little clean up if ( weaponSelectionIndex == 1 ) { uiInfo.selectedWeapon1 = NOWEAPON; memset(uiInfo.selectedWeapon1ItemName,0,sizeof(uiInfo.selectedWeapon1ItemName)); uiInfo.selectedWeapon1AmmoIndex = 0; } else if ( weaponSelectionIndex == 2 ) { uiInfo.selectedWeapon2 = NOWEAPON; memset(uiInfo.selectedWeapon2ItemName,0,sizeof(uiInfo.selectedWeapon2ItemName)); uiInfo.selectedWeapon2AmmoIndex = 0; } #ifndef JK2_MODE //FIXME hack to prevent error in jk2 by disabling DC->startLocalSound(DC->registerSound("sound/interface/weapon_deselect.mp3", qfalse), CHAN_LOCAL ); #endif UI_WeaponsSelectionsComplete(); // Test to see if the mission begin button should turn on or off } static void UI_NormalWeaponSelection ( const int selectionslot ) { itemDef_s *item; menuDef_t *menu; menu = Menu_GetFocused(); // Get current menu if (!menu) { return; } if (selectionslot == 1) { item = (itemDef_s *) Menu_FindItemByName( menu, "chosenweapon1_icon" ); if (item) { item->window.background = uiInfo.unlitWeapon1Icon; } } if (selectionslot == 2) { item = (itemDef_s *) Menu_FindItemByName( menu, "chosenweapon2_icon" ); if (item) { item->window.background = uiInfo.unlitWeapon2Icon; } } } static void UI_HighLightWeaponSelection ( const int selectionslot ) { itemDef_s *item; menuDef_t *menu; menu = Menu_GetFocused(); // Get current menu if (!menu) { return; } if (selectionslot == 1) { item = (itemDef_s *) Menu_FindItemByName( menu, "chosenweapon1_icon" ); if (item) { item->window.background = uiInfo.litWeapon1Icon; } } if (selectionslot == 2) { item = (itemDef_s *) Menu_FindItemByName( menu, "chosenweapon2_icon" ); if (item) { item->window.background = uiInfo.litWeapon2Icon; } } } // Update the player throwable weapons (okay it's a bad description) with the chosen weapon static void UI_AddThrowWeaponSelection ( const int weaponIndex, const int ammoIndex, const int ammoAmount, const char *iconItemName,const char *litIconItemName, const char *hexBackground, const char *soundfile ) { itemDef_s *item, *iconItem,*litIconItem; menuDef_t *menu; menu = Menu_GetFocused(); // Get current menu if (!menu) { return; } iconItem = (itemDef_s *) Menu_FindItemByName(menu, iconItemName ); litIconItem = (itemDef_s *) Menu_FindItemByName(menu, litIconItemName ); const char *chosenItemName, *chosenButtonName; // Has a throw weapon already been chosen? if (uiInfo.selectedThrowWeapon!=NOWEAPON) { // Clicked on the selected throwable weapon if (uiInfo.selectedThrowWeapon==weaponIndex) { // Deselect it UI_RemoveThrowWeaponSelection(); } return; } chosenItemName = "chosenthrowweapon_icon"; chosenButtonName = "chosenthrowweapon_button"; uiInfo.selectedThrowWeapon = weaponIndex; uiInfo.selectedThrowWeaponAmmoIndex = ammoIndex; uiInfo.weaponThrowButton = uiInfo.runScriptItem; if (uiInfo.weaponThrowButton) { uiInfo.weaponThrowButton->descText = "@MENUS_CLICKREMOVE"; } memcpy( uiInfo.selectedThrowWeaponItemName,hexBackground,sizeof(uiInfo.selectedWeapon1ItemName)); //Save the lit and unlit icons for the selected weapon slot uiInfo.litThrowableIcon = litIconItem->window.background; uiInfo.unlitThrowableIcon = iconItem->window.background; item = (itemDef_s *) Menu_FindItemByName(menu, chosenItemName ); if ((item) && (iconItem)) { item->window.background = iconItem->window.background; item->window.flags |= WINDOW_VISIBLE; } // Turn on throwchosenweapon button so player can unchoose the weapon item = (itemDef_s *) Menu_FindItemByName(menu, chosenButtonName ); if (item) { item->window.background = iconItem->window.background; item->window.flags |= WINDOW_VISIBLE; } // Switch hex background to be 'on' item = (itemDef_s *) Menu_FindItemByName(menu, hexBackground ); if (item) { item->window.foreColor[0] = 0.0f; item->window.foreColor[1] = 0.0f; item->window.foreColor[2] = 1.0f; item->window.foreColor[3] = 1.0f; } // Get player state client_t* cl = &svs.clients[0]; // 0 because only ever us as a player // NOTE : this UIScript can now be run from outside the game, so don't // return out here, just skip this part if (cl) // No client, get out { // Add weapon if (cl->gentity && cl->gentity->client) { playerState_t* pState = cl->gentity->client; if ((weaponIndex>0) && (weaponIndexstats[ STAT_WEAPONS ] |= ( 1 << weaponIndex ); } // Give them ammo too if ((ammoIndex>0) && (ammoIndexammo[ ammoIndex ] = ammoAmount; } } } if( soundfile ) { DC->startLocalSound(DC->registerSound(soundfile, qfalse), CHAN_LOCAL ); } UI_WeaponsSelectionsComplete(); // Test to see if the mission begin button should turn on or off } // Update the player weapons with the chosen throw weapon static void UI_RemoveThrowWeaponSelection ( void ) { itemDef_s *item; menuDef_t *menu; const char *chosenItemName, *chosenButtonName,*background; menu = Menu_GetFocused(); // Get current menu // Weapon not chosen if ( uiInfo.selectedThrowWeapon == NOWEAPON ) { return; } chosenItemName = "chosenthrowweapon_icon"; chosenButtonName = "chosenthrowweapon_button"; background = uiInfo.selectedThrowWeaponItemName; // Reset background of upper icon item = (itemDef_s *) Menu_FindItemByName( menu, background ); if ( item ) { item->window.foreColor[0] = 0.0f; item->window.foreColor[1] = 0.0f; item->window.foreColor[2] = 0.5f; item->window.foreColor[3] = 1.0f; } // Hide it icon item = (itemDef_s *) Menu_FindItemByName( menu, chosenItemName ); if ( item ) { item->window.flags &= ~WINDOW_VISIBLE; } // Hide button item = (itemDef_s *) Menu_FindItemByName( menu, chosenButtonName ); if ( item ) { item->window.flags &= ~WINDOW_VISIBLE; } // Get player state client_t* cl = &svs.clients[0]; // 0 because only ever us as a player // NOTE : this UIScript can now be run from outside the game, so don't // return out here, just skip this part if (cl) // No client, get out { // Remove weapon if (cl->gentity && cl->gentity->client) { playerState_t* pState = cl->gentity->client; if ((uiInfo.selectedThrowWeapon>0) && (uiInfo.selectedThrowWeaponstats[ STAT_WEAPONS ] &= ~( 1 << uiInfo.selectedThrowWeapon ); } // Remove ammo too if ((uiInfo.selectedThrowWeaponAmmoIndex>0) && (uiInfo.selectedThrowWeaponAmmoIndexammo[ uiInfo.selectedThrowWeaponAmmoIndex ] = 0; } } } // Now do a little clean up uiInfo.selectedThrowWeapon = NOWEAPON; memset(uiInfo.selectedThrowWeaponItemName,0,sizeof(uiInfo.selectedThrowWeaponItemName)); uiInfo.selectedThrowWeaponAmmoIndex = 0; if (uiInfo.weaponThrowButton) { uiInfo.weaponThrowButton->descText = "@MENUS_CLICKSELECT"; uiInfo.weaponThrowButton = NULL; } #ifndef JK2_MODE //FIXME hack to prevent error in jk2 by disabling DC->startLocalSound(DC->registerSound("sound/interface/weapon_deselect.mp3", qfalse), CHAN_LOCAL ); #endif UI_WeaponsSelectionsComplete(); // Test to see if the mission begin button should turn on or off } static void UI_NormalThrowSelection ( void ) { itemDef_s *item; menuDef_t *menu; menu = Menu_GetFocused(); // Get current menu if (!menu) { return; } item = (itemDef_s *) Menu_FindItemByName( menu, "chosenthrowweapon_icon" ); item->window.background = uiInfo.unlitThrowableIcon; } static void UI_HighLightThrowSelection ( void ) { itemDef_s *item; menuDef_t *menu; menu = Menu_GetFocused(); // Get current menu if (!menu) { return; } item = (itemDef_s *) Menu_FindItemByName( menu, "chosenthrowweapon_icon" ); item->window.background = uiInfo.litThrowableIcon; } static void UI_GetSaberCvars ( void ) { Cvar_Set ( "ui_saber_type", Cvar_VariableString ( "g_saber_type" ) ); Cvar_Set ( "ui_saber", Cvar_VariableString ( "g_saber" ) ); Cvar_Set ( "ui_saber2", Cvar_VariableString ( "g_saber2" ) ); Cvar_Set ( "ui_saber_color", Cvar_VariableString ( "g_saber_color" ) ); Cvar_Set ( "ui_saber2_color", Cvar_VariableString ( "g_saber2_color" ) ); Cvar_Set ( "ui_newfightingstyle", "0"); } static void UI_ResetSaberCvars ( void ) { Cvar_Set ( "g_saber_type", "single" ); Cvar_Set ( "g_saber", "single_1" ); Cvar_Set ( "g_saber2", "" ); Cvar_Set ( "ui_saber_type", "single" ); Cvar_Set ( "ui_saber", "single_1" ); Cvar_Set ( "ui_saber2", "" ); } extern qboolean ItemParse_asset_model_go( itemDef_t *item, const char *name ); extern qboolean ItemParse_model_g2skin_go( itemDef_t *item, const char *skinName ); static void UI_UpdateCharacterSkin( void ) { menuDef_t *menu; itemDef_t *item; char skin[MAX_QPATH]; menu = Menu_GetFocused(); // Get current menu if (!menu) { return; } item = (itemDef_s *) Menu_FindItemByName(menu, "character"); if (!item) { Com_Error( ERR_FATAL, "UI_UpdateCharacterSkin: Could not find item (character) in menu (%s)", menu->window.name); } Com_sprintf( skin, sizeof( skin ), "models/players/%s/|%s|%s|%s", Cvar_VariableString ( "ui_char_model"), Cvar_VariableString ( "ui_char_skin_head"), Cvar_VariableString ( "ui_char_skin_torso"), Cvar_VariableString ( "ui_char_skin_legs") ); ItemParse_model_g2skin_go( item, skin ); } static void UI_UpdateCharacter( qboolean changedModel ) { menuDef_t *menu; itemDef_t *item; char modelPath[MAX_QPATH]; menu = Menu_GetFocused(); // Get current menu if (!menu) { return; } item = (itemDef_s *) Menu_FindItemByName(menu, "character"); if (!item) { Com_Error( ERR_FATAL, "UI_UpdateCharacter: Could not find item (character) in menu (%s)", menu->window.name); } ItemParse_model_g2anim_go( item, ui_char_anim.string ); Com_sprintf( modelPath, sizeof( modelPath ), "models/players/%s/model.glm", Cvar_VariableString ( "ui_char_model" ) ); ItemParse_asset_model_go( item, modelPath ); if ( changedModel ) {//set all skins to first skin since we don't know you always have all skins //FIXME: could try to keep the same spot in each list as you swtich models UI_FeederSelection(FEEDER_PLAYER_SKIN_HEAD, 0, item); //fixme, this is not really the right item!! UI_FeederSelection(FEEDER_PLAYER_SKIN_TORSO, 0, item); UI_FeederSelection(FEEDER_PLAYER_SKIN_LEGS, 0, item); UI_FeederSelection(FEEDER_COLORCHOICES, 0, item); } UI_UpdateCharacterSkin(); } void UI_UpdateSaberType( void ) { char sType[MAX_QPATH]; DC->getCVarString( "ui_saber_type", sType, sizeof(sType) ); if ( Q_stricmp( "single", sType ) == 0 || Q_stricmp( "staff", sType ) == 0 ) { DC->setCVar( "ui_saber2", "" ); } } static void UI_UpdateSaberHilt( qboolean secondSaber ) { menuDef_t *menu; itemDef_t *item; char model[MAX_QPATH]; char modelPath[MAX_QPATH]; char skinPath[MAX_QPATH]; menu = Menu_GetFocused(); // Get current menu (either video or ingame video, I would assume) if (!menu) { return; } const char *itemName; const char *saberCvarName; if ( secondSaber ) { itemName = "saber2"; saberCvarName = "ui_saber2"; } else { itemName = "saber"; saberCvarName = "ui_saber"; } item = (itemDef_s *) Menu_FindItemByName(menu, itemName ); if(!item) { Com_Error( ERR_FATAL, "UI_UpdateSaberHilt: Could not find item (%s) in menu (%s)", itemName, menu->window.name); } DC->getCVarString( saberCvarName, model, sizeof(model) ); //read this from the sabers.cfg if ( UI_SaberModelForSaber( model, modelPath ) ) {//successfully found a model ItemParse_asset_model_go( item, modelPath );//set the model //get the customSkin, if any //COM_StripExtension( modelPath, skinPath, sizeof(skinPath) ); //COM_DefaultExtension( skinPath, sizeof( skinPath ), ".skin" ); if ( UI_SaberSkinForSaber( model, skinPath ) ) { ItemParse_model_g2skin_go( item, skinPath );//apply the skin } else { ItemParse_model_g2skin_go( item, NULL );//apply the skin } } } /* static void UI_UpdateSaberColor( qboolean secondSaber ) { int sabernumber; if (secondSaber) sabernumber = 2; else sabernumber = 1; ui.Cmd_ExecuteText( EXEC_APPEND, va("sabercolor %i %s\n",sabernumber, Cvar_VariableString("g_saber_color"))); } */ char GoToMenu[1024]; /* ================= Menus_SaveGoToMenu ================= */ void Menus_SaveGoToMenu(const char *menuTo) { memcpy(GoToMenu, menuTo, sizeof(GoToMenu)); } /* ================= UI_CheckVid1Data ================= */ void UI_CheckVid1Data(const char *menuTo,const char *warningMenuName) { menuDef_t *menu; itemDef_t *applyChanges; menu = Menu_GetFocused(); // Get current menu (either video or ingame video, I would assume) if (!menu) { Com_Printf(S_COLOR_YELLOW"WARNING: No videoMenu was found. Video data could not be checked\n"); return; } applyChanges = (itemDef_s *) Menu_FindItemByName(menu, "applyChanges"); if (!applyChanges) { // Menus_CloseAll(); Menus_OpenByName(menuTo); return; } if ((applyChanges->window.flags & WINDOW_VISIBLE)) // Is the APPLY CHANGES button active? { // Menus_SaveGoToMenu(menuTo); // Save menu you're going to // Menus_HideItems(menu->window.name); // HIDE videMenu in case you have to come back Menus_OpenByName(warningMenuName); // Give warning } else { // Menus_CloseAll(); // Menus_OpenByName(menuTo); } } /* ================= UI_ResetDefaults ================= */ void UI_ResetDefaults( void ) { ui.Cmd_ExecuteText( EXEC_APPEND, "cvar_restart\n"); Controls_SetDefaults(); ui.Cmd_ExecuteText( EXEC_APPEND, "exec default.cfg\n"); ui.Cmd_ExecuteText( EXEC_APPEND, "exec weapons_vr.cfg\n"); ui.Cmd_ExecuteText( EXEC_APPEND, "vid_restart\n" ); } /* ======================= UI_SortSaveGames ======================= */ static int UI_SortSaveGames( const void *A, const void *B ) { const int &a = ((savedata_t*)A)->currentSaveFileDateTime; const int &b = ((savedata_t*)B)->currentSaveFileDateTime; if (a > b) { return -1; } else { return (a < b); } } /* ======================= UI_AdjustSaveGameListBox ======================= */ // Yeah I could get fired for this... in a world of good and bad, this is bad // I wish we passed in the menu item to RunScript(), oh well... void UI_AdjustSaveGameListBox( int currentLine ) { menuDef_t *menu; itemDef_t *item; // could be in either the ingame or shell load menu (I know, I know it's bad) menu = Menus_FindByName("loadgameMenu"); if( !menu ) { menu = Menus_FindByName("ingameloadMenu"); } if (menu) { item = (itemDef_s *) Menu_FindItemByName((menuDef_t *) menu, "loadgamelist"); if (item) { listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData; if( listPtr ) { listPtr->cursorPos = currentLine; } item->cursorPos = currentLine; } } } /* ================= ReadSaveDirectory ================= */ //JLFSAVEGAME MPNOTUSED void ReadSaveDirectory (void) { int i; char *holdChar; int len; int fileCnt; // Clear out save data memset(s_savedata,0,sizeof(s_savedata)); s_savegame.saveFileCnt = 0; Cvar_Set("ui_gameDesc", "" ); // Blank out comment Cvar_Set("ui_SelectionOK", "0" ); #ifdef JK2_MODE memset( screenShotBuf,0,(SG_SCR_WIDTH * SG_SCR_HEIGHT * 4)); //blank out sshot #endif // Get everything in saves directory fileCnt = ui.FS_GetFileList("saves", ".sav", s_savegame.listBuf, LISTBUFSIZE ); Cvar_Set("ui_ResumeOK", "0" ); holdChar = s_savegame.listBuf; for ( i = 0; i < fileCnt; i++ ) { // strip extension len = strlen( holdChar ); holdChar[len-4] = '\0'; if ( Q_stricmp("current",holdChar)!=0 ) { time_t result; if (Q_stricmp("auto",holdChar)==0) { Cvar_Set("ui_ResumeOK", "1" ); } else { // Is this a valid file??? & Get comment of file result = ui.SG_GetSaveGameComment(holdChar, s_savedata[s_savegame.saveFileCnt].currentSaveFileComments, s_savedata[s_savegame.saveFileCnt].currentSaveFileMap); if (result != 0) // ignore Bad save game { s_savedata[s_savegame.saveFileCnt].currentSaveFileName = holdChar; s_savedata[s_savegame.saveFileCnt].currentSaveFileDateTime = result; struct tm *localTime; localTime = localtime( &result ); char timeStr[20] = {0}; strftime( timeStr, sizeof( timeStr ), "%y/%m/%d %H:%M", localTime ); strcpy(s_savedata[s_savegame.saveFileCnt].currentSaveFileDateTimeString, timeStr ); s_savegame.saveFileCnt++; if (s_savegame.saveFileCnt == MAX_SAVELOADFILES) { break; } } } } holdChar += len + 1; //move to next item } qsort( s_savedata, s_savegame.saveFileCnt, sizeof(savedata_t), UI_SortSaveGames ); }