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 }