This commit is contained in:
33333-33333 2026-07-16 22:12:03 +09:00
commit 2cc2f003df
71 changed files with 3359 additions and 1027 deletions

View file

@ -549,6 +549,7 @@ draw(ctx, t, lighting = null) {
} else if (this.type === "duplicator") {
ctx.save();
const loaded = !!this.storedFoodType;
const powered = globalThis.TarinaiSignalSystem?.powerOverride?.(this) !== false;
const bodyGrad = ctx.createLinearGradient(-this.r * 1.1, -this.r * 1.0, this.r * 1.1, this.r * 0.9);
bodyGrad.addColorStop(0, styleNight ? "#3d4852" : "#d8e2e6");
bodyGrad.addColorStop(0.45, styleNight ? "#65717b" : "#f2f6f7");
@ -566,7 +567,7 @@ draw(ctx, t, lighting = null) {
ctx.strokeStyle = styleNight ? "rgba(160,190,210,0.25)" : "rgba(82,98,108,0.32)";
ctx.stroke();
ctx.fillStyle = loaded ? "rgba(83,221,116,0.88)" : "rgba(139,160,170,0.62)";
ctx.fillStyle = !powered ? "rgba(180,76,70,0.72)" : (loaded ? "rgba(83,221,116,0.88)" : "rgba(139,160,170,0.62)");
ctx.beginPath();
ctx.arc(-this.r * 0.70, -this.r * 0.43, this.r * 0.13, 0, Math.PI * 2);
ctx.fill();
@ -624,6 +625,76 @@ draw(ctx, t, lighting = null) {
ctx.ellipse(-this.r * 0.48, -this.r * 0.72, this.r * 0.34, this.r * 0.08, -0.14, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
} else if (this.type === "seesaw") {
const r = this.r || 60;
const tilt = Number(this.seesawTilt || 0) || 0;
ctx.save();
ctx.fillStyle = styleNight ? "rgba(81,68,57,0.96)" : "rgba(130,99,69,0.98)";
ctx.strokeStyle = styleNight ? "rgba(41,34,29,0.86)" : "rgba(78,55,37,0.82)";
ctx.lineWidth = 2.4;
ctx.beginPath();
ctx.moveTo(-r * 0.22, r * 0.42);
ctx.lineTo(0, -r * 0.05);
ctx.lineTo(r * 0.22, r * 0.42);
ctx.closePath(); ctx.fill(); ctx.stroke();
ctx.save();
ctx.rotate(tilt);
const grad = ctx.createLinearGradient(0, -r * 0.14, 0, r * 0.14);
grad.addColorStop(0, styleNight ? "#c5895c" : "#f0ad6f");
grad.addColorStop(1, styleNight ? "#8d5d3f" : "#ba7447");
ctx.fillStyle = grad;
ctx.strokeStyle = styleNight ? "rgba(57,37,29,0.9)" : "rgba(104,59,35,0.85)";
roundedRect(ctx, -r * 1.08, -r * 0.13, r * 2.16, r * 0.26, r * 0.08);
ctx.fill(); ctx.stroke();
for (const side of [-1, 1]) {
ctx.fillStyle = side < 0 ? "rgba(88,177,231,0.98)" : "rgba(239,111,116,0.98)";
roundedRect(ctx, side * r * 0.79 - r * 0.18, -r * 0.26, r * 0.36, r * 0.22, r * 0.07);
ctx.fill(); ctx.stroke();
ctx.strokeStyle = "rgba(70,55,45,0.75)";
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(side * r * 0.90, -r * 0.22);
ctx.lineTo(side * r * 0.90, -r * 0.52);
ctx.stroke();
}
ctx.restore();
ctx.fillStyle = "rgba(70,58,48,0.9)";
ctx.beginPath(); ctx.arc(0, 0, r * 0.13, 0, Math.PI * 2); ctx.fill();
ctx.restore();
} else if (this.type === "circuit_board") {
const circuit = globalThis.TarinaiCircuitBoardSystem;
const angle = Number(this.angle || 0) || 0;
const active = Object.values(this._circuitOutputState || {}).some(Boolean);
ctx.save();
ctx.rotate(angle);
ctx.fillStyle = active ? "rgba(44,139,82,0.98)" : (styleNight ? "rgba(41,91,62,0.98)" : "rgba(47,126,76,0.98)");
ctx.strokeStyle = styleNight ? "rgba(19,48,31,0.92)" : "rgba(26,74,42,0.90)";
ctx.lineWidth = 2.4;
const boardHalfW = Number(circuit?.boardHalfWidth?.(this) ?? circuit?.HALF_W ?? 32) || 32;
const boardHalfH = Number(circuit?.boardHalfHeight?.(this) ?? circuit?.HALF_H ?? 32) || 32;
roundedRect(ctx, -boardHalfW, -boardHalfH, boardHalfW * 2, boardHalfH * 2, 10); ctx.fill(); ctx.stroke();
ctx.strokeStyle = "rgba(216,190,81,0.64)";
ctx.lineWidth = 1.4;
const traceRows = Math.max(1, Math.min(7, Math.floor(boardHalfH / 9)));
for (let i = -traceRows; i <= traceRows; i++) {
const y = i * Math.max(5, boardHalfH / Math.max(2, traceRows * 1.7));
ctx.beginPath(); ctx.moveTo(-boardHalfW * 0.72, y); ctx.lineTo(-boardHalfW * 0.28, y); ctx.lineTo(0, y * 0.45); ctx.stroke();
ctx.beginPath(); ctx.moveTo(boardHalfW * 0.72, y); ctx.lineTo(boardHalfW * 0.28, y); ctx.lineTo(0, y * 0.45); ctx.stroke();
}
ctx.fillStyle = "rgba(30,39,34,0.94)";
roundedRect(ctx, -15, -16, 30, 32, 5); ctx.fill();
ctx.fillStyle = "rgba(236,245,235,0.92)";
ctx.font = "bold 11px ui-rounded, sans-serif"; ctx.textAlign = "center"; ctx.textBaseline = "middle";
ctx.fillText("LOGIC", 0, 0);
for (const port of circuit?.ports?.(this) || []) {
const local = circuit.localPortPosition(port, this);
const on = port.direction === "input" ? Boolean(this._circuitInputState?.[port.id]) : Boolean(this._circuitOutputState?.[port.id]);
ctx.fillStyle = on ? "rgba(255,228,91,1)" : (port.direction === "input" ? "rgba(92,189,255,0.96)" : "rgba(255,143,77,0.96)");
ctx.strokeStyle = "rgba(25,35,31,0.88)";
ctx.lineWidth = 1.4;
ctx.beginPath(); ctx.arc(local.x, local.y, 5.4, 0, Math.PI * 2); ctx.fill(); ctx.stroke();
}
ctx.restore();
} else if (this.type === "signboard") {
ctx.save();
const boardGrad = ctx.createLinearGradient(0, -this.r * 1.28, 0, this.r * 0.12);
@ -685,8 +756,9 @@ draw(ctx, t, lighting = null) {
} else if (this.type === "dry_ice") {
const r = this.r || 21;
const time = this.world?.time || (typeof performance !== "undefined" ? performance.now() * 0.001 : 0);
const powered = globalThis.TarinaiSignalSystem?.powerOverride?.(this) !== false;
ctx.save();
if (itemShadowsEnabled()) {
if (powered && itemShadowsEnabled()) {
ctx.shadowColor = "rgba(90, 178, 255, 0.30)";
ctx.shadowBlur = 11;
}
@ -737,7 +809,7 @@ draw(ctx, t, lighting = null) {
roundedRect(ctx, -bodyW * 0.48, y + bodyH - footH * 0.4, bodyW * 0.96, footH, r * 0.10);
ctx.fill();
for (let i = 0; i < 4; i++) {
if (powered) for (let i = 0; i < 4; i++) {
const phase = (time * (0.42 + i * 0.06) + i * 0.23 + (this.seed || 0)) % 1;
const sx = -r * 0.50 + i * r * 0.33 + Math.sin(time * 1.4 + i) * r * 0.06;
const sy = y - capH * 0.62 - phase * r * 0.76;
@ -750,8 +822,9 @@ draw(ctx, t, lighting = null) {
ctx.restore();
} else if (this.type === "stove") {
const r = this.r || 24;
const powered = globalThis.TarinaiSignalSystem?.powerOverride?.(this) !== false;
ctx.save();
if (itemShadowsEnabled()) {
if (powered && itemShadowsEnabled()) {
ctx.shadowColor = "rgba(255, 120, 43, 0.34)";
ctx.shadowBlur = 9;
}
@ -764,17 +837,19 @@ draw(ctx, t, lighting = null) {
ctx.fillStyle = "rgba(42, 32, 28, 0.92)";
roundedRect(ctx, -r * 0.48, -r * 0.34, r * 0.96, r * 0.62, r * 0.14);
ctx.fill();
const flame = 0.85 + 0.15 * Math.sin((this.world?.time || (typeof performance !== "undefined" ? performance.now() * 0.001 : 0)) * 4.2 + (this.seed || 0));
ctx.fillStyle = "rgba(255, 168, 57, 0.92)";
ctx.beginPath();
ctx.moveTo(0, r * 0.16);
ctx.bezierCurveTo(-r * 0.38, -r * 0.10, -r * 0.10, -r * 0.52 * flame, 0, -r * 0.66 * flame);
ctx.bezierCurveTo(r * 0.34, -r * 0.20, r * 0.40, -r * 0.02, 0, r * 0.16);
ctx.fill();
ctx.fillStyle = "rgba(255, 235, 120, 0.82)";
ctx.beginPath();
ctx.ellipse(0, -r * 0.10, r * 0.16, r * 0.28 * flame, 0, 0, Math.PI * 2);
ctx.fill();
if (powered) {
const flame = 0.85 + 0.15 * Math.sin((this.world?.time || (typeof performance !== "undefined" ? performance.now() * 0.001 : 0)) * 4.2 + (this.seed || 0));
ctx.fillStyle = "rgba(255, 168, 57, 0.92)";
ctx.beginPath();
ctx.moveTo(0, r * 0.16);
ctx.bezierCurveTo(-r * 0.38, -r * 0.10, -r * 0.10, -r * 0.52 * flame, 0, -r * 0.66 * flame);
ctx.bezierCurveTo(r * 0.34, -r * 0.20, r * 0.40, -r * 0.02, 0, r * 0.16);
ctx.fill();
ctx.fillStyle = "rgba(255, 235, 120, 0.82)";
ctx.beginPath();
ctx.ellipse(0, -r * 0.10, r * 0.16, r * 0.28 * flame, 0, 0, Math.PI * 2);
ctx.fill();
}
ctx.restore();
} else if (this.type === "ant_nest") {
const count = clamp(Math.round(this.antCount ?? ANT_NEST_START_COUNT ?? 6), 0, ANT_NEST_MAX_COUNT ?? 10);
@ -873,9 +948,11 @@ draw(ctx, t, lighting = null) {
const r = this.r || 26;
const bodyAngle = Number.isFinite(Number(this.fanBodyAngle)) ? normalizedItemAngle(Number(this.fanBodyAngle), itemAngleFor(this)) : itemAngleFor(this);
const windAngle = itemAngleFor(this);
const spin = (this.fanSpin || 0) + (window.TarinaiSignalSystem?.powerOverride?.(this) === false ? 0 : t * 10.5);
const powered = globalThis.TarinaiSignalSystem?.powerOverride?.(this) !== false;
const spin = (this.fanSpin || 0) + (powered ? t * 10.5 : 0);
ctx.save();
ctx.rotate(windAngle);
if (powered) {
const windRange = 320;
const windStart = r * 1.02;
const windSpread = 0.62;
@ -934,6 +1011,7 @@ draw(ctx, t, lighting = null) {
ctx.stroke();
}
ctx.globalAlpha = fanAlpha;
}
ctx.restore();
ctx.save();
ctx.rotate(bodyAngle);
@ -1235,7 +1313,7 @@ draw(ctx, t, lighting = null) {
ctx.beginPath(); ctx.roundRect?.(-27,-18,54,36,8); if (!ctx.roundRect) { ctx.rect(-27,-18,54,36); } ctx.fill(); ctx.stroke();
ctx.fillStyle = active ? "#fff6c9" : "#7b838d"; ctx.beginPath(); ctx.arc(0,-3,9,0,Math.PI*2); ctx.fill();
const detectorMark = { tarinai:"\u305f", item:"\u7269", time:"\u6642", hunger_avg:"\u8179", stress_avg:"\u5727", sleep_avg:"\u7720", low_hp_count:"HP", sick_count:"\u75c5", temperature:"\u2103", zunchi_count:"\u7cde", ant_count:"\u87fb", water_count:"\u6c34" }[this.pressureTarget] || "\u305f";
const detectorLabel = this.pressureTarget === "time" ? detectorMark : `${detectorMark}${Number(this.pressureThreshold ?? 1)}`;
const detectorLabel = this.pressureTarget === "time" ? detectorMark : `${detectorMark}${Number(this.pressureMin ?? 1)}-${Number(this.pressureMax ?? 300)}`;
ctx.fillStyle = styleNight ? "#eef2f6" : "#26323e"; ctx.font="bold 10px ui-rounded, sans-serif"; ctx.textAlign="center"; ctx.fillText(detectorLabel,0,14);
ctx.restore();
} else if (this.type === "rotator") {