Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

ui_teamorders.c (10973B)


      1 /*
      2 ===========================================================================
      3 Copyright (C) 1999-2005 Id Software, Inc.
      4 
      5 This file is part of Quake III Arena source code.
      6 
      7 Quake III Arena source code is free software; you can redistribute it
      8 and/or modify it under the terms of the GNU General Public License as
      9 published by the Free Software Foundation; either version 2 of the License,
     10 or (at your option) any later version.
     11 
     12 Quake III Arena source code is distributed in the hope that it will be
     13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with Foobar; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     20 ===========================================================================
     21 */
     22 //
     23 /*
     24 =======================================================================
     25 
     26 TEAM ORDERS MENU
     27 
     28 =======================================================================
     29 */
     30 
     31 
     32 #include "ui_local.h"
     33 
     34 
     35 #define ART_FRAME		"menu/art/addbotframe"
     36 #define ART_BACK0		"menu/art/back_0"
     37 #define ART_BACK1		"menu/art/back_1"	
     38 
     39 #define ID_LIST_BOTS		10
     40 #define ID_LIST_CTF_ORDERS	11
     41 #define ID_LIST_TEAM_ORDERS	12
     42 
     43 
     44 typedef struct {
     45 	menuframework_s	menu;
     46 
     47 	menutext_s		banner;
     48 	menubitmap_s	frame;
     49 
     50 	menulist_s		list;
     51 
     52 	menubitmap_s	back;
     53 
     54 	int				gametype;
     55 	int				numBots;
     56 	int				selectedBot;
     57 	char			*bots[9];
     58 	char			botNames[9][16];
     59 } teamOrdersMenuInfo_t;
     60 
     61 static teamOrdersMenuInfo_t	teamOrdersMenuInfo;
     62 
     63 #define NUM_CTF_ORDERS		7
     64 static const char *ctfOrders[] = {
     65 	"I Am the Leader",
     66 	"Defend the Base",
     67 	"Follow Me",
     68 	"Get Enemy Flag",
     69 	"Camp Here",
     70 	"Report",
     71 	"I Relinquish Command",
     72 	NULL
     73 };
     74 static const char *ctfMessages[] = {
     75 	"i am the leader",
     76 	"%s defend the base",
     77 	"%s follow me",
     78 	"%s get enemy flag",
     79 	"%s camp here",
     80 	"%s report",
     81 	"i stop being the leader",
     82 	NULL
     83 };
     84 
     85 #define NUM_TEAM_ORDERS		6
     86 static const char *teamOrders[] = {
     87 	"I Am the Leader",
     88 	"Follow Me",
     89 	"Roam",
     90 	"Camp Here",
     91 	"Report",
     92 	"I Relinquish Command",
     93 	NULL
     94 };
     95 static const char *teamMessages[] = {
     96 	"i am the leader",
     97 	"%s follow me",
     98 	"%s roam",
     99 	"%s camp here",
    100 	"%s report",
    101 	"i stop being the leader",
    102 	NULL
    103 };
    104 
    105 
    106 /*
    107 ===============
    108 UI_TeamOrdersMenu_BackEvent
    109 ===============
    110 */
    111 static void UI_TeamOrdersMenu_BackEvent( void *ptr, int event ) {
    112 	if( event != QM_ACTIVATED ) {
    113 		return;
    114 	}
    115 	UI_PopMenu();
    116 }
    117 
    118 
    119 /*
    120 ===============
    121 UI_TeamOrdersMenu_SetList
    122 ===============
    123 */
    124 static void UI_TeamOrdersMenu_SetList( int id ) {
    125 	switch( id ) {
    126 	default:
    127 	case ID_LIST_BOTS:
    128 		teamOrdersMenuInfo.list.generic.id = id;
    129 		teamOrdersMenuInfo.list.numitems = teamOrdersMenuInfo.numBots;
    130 		teamOrdersMenuInfo.list.itemnames = (const char **)teamOrdersMenuInfo.bots;
    131 		 break;
    132 
    133 	case ID_LIST_CTF_ORDERS:
    134 		teamOrdersMenuInfo.list.generic.id = id;
    135 		teamOrdersMenuInfo.list.numitems = NUM_CTF_ORDERS;
    136 		teamOrdersMenuInfo.list.itemnames = ctfOrders;
    137 		break;
    138 
    139 	case ID_LIST_TEAM_ORDERS:
    140 		teamOrdersMenuInfo.list.generic.id = id;
    141 		teamOrdersMenuInfo.list.numitems = NUM_TEAM_ORDERS;
    142 		teamOrdersMenuInfo.list.itemnames = teamOrders;
    143 		break;
    144 	}
    145 
    146 	teamOrdersMenuInfo.list.generic.bottom = teamOrdersMenuInfo.list.generic.top + teamOrdersMenuInfo.list.numitems * PROP_HEIGHT;
    147 }
    148 
    149 
    150 /*
    151 =================
    152 UI_TeamOrdersMenu_Key
    153 =================
    154 */
    155 sfxHandle_t UI_TeamOrdersMenu_Key( int key ) {
    156 	menulist_s	*l;
    157 	int	x;
    158 	int	y;
    159 	int	index;
    160 
    161 	l = (menulist_s	*)Menu_ItemAtCursor( &teamOrdersMenuInfo.menu );
    162 	if( l != &teamOrdersMenuInfo.list ) {
    163 		return Menu_DefaultKey( &teamOrdersMenuInfo.menu, key );
    164 	}
    165 
    166 	switch( key ) {
    167 		case K_MOUSE1:
    168 			x = l->generic.left;
    169 			y = l->generic.top;
    170 			if( UI_CursorInRect( x, y, l->generic.right - x, l->generic.bottom - y ) ) {
    171 				index = (uis.cursory - y) / PROP_HEIGHT;
    172 				l->oldvalue = l->curvalue;
    173 				l->curvalue = index;
    174 
    175 				if( l->generic.callback ) {
    176 					l->generic.callback( l, QM_ACTIVATED );
    177 					return menu_move_sound;
    178 				}
    179 			}
    180 			return menu_null_sound;
    181 
    182 		case K_KP_UPARROW:
    183 		case K_UPARROW:
    184 			l->oldvalue = l->curvalue;
    185 
    186 			if( l->curvalue == 0 ) {
    187 				l->curvalue = l->numitems - 1;
    188 			}
    189 			else {
    190 				l->curvalue--;
    191 			}
    192 			return menu_move_sound;
    193 
    194 		case K_KP_DOWNARROW:
    195 		case K_DOWNARROW:
    196 			l->oldvalue = l->curvalue;
    197 
    198 			if( l->curvalue == l->numitems - 1 ) {
    199 				l->curvalue = 0;;
    200 			}
    201 			else {
    202 				l->curvalue++;
    203 			}
    204 			return menu_move_sound;
    205 	}
    206 
    207 	return Menu_DefaultKey( &teamOrdersMenuInfo.menu, key );
    208 }
    209 
    210 
    211 /*
    212 =================
    213 UI_TeamOrdersMenu_ListDraw
    214 =================
    215 */
    216 static void UI_TeamOrdersMenu_ListDraw( void *self ) {
    217 	menulist_s	*l;
    218 	int			x;
    219 	int			y;
    220 	int			i;
    221 	float		*color;
    222 	qboolean	hasfocus;
    223 	int			style;
    224 
    225 	l = (menulist_s *)self;
    226 
    227 	hasfocus = (l->generic.parent->cursor == l->generic.menuPosition);
    228 
    229 	x =	320;//l->generic.x;
    230 	y =	l->generic.y;
    231 	for( i = 0; i < l->numitems; i++ ) {
    232 		style = UI_LEFT|UI_SMALLFONT|UI_CENTER;
    233 		if( i == l->curvalue ) {
    234 			color = color_yellow;
    235 			if( hasfocus ) {
    236 				style |= UI_PULSE;
    237 			}
    238 		}
    239 		else {
    240 			color = color_orange;
    241 		}
    242 
    243 		UI_DrawProportionalString( x, y, l->itemnames[i], style, color );
    244 		y += PROP_HEIGHT;
    245 	}
    246 }
    247 
    248 
    249 /*
    250 ===============
    251 UI_TeamOrdersMenu_ListEvent
    252 ===============
    253 */
    254 static void UI_TeamOrdersMenu_ListEvent( void *ptr, int event ) {
    255 	int		id;
    256 	int		selection;
    257 	char	message[256];
    258 
    259 	if (event != QM_ACTIVATED)
    260 		return;
    261 
    262 	id = ((menulist_s *)ptr)->generic.id;
    263 	selection = ((menulist_s *)ptr)->curvalue;
    264 
    265 	if( id == ID_LIST_BOTS ) {
    266 		teamOrdersMenuInfo.selectedBot = selection;
    267 		if( teamOrdersMenuInfo.gametype == GT_CTF ) {
    268 			UI_TeamOrdersMenu_SetList( ID_LIST_CTF_ORDERS );
    269 		}
    270 		else {
    271 			UI_TeamOrdersMenu_SetList( ID_LIST_TEAM_ORDERS );
    272 		}
    273 		return;
    274 	}
    275 
    276 	if( id == ID_LIST_CTF_ORDERS ) {
    277 		Com_sprintf( message, sizeof(message), ctfMessages[selection], teamOrdersMenuInfo.botNames[teamOrdersMenuInfo.selectedBot] );
    278 	}
    279 	else {
    280 		Com_sprintf( message, sizeof(message), teamMessages[selection], teamOrdersMenuInfo.botNames[teamOrdersMenuInfo.selectedBot] );
    281 	}
    282 
    283 	trap_Cmd_ExecuteText( EXEC_APPEND, va( "say_team \"%s\"\n", message ) );
    284 	UI_PopMenu();
    285 }
    286 
    287 
    288 /*
    289 ===============
    290 UI_TeamOrdersMenu_BuildBotList
    291 ===============
    292 */
    293 static void UI_TeamOrdersMenu_BuildBotList( void ) {
    294 	uiClientState_t	cs;
    295 	int		numPlayers;
    296 	int		isBot;
    297 	int		n;
    298 	char	playerTeam;
    299 	char	botTeam;
    300 	char	info[MAX_INFO_STRING];
    301 
    302 	for( n = 0; n < 9; n++ ) {
    303 		teamOrdersMenuInfo.bots[n] = teamOrdersMenuInfo.botNames[n];
    304 	}
    305 
    306 	trap_GetClientState( &cs );
    307 
    308 	Q_strncpyz( teamOrdersMenuInfo.botNames[0], "Everyone", 16 );
    309 	teamOrdersMenuInfo.numBots = 1;
    310 
    311 	trap_GetConfigString( CS_SERVERINFO, info, sizeof(info) );
    312 	numPlayers = atoi( Info_ValueForKey( info, "sv_maxclients" ) );
    313 	teamOrdersMenuInfo.gametype = atoi( Info_ValueForKey( info, "g_gametype" ) );
    314 
    315 	for( n = 0; n < numPlayers && teamOrdersMenuInfo.numBots < 9; n++ ) {
    316 		trap_GetConfigString( CS_PLAYERS + n, info, MAX_INFO_STRING );
    317 
    318 		playerTeam = TEAM_SPECTATOR; // bk001204 = possible uninit use
    319 
    320 		if( n == cs.clientNum ) {
    321 			playerTeam = *Info_ValueForKey( info, "t" );
    322 			continue;
    323 		}
    324 
    325 		isBot = atoi( Info_ValueForKey( info, "skill" ) );
    326 		if( !isBot ) {
    327 			continue;
    328 		}
    329 
    330 		botTeam = *Info_ValueForKey( info, "t" );
    331 		if( botTeam != playerTeam ) {
    332 			continue;
    333 		}
    334 
    335 		Q_strncpyz( teamOrdersMenuInfo.botNames[teamOrdersMenuInfo.numBots], Info_ValueForKey( info, "n" ), 16 );
    336 		Q_CleanStr( teamOrdersMenuInfo.botNames[teamOrdersMenuInfo.numBots] );
    337 		teamOrdersMenuInfo.numBots++;
    338 	}
    339 }
    340 
    341 
    342 /*
    343 ===============
    344 UI_TeamOrdersMenu_Init
    345 ===============
    346 */
    347 static void UI_TeamOrdersMenu_Init( void ) {
    348 	UI_TeamOrdersMenu_Cache();
    349 
    350 	memset( &teamOrdersMenuInfo, 0, sizeof(teamOrdersMenuInfo) );
    351 	teamOrdersMenuInfo.menu.fullscreen = qfalse;
    352 	teamOrdersMenuInfo.menu.key = UI_TeamOrdersMenu_Key;
    353 
    354 	UI_TeamOrdersMenu_BuildBotList();
    355 
    356 	teamOrdersMenuInfo.banner.generic.type		= MTYPE_BTEXT;
    357 	teamOrdersMenuInfo.banner.generic.x			= 320;
    358 	teamOrdersMenuInfo.banner.generic.y			= 16;
    359 	teamOrdersMenuInfo.banner.string			= "TEAM ORDERS";
    360 	teamOrdersMenuInfo.banner.color				= color_white;
    361 	teamOrdersMenuInfo.banner.style				= UI_CENTER;
    362 
    363 	teamOrdersMenuInfo.frame.generic.type		= MTYPE_BITMAP;
    364 	teamOrdersMenuInfo.frame.generic.flags		= QMF_INACTIVE;
    365 	teamOrdersMenuInfo.frame.generic.name		= ART_FRAME;
    366 	teamOrdersMenuInfo.frame.generic.x			= 320-233;
    367 	teamOrdersMenuInfo.frame.generic.y			= 240-166;
    368 	teamOrdersMenuInfo.frame.width				= 466;
    369 	teamOrdersMenuInfo.frame.height				= 332;
    370 
    371 	teamOrdersMenuInfo.list.generic.type		= MTYPE_SCROLLLIST;
    372 	teamOrdersMenuInfo.list.generic.flags		= QMF_PULSEIFFOCUS;
    373 	teamOrdersMenuInfo.list.generic.ownerdraw	= UI_TeamOrdersMenu_ListDraw;
    374 	teamOrdersMenuInfo.list.generic.callback	= UI_TeamOrdersMenu_ListEvent;
    375 	teamOrdersMenuInfo.list.generic.x			= 320-64;
    376 	teamOrdersMenuInfo.list.generic.y			= 120;
    377 
    378 	teamOrdersMenuInfo.back.generic.type		= MTYPE_BITMAP;
    379 	teamOrdersMenuInfo.back.generic.name		= ART_BACK0;
    380 	teamOrdersMenuInfo.back.generic.flags		= QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
    381 	teamOrdersMenuInfo.back.generic.callback	= UI_TeamOrdersMenu_BackEvent;
    382 	teamOrdersMenuInfo.back.generic.x			= 0;
    383 	teamOrdersMenuInfo.back.generic.y			= 480-64;
    384 	teamOrdersMenuInfo.back.width				= 128;
    385 	teamOrdersMenuInfo.back.height				= 64;
    386 	teamOrdersMenuInfo.back.focuspic			= ART_BACK1;
    387 
    388 	Menu_AddItem( &teamOrdersMenuInfo.menu, &teamOrdersMenuInfo.banner );
    389 	Menu_AddItem( &teamOrdersMenuInfo.menu, &teamOrdersMenuInfo.frame );
    390 	Menu_AddItem( &teamOrdersMenuInfo.menu, &teamOrdersMenuInfo.list );
    391 	Menu_AddItem( &teamOrdersMenuInfo.menu, &teamOrdersMenuInfo.back );
    392 
    393 	teamOrdersMenuInfo.list.generic.left = 220;
    394 	teamOrdersMenuInfo.list.generic.top = teamOrdersMenuInfo.list.generic.y;
    395 	teamOrdersMenuInfo.list.generic.right = 420;
    396 	UI_TeamOrdersMenu_SetList( ID_LIST_BOTS );
    397 }
    398 
    399 
    400 /*
    401 =================
    402 UI_TeamOrdersMenu_Cache
    403 =================
    404 */
    405 void UI_TeamOrdersMenu_Cache( void ) {
    406 	trap_R_RegisterShaderNoMip( ART_FRAME );
    407 	trap_R_RegisterShaderNoMip( ART_BACK0 );
    408 	trap_R_RegisterShaderNoMip( ART_BACK1 );
    409 }
    410 
    411 
    412 /*
    413 ===============
    414 UI_TeamOrdersMenu
    415 ===============
    416 */
    417 void UI_TeamOrdersMenu( void ) {
    418 	UI_TeamOrdersMenu_Init();
    419 	UI_PushMenu( &teamOrdersMenuInfo.menu );
    420 }
    421 
    422 
    423 /*
    424 ===============
    425 UI_TeamOrdersMenu_f
    426 ===============
    427 */
    428 void UI_TeamOrdersMenu_f( void ) {
    429 	uiClientState_t	cs;
    430 	char	info[MAX_INFO_STRING];
    431 	int		team;
    432 
    433 	// make sure it's a team game
    434 	trap_GetConfigString( CS_SERVERINFO, info, sizeof(info) );
    435 	teamOrdersMenuInfo.gametype = atoi( Info_ValueForKey( info, "g_gametype" ) );
    436 	if( teamOrdersMenuInfo.gametype < GT_TEAM ) {
    437 		return;
    438 	}
    439 
    440 	// not available to spectators
    441 	trap_GetClientState( &cs );
    442 	trap_GetConfigString( CS_PLAYERS + cs.clientNum, info, MAX_INFO_STRING );
    443 	team = atoi( Info_ValueForKey( info, "t" ) );
    444 	if( team == TEAM_SPECTATOR ) {
    445 		return;
    446 	}
    447 
    448 	UI_TeamOrdersMenu();
    449 }