/
CodeByKate
/
lastserver-game
Обзор
Документация
Войти
/
CodeByKate
/
lastserver-game
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
code.js
197 строк
7 KB
CodeByKate
upload files
21 дек 2025, 21:44
21 дек 2025, 21:44
136e74f
Код
Авторство
О чём код?
/* code.js Lera's ability: detect nearby fragile platforms and attempt a repair mini-action. - Mini-game overlay (300x200) with green monospace text on semi-transparent black. - Accepts keys 1/2/3 for choices, Enter to confirm, Esc to cancel; auto-cancels after 10s. - Pauses the game while the mini-game is open. - Successful repair restores platform (alpha=1.0) and grants +15% of decayTimerMax to stability. - Cooldown (12s) tracked in cooldownRemaining and updated each frame via update(dt). - Failure triggers red flash and starts cooldown without stability gain. */ export default class LeraAbility { constructor(engine, entities){ this.engine = engine; this.entities = entities; this.cooldown = 12.0; this.cooldownRemaining = 0; this.busy = false; this._createOverlay(); } reset(){ this.cooldownRemaining = 0; this.busy = false; this._hideOverlay(); } _createOverlay(){ this.overlay = document.createElement('div'); Object.assign(this.overlay.style, { position: 'absolute', left: '50%', top: '50%', transform: 'translate(-50%,-50%)', width: '300px', height: '200px', padding: '12px', background: 'rgba(0,0,0,0.88)', color: '#7ee77e', fontFamily: 'monospace', fontSize: '13px', border: '1px solid rgba(126,231,126,0.08)', borderRadius: '6px', zIndex: 2000, display: 'none', boxSizing: 'border-box', textAlign: 'left' }); document.body.appendChild(this.overlay); this.overlay.innerHTML = ` <div id="code-window" style="white-space:pre;line-height:1.25;color:#7ee77e;font-size:13px;"></div> <div id="choices" style="margin-top:12px;display:flex;gap:8px;justify-content:center"></div> <div style="position:absolute;left:12px;right:12px;bottom:8px;font-size:12px;color:#9fdab3;text-align:center"> 1/2/3 — выбрать · Enter — подтвердить · Esc — отмена </div>`; // clickable choices and keyboard managed when open } _showOverlay(promptLines, choices){ const win = this.overlay.querySelector('#code-window'); const choicesCont = this.overlay.querySelector('#choices'); win.innerHTML = promptLines.map(l => `<div>${l}</div>`).join(''); choicesCont.innerHTML = ''; choices.forEach((c,i)=>{ const btn = document.createElement('button'); btn.textContent = `${i+1}. ${c.text}`; btn.style.padding = '6px 10px'; btn.style.borderRadius = '6px'; btn.style.background = 'linear-gradient(180deg,#071018,#0b1215)'; btn.style.color = '#cfeefb'; btn.style.border = '1px solid rgba(255,255,255,0.04)'; btn.style.cursor = 'pointer'; btn.onclick = ()=> this._onChoice(i+1); choicesCont.appendChild(btn); }); this.overlay.style.display = 'block'; } _hideOverlay(){ if(this.overlay) this.overlay.style.display = 'none'; } _onChoice(idx){ if(!this.busy) return; this.busy = false; this._hideOverlay(); if(this._keyHandler) window.removeEventListener('keydown', this._keyHandler); clearTimeout(this._autoFailTimer); if(typeof this._pausedBefore !== 'undefined') this.engine.pause(!!this._pausedBefore); const correct = (idx === this._correctIndex); if(correct && this._targetPlatform && this._targetPlatform.exists && this._targetPlatform.alpha > 0 && this._targetPlatform.alpha < 1){ // repair platform this._targetPlatform.alpha = 1; this._targetPlatform._started = false; this._targetPlatform._age = 0; this._targetPlatform._jitter = 0; // grant +15% stability of max const boost = Math.round(this.engine.decayTimerMax * 0.15); this.engine.decayTimer = Math.min(this.engine.decayTimerMax, this.engine.decayTimer + boost); this.engine._triggerFlash('green', 450); } else { this.engine._triggerFlash('red', 300); } // start cooldown (always) this.cooldownRemaining = this.cooldown; this._targetPlatform = null; } _onCancel(){ if(!this.busy) return; this.busy = false; this._hideOverlay(); if(this._keyHandler) window.removeEventListener('keydown', this._keyHandler); clearTimeout(this._autoFailTimer); if(typeof this._pausedBefore !== 'undefined') this.engine.pause(!!this._pausedBefore); // cooldown penalty this.cooldownRemaining = Math.min(this.cooldown, 6); this.engine._triggerFlash('red', 300); this._targetPlatform = null; } tryUse(){ if(this.busy || this.cooldownRemaining > 0 || this.engine.gameOver || this.engine.win){ if(this.cooldownRemaining > 0){ // show short UI message via engine/UI if available const uiMsg = document.getElementById('ability-msg'); if(uiMsg){ uiMsg.textContent = `Перезарядка: ${Math.ceil(this.cooldownRemaining)} сек`; uiMsg.style.display='block'; setTimeout(()=>uiMsg.style.display='none',1000); } this.engine._triggerFlash('red', 220); } return; } const near = this._findNearbyRepairable(); if(!near) return; this._targetPlatform = near; // prepare mini-game prompt and choices (correct answer always option 1) const prompt = [ "function boot() { console.lgo('boot'); }", "// Выберите исправление" ]; const choices = [ { text: "console.log('boot');" }, { text: "consol.log('boot');" }, { text: "console.lgo('boot');" } ]; // keep order fixed so correct is always 1 for clarity this._correctIndex = 1; this.busy = true; this._pausedBefore = this.engine.paused; this.engine.pause(true); this._showOverlay(prompt, choices); // keyboard handler this._lastNumChoice = null; this._keyHandler = (e)=>{ if(!this.busy) return; if(e.key === '1' || e.key === '2' || e.key === '3'){ this._lastNumChoice = parseInt(e.key,10); } else if(e.key === 'Enter'){ if(this._lastNumChoice) this._onChoice(this._lastNumChoice); } else if(e.key === 'Escape'){ this._onCancel(); } }; window.addEventListener('keydown', this._keyHandler); // auto-cancel after 10s this._autoFailTimer = setTimeout(()=>{ if(this.busy) this._onCancel(); }, 10000); } update(dt){ if(this.cooldownRemaining > 0){ this.cooldownRemaining = Math.max(0, this.cooldownRemaining - dt); } } _findNearbyRepairable(){ for(const p of this.entities.platforms){ if(!p.decaying || !p._started || !p.exists) continue; if(!(p.alpha > 0 && p.alpha < 1)) continue; const lx = this.entities.players.lera.x + this.entities.players.lera.w/2; const ly = this.entities.players.lera.y + this.entities.players.lera.h/2; const px = p.x + p.w/2; const py = p.y + p.h/2; const d = Math.hypot(lx-px, ly-py); if(d < 80) return p; } return null; } }