feat: WS sends selected_game_id on connect, gear indicator auto-adapts to game mapping (Forza/AC/iRacing)
This commit is contained in:
@@ -46,6 +46,60 @@ html,body{width:100%;height:100%;overflow:hidden;background:#000;
|
||||
</div></div></div>
|
||||
<script>
|
||||
const M={aspect_ratio:"1:1",render_mode:"contain",gear_style:"auto"};
|
||||
let GAME_ID='';
|
||||
|
||||
// Forza: 0=R, 1-8=1-8 (no neutral in UDP)
|
||||
// AC/F1: -1=R, 0=N, 1-8=1-8
|
||||
// iRacing: 0=N, 1=R, 2=1st... (offset +2)
|
||||
function gearLabel(g){
|
||||
if(!g&&g!==0)return'-';
|
||||
const style=M.gear_style||'auto';
|
||||
const isForza=GAME_ID&&(GAME_ID.includes('forza'));
|
||||
const isIRacing=GAME_ID&&GAME_ID.includes('iracing');
|
||||
|
||||
if(style==='forza'||isForza){
|
||||
if(g===0)return'R';
|
||||
if(g>=1&&g<=8)return String(g);
|
||||
return String(g);
|
||||
}
|
||||
if(style==='ac'||(!isForza&&!isIRacing)){
|
||||
if(g===-1)return'R';
|
||||
if(g===0)return'N';
|
||||
if(g>=1&&g<=8)return String(g);
|
||||
return String(g);
|
||||
}
|
||||
if(isIRacing){
|
||||
if(g===0)return'N';
|
||||
if(g===1)return'R';
|
||||
if(g>=2&&g<=9)return String(g-1);
|
||||
return String(g);
|
||||
}
|
||||
// fallback
|
||||
if(g===0)return'N';
|
||||
if(g>0)return String(g);
|
||||
return String(g);
|
||||
}
|
||||
|
||||
function gearBarIndex(g){
|
||||
if(!g&&g!==0)return-1;
|
||||
const isForza=GAME_ID&&GAME_ID.includes('forza');
|
||||
const isIRacing=GAME_ID&&GAME_ID.includes('iracing');
|
||||
|
||||
if(isForza){
|
||||
if(g===0)return 0; // R at index 0
|
||||
if(g>=1&&g<=8)return g+1; // 1->2
|
||||
}
|
||||
if(isIRacing){
|
||||
if(g===0)return 1; // N at index 1
|
||||
if(g===1)return 0; // R at index 0
|
||||
if(g>=2&&g<=9)return g; // 2->2(index for '1')
|
||||
}
|
||||
// AC/F1/default
|
||||
if(g===-1)return 0; // R
|
||||
if(g===0)return 1; // N
|
||||
if(g>=1&&g<=8)return g+1; // 1->2
|
||||
return -1;
|
||||
}
|
||||
(function(){
|
||||
const box=document.getElementById('box'),gearTxt=document.getElementById('gear-txt'),
|
||||
gearEl=document.getElementById('gear-el'),barRow=document.getElementById('bar-row');
|
||||
@@ -91,21 +145,8 @@ const M={aspect_ratio:"1:1",render_mode:"contain",gear_style:"auto"};
|
||||
|
||||
function updateGear(g){
|
||||
if(g===lastGear)return;lastGear=g;
|
||||
|
||||
// Determine mapping based on actual gear value
|
||||
let label,activeIndex;
|
||||
if(g<0){// AC style: negative is reverse
|
||||
label='R';activeIndex=0;
|
||||
}else if(g===0){
|
||||
// ambiguous: could be R (Forza) or N (AC)
|
||||
// Show R by default for Forza, but check gear_style
|
||||
label='R';activeIndex=0;
|
||||
}else{
|
||||
// Forward gear: g is 1-based in Forza, but some games might use 0-based
|
||||
label=String(g);
|
||||
if(g>=1&&g<=8)activeIndex=g+1; // gear 1 -> index 2
|
||||
else activeIndex=-1;
|
||||
}
|
||||
const label=gearLabel(g);
|
||||
const activeIndex=gearBarIndex(g);
|
||||
|
||||
gearTxt.textContent=label;
|
||||
gearEl.className='gear-circle active';
|
||||
@@ -131,8 +172,10 @@ const M={aspect_ratio:"1:1",render_mode:"contain",gear_style:"auto"};
|
||||
}
|
||||
|
||||
function connect(){
|
||||
ws=new WebSocket(wsUrl);ws.onopen=()=>{if(rt){clearTimeout(rt);rt=null}};
|
||||
ws.onmessage=(e)=>{try{const m=JSON.parse(e.data);if(m.type==='telemetry')updateGear(m.data.gear||0)}catch(e){}};
|
||||
ws=new WebSocket(wsUrl);ws.onopen=()=>{if(rt){clearTimeout(rt);rt=null}};
|
||||
ws.onmessage=(e)=>{try{const m=JSON.parse(e.data);
|
||||
if(m.type==='connected'){GAME_ID=m.selected_game_id||'';console.log('[Gear] game:',GAME_ID)}
|
||||
if(m.type==='telemetry')updateGear(m.data.gear||0)}catch(e){}};
|
||||
ws.onclose=()=>{rt=setTimeout(connect,2000)};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user