// Copyright (C) 2007 Id Software, Inc. // #include "precompiled.h" #pragma hdrstop #if defined( _DEBUG ) && !defined( ID_REDIRECT_NEWDELETE ) #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #include "../framework/Licensee.h" #include "roles/Inventory.h" #include "roles/FireTeams.h" #include "roles/ObjectiveManager.h" #include "roles/Tasks.h" #include "structures/TeamManager.h" #include "rules/GameRules.h" #include "Player.h" #include "../framework/BuildVersion.h" #include "../framework/KeyInput.h" #include "guis/UserInterfaceLocal.h" #include "guis/UserInterfaceManagerLocal.h" #include "guis/UIList.h" #include "guis/UIRadialMenu.h" #include "CommandMapInfo.h" #include "demos/DemoManager.h" #include "rules/UserGroup.h" #include "rules/AdminSystem.h" #include "rules/VoteManager.h" #include "Atmosphere.h" #include "misc/Door.h" #include "vehicles/Transport.h" #include "vehicles/VehicleWeapon.h" #include "ScriptEntity.h" #include "Waypoints/LocationMarker.h" #include "proficiency/StatsTracker.h" #include "../framework/async/Demo.h" #include "../sys/sys_local.h" #ifndef _XENON #include "../sdnet/SDNet.h" #endif #define ON_UIVALID( handle, thename ) sdUserInterfaceLocal* thename = GetUserInterface( handle ); if ( thename ) #define ON_UIINVALID( handle, thename ) sdUserInterfaceLocal* thename = GetUserInterface( handle ); if ( !thename ) idList< qhandle_t > idGameLocal::taskListHandles; /* ================ idGameLocal::HandleGuiEvent ================ */ bool idGameLocal::HandleGuiEvent( const sdSysEvent* event ) { if ( networkSystem->IsDedicated() ) { return false; } ON_UIVALID( uiMainMenuHandle, ui ) { if ( ui->IsActive() ) { return ui->PostEvent( event ); } } sdHudModule* module = localPlayerProperties.GetActiveHudModule(); if ( module && module->HandleGuiEvent( event ) ) { return true; } idPlayer* localPlayer = gameLocal.GetLocalPlayer(); if ( localPlayer ) { if( isServer && event->GetKey() == K_F1 && event->IsKeyDown() && isPaused && localPlayer->IsSinglePlayerToolTipPlaying() ) { cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "unPauseGame\n" ); return true; } if ( localPlayer->HandleGuiEvent( event ) ) { return true; } } if ( rules ) { if ( rules->HandleGuiEvent( event ) ) { return true; } } return false; } /* ================ idGameLocal::TranslateGuiBind ================ */ bool idGameLocal::TranslateGuiBind( const idKey& key, sdKeyCommand** cmd ) { ON_UIVALID( uiMainMenuHandle, ui ) { if ( ui->IsActive() ) { if ( ui->Translate( key, cmd ) ) { return true; } } } sdHudModule* module = gameLocal.localPlayerProperties.GetActiveHudModule(); if ( module != NULL ) { sdUserInterfaceLocal* ui = module->GetGui(); if ( ui != NULL ) { if ( ui->Translate( key, cmd ) ) { return true; } } } idPlayer* localPlayer = gameLocal.GetLocalPlayer(); if ( localPlayer ) { if ( localPlayer->TranslateGuiBind( key, cmd ) ) { return true; } } if ( rules != NULL ) { if ( rules->TranslateGuiBind( key, cmd ) ) { return true; } } return false; } /* ============ idGameLocal::ShowMainMenu ============ */ void idGameLocal::ShowMainMenu() { ON_UIVALID( uiMainMenuHandle, ui ) { ui->Activate(); } } /* ============ idGameLocal::HideMainMenu ============ */ void idGameLocal::HideMainMenu() { // ao: never called ON_UIVALID( uiMainMenuHandle, ui ) { ui->Deactivate( true ); } } /* ============ idGameLocal::IsMainMenuActive ============ */ bool idGameLocal::IsMainMenuActive() { ON_UIVALID( uiMainMenuHandle, ui ) { return ui->IsActive(); } return false; } /* ============ idGameLocal::DrawMainMenu ============ */ void idGameLocal::DrawMainMenu() { ON_UIINVALID( uiMainMenuHandle, ui ) { return; } if ( gamestate == GAMESTATE_NOMAP ) { sdGlobalStatsTracker::GetInstance().UpdateStatsRequests(); } ui->Draw(); } /* ============ idGameLocal::DrawSystemUI ============ */ void idGameLocal::DrawSystemUI() { ON_UIINVALID( uiSystemUIHandle, ui ) { return; } ui->Draw(); } /* ============ idGameLocal::DrawLoadScreen ============ */ void idGameLocal::DrawLoadScreen() { ON_UIINVALID( uiLevelLoadHandle, ui ) { return; } ui->Activate(); ui->Update(); ui->Draw(); } /* ============ idGameLocal::DrawPureWaitScreen ============ */ void idGameLocal::DrawPureWaitScreen() { ON_UIINVALID( pureWaitHandle, ui ) { return; } ui->Activate(); ui->Update(); ui->Draw(); } /* ============ idGameLocal::CreateKeyBindingList ============ */ void idGameLocal::CreateKeyBindingList( sdUIList* list ) { assert( list ); using namespace sdProperties; idStr category; if( sdProperty* property = list->GetScope().GetProperties().GetProperty( "bindCategory", PT_STRING )) { category = *property->value.stringValue; } sdUIList::ClearItems( list ); const sdDeclKeyBinding* bind = gameLocal.declKeyBindingType.LocalFind( category, false ); if( bind == NULL ) { return; } idWStr text; for( int i = 0; i < bind->GetKeys().GetNumKeyVals(); i++ ) { const idKeyValue* kv = bind->GetKeys().GetKeyVal( i ); int item = sdUIList::InsertItem( list, va( L"", kv->GetKey().c_str() ), -1, 0 ); int numKeys = 0; keyInputManager->KeysFromBinding( gameLocal.GetDefaultBindContext(), kv->GetValue(), numKeys, NULL ); idKey** keys = NULL; if( numKeys > 0 ) { keys = static_cast< idKey** >( _alloca( numKeys * sizeof( idKey* ) ) ); keyInputManager->KeysFromBinding( gameLocal.GetDefaultBindContext(), kv->GetValue(), numKeys, keys ); } if( numKeys > 0 ) { assert( keys != NULL ); keys[ 0 ]->GetLocalizedText( text ); sdUIList::CleanUserInput( text ); sdUIList::SetItemText( list, text.c_str(), item, 1 ); } else { sdUIList::SetItemText( list, L"", item, 1 ); } if( numKeys > 1 ) { assert( keys != NULL ); keys[ 1 ]->GetLocalizedText( text ); sdUIList::CleanUserInput( text ); sdUIList::SetItemText( list, text.c_str(), item, 2 ); } else { sdUIList::SetItemText( list, L"", item, 2 ); } sdUIList::SetItemText( list, va( L"%hs", kv->GetValue().c_str() ), item, 3 ); } } /* ============ idGameLocal::CreateCrosshairList ============ */ void idGameLocal::CreateCrosshairList( sdUIList* list ) { assert( list != NULL ); sdUIList::ClearItems( list ); int num = gameLocal.declStringMapType.Num(); for( int i = 0; i < num; i++ ) { const sdDeclStringMap* decl = gameLocal.declStringMapType.LocalFindByIndex( i, false ); if( idStr::Icmpn( decl->GetName(), "crosshairs", 10 ) != 0 ) { continue; } // ensure we're parsed gameLocal.declStringMapType.LocalFindByIndex( i, true ); const idDict& dict = decl->GetDict(); for( int j = 0; j < dict.GetNumKeyVals(); j++ ) { const idKeyValue* kv = dict.GetKeyVal( j ); sdUIList::InsertItem( list, va( L"\t%hs\t%hs", kv->GetValue().c_str(), decl->GetName(), kv->GetKey().c_str() ), -1, 0 ); } } } /* ============ idGameLocal::CreateDemoList ============ */ void idGameLocal::CreateDemoList( sdUIList* list ) { sdUIList::ClearItems( list ); idFileList* files = fileSystem->ListFiles( "demos", ".ndm" ); if( files == NULL ) { return; } idStr file; idWStr date; idStr fullPath; sysTime_t time; if( files->GetNumFiles() > 0 ) { list->BeginBatch(); list->SetItemGranularity( files->GetNumFiles() ); for( int i = 0; i < files->GetNumFiles(); i++ ) { file = files->GetFile( i ); if( networkSystem->CanPlayDemo( file.c_str() ) ) { unsigned int timeStamp; fullPath = files->GetBasePath(); fullPath += "/" + file; fileSystem->ReadFile( fullPath, NULL, &timeStamp ); sys->SecondsToTime( timeStamp, time ); sdNetProperties::FormatTimeStamp( time, date ); file.StripFileExtension(); int index = sdUIList::InsertItem( list, va( L"%hs\t%ls\t%hs", file.c_str(), date.c_str(), fullPath.c_str() ), -1, 0 ); list->SetItemDataInt( timeStamp, index, 1, true ); } } list->EndBatch(); } fileSystem->FreeFileList( files ); } /* ============ idGameLocal::CreateVehiclePlayerList ============ */ void idGameLocal::CreateVehiclePlayerList( sdUIList* list ) { idPlayer* localPlayer = gameLocal.GetLocalViewPlayer(); if ( localPlayer == NULL ) { if( g_debugPlayerList.GetInteger() ) { sdUIList::ClearItems( list ); idWStr formatString; for( int i = 0; i < g_debugPlayerList.GetInteger(); i++ ) { formatString = va( L"\tPlayer%i", i ); sdUIList::InsertItem( list, formatString.c_str(), -1, 0 ); } } return; } sdUIList::ClearItems( list ); idEntity* proxy = localPlayer->GetProxyEntity(); if( proxy == NULL ) { return; } if ( sdUsableInterface* iface = proxy->GetUsableInterface() ) { const wchar_t* formatString; int selIndex = -1; idWStr cleanPlayerName; for( int i = 0; i < iface->GetNumPositions(); i++ ) { const idPlayer* player = iface->GetPlayerAtPosition( i ); if( player == NULL ) { if( g_debugPlayerList.GetInteger() ) { formatString = va( L"\tPlayer%i", i ); sdUIList::InsertItem( list, formatString, -1, 0 ); } continue; } if( const sdDeclPlayerClass* pc = player->GetInventory().GetClass() ) { cleanPlayerName = va( L"%hs", player->userInfo.name.c_str() ); sdUIList::CleanUserInput( cleanPlayerName ); formatString = va( L"\t%ls", ( pc == NULL ) ? "" : pc->GetName(), cleanPlayerName.c_str() ); int index = sdUIList::InsertItem( list, formatString, -1, 0 ); if( player == localPlayer ) { selIndex = index; } } } list->SelectItem( selIndex ); } } /* ============ idGameLocal::CreateScoreboardList ============ */ void idGameLocal::CreateScoreboardList( sdUIList* list ) { if( gameLocal.rules ) { idStr teamName; if( sdUserInterfaceLocal* ui = list->GetUI() ) { ui->PopScriptVar( teamName ); } gameLocal.rules->UpdateScoreboard( list, teamName ); } else { if( sdUserInterfaceLocal* ui = list->GetUI() ) { idStr name; ui->PopScriptVar( name ); ui->PushScriptVar( 0.0f ); ui->PushScriptVar( 0.0f ); ui->PushScriptVar( 0.0f ); } } } /* ============ idGameLocal::CreatePlayerAdminList ============ */ void idGameLocal::CreatePlayerAdminList( sdUIList* list ) { sdAdminSystem::GetInstance().CreatePlayerAdminList( list ); } /* ============ idGameLocal::CreateUserGroupList ============ */ void idGameLocal::CreateUserGroupList( sdUIList* list ) { sdUserGroupManager::GetInstance().CreateUserGroupList( list ); } /* ============ idGameLocal::CreateUserGroupList ============ */ void idGameLocal::CreateServerConfigList( sdUIList* list ) { sdUserGroupManager::GetInstance().CreateServerConfigList( list ); } /* ============ idGameLocal::CreateFireTeamListEntry ============ */ void idGameLocal::CreateFireTeamListEntry( sdUIList* list, int index, idPlayer* player ) { static const idVec4 noDraw( 0.0f, 0.0f, 0.0f, 0.0f ); sdUIList::InsertItem( list, L"", index, 0 ); const sdDeclPlayerClass* cls = player->GetInventory().GetClass(); if ( cls != NULL ) { // class sdUIList::SetItemIcon( list, cls->GetName(), index, 0 ); } // rank/voip bool sendingVoice = ( sys->Milliseconds() - networkSystem->GetLastVoiceReceivedTime( player->entityNumber ) ) < SEC2MS( 0.5f ); if ( sendingVoice ) { sdUIList::SetItemIcon( list, "voip", index, 1 ); sdUIList::SetItemForeColor( list, colorWhite, index, 1 ); } else if ( const sdDeclRank* rank = player->GetProficiencyTable().GetRank() ) { sdUIList::SetItemIcon( list, rank->GetMaterial(), index, 1 ); sdUIList::SetItemForeColor( list, colorWhite, index, 1 ); } else { sdUIList::SetItemForeColor( list, noDraw, index, 1 ); } // name idWStr cleanPlayerName = va( L"%hs", player->userInfo.cleanName.c_str() ); sdUIList::CleanUserInput( cleanPlayerName ); sdUIList::SetItemText( list, cleanPlayerName.c_str(), index, 2 ); if( player->IsInLimbo() ) { sdUIList::SetItemForeColor( list, colorBlack, index, 2 ); } else { float healthFrac = player->GetHealth() / ( float )player->GetMaxHealth(); healthFrac = idMath::ClampFloat( 0.0f, 1.0f, healthFrac ); idVec4 healthColor( 1.0f - healthFrac, healthFrac, 0.0f, 1.0f ); sdUIList::SetItemForeColor( list, healthColor, index, 2 ); } } /* ============ idGameLocal::CreateFireTeamList ============ */ void idGameLocal::CreateFireTeamList( sdUIList* list ) { sdUIList::ClearItems( list ); int listType; if( sdUserInterfaceLocal* ui = list->GetUI() ) { ui->PopScriptVar( listType ); } if ( gameLocal.rules == NULL ) { return; } if ( gameLocal.GetLocalPlayer() == NULL ) { return; } if ( listType == FIRETEAMLIST_MYFIRETEAM ) { CreateFireTeamList_MyFireTeam( list ); } else if ( listType == FIRETEAMLIST_MAIN ) { CreateFireTeamList_Main( list ); } else if ( listType == FIRETEAMLIST_JOIN ) { CreateFireTeamList_Join( list ); } else if ( listType == FIRETEAMLIST_INVITE ) { CreateFireTeamList_Invite( list ); } else if ( listType == FIRETEAMLIST_KICK ) { CreateFireTeamList_Kick( list ); } else if ( listType == FIRETEAMLIST_PROMOTE ) { CreateFireTeamList_Promote( list ); } else if ( listType == FIRETEAMLIST_MANAGE ) { CreateFireTeamList_Manage( list ); } else { assert( 0 ); } } /* ============ idGameLocal::CreateFireTeamList_MyFireTeam ============ */ void idGameLocal::CreateFireTeamList_MyFireTeam( sdUIList* list ) { idPlayer* localPlayer = gameLocal.GetLocalPlayer(); sdFireTeam* fireTeam = gameLocal.rules->GetPlayerFireTeam( localPlayer->entityNumber ); if ( fireTeam != NULL ) { int index = 0; for ( int i = 0; i < fireTeam->GetNumMembers(); i++, index++ ) { idPlayer* player = fireTeam->GetMember( i ); CreateFireTeamListEntry( list, index, player ); } if ( g_debugPlayerList.GetInteger() ) { int i = 0; int num = 8; while ( list->GetNumItems() < num ) { idWStr formatString = va( L"\t\tPlayer%i\t100.00XP\t100%%", i ); sdUIList::InsertItem( list, formatString.c_str(), -1, 0 ); i++; } } } else { sdTeamInfo* localTeam = localPlayer->GetGameTeam(); if ( localTeam == NULL ) { return; } idStaticList< idPlayer*, MAX_CLIENTS > playerList; // Mission teams for ( int i = 0; i < MAX_CLIENTS; i++ ) { idPlayer* player = gameLocal.GetClient( i ); if ( player == NULL ) { continue; } if ( player->GetGameTeam() != localTeam ) { continue; } if ( gameLocal.rules->GetPlayerFireTeam( i ) != NULL ) { continue; } if( player->GetActiveTaskHandle() != localPlayer->GetActiveTaskHandle() ) { continue; } playerList.Append( player ); } for ( int i = 0; i < playerList.Num() && i < MAX_MISSION_TEAM_PLAYERS; i++ ) { idPlayer* player = playerList[ i ]; CreateFireTeamListEntry( list, i, player ); } } } /* ============ idGameLocal::CreateFireTeamList_Main ============ */ void idGameLocal::CreateFireTeamList_Main( sdUIList* list ) { idPlayer* localPlayer = gameLocal.GetLocalPlayer(); bool canJoin = false; bool canCreate = false; for ( int i = 0; i < sdTeamInfo::MAX_FIRETEAMS; i++ ) { sdFireTeam& fireTeam = localPlayer->GetTeam()->GetFireTeam( i ); if ( fireTeam.GetNumMembers() > 0 ) { if ( !fireTeam.IsPrivate() ) { if ( fireTeam.MaxMembers() - fireTeam.GetNumMembers() > 0 ) { canJoin = true; } } } else { canCreate = true; } } if ( canJoin ) { sdUIList::InsertItem( list, va( L" 1. %ls\tcanjoin", common->LocalizeText( "guis/hud/fireteam/menu/join" ).c_str() ), 0, 0 ); } else { sdUIList::InsertItem( list, va( L" 1. ^1%ls\tcannot", common->LocalizeText( "guis/hud/fireteam/menu/join" ).c_str() ), 0, 0 ); } if ( canCreate ) { sdUIList::InsertItem( list, va( L" 2. %ls\tcancreate", common->LocalizeText( "guis/hud/fireteam/menu/create" ).c_str() ), 1, 0 ); } else { sdUIList::InsertItem( list, va( L" 2. ^1%ls\tcannot", common->LocalizeText( "guis/hud/fireteam/menu/create" ).c_str() ), 1, 0 ); } } /* ============ idGameLocal::CreateFireTeamList_Join ============ */ void idGameLocal::CreateFireTeamList_Join( sdUIList* list ) { idPlayer* localPlayer = gameLocal.GetLocalPlayer(); int num = 0; for ( int i = 0; i < sdTeamInfo::MAX_FIRETEAMS; i++ ) { sdFireTeam& fireTeam = localPlayer->GetTeam()->GetFireTeam( i ); if ( !fireTeam.IsPrivate() ) { if ( fireTeam.GetNumMembers() > 0 && fireTeam.MaxMembers() - fireTeam.GetNumMembers() > 0 ) { sdUIList::InsertItem( list, va( L" %i. %hs\t%i", num+1, fireTeam.GetName(), i ), i, 0 ); num++; } } } } /* ============ idGameLocal::CreateFireTeamList_Invite ============ */ void idGameLocal::CreateFireTeamList_Invite( sdUIList* list ) { idPlayer* localPlayer = gameLocal.GetLocalPlayer(); sdFireTeam* fireTeam = gameLocal.rules->GetPlayerFireTeam( localPlayer->entityNumber ); if ( fireTeam == NULL ) { return; } int page; if( sdUserInterfaceLocal* ui = list->GetUI() ) { ui->PopScriptVar( page ); } assert( page >= 0 && page <= 1 ); int numAdded = 0; int numFound = 0; if ( fireTeam->MaxMembers() - fireTeam->GetNumMembers() >= 1 ) { for ( int i = 0; i < MAX_CLIENTS; i++ ) { idPlayer *p = gameLocal.GetClient( i ); if ( p != NULL && p->GetTeam() == localPlayer->GetTeam() ) { if ( gameLocal.rules->GetPlayerFireTeam( i ) == NULL ) { numFound++; if ( numFound > FIRETEAMLIST_PAGE_NUM_PLAYERS * page && numAdded < FIRETEAMLIST_PAGE_NUM_PLAYERS ) { sdUIList::InsertItem( list, va( L" %i. %hs\t%hs", numAdded+1, p->userInfo.cleanName.c_str(), p->userInfo.cleanName.c_str() ), numAdded, 0 ); numAdded++; } } } } } if ( numFound != numAdded ) { if ( page == 1 ) { sdUIList::InsertItem( list, va( L" %i. %ls\tprevpage", numAdded+1, common->LocalizeText( "guis/hud/fireteam/menu/prevpage" ).c_str() ), numAdded, 0 ); } else { sdUIList::InsertItem( list, va( L" %i. %ls\tnextpage", numAdded+1, common->LocalizeText( "guis/hud/fireteam/menu/nextpage" ).c_str() ), numAdded, 0 ); } numAdded++; } } /* ============ idGameLocal::CreateFireTeamList_Kick ============ */ void idGameLocal::CreateFireTeamList_Kick( sdUIList* list ) { idPlayer* localPlayer = gameLocal.GetLocalPlayer(); sdFireTeam* fireTeam = gameLocal.rules->GetPlayerFireTeam( localPlayer->entityNumber ); if ( fireTeam == NULL ) { return; } int numAdded = 0; for ( int i = 0; i < MAX_CLIENTS; i++ ) { idPlayer* p = gameLocal.GetClient( i ); if ( p != NULL && p != localPlayer && fireTeam->IsMember( p ) ) { sdUIList::InsertItem( list, va( L" %i. %hs\t%hs", numAdded+1, p->userInfo.cleanName.c_str(), p->userInfo.cleanName.c_str() ), numAdded, 0 ); numAdded++; } } } /* ============ idGameLocal::CreateFireTeamList_Promote ============ */ void idGameLocal::CreateFireTeamList_Promote( sdUIList* list ) { idPlayer* localPlayer = gameLocal.GetLocalPlayer(); sdFireTeam* fireTeam = gameLocal.rules->GetPlayerFireTeam( localPlayer->entityNumber ); if ( fireTeam == NULL ) { return; } int numAdded = 0; for ( int i = 0; i < MAX_CLIENTS; i++ ) { idPlayer* p = gameLocal.GetClient( i ); if ( p != NULL && p != localPlayer && fireTeam->IsMember( p ) ) { if ( !p->userInfo.isBot ) { sdUIList::InsertItem( list, va( L" %i. %hs\t%hs", numAdded+1, p->userInfo.cleanName.c_str(), p->userInfo.cleanName.c_str() ), numAdded, 0 ); numAdded++; } } } } /* ============ idGameLocal::CreateFireTeamList_Manage ============ */ void idGameLocal::CreateFireTeamList_Manage( sdUIList* list ) { idPlayer* localPlayer = gameLocal.GetLocalPlayer(); sdFireTeam* fireTeam = gameLocal.rules->GetPlayerFireTeam( localPlayer->entityNumber ); if ( fireTeam == NULL ) { return; } int index = 0; if ( fireTeam->IsCommander( localPlayer ) ) { bool canInvite = false; if ( fireTeam->MaxMembers() - fireTeam->GetNumMembers() > 0 ) { for ( int i = 0; i < MAX_CLIENTS; i++ ) { idPlayer *p = gameLocal.GetClient( i ); if ( p != NULL && p->GetTeam() == localPlayer->GetTeam() ) { if ( gameLocal.rules->GetPlayerFireTeam( i ) == NULL ) { canInvite = true; break; } } } } if ( canInvite ) { sdUIList::InsertItem( list, va( L" %i. %ls\tcaninvite", index+1, common->LocalizeText( "guis/hud/fireteam/menu/invite" ).c_str() ), index, 0 ); } else { sdUIList::InsertItem( list, va( L" %i. ^1%ls\tcannot", index+1, common->LocalizeText( "guis/hud/fireteam/menu/invite" ).c_str() ), index, 0 ); } index++; if ( fireTeam->GetNumMembers() > 1 ) { sdUIList::InsertItem( list, va( L" %i. %ls\tcankick", index+1, common->LocalizeText( "guis/hud/fireteam/menu/kick" ).c_str() ), index, 0 ); } else { sdUIList::InsertItem( list, va( L" %i. ^1%ls\tcannot", index+1, common->LocalizeText( "guis/hud/fireteam/menu/kick" ).c_str() ), index, 0 ); } index++; sdUIList::InsertItem( list, va( L" %i. %ls\tdisband", index+1, common->LocalizeText( "guis/hud/fireteam/menu/disband" ).c_str() ), index, 0 ); index++; sdUIList::InsertItem( list, va( L" %i. %ls\tleave", index+1, common->LocalizeText( "guis/hud/fireteam/menu/leave" ).c_str() ), index, 0 ); index++; int numPromote = 0; for ( int i = 0; i < MAX_CLIENTS; i++ ) { idPlayer* p = gameLocal.GetClient( i ); if ( p != NULL && p != localPlayer && fireTeam->IsMember( p ) ) { if ( !p->userInfo.isBot ) { numPromote++; } } } if ( numPromote > 0 ) { sdUIList::InsertItem( list, va( L" %i. %ls\tcanpromote", index+1, common->LocalizeText( "guis/hud/fireteam/menu/promote" ).c_str() ), index, 0 ); } else { sdUIList::InsertItem( list, va( L" %i. ^1%ls\tcannot", index+1, common->LocalizeText( "guis/hud/fireteam/menu/promote" ).c_str() ), index, 0 ); } index++; if ( fireTeam->IsPrivate() ) { sdUIList::InsertItem( list, va( L" %i. %ls\tpublic", index+1, common->LocalizeText( "guis/hud/fireteam/menu/makepublic" ).c_str() ), index, 0 ); } else { sdUIList::InsertItem( list, va( L" %i. %ls\tprivate", index+1, common->LocalizeText( "guis/hud/fireteam/menu/makeprivate" ).c_str() ), index, 0 ); } index++; sdUIList::InsertItem( list, va( L" %i. %ls\trename", index+1, common->LocalizeText( "guis/hud/fireteam/menu/rename" ).c_str() ), index, 0 ); index++; } else { bool canPropose = false; if ( fireTeam->MaxMembers() - fireTeam->GetNumMembers() >= 1 ) { for ( int i = 0; i < MAX_CLIENTS; i++ ) { idPlayer *p = gameLocal.GetClient( i ); if ( p != NULL && p->GetTeam() == localPlayer->GetTeam() ) { if ( gameLocal.rules->GetPlayerFireTeam( i ) == NULL ) { canPropose = true; } } } } if ( canPropose ) { sdUIList::InsertItem( list, va( L" %i. %ls\tcanpropose", index+1, common->LocalizeText( "guis/hud/fireteam/menu/propose" ).c_str() ), index, 0 ); } else { sdUIList::InsertItem( list, va( L" %i. ^1%ls\tcannot", index+1, common->LocalizeText( "guis/hud/fireteam/menu/propose" ).c_str() ), index, 0 ); } index++; sdUIList::InsertItem( list, va( L" %i. %ls\tleave", index+1, common->LocalizeText( "guis/hud/fireteam/menu/leave" ).c_str() ), index, 0 ); index++; } } /* ============ idGameLocal::GeneratePlayerListForTask ============ */ void idGameLocal::GeneratePlayerListForTask( idStr& playerList, const sdPlayerTask* task ) { sdStringBuilder_Heap builder; playerList.Clear(); sdTaskManagerLocal& manager = sdTaskManager::GetInstance(); for( int playerIndex = 0; playerIndex < gameLocal.numClients; playerIndex++ ) { idPlayer* player = gameLocal.GetClient( playerIndex ); if ( player == NULL ) { continue; } if ( player->GetActiveTaskHandle() != task->GetHandle() ) { continue; } builder += " " + player->userInfo.name; } builder.ToString( playerList ); } /* ============ idGameLocal::InsertTask ============ */ int idGameLocal::InsertTask( sdUIList* list, const sdPlayerTask* task, bool highlightActive ) { const char* iconMat = "guis/nodraw"; if ( task->GetInfo()->GetNumWayPoints() > 0 ) { const idMaterial* mat = task->GetInfo()->GetWaypointIcon( 0 ); if( mat != NULL ) { iconMat = mat->GetName(); } } idWStr xpString = task->GetInfo()->GetXPString(); sdUIList::CleanUserInput( xpString ); int index = sdUIList::InsertItem( list, va( L"\t%ls\t%ls", iconMat, task->GetTitle(), xpString.c_str() ), -1, 0 ); return index; } /* ============ idGameLocal::CreateActiveTaskList ============ */ void idGameLocal::CreateActiveTaskList( sdUIList* list ) { sdTaskManagerLocal& manager = sdTaskManager::GetInstance(); sdUIList::ClearItems( list ); bool showAll; list->GetUI()->PopScriptVar( showAll ); idPlayer* localPlayer = gameLocal.GetLocalPlayer(); idPlayer* localPlayerView = gameLocal.GetLocalViewPlayer(); if ( localPlayerView == NULL ) { return; } if ( g_debugPlayerList.GetInteger() ) { sdUIList::InsertItem( list, L"Task 1", 0, 1 ); idWStrList parms( 1 ); keyInputManager->KeysFromBinding( gameLocal.GetDefaultBindContext(), "_taskmenu", true, parms.Alloc() ); sdUIList::InsertItem( list, va( L"\t%ls", common->LocalizeText( "guis/hud/tasks_are_available", parms ).c_str() ), -1, 1 ); return; } sdTeamInfo* team = localPlayerView->GetGameTeam(); if ( team == NULL ) { return; } bool canSelect = true; sdPlayerTask* activeTask = NULL; sdFireTeam* fireTeam = gameLocal.rules->GetPlayerFireTeam( localPlayerView->entityNumber ); if ( fireTeam != NULL ) { activeTask = fireTeam->GetCommander()->GetActiveTask(); canSelect = fireTeam->GetCommander() == localPlayer; } else { activeTask = localPlayerView->GetActiveTask(); } const sdPlayerTask::nodeType_t& objectiveTasks = sdTaskManager::GetInstance().GetObjectiveTasks( team ); sdPlayerTask* objectiveTask = objectiveTasks.Next(); if ( ( showAll || activeTask == NULL ) && objectiveTask != NULL ) { int index = InsertTask( list, objectiveTask, false ); if( activeTask == NULL ) { list->SelectItem( index ); } } gameLocal.localPlayerProperties.SetHasTask( !showAll && canSelect && ( activeTask != NULL || ( activeTask == NULL && objectiveTask != NULL ) ) ); if( showAll && canSelect && localPlayerView == localPlayer ) { playerTaskList_t miniList; manager.BuildTaskList( localPlayer, miniList ); int num = Min( sdPlayerTask::MAX_CHOOSABLE_TASKS, miniList.Num() ); for( int i = 0; i < num; i++ ) { int index = InsertTask( list, miniList[ i ], false ); if( activeTask == miniList[ i ] ){ list->SelectItem( index ); } } /* int index = sdUIList::InsertItem( list, common->LocalizeText( "guis/game/scoreboard/nomission" ).c_str(), -1, 1 ); if( activeTask == NULL ) { list->SelectItem( index ); } */ idWStrList args( 1 ); keyInputManager->KeysFromBinding( gameLocal.GetDefaultBindContext(), "_taskmenu", true, args.Alloc() ); const idWStr localized = common->LocalizeText( "guis/hud/tasks_are_available", args ); sdUIList::InsertItem( list, localized.c_str(), -1, 1 ); return; } if ( activeTask != NULL ) { int index = InsertTask( list, activeTask, false ); list->SelectItem( index ); } if ( localPlayerView != localPlayer ) { return; } playerTaskList_t miniList; manager.BuildTaskList( localPlayer, miniList ); int numAvailableTasks = miniList.Num(); if( objectiveTask != NULL ) { numAvailableTasks++; } if ( numAvailableTasks > 1 && canSelect ) { idWStrList args( 1 ); keyInputManager->KeysFromBinding( gameLocal.GetDefaultBindContext(), "_taskmenu", true, args.Alloc() ); const idWStr localized = common->LocalizeText( "guis/hud/tasks_are_available", args ); sdUIList::InsertItem( list, localized.c_str(), -1, 1 ); } if ( list->GetNumItems() == 0 ) { const idWStr localized = common->LocalizeText( "guis/hud/no_tasks" ); sdUIList::InsertItem( list, localized.c_str(), -1, 1 ); } } /* ============ idGameLocal::GetTaskListHandle ============ */ qhandle_t idGameLocal::GetTaskListHandle( int index ) { if ( index < 0 || index >= taskListHandles.Num() ) { return -1; } return taskListHandles[ index ]; } /* ============ idGameLocal::TestGUI_f ============ */ void idGameLocal::TestGUI_f( const idCmdArgs& args ) { if( args.Argc() < 2 || idStr::Length( args.Argv( 1 )) == 0 ) { gameLocal.uiMainMenuHandle = gameLocal.LoadUserInterface( "mainmenu", false, true ); } else { gameLocal.uiMainMenuHandle = gameLocal.LoadUserInterface( args.Argv( 1 ), false, true ); // jrad - something of a hack: // ensure that we're pushing the proper times through to the gui sdUserInterfaceLocal* ui =gameLocal.GetUserInterface( gameLocal.uiMainMenuHandle ); if( ui != NULL ) { ui->SetGUIFlag( sdUserInterfaceLocal::GUI_FRONTEND ); } } gameLocal.ShowMainMenu(); } /* ================ idGameLocal::LoadUserInterface ================ */ guiHandle_t idGameLocal::LoadUserInterface( const char* name, bool requireUnique, bool permanent, const char* theme, sdHudModule* module ) { return uiManager->AllocUI( name, requireUnique, permanent, theme, module ); } /* ================ idGameLocal::FreeUserInterface ================ */ void idGameLocal::FreeUserInterface( guiHandle_t handle ) { uiManager->FreeUserInterface( handle ); } /* ================ idGameLocal::GetUserInterface ================ */ sdUserInterfaceLocal* idGameLocal::GetUserInterface( const guiHandle_t handle ) { return static_cast< sdUserInterfaceLocal* >( uiManager->GetUserInterface( handle ) ); } /* ============ idGameLocal::GetUserInterfaceWindow ============ */ sdUIWindow* idGameLocal::GetUserInterfaceWindow( const guiHandle_t handle, const char* windowName ) { if( handle.IsValid() ) { sdUserInterfaceLocal* ui = GetUserInterface( handle ); if( ui ) { return ui->GetWindow( windowName )->Cast< sdUIWindow >(); } } return NULL; } /* ============ idGameLocal::GetUserInterfaceProperty ============ */ sdProperties::sdProperty* idGameLocal::GetUserInterfaceProperty( guiHandle_t handle, const char* propertyName, sdProperties::ePropertyType expectedType ) { if( sdUserInterfaceLocal* ui = GetUserInterface( handle ) ) { return ui->GetState().GetProperty( propertyName, expectedType ); } return NULL; } /* ============ idGameLocal::GetUserInterfaceProperty_r ============ */ sdProperties::sdProperty* idGameLocal::GetUserInterfaceProperty_r( guiHandle_t handle, const char* propertyName, sdProperties::ePropertyType expectedType ) { sdProperties::sdProperty* property = GetUserInterfaceProperty( handle, propertyName, expectedType ); if( property ) { return property; } if( sdUserInterfaceLocal* ui = GetUserInterface( handle ) ) { idLexer parser( propertyName, idStr::Length( propertyName ), "GetUserInterfaceProperty_r", sdDeclGUI::LEXER_FLAGS | LEXFL_NOERRORS ); sdUserInterfaceScope* scope = GetUserInterfaceScope( ui->GetState(), &parser ); if( scope ) { idToken token; if( parser.ReadToken( &token )) { return scope->GetProperty( token, expectedType ); } } } return NULL; } /* ================ idGameLocal::GetUserInterfaceScope ================ */ sdUserInterfaceScope* idGameLocal::GetGlobalUserInterfaceScope( sdUserInterfaceScope& scope, const char* name ) { for( int i = 0; i < uiScopes.Num(); i++ ) { guiScope_t& scope = uiScopes[ i ]; if( idStr::Icmp( name, scope.name ) == 0 ) { return scope.scope; } } return NULL; } /* ================ idGameLocal::GetUserInterfaceScope ================ */ sdUserInterfaceScope* idGameLocal::GetUserInterfaceScope( sdUserInterfaceScope& scope, idLexer* src ) { idToken dot; idToken token; if ( !src->ReadToken( &token ) ) { return &scope; } if ( token.type != TT_NAME ) { src->UnreadToken( &token ); return &scope; } sdUserInterfaceScope* altScope = &scope; sdUserInterfaceScope* globalScope = GetGlobalUserInterfaceScope( scope, token ); if ( globalScope ) { if ( !src->ReadToken( &dot ) || dot != "." ) { src->UnreadToken( &dot ); src->UnreadToken( &token ); return &scope; } src->ReadToken( &token ); altScope = globalScope; } while( true ) { sdUserInterfaceScope* temp; if ( !token.Cmp( "self" ) ) { temp = altScope; } else { temp = altScope->GetSubScope( token ); } if ( !temp || !src->ReadToken( &dot ) ) { src->UnreadToken( &token ); return altScope; } if ( dot != "." ) { src->UnreadToken( &dot ); src->UnreadToken( &token ); return altScope; } src->ReadToken( &token ); altScope = temp; if ( token.type != TT_NAME ) { return altScope; } } } /* ================ sdUIScopeParser::sdUIScopeParser ================ */ sdUIScopeParser::sdUIScopeParser( const char* text ) { idStr::Copynz( entryText, text, sizeof( entryText ) ); int len = idStr::Length( entryText ); ( *entries.Alloc() ) = entryText; int index = 0; while ( ( index = idStr::FindChar( entryText, '.', index, len - 1 ) ) != idStr::INVALID_POSITION ) { entryText[ index ] = '\0'; index++; const char** entry = entries.Alloc(); if ( entry == NULL ) { gameLocal.Error( "sdUIScopeParser: Max Entries Hit" ); } *entry = &entryText[ index ]; } entryIndex = 0; } /* ================ idGameLocal::GetUserInterfaceScope ================ */ sdUserInterfaceScope* idGameLocal::GetUserInterfaceScope( sdUserInterfaceScope& scope, sdUIScopeParser& src ) { sdUserInterfaceScope* altScope = &scope; const char* token = src.GetNextEntry(); if ( src.IsLastEntry() ) { src.Revert(); return altScope; } sdUserInterfaceScope* globalScope = GetGlobalUserInterfaceScope( scope, token ); if ( globalScope != NULL ) { altScope = globalScope; token = src.GetNextEntry(); } while ( true ) { if ( src.IsLastEntry() ) { src.Revert(); return altScope; } sdUserInterfaceScope* temp = altScope->GetSubScope( token ); if ( temp == NULL ) { gameLocal.Warning( "idGameLocal::GetUserInterfaceScope Failed To Find Scope: '%s'", token ); return altScope; } altScope = temp; token = src.GetNextEntry(); } } /* ============ idGameLocal::GuiFrameEvents ============ */ void idGameLocal::GuiFrameEvents( bool outOfSequence ) { uiManager->Update( outOfSequence ); } /* ============ idGameLocal::CreateInventoryList ============ */ void idGameLocal::CreateInventoryList( sdUIList* list ) { sdUserInterfaceLocal* ui = list->GetUI(); assert( ui ); idStr classname; int bank; int package; ui->PopScriptVar( classname ); ui->PopScriptVar( bank ); ui->PopScriptVar( package ); idPlayer* player = gameLocal.GetLocalPlayer(); idList< itemBankPair_t > items; ui->EnumerateItemsForBank( items, classname, bank, package ); for( int i = 0; i < items.Num(); i++ ) { const wchar_t* formatString = va( L"\t", items[ i ].first->GetData().GetString( "mtr_weaponmenu", "default" ), items[ i ].first->GetItemName()->GetName() ); int index = sdUIList::InsertItem( list, formatString, -1, 0 ); list->SetItemDataInt( items[ i ].second, index, 0 ); } } typedef sdPair< int, const vidmode_t* > modePair_t; struct sortVidMode_t { int operator()( const modePair_t& a, const modePair_t& b ) { if( a.second->width == b.second->width ) { return a.second->height - b.second->height; } return a.second->width - b.second->width; return 0; } }; /* ============ idGameLocal::CreateVideoModeList ============ */ void idGameLocal::CreateVideoModeList( sdUIList* list ) { sdUIList::ClearItems( list ); bool fullScreen; list->GetUI()->PopScriptVar( fullScreen ); int aspect; list->GetUI()->PopScriptVar( aspect ); int currentMode = cvarSystem->GetCVarInteger( "r_mode" ); int startMode = 3; int selIndex = -1; static const char* ratios[ 4 ] = { "(4:3)", "(16:9)", "(16:10)", "(5:4)" }; idList< modePair_t > modes; for( int i = startMode; i < common->GetNumVideoModes(); i++ ) { const vidmode_t& mode = common->GetVideoMode( i ); // don't show modes that the monitor says it doesn't support if ( fullScreen && !mode.available ) { continue; } if ( aspect != -1 && aspect != mode.aspectRatio ) { continue; } modes.Append( modePair_t( i, &mode ) ); } sdQuickSort( modes.Begin(), modes.End(), sortVidMode_t() ); int nextBestModeWidth = -1; int nextBestMode = -1; const int currentWidth = currentMode == -1 ? cvarSystem->GetCVarInteger( "r_customWidth" ) : common->GetVideoMode( currentMode ).width; for( int i = 0; i < modes.Num(); i++ ) { const vidmode_t& mode = *modes[ i ].second; int index = sdUIList::InsertItem( list, va( L"%ix%i %hs\t%i", mode.width, mode.height, ratios[ mode.aspectRatio ], modes[ i ].first ), -1, 0 ); if( modes[ i ].first == currentMode ) { selIndex = index; } if( modes[ i ].second->width < currentWidth && modes[ i ].second->width > nextBestModeWidth ) { nextBestMode = index; nextBestModeWidth = modes[ i ].second->width; } } if( selIndex != -1 ) { list->SelectItem( selIndex ); } else if( nextBestMode != -1 ) { list->SelectItem( nextBestMode ); } } /* ============ idGameLocal::CreateCampaignList ============ */ void idGameLocal::CreateCampaignList( sdUIList* list ) { sdUIList::ClearItems( list ); for( int i = 0; i < gameLocal.campaignMetaDataList->GetNumMetaData(); i++ ) { const metaDataContext_t& metaDataContext = gameLocal.campaignMetaDataList->GetMetaDataContext( i ); if ( !gameLocal.IsMetaDataValidForPlay( metaDataContext, true ) ) { continue; } const idDict& dict = *metaDataContext.meta; const char* materialName = dict.GetString( "server_shot_thumb" ); const char* prettyName = dict.GetString( "pretty_name" ); const char* defName = dict.GetString( "metadata_name" ); int index = sdUIList::InsertItem( list, va( L"%hs\t%hs\t%hs", prettyName, defName, materialName ), -1, 0 ); } } /* ============ idGameLocal::CreateMapList ============ */ void idGameLocal::CreateMapList( sdUIList* list ) { sdUIList::ClearItems( list ); sdAddonMetaDataList* metaData = fileSystem->ListAddonMetaData( "mapMetaData" ); for( int i = 0; i < metaData->GetNumMetaData(); i++ ) { const metaDataContext_t& metaDataContext = metaData->GetMetaDataContext( i ); if ( !gameLocal.IsMetaDataValidForPlay( metaDataContext, true ) ) { continue; } const idDict& data = *metaDataContext.meta; const char* materialName = data.GetString( "server_shot_thumb", "levelshots/thumbs/generic.tga" ); const char* defName = data.GetString( "metadata_name" ); const char* prettyName = data.GetString( "pretty_name" ); int index = sdUIList::InsertItem( list, va( L"%hs\t%hs\t%hs", prettyName, defName, materialName ), -1, 0 ); } fileSystem->FreeAddonMetaDataList( metaData ); } /* ============ idGameLocal::PacifierUpdate ============ */ void idGameLocal::PacifierUpdate() { gameLocal.localPlayerProperties.PacifierUpdate(); deviceContext->BeginEmitFullScreen(); if ( sdUserInterfaceLocal* ui = GetUserInterface( uiLevelLoadHandle ) ) { ui->SetCurrentTime( sys->Milliseconds() ); ui->Update(); ui->Draw(); } deviceContext->End(); } /* ============ idGameLocal::ShowLevelLoadScreen ============ */ void idGameLocal::ShowLevelLoadScreen( const char* mapName ) { if ( networkSystem->IsDedicated() ) { return; } /* if ( !reloadingSameMap ) { bytesNeededForMapLoad = GetBytesNeededForMapLoad( mapName ); } else { bytesNeededForMapLoad = 30 * 1024 * 1024; } */ idStr stripped = mapName; stripped.StripFileExtension(); mapMetaData = mapMetaDataList->FindMetaData( stripped, &defaultMetaData ); mapInfo = declMapInfoType.LocalFind( mapMetaData->GetString( "mapinfo", "default" ) ); using namespace sdProperties; if ( sdUserInterfaceScope* scope = globalProperties.GetSubScope( "mapinfo" ) ) { if ( sdProperty* property = scope->GetProperty( "numObjectives", PT_FLOAT ) ) { *property->value.floatValue = mapInfo->GetData().GetFloat( "numObjectives", "0" ); } } sdUserInterfaceLocal* ui; ui = GetUserInterface( pureWaitHandle ); if ( ui != NULL ) { ui->Deactivate( false ); } uiLevelLoadHandle = LoadUserInterface( "loadscreen", false, true ); UpdateCampaignStats( true ); ui = GetUserInterface( uiLevelLoadHandle ); if ( ui != NULL ) { ui->SetCurrentTime( sys->Milliseconds() ); ui->Activate(); PacifierUpdate(); } } /* ============ idGameLocal::UpdateLevelLoadScreen ============ */ void idGameLocal::UpdateLevelLoadScreen( const wchar_t* status ) { if ( networkSystem->IsDedicated() ) { return; } using namespace sdProperties; sdUserInterfaceScope* scope = globalProperties.GetSubScope( "mapinfo" ); if( scope ) { if( sdProperty* property = scope->GetProperty( "mapStatus", PT_WSTRING )) { *property->value.wstringValue = status; } } common->PacifierUpdate(); } /* ============ idGameLocal::HideLevelLoadScreen ============ */ void idGameLocal::HideLevelLoadScreen() { if ( networkSystem->IsDedicated() ) { return; } if ( sdUserInterfaceLocal* ui = GetUserInterface( uiLevelLoadHandle ) ) { ui->Deactivate(); } } /* ============ idGameLocal::GetUIManager ============ */ sdUserInterfaceManager* idGameLocal::GetUIManager() { return uiManager; } /* ============ idGameLocal::SetGUIFloat ============ */ void idGameLocal::SetGUIFloat( int handle, const char* name, float value ) { if ( networkSystem->IsDedicated() ) { gameLocal.Warning( "Tried to run a GUI command on the server" ); } sdUserInterfaceScope* scope; if ( handle == GUI_GLOBALS_HANDLE ) { scope = &gameLocal.globalProperties; } else { sdUserInterfaceLocal* ui = gameLocal.GetUserInterface( handle ); if ( !ui ) { gameLocal.Warning( "idGameLocal::SetGUIFloat: could not find GUI" ); return; } scope = &ui->GetState(); } sdUIScopeParser parser( name ); scope = gameLocal.GetUserInterfaceScope( *scope, parser ); sdProperties::sdProperty* prop = NULL; const char* token = parser.GetNextEntry(); if ( token == NULL ) { assert( false ); } else { prop = scope->GetProperty( token, sdProperties::PT_FLOAT ); } if ( prop != NULL ) { *( prop->value.floatValue ) = value; } else { gameLocal.Warning( "idGameLocal::SetGUIFloat: could not find float property '%s'", name ); } } /* ============ idGameLocal::GetGUIFloat ============ */ float idGameLocal::GetGUIFloat( int handle, const char* name ) { if( networkSystem->IsDedicated() ) { gameLocal.Warning( "Tried to run a GUI command on the server" ); } sdUserInterfaceScope* scope; if ( handle == GUI_GLOBALS_HANDLE ) { scope = &gameLocal.globalProperties; } else { sdUserInterfaceLocal* ui = gameLocal.GetUserInterface( handle ); if( !ui ) { gameLocal.Warning( "idGameLocal::GetGUIFloat: could not find GUI" ); return 0.0f; } scope = &ui->GetState(); } sdUIScopeParser parser( name ); scope = gameLocal.GetUserInterfaceScope( *scope, parser ); sdProperties::sdProperty* prop = NULL; const char* token = parser.GetNextEntry(); if ( token == NULL ) { assert( false ); } else { prop = scope->GetProperty( token, sdProperties::PT_FLOAT ); } if ( prop == NULL ) { gameLocal.Warning( "idGameLocal::GetGUIFloat: could not find float property '%s'", name ); return 0.f; } return prop->value.floatValue->GetValue(); } /* ============ idGameLocal::SetGUIInt ============ */ void idGameLocal::SetGUIInt( int handle, const char* name, int value ) { if ( networkSystem->IsDedicated() ) { gameLocal.Warning( "Tried to run a GUI command on the server" ); } sdUserInterfaceScope* scope; if ( handle == GUI_GLOBALS_HANDLE ) { scope = &gameLocal.globalProperties; } else { sdUserInterfaceLocal* ui = gameLocal.GetUserInterface( handle ); if ( !ui ) { gameLocal.Warning( "idGameLocal::SetGUIInt: could not find GUI" ); return; } scope = &ui->GetState(); } sdUIScopeParser parser( name ); scope = gameLocal.GetUserInterfaceScope( *scope, parser ); sdProperties::sdProperty* prop = NULL; const char* token = parser.GetNextEntry(); if ( token == NULL ) { assert( false ); } else { prop = scope->GetProperty( token, sdProperties::PT_INT ); } if ( prop != NULL ) { *( prop->value.intValue ) = value; } else { gameLocal.Warning( "idGameLocal::SetGUIInt: could not find int property '%s'", name ); } } /* ============ idGameLocal::SetGUIVec2 ============ */ void idGameLocal::SetGUIVec2( int handle, const char* name, const idVec2& value ) { if ( networkSystem->IsDedicated() ) { gameLocal.Warning( "Tried to run a GUI command on the server" ); } sdUserInterfaceScope* scope; if ( handle == GUI_GLOBALS_HANDLE ) { scope = &gameLocal.globalProperties; } else { sdUserInterfaceLocal* ui = gameLocal.GetUserInterface( handle ); if( !ui ) { gameLocal.Warning( "idGameLocal::SetGUIVec2: could not find GUI" ); return; } scope = &ui->GetState(); } sdUIScopeParser parser( name ); scope = gameLocal.GetUserInterfaceScope( *scope, parser ); sdProperties::sdProperty* prop = NULL; const char* token = parser.GetNextEntry(); if ( token == NULL ) { assert( false ); } else { prop = scope->GetProperty( token, sdProperties::PT_VEC2 ); } if ( prop != NULL ) { *( prop->value.vec2Value ) = value; } else { gameLocal.Warning( "idGameLocal::SetGUIVec2: could not find vec2 property '%s'", name ); } } /* ============ idGameLocal::SetGUIVec3 ============ */ void idGameLocal::SetGUIVec3( int handle, const char* name, const idVec3& value ) { if ( networkSystem->IsDedicated() ) { gameLocal.Warning( "Tried to run a GUI command on the server" ); } sdUserInterfaceScope* scope; if ( handle == GUI_GLOBALS_HANDLE ) { scope = &gameLocal.globalProperties; } else { sdUserInterfaceLocal* ui = gameLocal.GetUserInterface( handle ); if( !ui ) { gameLocal.Warning( "idGameLocal::SetGUIVec3: could not find GUI" ); return; } scope = &ui->GetState(); } sdUIScopeParser parser( name ); scope = gameLocal.GetUserInterfaceScope( *scope, parser ); sdProperties::sdProperty* prop = NULL; const char* token = parser.GetNextEntry(); if ( token == NULL ) { assert( false ); } else { prop = scope->GetProperty( token, sdProperties::PT_VEC3 ); } if ( prop != NULL ) { *( prop->value.vec3Value ) = value; } else { gameLocal.Warning( "idGameLocal::SetGUIVec3: could not find vec3 property '%s'", name ); } } /* ============ idGameLocal::SetGUIVec4 ============ */ void idGameLocal::SetGUIVec4( int handle, const char* name, const idVec4& value ) { if ( networkSystem->IsDedicated() ) { gameLocal.Warning( "Tried to run a GUI command on the server" ); } sdUserInterfaceScope* scope; if ( handle == GUI_GLOBALS_HANDLE ) { scope = &gameLocal.globalProperties; } else { sdUserInterfaceLocal* ui = gameLocal.GetUserInterface( handle ); if( !ui ) { gameLocal.Warning( "idGameLocal::SetGUIVec4: could not find GUI" ); return; } scope = &ui->GetState(); } sdUIScopeParser parser( name ); scope = gameLocal.GetUserInterfaceScope( *scope, parser ); sdProperties::sdProperty* prop = NULL; const char* token = parser.GetNextEntry(); if ( token == NULL ) { assert( false ); } else { prop = scope->GetProperty( token, sdProperties::PT_VEC4 ); } if ( prop != NULL ) { *( prop->value.vec4Value ) = value; } else { gameLocal.Warning( "idGameLocal::SetGUIVec4: could not find vec4 property '%s'", name ); } } /* ============ idGameLocal::SetGUIString ============ */ void idGameLocal::SetGUIString( int handle, const char* name, const char* value ) { if ( networkSystem->IsDedicated() ) { gameLocal.Warning( "Tried to run a GUI command on the server" ); } sdUserInterfaceScope* scope; if ( handle == GUI_GLOBALS_HANDLE ) { scope = &gameLocal.globalProperties; } else { sdUserInterfaceLocal* ui = gameLocal.GetUserInterface( handle ); if( !ui ) { gameLocal.Warning( "idGameLocal::SetGUIString: could not find GUI" ); return; } scope = &ui->GetState(); } sdUIScopeParser parser( name ); scope = gameLocal.GetUserInterfaceScope( *scope, parser ); sdProperties::sdProperty* prop = NULL; const char* token = parser.GetNextEntry(); if ( token == NULL ) { assert( false ); } else { prop = scope->GetProperty( token, sdProperties::PT_STRING ); } if ( prop != NULL ) { *( prop->value.stringValue ) = value; } else { gameLocal.Warning( "idGameLocal::SetGUIString: could not find string property '%s'", name ); } } /* ============ idGameLocal::SetGUIWString ============ */ void idGameLocal::SetGUIWString( int handle, const char* name, const wchar_t* value ) { if( networkSystem->IsDedicated() ) { gameLocal.Warning( "Tried to run a GUI command on the server" ); } sdUserInterfaceScope* scope; if ( handle == GUI_GLOBALS_HANDLE ) { scope = &gameLocal.globalProperties; } else { sdUserInterfaceLocal* ui = gameLocal.GetUserInterface( handle ); if( !ui ) { gameLocal.Warning( "idGameLocal::SetGUIWString: could not find GUI" ); return; } scope = &ui->GetState(); } sdUIScopeParser parser( name ); scope = gameLocal.GetUserInterfaceScope( *scope, parser ); sdProperties::sdProperty* prop = NULL; const char* token = parser.GetNextEntry(); if ( token == NULL ) { assert( false ); } else { prop = scope->GetProperty( token, sdProperties::PT_WSTRING ); } if ( prop != NULL ) { *( prop->value.wstringValue ) = value; } else { gameLocal.Warning( "idGameLocal::SetGUIWString: could not find string property '%s'", name ); } } /* ============ idGameLocal::SetGUITheme ============ */ void idGameLocal::SetGUITheme( guiHandle_t handle, const char* theme ) { if( !handle ) { gameLocal.Error( "SetGUITheme: Invalid GUI handle." ); return; } sdUserInterfaceLocal* ui = static_cast< sdUserInterfaceLocal* >( uiManager->GetUserInterface( handle ) ); if( !ui ) { gameLocal.Warning( "idGameLocal::SetGUITheme : Could not find GUI." ); return; } ui->SetTheme( theme ); } /* ============ idGameLocal::GUIPostNamedEvent ============ */ void idGameLocal::GUIPostNamedEvent( int handle, const char* window, const char* name ) { if( networkSystem->IsDedicated() ) { gameLocal.Warning( "Tried to run a GUI command on the server" ); } sdUserInterfaceLocal* ui = gameLocal.GetUserInterface( handle ); if( !ui ) { gameLocal.Warning( "idGameLocal::GUIPostNamedEvent: could not find GUI" ); return; } sdUIObject* object = NULL; if( idStr::Length( window )) { object = ui->GetWindow( window ); } if( !object && idStr::Length( window )) { gameLocal.Warning( "idGameLocal::GUIPostNamedEvent: could not find window '%s'", window ); return; } else if( object ) { object->PostNamedEvent( name, false ); } else { ui->PostNamedEvent( name ); } } /* ============ idGameLocal::UpdateCampaignStats ============ */ void idGameLocal::UpdateCampaignStats( bool allowMedia ) { if( networkSystem->IsDedicated() ) { return; } sdGameRules* rulesInstance = gameLocal.GetRulesInstance( serverInfo.GetString( "si_rules" ) ); if( rulesInstance != NULL ) { rulesInstance->UpdateClientFromServerInfo( serverInfo, allowMedia ); } } /* ============ idGameLocal::CreateWeaponSwitchList ============ */ void idGameLocal::CreateWeaponSwitchList( sdUIList* list ) { sdUIList::ClearItems( list ); idPlayer* localPlayer = gameLocal.GetLocalPlayer(); if( localPlayer == NULL ) { return; } using namespace sdProperties; const sdInventory& inv = localPlayer->GetInventory(); const int currentWeapon = inv.GetCurrentWeapon(); const int switchingWeapon = inv.GetSwitchingWeapon(); if( currentWeapon == -1 || switchingWeapon == -1 ) { return; } const sdDeclInvItem* item = inv.GetItem( currentWeapon ); const sdDeclInvItem* switchItem = inv.GetItem( switchingWeapon ); typedef sdPair< const sdDeclInvItem*, int > invElement_t; idStaticList< invElement_t, 10 > items; for( int i = 0; i < inv.GetNumItems(); i++ ) { if ( !inv.CanAutoEquip( i, false ) ) { continue; } const sdDeclInvItem* item = inv.GetItem( i ); if ( inv.GetSlotForWeapon( i ) != -1 ) { int j = 0; const sdDeclInvSlot* slot = gameLocal.declInvSlotType.LocalFindByIndex( item->GetSlot() ); while( j < items.Num() ) { if( item->GetSlot() < items[ j ].first->GetSlot() ) { break; } const sdDeclInvSlot* otherSlot = gameLocal.declInvSlotType.LocalFindByIndex( items[ j ].first->GetSlot() ); if( slot->GetBank() < otherSlot->GetBank() ) { break; } j++; } items.Insert( invElement_t( item, i ), j ); } } int offset = 0; for( int i = 0; i < items.Num(); i++ ) { int bankNumber = i; const sdDeclInvItem* invItem = inv.GetItem( items[ i ].second ); const bool available = inv.CheckWeaponHasAmmo( invItem ) || invItem->GetData().GetBool( "select_when_empty", "0" ); const char* material = invItem->GetData().GetString( "mtr_weaponmenu", "_default" ); const int title = invItem->GetItemName()->Index(); float weaponAmmo = -1.0f; const idList< itemClip_t >& itemClips = invItem->GetClips(); if ( itemClips.Num() && itemClips[ 0 ].ammoPerShot > 0 ) { float ammo; float totalAmmo; if( invItem->GetData().GetBool( "show_all_ammo", "0" )) { ammo = inv.GetAmmo( itemClips[ 0 ].ammoType ) / itemClips[ 0 ].ammoPerShot; totalAmmo = inv.GetMaxAmmo( itemClips[ 0 ].ammoType ) / itemClips[ 0 ].ammoPerShot; } else { ammo = inv.GetClip( items[ i ].second, 0 ); totalAmmo = inv.GetClipSize( items[ i ].second, 0 ); } weaponAmmo = idMath::ClampFloat( 0.0f, 1.0f, ammo / totalAmmo ); } int index = sdUIList::InsertItem( list, va( L"%i\t\t%f\t%i\t%i", invItem->GetSlot(), material, weaponAmmo, title, available ), -1, 0 ); if( invItem == switchItem ) { list->SelectItem( index ); localPlayer->SetWeaponSelectionItemIndex( bankNumber ); } } } /* ============ idGameLocal::CreateColorList ============ */ void idGameLocal::CreateColorList( sdUIList* list ) { idVec4 customColor; list->GetUI()->PopScriptVar( customColor ); idStr currentColorStr; list->GetUI()->PopScriptVar( currentColorStr ); idVec4 currentColor = colorWhite; if( !currentColorStr.IsEmpty() ) { currentColor = sdTypeFromString< idVec4 >( currentColorStr.c_str() ); } // if refreshing, only add new custom colors bool refreshOnly; list->GetUI()->PopScriptVar( refreshOnly ); if( refreshOnly == false ) { sdUIList::ClearItems( list ); } idWStr str; idWStr colorSymbol; idStr color; bool customMatchesDefault = false; int toSelect = -1; static const float COLOR_EPSILON = 0.001f; // check against previous custom colors if( refreshOnly == false || list->GetNumItems() == 0 ) { // skip default color for( int i = 1; i < COLOR_BITS + 1; i++ ) { const idVec4& c = idStr::ColorForIndex( i ); if( c.ToVec3().Compare( customColor.ToVec3(), COLOR_EPSILON ) ) { customMatchesDefault = true; } colorSymbol = va( L"%hs", idStr::StrForColorIndex( i ) ); sdUIList::CleanUserInput( colorSymbol ); color = c.ToString( 2 ); str = va( L"\t%ls\t%hs", color.c_str(), colorSymbol.c_str(), color.c_str() ); int index = sdUIList::InsertItem( list, str.c_str(), -1, 0 ); if( currentColor.ToVec3().Compare( c.ToVec3(), COLOR_EPSILON ) ) { toSelect = index; } } } else { for( int i = 0; i < list->GetNumItems(); i++ ) { idVec4 c = sdTypeFromString< idVec4 >( va( "%ls", list->GetItemText( i, 2, true ) ) ); if( c.ToVec3().Compare( customColor.ToVec3(), COLOR_EPSILON ) ) { customMatchesDefault = true; } if( currentColor.ToVec3().Compare( c.ToVec3(), COLOR_EPSILON ) ) { toSelect = i; } } } if( !customMatchesDefault ) { str = va( L"\t%\t%hs", customColor.ToString( 2 ), customColor.ToString( 2 ) ); int index = sdUIList::InsertItem( list, str.c_str(), -1, 0 ); if( currentColor.ToVec3().Compare( customColor.ToVec3(), COLOR_EPSILON ) ) { toSelect = index; } } list->SelectItem( toSelect ); } /* ============ idGameLocal::CreateSpawnLocationList ============ */ void idGameLocal::CreateSpawnLocationList( sdUIList* list ) { sdUIList::ClearItems( list ); idStr team; list->GetUI()->PopScriptVar( team ); const sdTeamInfo* info = sdTeamManager::GetInstance().GetTeamSafe( team.c_str() ); if( info == NULL ) { return; } int currentSpawn = -1; int defaultSpawn = -1; int numLocs = info->GetNumSpawnLocations(); int* spawnCounts = static_cast< int* >( _alloca( numLocs * sizeof( int ) ) ); memset( &spawnCounts[ 0 ], 0, numLocs * sizeof( int ) ); const idPlayer* localPlayer = gameLocal.GetLocalPlayer(); for( int i = 0; i < MAX_CLIENTS; i++ ) { idPlayer* player = gameLocal.GetClient( i ); if( player == NULL || player->GetGameTeam() != info ) { continue; } const idEntity* playerSpawnLoc = player->GetSpawnPoint(); for( int si = 0; si < numLocs; si++ ) { const idEntity* spawn = info->GetSpawnLocation( si ); if( playerSpawnLoc == NULL && spawn == info->GetDefaultSpawn() ) { defaultSpawn = si; if( playerSpawnLoc == NULL ) { spawnCounts[ defaultSpawn ]++; break; } } if( spawn == playerSpawnLoc ) { spawnCounts[ si ]++; if( player == localPlayer ) { currentSpawn = si; } break; } } } idWStr loc; for( int i = 0; i < numLocs; i++ ) { const idEntity* spawn = info->GetSpawnLocation( i ); sdLocationMarker::GetLocationText( spawn->GetPhysics()->GetOrigin(), loc ); int index = sdUIList::InsertItem( list, va( L"%ls\t%i\t%hs", loc.c_str(), spawnCounts[ i ], spawn->GetName() ), -1, 0 ); if( i == currentSpawn ) { list->SelectItem( index ); } } int index = sdUIList::InsertItem( list, L"\t\t", -1, 0 ); if( currentSpawn == -1 ) { list->SelectItem( index ); } } /* ============ idGameLocal::CreateMSAAList ============ */ void idGameLocal::CreateMSAAList( sdUIList* list ) { int num = renderSystem->GetNumMSAAModes(); for (int i=0; iGetMSAAMode( i, val ); int index = sdUIList::InsertItem( list, va( L"%hs", msaaName ), -1, 0 ); list->SetItemDataInt( val, index, 0, true ); } } /* ============ idGameLocal::CreateSoundPlaybackList ============ */ void idGameLocal::CreateSoundPlaybackList( sdUIList* list ) { sdUIList::ClearItems( list ); const idWStrList* devices = soundSystem->ListSoundPlaybackDevices(); for( int i = 0; devices != NULL && i < devices->Num(); i++ ) { const idWStr& str = (*devices)[ i ]; int hash = soundSystem->GetAudioDeviceHash( str.c_str() ); sdUIList::InsertItem( list, va( L"%ls\t%d", str.c_str(), hash ), -1, 0 ); } soundSystem->FreeDeviceList( devices ); } /* ============ idGameLocal::CreateSoundCaptureList ============ */ void idGameLocal::CreateSoundCaptureList( sdUIList* list ) { sdUIList::ClearItems( list ); const idWStrList* devices = soundSystem->ListSoundCaptureDevices(); for( int i = 0; devices != NULL && i < devices->Num(); i++ ) { const idWStr& str = (*devices)[ i ]; int hash = soundSystem->GetAudioDeviceHash( str.c_str() ); sdUIList::InsertItem( list, va( L"%ls\t%d", str.c_str(), hash ), -1, 0 ); } soundSystem->FreeDeviceList( devices ); } /* ============ idGameLocal::CreateModList ============ */ void idGameLocal::CreateModList( sdUIList* list ) { sdUIList::ClearItems( list ); idModList* mods = fileSystem->ListMods(); if( mods != NULL ) { for( int i = 0; i < mods->GetNumMods(); i++ ) { sdUIList::InsertItem( list, va( L"%hs\t%hs", mods->GetDescription( i ), mods->GetMod( i ) ), -1, 0 ); } fileSystem->FreeModList( mods ); } } static void AddLifeStatsItems( sdUIList* list, const char* material, const idList< const sdStatsTracker::lifeStatsData_t* >& data ) { for( int i = 0; i < data.Num(); i++ ) { const sdStatsTracker::lifeStatsData_t* item = data[ i ]; const lifeStat_t& stat = gameLocal.lifeStats[ item->index ]; switch( item->newValue.GetType() ) { case sdNetStatKeyValue::SVT_INT: case sdNetStatKeyValue::SVT_INT_MAX: if( stat.isTimeBased ) { idStr::hmsFormat_t format; format.showZeroMinutes = true; sdUIList::InsertItem( list, va( L"\t\t%hs (%hs)", material, stat.text->GetName(), idStr::MS2HMS( item->newValue.GetInt() * 1000, format ), idStr::MS2HMS( item->oldValue.GetInt() * 1000, format ) ), -1, 0 ); } else { sdUIList::InsertItem( list, va( L"\t\t%i (%i)", material, stat.text->GetName(), item->newValue.GetInt(), item->oldValue.GetInt() ), -1, 0 ); } break; case sdNetStatKeyValue::SVT_FLOAT: case sdNetStatKeyValue::SVT_FLOAT_MAX: sdUIList::InsertItem( list, va( L"\t\t%i (%i)", material, stat.text->GetName(), idMath::Ftoi( idMath::Ceil( item->newValue.GetFloat() ) ), idMath::Ftoi( idMath::Ceil( item->oldValue.GetFloat() ) ) ), -1, 0 ); break; } } } /* ============ idGameLocal::CreateLifeStatsList ============ */ void idGameLocal::CreateLifeStatsList( sdUIList* list ) { sdUIList::ClearItems( list ); idList< const sdStatsTracker::lifeStatsData_t* > improved; idList< const sdStatsTracker::lifeStatsData_t* > unchanged; idList< const sdStatsTracker::lifeStatsData_t* > worse; sdGlobalStatsTracker::GetInstance().GetTopLifeStats( improved, unchanged, worse ); AddLifeStatsItems( list, "improved", improved ); AddLifeStatsItems( list, "unchanged", unchanged ); AddLifeStatsItems( list, "nodraw", worse ); } class sdSortCategories { public: sdSortCategories( const sdProficiencyTable& table ) : table( table ) {} int operator()( const sdDeclPlayerClass::proficiencyCategory_t* lhs, const sdDeclPlayerClass::proficiencyCategory_t* rhs ) { float lhsPercent = table.GetPercent( lhs->index ); float rhsPercent = table.GetPercent( rhs->index ); return ( idMath::Ftoi( rhsPercent * 100 ) ) - ( idMath::Ftoi( lhsPercent * 100 ) ); } const sdProficiencyTable& table; }; /* ============ idGameLocal::CreatePredictedUpgradesList ============ */ void idGameLocal::CreatePredictedUpgradesList( sdUIList* list ) { sdUIList::ClearItems( list ); idPlayer* localPlayer = gameLocal.GetLocalPlayer(); if( localPlayer == NULL ) { return; } const sdTeamInfo* ti = localPlayer->GetGameTeam(); idList< const sdDeclPlayerClass::proficiencyCategory_t* > bestCategories; const sdProficiencyTable& table = localPlayer->GetProficiencyTable(); for( int i = 0; i < gameLocal.declPlayerClassType.Num(); i++ ) { const sdDeclPlayerClass* pc = gameLocal.declPlayerClassType.LocalFindByIndex( i ); if( pc->GetTeam() != ti && ti != NULL ) { continue; } for ( int j = 0; j < pc->GetNumProficiencies(); j++ ) { const sdDeclPlayerClass::proficiencyCategory_t& category = pc->GetProficiency( j ); float percent = table.GetPercent( category.index ); if( percent >= 1.0f ) { continue; } int k; for( k = 0; k < bestCategories.Num(); k++ ) { if( bestCategories[ k ]->index == category.index ) { break; } } if( k >= bestCategories.Num() ) { bestCategories.Append( &category ); } } } sdQuickSort( bestCategories.Begin(), bestCategories.End(), sdSortCategories( table ) ); int numAdded = 0; for( int i = 0; i < bestCategories.Num() && numAdded < 2; i++ ) { int currentLevel = table.GetLevel( bestCategories[ i ]->index ); if( currentLevel < bestCategories[ i ]->upgrades.Num() ) { const sdDeclProficiencyType* type = gameLocal.declProficiencyTypeType.LocalFindByIndex( bestCategories[ i ]->index ); const sdDeclPlayerClass::proficiencyUpgrade_t& upgrade = bestCategories[ i ]->upgrades[ currentLevel ]; int index = sdUIList::InsertItem( list, va( L"\t\t%hs", upgrade.materialInfo.c_str(), upgrade.title->GetName(), type->GetName() ), -1, 0 ); float percent = table.GetPercent( bestCategories[ i ]->index ); // push some extra data along for the GUI list->SetItemDataInt( percent * 100 , index, 0, true ); list->SetItemDataInt( currentLevel, index, 1, true ); numAdded++; } } } /* ============ idGameLocal::CreateUpgradesReviewList ============ */ void idGameLocal::CreateUpgradesReviewList( sdUIList* list ) { sdUIList::ClearItems( list ); idPlayer* localPlayer = gameLocal.GetLocalPlayer(); if( localPlayer == NULL ) { return; } const sdTeamInfo* ti = localPlayer->GetGameTeam(); const sdProficiencyTable& table = localPlayer->GetProficiencyTable(); idList< const sdDeclPlayerClass::proficiencyCategory_t* > bestCategories; for( int i = 0; i < gameLocal.declPlayerClassType.Num(); i++ ) { const sdDeclPlayerClass* pc = gameLocal.declPlayerClassType.LocalFindByIndex( i ); if( pc->GetTeam() != ti && ti != NULL ) { continue; } for ( int j = 0; j < pc->GetNumProficiencies(); j++ ) { const sdDeclPlayerClass::proficiencyCategory_t& category = pc->GetProficiency( j ); int k; for( k = 0; k < bestCategories.Num(); k++ ) { if( bestCategories[ k ]->index == category.index ) { break; } } if( k < bestCategories.Num() ) { continue; } bestCategories.Append( &category ); int currentLevel = table.GetLevel(category.index ); for ( int level = 0; level < currentLevel && level < category.upgrades.Num(); level++ ) { const sdDeclPlayerClass::proficiencyUpgrade_t& upgrade = category.upgrades[ level ]; int index = sdUIList::InsertItem( list, va( L"\t", upgrade.materialInfo.c_str(), upgrade.title->GetName()), -1, 0 ); } } } } /* =============== idGameLocal::UpdateHudStats =============== */ void idGameLocal::UpdateHudStats( idPlayer* player ) { localPlayerProperties.Update( player ); limboProperties.Update(); sdAdminSystem::GetInstance().UpdateProperties(); } #undef ON_UIVALID #undef ON_UIINVALID