mirror of
https://github.com/Lolendor/reVCDOS.git
synced 2026-10-10 03:43:12 +08:00
cheats for mobile (touch devices)
This commit is contained in:
Vendored
+550
-12
@@ -1,28 +1,144 @@
|
||||
|
||||
(function() {
|
||||
// Touch device detection
|
||||
const isMobile = /Mobi|Android|iPhone|iPad|iPod/i.test(navigator.userAgent);
|
||||
const isTouch = isMobile && window.matchMedia('(pointer: coarse)').matches;
|
||||
|
||||
const style = document.createElement('style');
|
||||
style.textContent = `
|
||||
#cheat-engine-ui {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 340px;
|
||||
width: ${isTouch ? '100vw' : '340px'};
|
||||
height: 100vh;
|
||||
background: rgba(10, 10, 10, 0.9);
|
||||
background: rgba(10, 10, 10, 0.95);
|
||||
backdrop-filter: blur(15px);
|
||||
color: #eee;
|
||||
font-family: 'Consolas', 'Monaco', monospace;
|
||||
padding: 20px 20px 100px 20px; /* Extra bottom padding for scroll */
|
||||
padding: ${isTouch ? '15px 15px 150px 15px' : '20px 20px 100px 20px'};
|
||||
z-index: 10000;
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
gap: ${isTouch ? '12px' : '15px'};
|
||||
overflow-y: auto;
|
||||
user-select: none;
|
||||
border-left: 2px solid #ff00ff;
|
||||
border-left: ${isTouch ? 'none' : '2px solid #ff00ff'};
|
||||
box-shadow: -10px 0 30px rgba(0,0,0,0.8);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Touch toggle button */
|
||||
#cheat-toggle-btn {
|
||||
display: ${isTouch ? 'flex' : 'none'};
|
||||
position: fixed;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background: rgba(255, 0, 255, 0.3);
|
||||
border: 2px solid #ff00ff;
|
||||
border-radius: 50%;
|
||||
color: #ff00ff;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
z-index: 9999;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
backdrop-filter: blur(5px);
|
||||
touch-action: manipulation;
|
||||
}
|
||||
#cheat-toggle-btn:active {
|
||||
background: rgba(255, 0, 255, 0.6);
|
||||
transform: scale(0.95);
|
||||
}
|
||||
#cheat-toggle-btn.active {
|
||||
background: rgba(255, 0, 255, 0.6);
|
||||
}
|
||||
|
||||
/* Airbreak touch controls */
|
||||
#airbreak-touch-controls {
|
||||
display: none;
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
left: 20px;
|
||||
z-index: 10001;
|
||||
touch-action: none;
|
||||
}
|
||||
#airbreak-touch-controls.active {
|
||||
display: block;
|
||||
}
|
||||
.airbreak-joystick {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
background: rgba(0, 255, 255, 0.2);
|
||||
border: 2px solid #0ff;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
touch-action: none;
|
||||
}
|
||||
.airbreak-joystick-knob {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background: rgba(0, 255, 255, 0.6);
|
||||
border: 2px solid #0ff;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
pointer-events: none;
|
||||
}
|
||||
.airbreak-vertical-btns {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
z-index: 10001;
|
||||
}
|
||||
.airbreak-v-btn {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background: rgba(0, 255, 255, 0.2);
|
||||
border: 2px solid #0ff;
|
||||
border-radius: 10px;
|
||||
color: #0ff;
|
||||
font-size: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
touch-action: manipulation;
|
||||
}
|
||||
.airbreak-v-btn:active {
|
||||
background: rgba(0, 255, 255, 0.5);
|
||||
}
|
||||
#airbreak-toggle-fly {
|
||||
position: fixed;
|
||||
bottom: 160px;
|
||||
right: 20px;
|
||||
width: 80px;
|
||||
height: 40px;
|
||||
background: rgba(255, 255, 0, 0.2);
|
||||
border: 2px solid #ff0;
|
||||
border-radius: 10px;
|
||||
color: #ff0;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
z-index: 10001;
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
touch-action: manipulation;
|
||||
}
|
||||
#airbreak-toggle-fly.active {
|
||||
background: rgba(255, 255, 0, 0.5);
|
||||
}
|
||||
#airbreak-toggle-fly.visible {
|
||||
display: flex;
|
||||
}
|
||||
#cheat-engine-ui h1 {
|
||||
font-size: 18px;
|
||||
text-align: left;
|
||||
@@ -58,15 +174,17 @@
|
||||
cursor: pointer;
|
||||
transition: all 0.1s;
|
||||
text-transform: uppercase;
|
||||
font-size: 10px;
|
||||
font-size: ${isTouch ? '12px' : '10px'};
|
||||
min-height: ${isTouch ? '44px' : 'auto'};
|
||||
touch-action: manipulation;
|
||||
}
|
||||
#cheat-engine-ui button:hover {
|
||||
#cheat-engine-ui button:hover, #cheat-engine-ui button:active {
|
||||
background: #ff00ff;
|
||||
color: #000;
|
||||
border-color: #ff00ff;
|
||||
}
|
||||
#cheat-engine-ui .results {
|
||||
max-height: 120px;
|
||||
max-height: ${isTouch ? '150px' : '120px'};
|
||||
overflow-y: auto;
|
||||
background: rgba(0,0,0,0.3);
|
||||
border: 1px solid #222;
|
||||
@@ -74,24 +192,47 @@
|
||||
.cheat-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 4px;
|
||||
gap: ${isTouch ? '8px' : '4px'};
|
||||
}
|
||||
.cheat-cat {
|
||||
font-size: 11px;
|
||||
font-size: ${isTouch ? '13px' : '11px'};
|
||||
color: #0ff;
|
||||
margin-top: 10px;
|
||||
margin-top: ${isTouch ? '15px' : '10px'};
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.cheat-btn {
|
||||
background: transparent !important;
|
||||
border: 1px solid #444 !important;
|
||||
text-align: left;
|
||||
padding: ${isTouch ? '12px 10px' : '6px 10px'};
|
||||
}
|
||||
.cheat-btn:hover {
|
||||
.cheat-btn:hover, .cheat-btn:active {
|
||||
border-color: #0ff !important;
|
||||
color: #0ff !important;
|
||||
background: rgba(0, 255, 255, 0.1) !important;
|
||||
}
|
||||
|
||||
/* Close button for touch */
|
||||
#cheat-close-btn {
|
||||
display: ${isTouch ? 'flex' : 'none'};
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 15px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background: rgba(255, 0, 0, 0.3);
|
||||
border: 2px solid #f00;
|
||||
border-radius: 50%;
|
||||
color: #f00;
|
||||
font-size: 20px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
touch-action: manipulation;
|
||||
}
|
||||
#cheat-close-btn:active {
|
||||
background: rgba(255, 0, 0, 0.6);
|
||||
}
|
||||
::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
@@ -104,9 +245,44 @@
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
|
||||
// Create touch toggle button
|
||||
const toggleBtn = document.createElement('div');
|
||||
toggleBtn.id = 'cheat-toggle-btn';
|
||||
toggleBtn.innerHTML = '⚙';
|
||||
toggleBtn.title = 'Open Cheat Menu';
|
||||
document.body.appendChild(toggleBtn);
|
||||
|
||||
// Create airbreak touch controls
|
||||
const airbreakTouchControls = document.createElement('div');
|
||||
airbreakTouchControls.id = 'airbreak-touch-controls';
|
||||
airbreakTouchControls.innerHTML = `
|
||||
<div class="airbreak-joystick" id="airbreak-joystick">
|
||||
<div class="airbreak-joystick-knob" id="airbreak-joystick-knob"></div>
|
||||
</div>
|
||||
`;
|
||||
document.body.appendChild(airbreakTouchControls);
|
||||
|
||||
// Create vertical buttons for airbreak (up/down)
|
||||
const airbreakVerticalBtns = document.createElement('div');
|
||||
airbreakVerticalBtns.className = 'airbreak-vertical-btns';
|
||||
airbreakVerticalBtns.id = 'airbreak-vertical-btns';
|
||||
airbreakVerticalBtns.innerHTML = `
|
||||
<div class="airbreak-v-btn" id="airbreak-up-btn">↑</div>
|
||||
<div class="airbreak-v-btn" id="airbreak-down-btn">↓</div>
|
||||
`;
|
||||
airbreakVerticalBtns.style.display = 'none';
|
||||
document.body.appendChild(airbreakVerticalBtns);
|
||||
|
||||
// Create fly toggle button for touch
|
||||
const flyToggleBtn = document.createElement('div');
|
||||
flyToggleBtn.id = 'airbreak-toggle-fly';
|
||||
flyToggleBtn.innerHTML = 'FLY';
|
||||
document.body.appendChild(flyToggleBtn);
|
||||
|
||||
const ui = document.createElement('div');
|
||||
ui.id = 'cheat-engine-ui';
|
||||
ui.innerHTML = `
|
||||
<div id="cheat-close-btn">✕</div>
|
||||
<h1>Cheat Engine</h1>
|
||||
|
||||
<div class="ce-section">
|
||||
@@ -337,6 +513,7 @@
|
||||
function toggleMenu() {
|
||||
menuOpen = !menuOpen;
|
||||
ui.style.display = menuOpen ? 'flex' : 'none';
|
||||
toggleBtn.classList.toggle('active', menuOpen);
|
||||
|
||||
if (menuOpen) {
|
||||
if (document.pointerLockElement) document.exitPointerLock();
|
||||
@@ -348,6 +525,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Keyboard toggle (F3)
|
||||
window.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'F3') {
|
||||
e.preventDefault();
|
||||
@@ -356,6 +534,116 @@
|
||||
}
|
||||
}, true);
|
||||
|
||||
// Touch toggle button handler with drag support
|
||||
let toggleBtnDragging = false;
|
||||
let toggleBtnStartX = 0;
|
||||
let toggleBtnStartY = 0;
|
||||
let toggleBtnInitialLeft = 0;
|
||||
let toggleBtnInitialTop = 0;
|
||||
const dragThreshold = 10; // pixels to move before considered a drag
|
||||
|
||||
// Load saved position from localStorage
|
||||
const savedPos = localStorage.getItem('cheat-toggle-pos');
|
||||
if (savedPos) {
|
||||
try {
|
||||
const pos = JSON.parse(savedPos);
|
||||
toggleBtn.style.right = 'auto';
|
||||
toggleBtn.style.left = pos.left + 'px';
|
||||
toggleBtn.style.top = pos.top + 'px';
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
toggleBtn.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if (!toggleBtnDragging) {
|
||||
toggleMenu();
|
||||
}
|
||||
});
|
||||
|
||||
if (isTouch) {
|
||||
toggleBtn.addEventListener('touchstart', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
toggleBtnDragging = false;
|
||||
|
||||
const touch = e.touches[0];
|
||||
toggleBtnStartX = touch.clientX;
|
||||
toggleBtnStartY = touch.clientY;
|
||||
|
||||
// Get current position
|
||||
const rect = toggleBtn.getBoundingClientRect();
|
||||
toggleBtnInitialLeft = rect.left;
|
||||
toggleBtnInitialTop = rect.top;
|
||||
}, { passive: false });
|
||||
|
||||
toggleBtn.addEventListener('touchmove', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const touch = e.touches[0];
|
||||
const deltaX = touch.clientX - toggleBtnStartX;
|
||||
const deltaY = touch.clientY - toggleBtnStartY;
|
||||
|
||||
// Check if we've moved enough to consider it a drag
|
||||
if (Math.abs(deltaX) > dragThreshold || Math.abs(deltaY) > dragThreshold) {
|
||||
toggleBtnDragging = true;
|
||||
}
|
||||
|
||||
if (toggleBtnDragging) {
|
||||
let newLeft = toggleBtnInitialLeft + deltaX;
|
||||
let newTop = toggleBtnInitialTop + deltaY;
|
||||
|
||||
// Clamp to screen bounds
|
||||
const btnWidth = toggleBtn.offsetWidth;
|
||||
const btnHeight = toggleBtn.offsetHeight;
|
||||
newLeft = Math.max(0, Math.min(window.innerWidth - btnWidth, newLeft));
|
||||
newTop = Math.max(0, Math.min(window.innerHeight - btnHeight, newTop));
|
||||
|
||||
toggleBtn.style.right = 'auto';
|
||||
toggleBtn.style.left = newLeft + 'px';
|
||||
toggleBtn.style.top = newTop + 'px';
|
||||
}
|
||||
}, { passive: false });
|
||||
|
||||
toggleBtn.addEventListener('touchend', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if (toggleBtnDragging) {
|
||||
// Save position
|
||||
const rect = toggleBtn.getBoundingClientRect();
|
||||
localStorage.setItem('cheat-toggle-pos', JSON.stringify({
|
||||
left: rect.left,
|
||||
top: rect.top
|
||||
}));
|
||||
} else {
|
||||
// It was a tap, not a drag - toggle menu
|
||||
toggleMenu();
|
||||
}
|
||||
|
||||
toggleBtnDragging = false;
|
||||
}, { passive: false });
|
||||
}
|
||||
|
||||
// Close button handler (works for both touch and click)
|
||||
const closeBtn = document.getElementById('cheat-close-btn');
|
||||
if (closeBtn) {
|
||||
closeBtn.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
toggleMenu();
|
||||
});
|
||||
|
||||
if (isTouch) {
|
||||
closeBtn.addEventListener('touchstart', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
toggleMenu();
|
||||
}, { passive: false });
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('keydown', (e) => {
|
||||
if (menuOpen && e.target.tagName === 'INPUT') e.stopPropagation();
|
||||
}, true);
|
||||
@@ -368,6 +656,17 @@
|
||||
window.addEventListener('mousedown', (e) => {
|
||||
if (menuOpen && ui.contains(e.target)) e.stopPropagation();
|
||||
}, true);
|
||||
|
||||
// Touch event handling for menu
|
||||
window.addEventListener('touchstart', (e) => {
|
||||
if (menuOpen && ui.contains(e.target)) e.stopPropagation();
|
||||
}, true);
|
||||
window.addEventListener('touchmove', (e) => {
|
||||
if (menuOpen && ui.contains(e.target)) e.stopPropagation();
|
||||
}, true);
|
||||
window.addEventListener('touchend', (e) => {
|
||||
if (menuOpen && ui.contains(e.target)) e.stopPropagation();
|
||||
}, true);
|
||||
|
||||
function updateStatus(text) {
|
||||
document.getElementById('ce-status').textContent = text;
|
||||
@@ -972,4 +1271,243 @@
|
||||
flySpeed = parseFloat(document.getElementById('ce-fly-speed').value) || 2.0;
|
||||
};
|
||||
|
||||
// ========== TOUCH CONTROLS FOR AIRBREAK ==========
|
||||
|
||||
if (isTouch) {
|
||||
const joystick = document.getElementById('airbreak-joystick');
|
||||
const joystickKnob = document.getElementById('airbreak-joystick-knob');
|
||||
const upBtn = document.getElementById('airbreak-up-btn');
|
||||
const downBtn = document.getElementById('airbreak-down-btn');
|
||||
const verticalBtns = document.getElementById('airbreak-vertical-btns');
|
||||
|
||||
let joystickActive = false;
|
||||
let joystickCenterX = 0;
|
||||
let joystickCenterY = 0;
|
||||
const joystickRadius = 60; // Half of the joystick width
|
||||
const deadzone = 15;
|
||||
|
||||
// Update visibility of touch controls based on airbreak state
|
||||
function updateTouchControlsVisibility() {
|
||||
if (airbreakConfigured && airbreakEnabled) {
|
||||
airbreakTouchControls.classList.add('active');
|
||||
verticalBtns.style.display = 'flex';
|
||||
} else {
|
||||
airbreakTouchControls.classList.remove('active');
|
||||
verticalBtns.style.display = 'none';
|
||||
}
|
||||
|
||||
// Show fly toggle button when configured
|
||||
if (airbreakConfigured) {
|
||||
flyToggleBtn.classList.add('visible');
|
||||
flyToggleBtn.classList.toggle('active', airbreakEnabled);
|
||||
flyToggleBtn.textContent = airbreakEnabled ? 'STOP' : 'FLY';
|
||||
} else {
|
||||
flyToggleBtn.classList.remove('visible');
|
||||
}
|
||||
}
|
||||
|
||||
// Fly toggle button with drag support
|
||||
let flyBtnDragging = false;
|
||||
let flyBtnStartX = 0;
|
||||
let flyBtnStartY = 0;
|
||||
let flyBtnInitialRight = 0;
|
||||
let flyBtnInitialBottom = 0;
|
||||
|
||||
// Load saved fly button position
|
||||
const savedFlyPos = localStorage.getItem('cheat-fly-pos');
|
||||
if (savedFlyPos) {
|
||||
try {
|
||||
const pos = JSON.parse(savedFlyPos);
|
||||
flyToggleBtn.style.right = pos.right + 'px';
|
||||
flyToggleBtn.style.bottom = pos.bottom + 'px';
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
flyToggleBtn.addEventListener('touchstart', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
flyBtnDragging = false;
|
||||
|
||||
const touch = e.touches[0];
|
||||
flyBtnStartX = touch.clientX;
|
||||
flyBtnStartY = touch.clientY;
|
||||
|
||||
// Get current position (calculate from right/bottom)
|
||||
const rect = flyToggleBtn.getBoundingClientRect();
|
||||
flyBtnInitialRight = window.innerWidth - rect.right;
|
||||
flyBtnInitialBottom = window.innerHeight - rect.bottom;
|
||||
}, { passive: false });
|
||||
|
||||
flyToggleBtn.addEventListener('touchmove', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const touch = e.touches[0];
|
||||
const deltaX = touch.clientX - flyBtnStartX;
|
||||
const deltaY = touch.clientY - flyBtnStartY;
|
||||
|
||||
// Check if we've moved enough to consider it a drag
|
||||
if (Math.abs(deltaX) > dragThreshold || Math.abs(deltaY) > dragThreshold) {
|
||||
flyBtnDragging = true;
|
||||
}
|
||||
|
||||
if (flyBtnDragging) {
|
||||
let newRight = flyBtnInitialRight - deltaX;
|
||||
let newBottom = flyBtnInitialBottom - deltaY;
|
||||
|
||||
// Clamp to screen bounds
|
||||
const btnWidth = flyToggleBtn.offsetWidth;
|
||||
const btnHeight = flyToggleBtn.offsetHeight;
|
||||
newRight = Math.max(0, Math.min(window.innerWidth - btnWidth, newRight));
|
||||
newBottom = Math.max(0, Math.min(window.innerHeight - btnHeight, newBottom));
|
||||
|
||||
flyToggleBtn.style.right = newRight + 'px';
|
||||
flyToggleBtn.style.bottom = newBottom + 'px';
|
||||
}
|
||||
}, { passive: false });
|
||||
|
||||
flyToggleBtn.addEventListener('touchend', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if (flyBtnDragging) {
|
||||
// Save position
|
||||
const rect = flyToggleBtn.getBoundingClientRect();
|
||||
localStorage.setItem('cheat-fly-pos', JSON.stringify({
|
||||
right: window.innerWidth - rect.right,
|
||||
bottom: window.innerHeight - rect.bottom
|
||||
}));
|
||||
} else {
|
||||
// It was a tap, not a drag - toggle fly mode
|
||||
if (airbreakConfigured) {
|
||||
airbreakEnabled = !airbreakEnabled;
|
||||
|
||||
if (airbreakEnabled) {
|
||||
const view = getView();
|
||||
lockedZ = view.getFloat32(positionAddr + 8, true);
|
||||
lockedHealth = view.getFloat32(healthAddr, true);
|
||||
console.log(`[AirBreak Touch] ENABLED - Locked Z=${lockedZ.toFixed(2)}, HP=${lockedHealth.toFixed(2)}`);
|
||||
}
|
||||
|
||||
document.getElementById('ce-airbreak-status').textContent =
|
||||
airbreakEnabled ?
|
||||
`FLYING! Z=${lockedZ.toFixed(1)} HP=${lockedHealth.toFixed(0)}` :
|
||||
`Ready! [Tap FLY]`;
|
||||
document.getElementById('ce-airbreak-status').style.color = airbreakEnabled ? '#ff0' : '#0f0';
|
||||
|
||||
updateTouchControlsVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
flyBtnDragging = false;
|
||||
}, { passive: false });
|
||||
|
||||
// Joystick touch handling
|
||||
joystick.addEventListener('touchstart', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
joystickActive = true;
|
||||
|
||||
const rect = joystick.getBoundingClientRect();
|
||||
joystickCenterX = rect.left + rect.width / 2;
|
||||
joystickCenterY = rect.top + rect.height / 2;
|
||||
|
||||
handleJoystickMove(e.touches[0]);
|
||||
}, { passive: false });
|
||||
|
||||
joystick.addEventListener('touchmove', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if (joystickActive) {
|
||||
handleJoystickMove(e.touches[0]);
|
||||
}
|
||||
}, { passive: false });
|
||||
|
||||
joystick.addEventListener('touchend', (e) => {
|
||||
e.preventDefault();
|
||||
joystickActive = false;
|
||||
|
||||
// Reset knob position
|
||||
joystickKnob.style.transform = 'translate(-50%, -50%)';
|
||||
|
||||
// Reset movement
|
||||
keysPressed.w = false;
|
||||
keysPressed.s = false;
|
||||
keysPressed.a = false;
|
||||
keysPressed.d = false;
|
||||
}, { passive: false });
|
||||
|
||||
joystick.addEventListener('touchcancel', (e) => {
|
||||
joystickActive = false;
|
||||
joystickKnob.style.transform = 'translate(-50%, -50%)';
|
||||
keysPressed.w = false;
|
||||
keysPressed.s = false;
|
||||
keysPressed.a = false;
|
||||
keysPressed.d = false;
|
||||
});
|
||||
|
||||
function handleJoystickMove(touch) {
|
||||
let deltaX = touch.clientX - joystickCenterX;
|
||||
let deltaY = touch.clientY - joystickCenterY;
|
||||
|
||||
// Clamp to radius
|
||||
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
||||
if (distance > joystickRadius) {
|
||||
deltaX = (deltaX / distance) * joystickRadius;
|
||||
deltaY = (deltaY / distance) * joystickRadius;
|
||||
}
|
||||
|
||||
// Move knob
|
||||
joystickKnob.style.transform = `translate(calc(-50% + ${deltaX}px), calc(-50% + ${deltaY}px))`;
|
||||
|
||||
// Apply movement (with deadzone)
|
||||
keysPressed.w = deltaY < -deadzone;
|
||||
keysPressed.s = deltaY > deadzone;
|
||||
keysPressed.a = deltaX < -deadzone;
|
||||
keysPressed.d = deltaX > deadzone;
|
||||
}
|
||||
|
||||
// Up/Down buttons for vertical movement
|
||||
upBtn.addEventListener('touchstart', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
keysPressed.space = true;
|
||||
}, { passive: false });
|
||||
|
||||
upBtn.addEventListener('touchend', (e) => {
|
||||
e.preventDefault();
|
||||
keysPressed.space = false;
|
||||
}, { passive: false });
|
||||
|
||||
upBtn.addEventListener('touchcancel', () => {
|
||||
keysPressed.space = false;
|
||||
});
|
||||
|
||||
downBtn.addEventListener('touchstart', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
keysPressed.shift = true;
|
||||
}, { passive: false });
|
||||
|
||||
downBtn.addEventListener('touchend', (e) => {
|
||||
e.preventDefault();
|
||||
keysPressed.shift = false;
|
||||
}, { passive: false });
|
||||
|
||||
downBtn.addEventListener('touchcancel', () => {
|
||||
keysPressed.shift = false;
|
||||
});
|
||||
|
||||
// Monitor airbreak state changes
|
||||
const originalSetupAirbreak = setupAirbreak;
|
||||
setupAirbreak = function() {
|
||||
originalSetupAirbreak();
|
||||
updateTouchControlsVisibility();
|
||||
};
|
||||
document.getElementById('ce-setup-airbreak').onclick = setupAirbreak;
|
||||
|
||||
// Update controls visibility periodically
|
||||
setInterval(updateTouchControlsVisibility, 500);
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
Vendored
+1
-1
@@ -36,7 +36,7 @@ const DATA_PACKAGE = {
|
||||
start: 7604416,
|
||||
end: 33051462
|
||||
}, {
|
||||
filename: "/vc-assets/local/audio/sfx.sdt",
|
||||
filename: "/vc-assets/local/audio/sdt",
|
||||
start: 33051462,
|
||||
end: 33250282
|
||||
}, {
|
||||
|
||||
Reference in New Issue
Block a user