q3rally/engine/code/q3_ui/ui_teamorders.c
zturtleman 9b86138351 ioquake3 resync to revision 3550 from 3534.
Fix IQM quat normalize fail case
Remove erroneous newlines from Com_Error in sdl_glimp.c
Restore OpenGL 1.1 support (GL_CLAMP)
q3rcc: Allow to override build date
Fix lightning gun handling for corpses and single player podiums
Fix for macOS Catalina screen resolution issue
Fix team orders menu not listing clients with lower clientnums
Fix duplicate team join center print for bots and g_teamAutoJoin
E2K: fixed build by MCST lcc compiler when using USE_CURL=1 option
2020-03-15 19:40:23 +00:00

450 lines
11 KiB
C

/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2002-2015 Q3Rally Team (Per Thormann - q3rally@gmail.com)
This file is part of q3rally source code.
q3rally source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
q3rally source code 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 q3rally; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//
/*
=======================================================================
TEAM ORDERS MENU
=======================================================================
*/
#include "ui_local.h"
#define ART_FRAME "menu/art/addbotframe"
#define ART_BACK0 "menu/art/back_0"
#define ART_BACK1 "menu/art/back_1"
#define ID_LIST_BOTS 10
#define ID_LIST_CTF_ORDERS 11
#define ID_LIST_TEAM_ORDERS 12
typedef struct {
menuframework_s menu;
menutext_s banner;
menubitmap_s frame;
menulist_s list;
menubitmap_s back;
int gametype;
int numBots;
int selectedBot;
char *bots[9];
char botNames[9][16];
} teamOrdersMenuInfo_t;
static teamOrdersMenuInfo_t teamOrdersMenuInfo;
#define NUM_CTF_ORDERS 7
static const char *ctfOrders[] = {
"I Am the Leader",
"Defend the Base",
"Follow Me",
"Get Enemy Flag",
"Camp Here",
"Report",
"I Relinquish Command",
NULL
};
static const char *ctfMessages[] = {
"i am the leader",
"%s defend the base",
"%s follow me",
"%s get enemy flag",
"%s camp here",
"%s report",
"i stop being the leader",
NULL
};
#define NUM_TEAM_ORDERS 6
static const char *teamOrders[] = {
"I Am the Leader",
"Follow Me",
"Roam",
"Camp Here",
"Report",
"I Relinquish Command",
NULL
};
static const char *teamMessages[] = {
"i am the leader",
"%s follow me",
"%s roam",
"%s camp here",
"%s report",
"i stop being the leader",
NULL
};
/*
===============
UI_TeamOrdersMenu_BackEvent
===============
*/
static void UI_TeamOrdersMenu_BackEvent( void *ptr, int event ) {
if( event != QM_ACTIVATED ) {
return;
}
UI_PopMenu();
}
/*
===============
UI_TeamOrdersMenu_SetList
===============
*/
static void UI_TeamOrdersMenu_SetList( int id ) {
switch( id ) {
default:
case ID_LIST_BOTS:
teamOrdersMenuInfo.list.generic.id = id;
teamOrdersMenuInfo.list.numitems = teamOrdersMenuInfo.numBots;
teamOrdersMenuInfo.list.itemnames = (const char **)teamOrdersMenuInfo.bots;
break;
case ID_LIST_CTF_ORDERS:
teamOrdersMenuInfo.list.generic.id = id;
teamOrdersMenuInfo.list.numitems = NUM_CTF_ORDERS;
teamOrdersMenuInfo.list.itemnames = ctfOrders;
break;
case ID_LIST_TEAM_ORDERS:
teamOrdersMenuInfo.list.generic.id = id;
teamOrdersMenuInfo.list.numitems = NUM_TEAM_ORDERS;
teamOrdersMenuInfo.list.itemnames = teamOrders;
break;
}
teamOrdersMenuInfo.list.generic.bottom = teamOrdersMenuInfo.list.generic.top + teamOrdersMenuInfo.list.numitems * PROP_HEIGHT;
}
/*
=================
UI_TeamOrdersMenu_Key
=================
*/
sfxHandle_t UI_TeamOrdersMenu_Key( int key ) {
menulist_s *l;
int x;
int y;
int index;
l = (menulist_s *)Menu_ItemAtCursor( &teamOrdersMenuInfo.menu );
if( l != &teamOrdersMenuInfo.list ) {
return Menu_DefaultKey( &teamOrdersMenuInfo.menu, key );
}
switch( key ) {
case K_MOUSE1:
x = l->generic.left;
y = l->generic.top;
if( UI_CursorInRect( x, y, l->generic.right - x, l->generic.bottom - y ) ) {
index = (uis.cursory - y) / PROP_HEIGHT;
l->oldvalue = l->curvalue;
l->curvalue = index;
if( l->generic.callback ) {
l->generic.callback( l, QM_ACTIVATED );
return menu_move_sound;
}
}
return menu_null_sound;
case K_KP_UPARROW:
case K_UPARROW:
l->oldvalue = l->curvalue;
if( l->curvalue == 0 ) {
l->curvalue = l->numitems - 1;
}
else {
l->curvalue--;
}
return menu_move_sound;
case K_KP_DOWNARROW:
case K_DOWNARROW:
l->oldvalue = l->curvalue;
if( l->curvalue == l->numitems - 1 ) {
l->curvalue = 0;;
}
else {
l->curvalue++;
}
return menu_move_sound;
}
return Menu_DefaultKey( &teamOrdersMenuInfo.menu, key );
}
/*
=================
UI_TeamOrdersMenu_ListDraw
=================
*/
static void UI_TeamOrdersMenu_ListDraw( void *self ) {
menulist_s *l;
int x;
int y;
int i;
float *color;
qboolean hasfocus;
int style;
l = (menulist_s *)self;
hasfocus = (l->generic.parent->cursor == l->generic.menuPosition);
x = 320;//l->generic.x;
y = l->generic.y;
for( i = 0; i < l->numitems; i++ ) {
style = UI_LEFT|UI_SMALLFONT|UI_CENTER;
if( i == l->curvalue ) {
color = color_yellow;
if( hasfocus ) {
style |= UI_PULSE;
}
}
else {
color = color_orange;
}
UI_DrawProportionalString( x, y, l->itemnames[i], style, color );
y += PROP_HEIGHT;
}
}
/*
===============
UI_TeamOrdersMenu_ListEvent
===============
*/
static void UI_TeamOrdersMenu_ListEvent( void *ptr, int event ) {
int id;
int selection;
char message[256];
if (event != QM_ACTIVATED)
return;
id = ((menulist_s *)ptr)->generic.id;
selection = ((menulist_s *)ptr)->curvalue;
if( id == ID_LIST_BOTS ) {
teamOrdersMenuInfo.selectedBot = selection;
if( teamOrdersMenuInfo.gametype == GT_CTF ) {
UI_TeamOrdersMenu_SetList( ID_LIST_CTF_ORDERS );
}
else {
UI_TeamOrdersMenu_SetList( ID_LIST_TEAM_ORDERS );
}
return;
}
if( id == ID_LIST_CTF_ORDERS ) {
Com_sprintf( message, sizeof(message), ctfMessages[selection], teamOrdersMenuInfo.botNames[teamOrdersMenuInfo.selectedBot] );
}
else {
Com_sprintf( message, sizeof(message), teamMessages[selection], teamOrdersMenuInfo.botNames[teamOrdersMenuInfo.selectedBot] );
}
trap_Cmd_ExecuteText( EXEC_APPEND, va( "say_team \"%s\"\n", message ) );
UI_PopMenu();
}
/*
===============
UI_TeamOrdersMenu_BuildBotList
===============
*/
static void UI_TeamOrdersMenu_BuildBotList( void ) {
uiClientState_t cs;
int numPlayers;
int isBot;
int n;
char playerTeam;
char botTeam;
char info[MAX_INFO_STRING];
for( n = 0; n < 9; n++ ) {
teamOrdersMenuInfo.bots[n] = teamOrdersMenuInfo.botNames[n];
}
trap_GetClientState( &cs );
Q_strncpyz( teamOrdersMenuInfo.botNames[0], "Everyone", 16 );
teamOrdersMenuInfo.numBots = 1;
trap_GetConfigString( CS_SERVERINFO, info, sizeof(info) );
numPlayers = atoi( Info_ValueForKey( info, "sv_maxclients" ) );
teamOrdersMenuInfo.gametype = atoi( Info_ValueForKey( info, "g_gametype" ) );
trap_GetConfigString( CS_PLAYERS + cs.clientNum, info, MAX_INFO_STRING );
playerTeam = *Info_ValueForKey( info, "t" );
for( n = 0; n < numPlayers && teamOrdersMenuInfo.numBots < 9; n++ ) {
if( n == cs.clientNum ) {
continue;
}
trap_GetConfigString( CS_PLAYERS + n, info, MAX_INFO_STRING );
isBot = atoi( Info_ValueForKey( info, "skill" ) );
if( !isBot ) {
continue;
}
botTeam = *Info_ValueForKey( info, "t" );
if( botTeam != playerTeam ) {
continue;
}
Q_strncpyz( teamOrdersMenuInfo.botNames[teamOrdersMenuInfo.numBots], Info_ValueForKey( info, "n" ), 16 );
Q_CleanStr( teamOrdersMenuInfo.botNames[teamOrdersMenuInfo.numBots] );
teamOrdersMenuInfo.numBots++;
}
}
/*
===============
UI_TeamOrdersMenu_Init
===============
*/
static void UI_TeamOrdersMenu_Init( void ) {
UI_TeamOrdersMenu_Cache();
memset( &teamOrdersMenuInfo, 0, sizeof(teamOrdersMenuInfo) );
teamOrdersMenuInfo.menu.fullscreen = qfalse;
teamOrdersMenuInfo.menu.key = UI_TeamOrdersMenu_Key;
UI_TeamOrdersMenu_BuildBotList();
teamOrdersMenuInfo.banner.generic.type = MTYPE_BTEXT;
teamOrdersMenuInfo.banner.generic.x = 320;
teamOrdersMenuInfo.banner.generic.y = 16;
teamOrdersMenuInfo.banner.string = "TEAM ORDERS";
teamOrdersMenuInfo.banner.color = color_white;
teamOrdersMenuInfo.banner.style = UI_CENTER;
teamOrdersMenuInfo.frame.generic.type = MTYPE_BITMAP;
teamOrdersMenuInfo.frame.generic.flags = QMF_INACTIVE;
teamOrdersMenuInfo.frame.generic.name = ART_FRAME;
teamOrdersMenuInfo.frame.generic.x = 320-233;
teamOrdersMenuInfo.frame.generic.y = 240-166;
teamOrdersMenuInfo.frame.width = 466;
teamOrdersMenuInfo.frame.height = 332;
teamOrdersMenuInfo.list.generic.type = MTYPE_SCROLLLIST;
teamOrdersMenuInfo.list.generic.flags = QMF_PULSEIFFOCUS;
teamOrdersMenuInfo.list.generic.ownerdraw = UI_TeamOrdersMenu_ListDraw;
teamOrdersMenuInfo.list.generic.callback = UI_TeamOrdersMenu_ListEvent;
teamOrdersMenuInfo.list.generic.x = 320-64;
teamOrdersMenuInfo.list.generic.y = 120;
teamOrdersMenuInfo.back.generic.type = MTYPE_BITMAP;
teamOrdersMenuInfo.back.generic.name = ART_BACK0;
teamOrdersMenuInfo.back.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
teamOrdersMenuInfo.back.generic.callback = UI_TeamOrdersMenu_BackEvent;
teamOrdersMenuInfo.back.generic.x = 0;
teamOrdersMenuInfo.back.generic.y = 480-64;
teamOrdersMenuInfo.back.width = 128;
teamOrdersMenuInfo.back.height = 64;
teamOrdersMenuInfo.back.focuspic = ART_BACK1;
Menu_AddItem( &teamOrdersMenuInfo.menu, &teamOrdersMenuInfo.banner );
Menu_AddItem( &teamOrdersMenuInfo.menu, &teamOrdersMenuInfo.frame );
Menu_AddItem( &teamOrdersMenuInfo.menu, &teamOrdersMenuInfo.list );
Menu_AddItem( &teamOrdersMenuInfo.menu, &teamOrdersMenuInfo.back );
teamOrdersMenuInfo.list.generic.left = 220;
teamOrdersMenuInfo.list.generic.top = teamOrdersMenuInfo.list.generic.y;
teamOrdersMenuInfo.list.generic.right = 420;
UI_TeamOrdersMenu_SetList( ID_LIST_BOTS );
}
/*
=================
UI_TeamOrdersMenu_Cache
=================
*/
void UI_TeamOrdersMenu_Cache( void ) {
trap_R_RegisterShaderNoMip( ART_FRAME );
trap_R_RegisterShaderNoMip( ART_BACK0 );
trap_R_RegisterShaderNoMip( ART_BACK1 );
}
/*
===============
UI_TeamOrdersMenu
===============
*/
void UI_TeamOrdersMenu( void ) {
UI_TeamOrdersMenu_Init();
UI_PushMenu( &teamOrdersMenuInfo.menu );
}
/*
===============
UI_TeamOrdersMenu_f
===============
*/
void UI_TeamOrdersMenu_f( void ) {
uiClientState_t cs;
char info[MAX_INFO_STRING];
int team;
// make sure it's a team game
trap_GetConfigString( CS_SERVERINFO, info, sizeof(info) );
teamOrdersMenuInfo.gametype = atoi( Info_ValueForKey( info, "g_gametype" ) );
if( teamOrdersMenuInfo.gametype < GT_TEAM ) {
return;
}
// not available to spectators
trap_GetClientState( &cs );
trap_GetConfigString( CS_PLAYERS + cs.clientNum, info, MAX_INFO_STRING );
team = atoi( Info_ValueForKey( info, "t" ) );
if( team == TEAM_SPECTATOR ) {
return;
}
UI_TeamOrdersMenu();
}