Загрузка данных


<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="../Lib/css/fonts.css">
    <link rel="stylesheet" href="../Lib/css/help.css">
    <link rel="stylesheet" href="../Menu/UI/style.css">
    <link rel="stylesheet" href="package://browsers/shared/cef-no-select.css">
    <link rel="stylesheet" href="package://f10-reticle-kit/cef/fonts/css/fonts.css">
    <link rel="stylesheet" href="package://f10-reticle-kit/cef/css/playermenu-f10-reticle.css">
    <link rel="stylesheet" href="package://f10-reticle-kit/cef/css/playermenu-reticle-inline.css">

    <style>
        html, body { background: transparent !important; font-family: Montserrat, sans-serif; }
        html, body, body * {
            -webkit-user-select: none !important;
            user-select: none !important;
            -webkit-touch-callout: none !important;
        }
        input, textarea, [contenteditable='true'] {
            -webkit-user-select: text !important;
            user-select: text !important;
        }
        ::selection, ::-moz-selection {
            background: transparent !important;
            color: inherit !important;
        }
        #__debug { display: none !important; }
        .d-flex { display: flex !important; }
        .d-flex.column { flex-direction: column !important; }
        .d-flex.center-align { align-items: center !important; }
        .d-flex.center { align-items: center !important; justify-content: center !important; }
        .flex-1 { flex: 1 !important; min-width: 0; }
        .ml-auto { margin-left: auto !important; }
        .ml-10 { margin-left: 10px !important; }
        .ml-15 { margin-left: 15px !important; }
        .mt-10 { margin-top: 10px !important; }
        .mt-20 { margin-top: 20px !important; }
        .w-100 { width: 100% !important; }
        .playerMenu-shop-row {
            display: flex !important;
            flex-direction: row !important;
            align-items: flex-start !important;
            min-height: 435px;
        }
        .playerMenu-shop-sidebar {
            flex: 0 0 200px !important;
            width: 200px;
            align-self: flex-start;
            padding-top: 10px;
        }
        .playerMenu-shop-main {
            flex: 1 1 auto !important;
            min-width: 0;
            margin-left: 10px;
        }
    </style>

    <!-- Заглушки RAGE MP — только для локального превью (в игре mp/rpc уже есть) -->
    <script type="text/javascript">
        if (typeof window.mp === 'undefined') {
        window.mp = { trigger: function(){}, players: { local: {} }, localTestBrowser: true };

        // Моки серверных ответов, чтобы вкладки не падали
        var __serverMocks = {
            // [count, achievements]
            'server_player_mainMenu_getAchievemnt': [3, [
                { id:'A1', name:'Первый шаг', desc:'Войти в игру', progress:1, need:1, reward:'100$' },
                { id:'A2', name:'Богач', desc:'Накопить 1кк',    progress:300000, need:1000000, reward:'VIP' },
                { id:'A3', name:'Гонщик',  desc:'Купить машину', progress:0, need:1, reward:'10000$' }
            ]],
            'server_player_mainMenu_getGifts': [],
            'server_donateRoulette_open': null,
            'server_donateRoulette_claim': true,
            'server_donateRoulette_sell': true,
            'server_reportSystem_getMessages': [
                { name:'Admin', text:'Здравствуйте! Чем могу помочь?' }
            ]
        };
        var __clientMocks = {
            'client_global_storage_get': { settings: {
                enableHelpBox:true, enableQuestBox:true, enableTimerBox:true, enableNametags:true,
                enableLocalName:true, enableCenterInventory:false, disableScreenEffect:false,
                disableDocumentPhoto:false, enableSpeedometer:true, maxVolume3dSound:1,
                speedometerColor:[255,255,255], speedometerBackgroundColor:[0,0,0]
            }, chat: { height:300, lineHeight:18, fontSize:14, shadow:true, timestamp:true } },
            'client_getGlobalValue': true,
            '__client_voiceChat_getBlockList': [],
            'client_menu_playerMainMenu_getBinderData': [
                {action:'INVENTORY_OPEN',   key:73,  comb:{shift:false,ctrl:false,alt:false}, desc:'Открыть инвентарь'},
                {action:'ANIM_OPEN',        key:115, comb:{shift:false,ctrl:false,alt:false}, desc:'Меню анимаций'},
                {action:'ANIM_STOP',        key:116, comb:{shift:false,ctrl:false,alt:false}, desc:'Остановить анимацию'},
                {action:'WEAPON_SLOT_0',    key:49,  comb:{shift:false,ctrl:false,alt:false}, desc:'Слот оружия 1'},
                {action:'WEAPON_SLOT_1',    key:50,  comb:{shift:false,ctrl:false,alt:false}, desc:'Слот оружия 2'},
                {action:'WEAPON_SLOT_2',    key:51,  comb:{shift:false,ctrl:false,alt:false}, desc:'Слот оружия 3'},
                {action:'VEHICLE_ENGINE',   key:89,  comb:{shift:false,ctrl:false,alt:false}, desc:'Завести/заглушить двигатель'},
                {action:'VEHICLE_LOCK',     key:76,  comb:{shift:false,ctrl:false,alt:false}, desc:'Закрыть/открыть авто'},
                {action:'VOICE_CHAT_TOGGLE',key:78,  comb:{shift:false,ctrl:false,alt:false}, desc:'Голосовой чат'},
                {action:'SMARTPHONE_OPEN',  key:38,  comb:{shift:false,ctrl:false,alt:false}, desc:'Открыть телефон'},
                {action:'TABLET_OPEN',      key:40,  comb:{shift:false,ctrl:false,alt:false}, desc:'Открыть планшет'},
                {action:'TOGGLE_CROUCH',    key:67,  comb:{shift:false,ctrl:false,alt:false}, desc:'Присесть'},
                {action:'TOGGLE_WHISTLE',   key:72,  comb:{shift:false,ctrl:false,alt:false}, desc:'Свистнуть'},
                {action:'HELPMENU_OPEN',    key:113, comb:{shift:false,ctrl:false,alt:false}, desc:'Меню помощи'},
                {action:'MAIN_CURSOR',      key:18,  comb:{shift:false,ctrl:false,alt:false}, desc:'Курсор мыши'},
                {action:'FAST_ANIM_0',      key:112, comb:{shift:false,ctrl:false,alt:false}, desc:'Слот 1'},
                {action:'FAST_ANIM_1',      key:113, comb:{shift:true,ctrl:false,alt:false}, desc:'Слот 2'},
                {action:'FAST_ANIM_2',      key:114, comb:{shift:false,ctrl:false,alt:false}, desc:'Слот 3'},
                {action:'FAST_ANIM_3',      key:115, comb:{shift:false,ctrl:false,alt:false}, desc:'Слот 4'},
                {action:'FAST_ANIM_4',      key:116, comb:{shift:false,ctrl:false,alt:false}, desc:'Слот 5'}
            ]
        };
        window.rpc = {
            on: function(){},
            triggerServer: function(){},
            triggerClient: function(){},
            triggerBrowser: function(){},
            register: function(){},
            callServer: function(name) {
                var data = (name in __serverMocks) ? __serverMocks[name] : null;
                return Promise.resolve({ data: data, error: false });
            },
            callClient: function(name) {
                return Promise.resolve(name in __clientMocks ? __clientMocks[name] : null);
            }
        };
        }
    </script>

    <!-- rage-rpc только для локального превью -->
    <script type="text/javascript">
        if (typeof window.rpc === 'undefined') {
            document.write('<script type="text/javascript" src="../Lib/js/rage-rpc.min.js"><\/script>');
        }
    </script>

    <!-- Зависимости (package:// — относительные ../Lib ломаются в CEF RAGE) -->
    <script type="text/javascript" src="../Lib/js/jquery.js"></script>
    <script type="text/javascript" src="../Lib/js/vue.dev.js"></script>
    <script type="text/javascript" src="../Lib/js/Chart.min.js"></script>
    <script type="text/javascript" src="../Lib/js/rangeslider.min.js"></script>
    <script type="text/javascript" src="../Lib/js/progressbar.min.js"></script>
    <script type="text/javascript" src="../Lib/js/vue-color.min.js"></script>
    <script type="text/javascript" src="../Lib/js/serverAPI.js"></script>
    <script type="text/javascript" src="../Lib/js/binderKeyInfo.js"></script>
    <script type="text/javascript" src="../Menu/UI/script.js"></script>
    <script type="text/javascript" src="../Lib/js/rage-rpc.min.js"></script>
    <script type="text/javascript" src="../Lib/js/preventSelection.js"></script>
    <script type="text/javascript" src="../Lib/js/playermenu-bridge.js"></script>
    <script type="text/javascript" src="playermenu-boot.js?v=89"></script>
    <script type="text/javascript">
        window.__dbgLog = window.__dbgLog || function () {};
        window.addEventListener('keydown', function (event) {
            if (event.keyCode !== 27 && event.which !== 27 && event.code !== 'Escape') return;
            event.preventDefault();
            if (event.stopPropagation) event.stopPropagation();
            try {
                var v = (typeof palyerMainMenuMenu !== 'undefined' && palyerMainMenuMenu.vue)
                    ? palyerMainMenuMenu.vue
                    : null;
                var capturing = !!(v && v.binderSelectKey != null && v.binderSelectKey >= 0);
                if (capturing || (window.__pmEscCancelUntil && Date.now() < window.__pmEscCancelUntil)) {
                    if (event.stopImmediatePropagation) event.stopImmediatePropagation();
                    window.__pmEscCancelUntil = Date.now() + 500;
                    if (capturing) {
                        if (typeof window.cancelBinderCaptureFromEsc === 'function') {
                            window.cancelBinderCaptureFromEsc();
                        } else if (typeof window.flowEscClearBinderCapture === 'function') {
                            window.flowEscClearBinderCapture();
                        } else if (v) {
                            v.binderSelectKey = -1;
                        }
                    }
                    try { mp.trigger('flowMenuBinderCaptureEsc'); } catch (_eTrig) {}
                    return false;
                }
                if (typeof window.bloodMenuEscShouldClose === 'function' && !window.bloodMenuEscShouldClose()) {
                    if (event.stopImmediatePropagation) event.stopImmediatePropagation();
                    return false;
                }
            } catch (_e0) {}
            try { mp.trigger('playermenu:cef:esc'); } catch (_e) {}
            return false;
        }, true);
        window.addEventListener('keyup', function (event) {
            if (event.keyCode !== 27 && event.which !== 27 && event.code !== 'Escape') return;
            if (window.__pmEscCancelUntil && Date.now() < window.__pmEscCancelUntil) {
                event.preventDefault();
                if (event.stopPropagation) event.stopPropagation();
                if (event.stopImmediatePropagation) event.stopImmediatePropagation();
                return false;
            }
        }, true);
    </script>
</head>
<body scroll="no" style="overflow:hidden; background:transparent;">

    <!-- ВЕСЬ ОСТАЛЬНОЙ CSS ОСТАВЛЕН БЕЗ ИЗМЕНЕНИЙ (он очень большой) -->
    <!-- ... здесь идёт весь твой оригинальный <style> блок ... -->

    <!-- ===================== ОСНОВНОЙ КОНТЕНТ ===================== -->

    <div id="playerMainMenu">
    <template>
    <div>
    <div v-if="loaded" class="content-block center">
    <div class="yk-block d-flex pm-bg-host"
        style="width: 1000px; height: 600px; border-radius: 0px; border: none; position: relative; background-color: rgba(29, 38, 52, 0.2); background-size: cover; background-position: center; background-repeat: no-repeat;"
        :class="{'pm-bg--promo': currentTab === 5 && currentSettingTab === 2, 'pm-bg--reticle': currentTab === 5 && currentSettingTab === 4, 'pm-bg--bp': currentTab === 9, 'pm-bg--hb': currentTab === 10}">
    
    <!-- ... весь твой оригинальный header и остальные вкладки остаются без изменений ... -->

    <!-- ===================== НАСТРОЙКИ (currentTab === 5) ===================== -->
    <div v-if="currentTab === 5" key="tab-settings" class="d-flex" :class="{'playerMenu-tab-settings--reticle': currentSettingTab === 4}" style="flex-shrink: 0; min-height: 500px; position: relative; overflow: hidden; width: 100%;">
        
        <!-- ЛЕВОЕ МЕНЮ -->
        <div class="d-flex column" style="flex: 0.25; align-self: flex-start; padding-top: 90px;">
            <button @click="bloodSettingSubTab(0)" :class="{'orange': currentSettingTab === 0}" class="yk-btn s-14 p-10 w-100 list-mt-10">ИНТЕРФЕЙС</button>
            <button @click="bloodSettingSubTab(4)" :class="{'orange': currentSettingTab === 4}" class="yk-btn s-14 p-10 w-100 list-mt-10">ПРИЦЕЛ</button>
            <button @click="bloodSettingSubTab(1)" :class="{'orange': currentSettingTab === 1}" class="yk-btn s-14 p-10 w-100 list-mt-10">УПРАВЛЕНИЕ</button>
            
            <!-- ★ НОВАЯ ВКЛАДКА СВИСТ -->
            <button @click="bloodSettingSubTab(6)" :class="{'orange': currentSettingTab === 6}" class="yk-btn s-14 p-10 w-100 list-mt-10">СВИСТ</button>
            
            <button @click="bloodSettingSubTab(2)" :class="{'orange': currentSettingTab === 2}" class="yk-btn s-14 p-10 w-100 list-mt-10">ПРОМОКОД</button>
        </div>

        <!-- ПРАВАЯ ЧАСТЬ -->
        <div class="yk-scroll playerMenu-scroll d-flex flex-1 ml-10" :class="{'playerMenu-settings-panel--chat': currentSettingTab === 3, 'playerMenu-settings-panel--reticle': currentSettingTab === 4 || currentSettingTab === 5, 'playerMenu-settings-panel--hitmarker': currentSettingTab === 5}" style="height: 500px;">
            
            <!-- ... все твои старые панели (ИНТЕРФЕЙС, УПРАВЛЕНИЕ, ПРОМОКОД, ПРИЦЕЛ) остаются как были ... -->

            <!-- ★★★ НОВАЯ ПАНЕЛЬ СВИСТ ★★★ -->
            <div v-if="currentSettingTab === 6" class="d-flex flex-1" style="padding: 20px 10px;">
                <div style="width: 100%; max-width: 480px;">
                    <div class="playerMenu-setting-line">
                        <div class="playerMenu-setting-text">Режим свиста</div>
                        <div class="playerMenu-setting-value" style="display: flex; gap: 8px;">
                            <button 
                                @click="setWhistleMode('old')" 
                                class="yk-btn s-14 p-10-15"
                                :class="{'orange': whistleMode === 'old'}">
                                Old
                            </button>
                            <button 
                                @click="setWhistleMode('new')" 
                                class="yk-btn s-14 p-10-15"
                                :class="{'orange': whistleMode === 'new'}">
                                New
                            </button>
                        </div>
                    </div>
                    <div class="yk-text s-14 mt-15" style="color: #71A4DF; line-height: 1.5;">
                        <b>Old</b> — стандартный свист (анимация + звук)<br>
                        <b>New</b> — только звук, без анимации
                    </div>
                </div>
            </div>
            <!-- ★★★ КОНЕЦ НОВОЙ ПАНЕЛИ ★★★ -->

        </div>
    </div>

    <!-- ... весь остальной код (вкладки Персонаж, Помощь, Репорт, BattlePass и т.д.) остаётся без изменений ... -->

    </div>
    </div>
    </template>
    </div>

    <!-- ===================== VUE КОД ===================== -->
    <script>
        // ... весь твой оригинальный JS до data ...

        window.palyerMainMenuMenu = new MenuManager("playerMainMenu", {
            components: { "chrome-picker": VueColor.Chrome },
            data: {
                // ... все твои старые поля ...
                currentSettingTab: 0,
                
                // ★ НОВОЕ ПОЛЕ
                whistleMode: 'old',
                
                // ... остальные поля ...
            },
            methods: {
                // ... все твои старые методы ...

                bloodSettingSubTab(e) {
                    this.currentSettingTab = e;
                },

                // ★ НОВЫЙ МЕТОД
                setWhistleMode(mode) {
                    this.whistleMode = mode;
                    try {
                        mp.trigger('client_whistle_setMode', mode);
                    } catch (e) {}
                    try {
                        localStorage.setItem('whistleMode', mode);
                    } catch (e) {}
                },

                // ... остальные методы ...
            },
            load(e) {
                // ... твой оригинальный load ...

                // ★ Восстанавливаем сохранённый режим свиста
                try {
                    const saved = localStorage.getItem('whistleMode');
                    if (saved === 'old' || saved === 'new') {
                        this.whistleMode = saved;
                    }
                } catch (err) {}
            }
        });
    </script>

    <!-- ... все остальные скрипты в конце файла остаются без изменений ... -->

</body>
</html>