Загрузка данных
<!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>