diff --git a/game.js b/game.js index 771d078..c0aa49d 100644 --- a/game.js +++ b/game.js @@ -390,7 +390,6 @@ function customConfirm(msg, onYes) { // Give loot to the killer if (sm.kind === 'chicken') playSound('hurt_chicken'); spawnDrops(sm.x, sm.y, sm.kind); - grantXP(getMobXP(sm.kind)); rebuildHotbar(); } serverMobs.delete(data.id); @@ -1207,6 +1206,7 @@ function customConfirm(msg, onYes) { // UI const hpEl = document.getElementById('hp'); const foodEl = document.getElementById('food'); + const tempEl = document.getElementById("temp"); const sxEl = document.getElementById('sx'); const syEl = document.getElementById('sy'); const todEl = document.getElementById('tod'); @@ -1256,6 +1256,7 @@ function customConfirm(msg, onYes) { // Область карты — центрирована на игроке const pGX = Math.floor(player.x / TILE); + const biome = getCachedBiome(pGX); const pGY = Math.floor(player.y / TILE); const viewW = Math.floor(mW / scale); const viewH = Math.floor(mH / scale); @@ -2586,7 +2587,7 @@ registerProcessor('voice-playback', VoicePlaybackProcessor); vy: -1 - Math.random() * 2, item: entry.item, qty: qty, - age: 0 + age: 0, xpValue: getMobXP(kind) }); } } @@ -2618,6 +2619,7 @@ registerProcessor('voice-playback', VoicePlaybackProcessor); if (dx*dx + dy*dy < 30*30) { if (!inv[d.item]) inv[d.item] = 0; inv[d.item] += d.qty; + if (d.xpValue) grantXP(Math.ceil(d.xpValue * 0.3)); drops.splice(i, 1); rebuildHotbar(); } @@ -2707,6 +2709,7 @@ registerProcessor('voice-playback', VoicePlaybackProcessor); xp: player.xp, level: player.level }, + temperature: player.temperature, inventory: inv, time: worldTime, isNight: isNightTime, @@ -2789,6 +2792,7 @@ registerProcessor('voice-playback', VoicePlaybackProcessor); // Миграция версий if(saveData.version === 1){ + player.temperature = saveData.player.temperature !== undefined ? saveData.player.temperature : 15; migrateV1toV2(saveData); } @@ -3346,7 +3350,6 @@ registerProcessor('voice-playback', VoicePlaybackProcessor); if(m.hp<=0){ if(m.kind === 'chicken') playSound('hurt_chicken'); spawnDrops(m.x + m.w/2, m.y + m.h/2, m.kind); - grantXP(getMobXP(m.kind)); // Remove from the correct array if(m.id !== undefined){ serverMobs.delete(m.id); @@ -4256,6 +4259,66 @@ registerProcessor('voice-playback', VoicePlaybackProcessor); // голод убывает, но HP не отнимает (как просили) player.hunger = Math.max(0, player.hunger - dt*0.2); // замедлил в 4 раза + + // ========== ТЕМПЕРАТУРА ========== + if (player.temperature === undefined) player.temperature = 15; + const BIOME_TEMP = { tundra: -20, plains: 15, swamp: 20, desert: 45, mountains: 5 }; + const UNDERGROUND_TEMP = 15; + const COLD_THRESHOLD = -5; + const HEAT_THRESHOLD = 35; + const HEAT_RADIUS = 5; + const pGX = Math.floor(player.x / TILE); + const biome = getCachedBiome(pGX); + const pGY = Math.floor(player.y / TILE); + const sGY = surfaceGyAt(pGX); + const isUndergroundTemp = (sGY - pGY) > 2; + let targetTemp = BIOME_TEMP[biome] || 15; + if (isUndergroundTemp) targetTemp = UNDERGROUND_TEMP; + if (isNight() && !isUndergroundTemp) targetTemp -= 10; + if ((weatherState.type === 'rain' || weatherState.type === 'storm') && !isUndergroundTemp) targetTemp -= 5; + player.temperature += (targetTemp - player.temperature) * dt * 0.3; + let nearHeat = false, nearCool = false; + for (let dx = -HEAT_RADIUS; dx <= HEAT_RADIUS; dx++) { + for (let dy = -HEAT_RADIUS; dy <= HEAT_RADIUS; dy++) { + const b = getBlock(pGX + dx, pGY + dy); + if (!b || b.dead) continue; + if (b.t === 'campfire' || b.t === 'torch') nearHeat = true; + if (b.t === 'water' && biome === 'desert') nearCool = true; + } + } + if (nearHeat) { + player.temperature += (30 - player.temperature) * dt * 2; + if (player.hp < 100) player.hp = Math.min(100, player.hp + 8 * dt); + } + if (nearCool) { + player.temperature += (15 - player.temperature) * dt * 1.5; + if (player.hp < 100 && player.temperature > HEAT_THRESHOLD) { + player.hp = Math.min(100, player.hp + 8 * dt); + } + } + if (isUndergroundTemp && !nearHeat) { + if (player.hp < 100 && player.temperature >= COLD_THRESHOLD && player.temperature <= HEAT_THRESHOLD) { + player.hp = Math.min(100, player.hp + 2 * dt); + } + } + const aboveBlk = getBlock(pGX, pGY - 1); + const inShade = aboveBlk && BLOCKS[aboveBlk.t] && BLOCKS[aboveBlk.t].solid && aboveBlk.t !== 'glass'; + if (inShade && !isUndergroundTemp && !nearCool) { + player.temperature -= 5 * dt; + if (player.temperature > HEAT_THRESHOLD - 2 && player.hp < 100) { + player.hp = Math.min(100, player.hp + 1 * dt); + } + } + if (player.temperature < COLD_THRESHOLD) { + const severity = Math.abs(player.temperature - COLD_THRESHOLD) / 15; + player.hp -= 3 * severity * dt; + if (severity > 0.5) player.vx *= (1 - 0.3 * Math.min(1, severity) * dt); + } + if (player.temperature > HEAT_THRESHOLD) { + const severity = (player.temperature - HEAT_THRESHOLD) / 15; + player.hp -= 2.5 * severity * dt; + if (severity > 0.5) player.hunger -= 0.5 * severity * dt; + } // Игрок не может двигаться во время сна if(player.sleeping){ player.vx = 0; @@ -4482,7 +4545,6 @@ registerProcessor('voice-playback', VoicePlaybackProcessor); } if(m.hp <= 0){ spawnDrops(m.x + m.w/2, m.y + m.h/2, m.kind); - grantXP(getMobXP(m.kind)); // Remove from the correct array if(m.id !== undefined){ serverMobs.delete(m.id); @@ -5002,6 +5064,7 @@ registerProcessor('voice-playback', VoicePlaybackProcessor); const xpInLevel = player.xp - lvXpCur; const xpNeeded = lvXpNext - lvXpCur; document.getElementById('xpbar').textContent = xpInLevel + '/' + xpNeeded; + tempEl.textContent = Math.round(player.temperature) + "°C"; worldIdEl.textContent = worldId; if(isMultiplayer){ document.getElementById('multiplayerStatus').style.display = 'flex'; @@ -5024,6 +5087,19 @@ registerProcessor('voice-playback', VoicePlaybackProcessor); } // Рисуем дропы + // Температурный оверлей (заморозка/тепловой удар) + if (typeof player.temperature !== 'undefined' && (player.temperature < -5 || player.temperature > 35)) { + const severity = player.temperature < -5 + ? Math.abs(player.temperature + 5) / 20 + : (player.temperature - 35) / 20; + const alpha = Math.min(0.35, severity * 0.15); + if (player.temperature < -5) { + ctx.fillStyle = 'rgba(100,150,255,' + alpha + ')'; + } else { + ctx.fillStyle = 'rgba(255,100,50,' + alpha + ')'; + } + ctx.fillRect(0, 0, W, H); + } drawDrops(ctx); // Пикап дропов pickupDrops(); diff --git a/index.html b/index.html index a78eecc..12dc1dc 100644 --- a/index.html +++ b/index.html @@ -17,6 +17,7 @@
❤️ 100   🍗 100
🫁 100
+
🌡️ 15°C
📍 X:0 Y:0
🕒 День
🌐 default
@@ -93,6 +94,6 @@
- +