feat: temperature system + XP on loot pickup
This commit is contained in:
parent
94e6f535d0
commit
d948b1743d
84
game.js
84
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();
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
<div id="stats">
|
||||
<div class="row">❤️ <span id="hp">100</span> 🍗 <span id="food">100</span></div>
|
||||
<div class="row">🫁 <span id="o2">100</span></div>
|
||||
<div class="row">🌡️ <span id="temp">15°C</span></div>
|
||||
<div class="row">📍 X:<span id="sx">0</span> Y:<span id="sy">0</span></div>
|
||||
<div class="row">🕒 <span id="tod">День</span></div>
|
||||
<div class="row">🌐 <span id="worldId" style="cursor:pointer; text-decoration:underline;" title="Нажмите, чтобы скопировать ссылку">default</span></div>
|
||||
|
|
@ -93,6 +94,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<script src="game.js?v=25"></script>
|
||||
<script src="game.js?v=26"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Reference in New Issue