123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538 |
- /*
- ===========================================================================
- Doom 3 BFG Edition GPL Source Code
- Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
- Doom 3 BFG Edition 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 3 of the License, or
- (at your option) any later version.
- Doom 3 BFG Edition 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- #include "../idlib/precompiled.h"
- #pragma hdrstop
- #include "Game_local.h"
- #include "..\..\doomclassic\doom\doomdef.h"
- idCVar achievements_Verbose( "achievements_Verbose", "1", CVAR_BOOL, "debug spam" );
- idCVar g_demoMode( "g_demoMode", "0", CVAR_INTEGER, "this is a demo" );
- bool idAchievementManager::cheatingDialogShown = false;
- const struct achievementInfo_t {
- int required;
- bool lifetime; // true means the current count is stored on the player profile. Doesn't matter for single count achievements.
- } achievementInfo [ACHIEVEMENTS_NUM] = {
- { 50, true }, // ACHIEVEMENT_EARN_ALL_50_TROPHIES
- { 1, true }, // ACHIEVEMENT_COMPLETED_DIFFICULTY_0
- { 1, true }, // ACHIEVEMENT_COMPLETED_DIFFICULTY_1
- { 1, true }, // ACHIEVEMENT_COMPLETED_DIFFICULTY_2
- { 1, true }, // ACHIEVEMENT_COMPLETED_DIFFICULTY_3
- { 64, false }, // ACHIEVEMENT_PDAS_BASE
- { 14, false }, // ACHIEVEMENT_WATCH_ALL_VIDEOS
- { 1, false }, // ACHIEVEMENT_KILL_MONSTER_WITH_1_HEALTH_LEFT
- { 35, false }, // ACHIEVEMENT_OPEN_ALL_LOCKERS
- { 20, true }, // ACHIEVEMENT_KILL_20_ENEMY_FISTS_HANDS
- { 1, true }, // ACHIEVEMENT_KILL_SCI_NEXT_TO_RCR
- { 1, true }, // ACHIEVEMENT_KILL_TWO_IMPS_ONE_SHOTGUN
- { 1, true }, // ACHIEVEMENT_SCORE_25000_TURKEY_PUNCHER
- { 50, true }, // ACHIEVEMENT_DESTROY_BARRELS
- { 1, true }, // ACHIEVEMENT_GET_BFG_FROM_SECURITY_OFFICE
- { 1, true }, // ACHIEVEMENT_COMPLETE_LEVEL_WITHOUT_TAKING_DMG
- { 1, true }, // ACHIEVEMENT_FIND_RAGE_LOGO
- { 1, true }, // ACHIEVEMENT_SPEED_RUN
- { 1, true }, // ACHIEVEMENT_DEFEAT_VAGARY_BOSS
- { 1, true }, // ACHIEVEMENT_DEFEAT_GUARDIAN_BOSS
- { 1, true }, // ACHIEVEMENT_DEFEAT_SABAOTH_BOSS
- { 1, true }, // ACHIEVEMENT_DEFEAT_CYBERDEMON_BOSS
- { 1, true }, // ACHIEVEMENT_SENTRY_BOT_ALIVE_TO_DEST
- { 20, true }, // ACHIEVEMENT_KILL_20_ENEMY_WITH_CHAINSAW
- { 1, true }, // ACHIEVEMENT_ID_LOGO_SECRET_ROOM
- { 1, true }, // ACHIEVEMENT_BLOODY_HANDWORK_OF_BETRUGER
- { 1, true }, // ACHIEVEMENT_TWO_DEMONS_FIGHT_EACH_OTHER
- { 20, true }, // ACHIEVEMENT_USE_SOUL_CUBE_TO_DEFEAT_20_ENEMY
- { 1, true }, // ACHIEVEMENT_ROE_COMPLETED_DIFFICULTY_0
- { 1, true }, // ACHIEVEMENT_ROE_COMPLETED_DIFFICULTY_1
- { 1, true }, // ACHIEVEMENT_ROE_COMPLETED_DIFFICULTY_2
- { 1, true }, // ACHIEVEMENT_ROE_COMPLETED_DIFFICULTY_3
- { 22, false }, // ACHIEVEMENT_PDAS_ROE
- { 1, true }, // ACHIEVEMENT_KILL_5_ENEMY_HELL_TIME
- { 1, true }, // ACHIEVEMENT_DEFEAT_HELLTIME_HUNTER
- { 1, true }, // ACHIEVEMENT_DEFEAT_BERSERK_HUNTER
- { 1, true }, // ACHIEVEMENT_DEFEAT_INVULNERABILITY_HUNTER
- { 1, true }, // ACHIEVEMENT_DEFEAT_MALEDICT_BOSS
- { 20, true }, // ACHIEVEMENT_GRABBER_KILL_20_ENEMY
- { 20, true }, // ACHIEVEMENT_ARTIFACT_WITH_BERSERK_PUNCH_20
- { 1, true }, // ACHIEVEMENT_LE_COMPLETED_DIFFICULTY_0
- { 1, true }, // ACHIEVEMENT_LE_COMPLETED_DIFFICULTY_1
- { 1, true }, // ACHIEVEMENT_LE_COMPLETED_DIFFICULTY_2
- { 1, true }, // ACHIEVEMENT_LE_COMPLETED_DIFFICULTY_3
- { 10, false }, // ACHIEVEMENT_PDAS_LE
- { 1, true }, // ACHIEVEMENT_MP_KILL_PLAYER_VIA_TELEPORT
- { 1, true }, // ACHIEVEMENT_MP_CATCH_ENEMY_IN_ROFC
- { 5, true }, // ACHIEVEMENT_MP_KILL_5_PLAYERS_USING_INVIS
- { 1, true }, // ACHIEVEMENT_MP_COMPLETE_MATCH_WITHOUT_DYING
- { 1, true }, // ACHIEVEMENT_MP_USE_BERSERK_TO_KILL_PLAYER
- { 1, true }, // ACHIEVEMENT_MP_KILL_2_GUYS_IN_ROOM_WITH_BFG
- };
- /*
- ================================================================================================
- idAchievementManager
- ================================================================================================
- */
- /*
- ========================
- idAchievementManager::idAchievementManager
- ========================
- */
- idAchievementManager::idAchievementManager() :
- lastImpKilledTime( 0 ),
- lastPlayerKilledTime( 0 ),
- playerTookDamage( false ) {
- counts.Zero();
- ResetHellTimeKills();
- }
- /*
- ========================
- idAchievementManager::Init
- ========================
- */
- void idAchievementManager::Init( idPlayer * player ) {
- owner = player;
- SyncAchievments();
- }
- /*
- ========================
- idAchievementManager::SyncAchievments
- ========================
- */
- void idAchievementManager::SyncAchievments() {
- idLocalUser * user = GetLocalUser();
- if ( user == NULL || user->GetProfile() == NULL ) {
- return;
- }
- // Set achievement counts
- for ( int i = 0; i < counts.Num(); i++ ) {
- if ( user->GetProfile()->GetAchievement( i ) ) {
- counts[i] = achievementInfo[i].required;
- } else if ( achievementInfo[i].lifetime ) {
- counts[i] = user->GetStatInt( i );
- }
- }
- }
- /*
- ========================
- idAchievementManager::GetLocalUser
- ========================
- */
- idLocalUser * idAchievementManager::GetLocalUser() {
- if ( !verify( owner != NULL ) ) {
- return NULL;
- }
- return session->GetGameLobbyBase().GetLocalUserFromLobbyUser( gameLocal.lobbyUserIDs[ owner->GetEntityNumber() ] );
- }
- /*
- ========================
- idAchievementManager::Save
- ========================
- */
- void idAchievementManager::Save( idSaveGame * savefile ) const {
- owner.Save( savefile );
- for ( int i = 0; i < ACHIEVEMENTS_NUM; i++ ) {
- savefile->WriteInt( counts[i] );
- }
- savefile->WriteInt( lastImpKilledTime );
- savefile->WriteInt( lastPlayerKilledTime );
- savefile->WriteBool( playerTookDamage );
- savefile->WriteInt( currentHellTimeKills );
- }
- /*
- ========================
- idAchievementManager::Restore
- ========================
- */
- void idAchievementManager::Restore( idRestoreGame * savefile ) {
- owner.Restore( savefile );
-
- for ( int i = 0; i < ACHIEVEMENTS_NUM; i++ ) {
- savefile->ReadInt( counts[i] );
- }
- savefile->ReadInt( lastImpKilledTime );
- savefile->ReadInt( lastPlayerKilledTime );
- savefile->ReadBool( playerTookDamage );
- savefile->ReadInt( currentHellTimeKills );
- SyncAchievments();
- }
- /*
- ========================
- idAchievementManager::EventCompletesAchievement
- ========================
- */
- void idAchievementManager::EventCompletesAchievement( const achievement_t eventId ) {
- if ( g_demoMode.GetBool() ) {
- return;
- }
- idLocalUser * localUser = GetLocalUser();
- if ( localUser == NULL || localUser->GetProfile() == NULL ) {
- // Send a Reliable Message to the User that needs to unlock this.
- if ( owner != NULL ) {
- int playerId = owner->entityNumber;
- const int bufferSize = sizeof( playerId ) + sizeof( eventId );
- byte buffer[ bufferSize ];
- idBitMsg msg;
- msg.InitWrite( buffer, bufferSize );
- msg.WriteByte( playerId );
- msg.WriteByte( eventId );
- msg.WriteByteAlign();
- idLib::Printf( "Host Sending Achievement\n");
- session->GetActingGameStateLobbyBase().SendReliableToLobbyUser( gameLocal.lobbyUserIDs[ owner->entityNumber ], GAME_RELIABLE_MESSAGE_ACHIEVEMENT_UNLOCK, msg );
- }
- return; // Remote user or build game
- }
- // Check to see if we've already given the achievement.
- // If so, don't do again because we don't want to autosave every time a trigger is hit
- if ( localUser->GetProfile()->GetAchievement( eventId ) ) {
- return;
- }
- #ifdef ID_RETAIL
- if ( common->GetConsoleUsed() ) {
- if ( !cheatingDialogShown ) {
- common->Dialog().AddDialog( GDM_ACHIEVEMENTS_DISABLED_DUE_TO_CHEATING, DIALOG_ACCEPT, NULL, NULL, true );
- cheatingDialogShown = true;
- }
- return;
- }
- #endif
- counts[eventId]++;
- if ( counts[eventId] >= achievementInfo[eventId].required ) {
- session->GetAchievementSystem().AchievementUnlock( localUser, eventId );
- } else {
- if ( achievementInfo[eventId].lifetime ) {
- localUser->SetStatInt( eventId, counts[eventId] );
- }
- }
- }
- /*
- ========================
- idAchievementManager::IncrementHellTimeKills
- ========================
- */
- void idAchievementManager::IncrementHellTimeKills() {
- currentHellTimeKills++;
- if ( currentHellTimeKills >= 5 ) {
- EventCompletesAchievement( ACHIEVEMENT_KILL_5_ENEMY_HELL_TIME );
- }
- }
- /*
- ========================
- idAchievementManager::SavePersistentData
- ========================
- */
- void idAchievementManager::SavePersistentData( idDict & playerInfo ) {
- for ( int i = 0; i < ACHIEVEMENTS_NUM; ++i ) {
- playerInfo.SetInt( va( "ach_%d", i ), counts[i] );
- }
- }
- /*
- ========================
- idAchievementManager::RestorePersistentData
- ========================
- */
- void idAchievementManager::RestorePersistentData( const idDict & spawnArgs ) {
- for( int i = 0; i < ACHIEVEMENTS_NUM; ++i ) {
- counts[i] = spawnArgs.GetInt( va( "ach_%d", i), "0" );
- }
- }
- /*
- ========================
- idAchievementManager::LocalUser_CompleteAchievement
- ========================
- */
- void idAchievementManager::LocalUser_CompleteAchievement( achievement_t id ) {
- idLocalUser * localUser = session->GetSignInManager().GetMasterLocalUser();
- // Check to see if we've already given the achievement.
- // If so, don't do again because we don't want to autosave every time a trigger is hit
- if( localUser == NULL || localUser->GetProfile()->GetAchievement( id ) ) {
- return;
- }
- #ifdef ID_RETAIL
- if ( common->GetConsoleUsed() ) {
- if ( !cheatingDialogShown ) {
- common->Dialog().AddDialog( GDM_ACHIEVEMENTS_DISABLED_DUE_TO_CHEATING, DIALOG_ACCEPT, NULL, NULL, true );
- cheatingDialogShown = true;
- }
- return;
- }
- #endif
- session->GetAchievementSystem().AchievementUnlock( localUser, id );
- }
- /*
- ========================
- idAchievementManager::CheckDoomClassicsAchievements
- Processed when the player finishes a level.
- ========================
- */
- void idAchievementManager::CheckDoomClassicsAchievements( int killcount, int itemcount, int secretcount, int skill, int mission, int map, int episode, int totalkills, int totalitems, int totalsecret ) {
- const skill_t difficulty = (skill_t)skill;
- const currentGame_t currentGame = common->GetCurrentGame();
- const GameMission_t expansion = (GameMission_t)mission;
- idLocalUser * localUser = session->GetSignInManager().GetMasterLocalUser();
- if ( localUser != NULL && localUser->GetProfile() != NULL ) {
- // GENERAL ACHIEVEMENT UNLOCKING.
- if( currentGame == DOOM_CLASSIC ) {
- LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM1_NEOPHYTE_COMPLETE_ANY_LEVEL );
- } else if( currentGame == DOOM2_CLASSIC ) {
- LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM2_JUST_GETTING_STARTED_COMPLETE_ANY_LEVEL );
- }
- // Complete Any Level on Nightmare.
- if ( difficulty == sk_nightmare && currentGame == DOOM_CLASSIC ) {
- LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM1_NIGHTMARE_COMPLETE_ANY_LEVEL_NIGHTMARE );
- }
- const bool gotAllKills = killcount >= totalkills;
- const bool gotAllItems = itemcount >= totalitems;
- const bool gotAllSecrets = secretcount >= totalsecret;
-
- if ( gotAllItems && gotAllKills && gotAllSecrets ) {
- if( currentGame == DOOM_CLASSIC ) {
- LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM1_BURNING_OUT_OF_CONTROL_COMPLETE_KILLS_ITEMS_SECRETS );
- } else if( currentGame == DOOM2_CLASSIC ) {
- LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM2_BURNING_OUT_OF_CONTROL_COMPLETE_KILLS_ITEMS_SECRETS );
- }
- }
- // DOOM EXPANSION ACHIEVEMENTS
- if( expansion == doom ) {
- if( map == 8 ) {
- // Medium or higher skill level.
- if( difficulty >= sk_medium ) {
- localUser->SetStatInt( STAT_DOOM_COMPLETED_EPISODE_1_MEDIUM + ( episode - 1 ), 1 );
- }
- // Hard or higher skill level.
- if( difficulty >= sk_hard ) {
- localUser->SetStatInt( STAT_DOOM_COMPLETED_EPISODE_1_HARD + ( episode - 1 ), 1 );
- localUser->SetStatInt( STAT_DOOM_COMPLETED_EPISODE_1_MEDIUM + ( episode - 1 ), 1 );
- }
- if ( difficulty == sk_nightmare ) {
- localUser->SetStatInt( STAT_DOOM_COMPLETED_EPISODE_1_HARD + ( episode - 1 ), 1 );
- localUser->SetStatInt( STAT_DOOM_COMPLETED_EPISODE_1_MEDIUM + ( episode - 1 ), 1 );
- }
- // Save the Settings.
- localUser->SaveProfileSettings();
- }
- // Check to see if we've completed all episodes.
- const int episode1completed = localUser->GetStatInt( STAT_DOOM_COMPLETED_EPISODE_1_MEDIUM );
- const int episode2completed = localUser->GetStatInt( STAT_DOOM_COMPLETED_EPISODE_2_MEDIUM );
- const int episode3completed = localUser->GetStatInt( STAT_DOOM_COMPLETED_EPISODE_3_MEDIUM );
- const int episode4completed = localUser->GetStatInt( STAT_DOOM_COMPLETED_EPISODE_4_MEDIUM );
- const int episode1completed_hard = localUser->GetStatInt( STAT_DOOM_COMPLETED_EPISODE_1_HARD );
- const int episode2completed_hard = localUser->GetStatInt( STAT_DOOM_COMPLETED_EPISODE_2_HARD );
- const int episode3completed_hard = localUser->GetStatInt( STAT_DOOM_COMPLETED_EPISODE_3_HARD );
- const int episode4completed_hard = localUser->GetStatInt( STAT_DOOM_COMPLETED_EPISODE_4_HARD );
- if ( currentGame == DOOM_CLASSIC ) {
- if ( episode1completed ) {
- LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM1_EPISODE1_COMPLETE_MEDIUM );
- }
- if ( episode2completed ) {
- LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM1_EPISODE2_COMPLETE_MEDIUM );
- }
- if ( episode3completed ) {
- LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM1_EPISODE3_COMPLETE_MEDIUM );
- }
- if ( episode4completed ) {
- LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM1_EPISODE4_COMPLETE_MEDIUM );
- }
- if ( episode1completed_hard && episode2completed_hard && episode3completed_hard && episode4completed_hard ) {
- LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM1_RAMPAGE_COMPLETE_ALL_HARD );
- }
- }
- } else if( expansion == doom2 ) {
- if( map == 30 ) {
- if ( currentGame == DOOM2_CLASSIC ) {
- LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM2_FROM_EARTH_TO_HELL_COMPLETE_HELL_ON_EARTH );
- if ( difficulty >= sk_hard ) {
- LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM2_SUPERIOR_FIREPOWER_COMPLETE_ALL_HARD );
- }
- }
- }
- } else if( expansion == pack_nerve ) {
- if( map == 8 ) {
- if ( currentGame == DOOM2_CLASSIC ) {
- LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM2_AND_BACK_AGAIN_COMPLETE_NO_REST );
- }
- }
- }
- }
- }
- /*
- =================
- AchievementsReset
- =================
- */
- CONSOLE_COMMAND( AchievementsReset, "Lock an achievement", NULL ) {
- idLocalUser * user = session->GetSignInManager().GetMasterLocalUser();
- if ( user == NULL ) {
- idLib::Printf( "Must be signed in\n" );
- return;
- }
- if ( args.Argc() == 1 ) {
- for ( int i = 0; i < ACHIEVEMENTS_NUM; i++ ) {
- user->SetStatInt( i, 0 );
- session->GetAchievementSystem().AchievementLock( user, i );
- }
- } else {
- int i = atoi( args.Argv( 1 ) );
- user->SetStatInt( i, 0 );
- session->GetAchievementSystem().AchievementLock( user, i );
- }
- user->SaveProfileSettings();
- }
- /*
- =================
- AchievementsUnlock
- =================
- */
- CONSOLE_COMMAND( AchievementsUnlock, "Unlock an achievement", NULL ) {
- idLocalUser * user = session->GetSignInManager().GetMasterLocalUser();
- if ( user == NULL ) {
- idLib::Printf( "Must be signed in\n" );
- return;
- }
- if ( args.Argc() == 1 ) {
- for ( int i = 0; i < ACHIEVEMENTS_NUM; i++ ) {
- user->SetStatInt( i, achievementInfo[i].required );
- session->GetAchievementSystem().AchievementUnlock( user, i );
- }
- } else {
- int i = atoi( args.Argv( 1 ) );
- user->SetStatInt( i, achievementInfo[i].required );
- session->GetAchievementSystem().AchievementUnlock( user, i );
- }
- user->SaveProfileSettings();
- }
- /*
- =================
- AchievementsList
- =================
- */
- CONSOLE_COMMAND( AchievementsList, "Lists achievements and status", NULL ) {
- idPlayer * player = gameLocal.GetLocalPlayer();
- idLocalUser * user = ( player == NULL ) ? session->GetSignInManager().GetMasterLocalUser() : session->GetGameLobbyBase().GetLocalUserFromLobbyUser( gameLocal.lobbyUserIDs[ player->GetEntityNumber() ] );
- if ( user == NULL ) {
- idLib::Printf( "Must be signed in\n" );
- return;
- }
- idPlayerProfile * profile = user->GetProfile();
- idArray<bool, 128> achievementState;
- bool achievementStateValid = session->GetAchievementSystem().GetAchievementState( user, achievementState );
- for ( int i = 0; i < ACHIEVEMENTS_NUM; i++ ) {
- const char * pInfo = "";
- if ( profile == NULL ) {
- pInfo = S_COLOR_RED "unknown" S_COLOR_DEFAULT;
- } else if ( !profile->GetAchievement( i ) ) {
- pInfo = S_COLOR_YELLOW "locked" S_COLOR_DEFAULT;
- } else {
- pInfo = S_COLOR_GREEN "unlocked" S_COLOR_DEFAULT;
- }
- const char * sInfo = "";
- if ( !achievementStateValid ) {
- sInfo = S_COLOR_RED "unknown" S_COLOR_DEFAULT;
- } else if ( !achievementState[i] ) {
- sInfo = S_COLOR_YELLOW "locked" S_COLOR_DEFAULT;
- } else {
- sInfo = S_COLOR_GREEN "unlocked" S_COLOR_DEFAULT;
- }
- int count = 0;
- if ( achievementInfo[i].lifetime ) {
- count = user->GetStatInt( i );
- } else if ( player != NULL ) {
- count = player->GetAchievementManager().GetCount( (achievement_t) i );
- } else {
- count = 0;
- }
- achievementDescription_t data;
- bool descriptionValid = session->GetAchievementSystem().GetAchievementDescription( user, i, data );
- idLib::Printf( "%02d: %2d/%2d | %12.12s | %12.12s | %s%s\n", i, count, achievementInfo[i].required, pInfo, sInfo, descriptionValid ? data.hidden ? "(hidden) " : "" : "(unknown) ", descriptionValid ? data.name : "" );
- }
- }
|