aaa
This commit is contained in:
parent
2e90add2e1
commit
db81a509cf
6 changed files with 56 additions and 21 deletions
|
|
@ -267,11 +267,26 @@
|
||||||
return structure;
|
return structure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hydrateStructure(structure) {
|
||||||
|
if (!structure || !structure.isStructure) return structure;
|
||||||
|
structure.update = updateStructure;
|
||||||
|
structure.draw = drawStructure;
|
||||||
|
structure.damage = damageStructure;
|
||||||
|
const def = StructureRegistry[structure.type];
|
||||||
|
if (def) {
|
||||||
|
structure.roles = structure.roles || { ...def.roles };
|
||||||
|
structure.needEffects = structure.needEffects || { ...def.needEffects };
|
||||||
|
structure.r = structure.r || (structure.type === "plushie" ? 14 : 28);
|
||||||
|
structure.amount = Math.max(0, structure.hp || structure.amount || 1);
|
||||||
|
}
|
||||||
|
return structure;
|
||||||
|
}
|
||||||
|
|
||||||
function consumeGrassMaterial(grass) {
|
function consumeGrassMaterial(grass) {
|
||||||
if (!grass || grass.dead) return false;
|
if (!grass || grass.dead) return false;
|
||||||
grass.amount = Math.max(0, Number(grass.amount || 0) - 34);
|
grass.amount = Math.max(0, Number(grass.amount || 0) - 34);
|
||||||
grass.growth = clamp((grass.growth || 0.5) - 0.24, 0.04, 1.2);
|
grass.growth = clamp((grass.growth || 0.5) - 0.24, 0.04, 1.2);
|
||||||
if (grass.amount <= 1) grass.dead = true;
|
if (grass.amount <= 1) grass.amount = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -406,8 +421,12 @@
|
||||||
const w = world || global.world;
|
const w = world || global.world;
|
||||||
const def = StructureRegistry[this.type];
|
const def = StructureRegistry[this.type];
|
||||||
def?.onDestroyed?.(this, w, breaker);
|
def?.onDestroyed?.(this, w, breaker);
|
||||||
this.dead = true;
|
|
||||||
this.amount = 0;
|
this.amount = 0;
|
||||||
|
try {
|
||||||
|
Object.defineProperty(this, "dead", { value: true, configurable: true, writable: true });
|
||||||
|
} catch (_) {
|
||||||
|
// Item.dead is a getter derived from amount; amount=0 is enough for those instances.
|
||||||
|
}
|
||||||
w?.markTerrainDirty?.(`structure-destroyed:${this.type}`);
|
w?.markTerrainDirty?.(`structure-destroyed:${this.type}`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -529,6 +548,7 @@
|
||||||
addNeedShock,
|
addNeedShock,
|
||||||
runNeedDecision,
|
runNeedDecision,
|
||||||
createStructure,
|
createStructure,
|
||||||
|
hydrateStructure,
|
||||||
damageStructure,
|
damageStructure,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
26
js/render.js
26
js/render.js
|
|
@ -870,8 +870,8 @@ function drawSelectedCard(ctx, world, lighting) {
|
||||||
if (!t || t.dead || !world.tarinai.includes(t)) return;
|
if (!t || t.dead || !world.tarinai.includes(t)) return;
|
||||||
const w = world.viewportW || world.w;
|
const w = world.viewportW || world.w;
|
||||||
const h = world.viewportH || world.h;
|
const h = world.viewportH || world.h;
|
||||||
const cardW = 152;
|
const cardW = 172;
|
||||||
const cardH = 80;
|
const cardH = 96;
|
||||||
let x = t.x + 18;
|
let x = t.x + 18;
|
||||||
let y = t.y - 100;
|
let y = t.y - 100;
|
||||||
x = clamp(x, 10, w - cardW - 10);
|
x = clamp(x, 10, w - cardW - 10);
|
||||||
|
|
@ -889,9 +889,25 @@ function drawSelectedCard(ctx, world, lighting) {
|
||||||
const child = t.juvenile && t.parentToFollow?.() ? " / \u5b50" : "";
|
const child = t.juvenile && t.parentToFollow?.() ? " / \u5b50" : "";
|
||||||
const zHint = t.digest > 4.9 ? " / \u305a\u3093\u3061" : "";
|
const zHint = t.digest > 4.9 ? " / \u305a\u3093\u3061" : "";
|
||||||
ctx.fillText(`${stateLabel(t.state)}${child}${zHint}`, x + 10, y + 35);
|
ctx.fillText(`${stateLabel(t.state)}${child}${zHint}`, x + 10, y + 35);
|
||||||
const genLabel = (t.displayGeneration && t.displayGeneration()) ? ` \u4e16\u4ee3 ${t.generation}` : "";
|
const needSystem = window.TarinaiNeedSystem;
|
||||||
ctx.fillText(`\u7dcf\u5408\u7684\u6c17\u5206 ${fmt(t.mood)}${genLabel} \u4f53\u529b ${fmt(t.energy)}`, x + 10, y + 52);
|
const needLabels = needSystem?.NEED_LABELS || {
|
||||||
ctx.fillText(`\u30b9\u30c8\u30ec\u30b9 ${fmt(t.stress)} \u7a7a\u8179 ${fmt(t.hunger)}`, x + 10, y + 68);
|
food: "\u6442\u990c",
|
||||||
|
sleep: "\u7761\u7720",
|
||||||
|
health: "\u5065\u5eb7",
|
||||||
|
safety: "\u5b89\u5168",
|
||||||
|
social: "\u95a2\u4fc2",
|
||||||
|
fulfill: "\u5145\u8db3",
|
||||||
|
};
|
||||||
|
const needKeys = needSystem?.NEED_KEYS || ["food", "sleep", "health", "safety", "social", "fulfill"];
|
||||||
|
const needValue = key => needSystem?.getNeedDisplayValue ? needSystem.getNeedDisplayValue(t.needs?.[key] || 0) : Math.round((t.needs?.[key] || 0) / 10);
|
||||||
|
const activeNeed = t.intent?.need || t.need || "";
|
||||||
|
const rowA = needKeys.slice(0, 3).map(key => `${needLabels[key]}${key === activeNeed ? "\u25b2" : ""} ${needValue(key)}`).join(" ");
|
||||||
|
const rowB = needKeys.slice(3).map(key => `${needLabels[key]}${key === activeNeed ? "\u25b2" : ""} ${needValue(key)}`).join(" ");
|
||||||
|
ctx.fillText(rowA, x + 10, y + 52);
|
||||||
|
ctx.fillText(rowB, x + 10, y + 68);
|
||||||
|
let actionText = `\u3044\u307e ${t.intent?.actionLabel || stateLabel(t.state)}`;
|
||||||
|
while (actionText.length > 4 && ctx.measureText(actionText).width > cardW - 20) actionText = `${actionText.slice(0, -4)}...`;
|
||||||
|
ctx.fillText(actionText, x + 10, y + 84);
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2926,6 +2926,7 @@
|
||||||
if (!saved || !saved.type) continue;
|
if (!saved || !saved.type) continue;
|
||||||
const item = new Item(saved.type, Number(saved.x) || 0, Number(saved.y) || 0);
|
const item = new Item(saved.type, Number(saved.x) || 0, Number(saved.y) || 0);
|
||||||
applyOwnData(item, saved, new Set(["target", "targetRef", "world"]));
|
applyOwnData(item, saved, new Set(["target", "targetRef", "world"]));
|
||||||
|
if (item.isStructure && global.TarinaiNeedSystem?.hydrateStructure) global.TarinaiNeedSystem.hydrateStructure(item);
|
||||||
worldRef.items.push(item);
|
worldRef.items.push(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,8 +79,7 @@
|
||||||
this.fallMax = Math.max(this.fallMax || 0, this.fallTimer);
|
this.fallMax = Math.max(this.fallMax || 0, this.fallTimer);
|
||||||
}
|
}
|
||||||
if (Number.isFinite(opts.stress) && opts.stress > 0) {
|
if (Number.isFinite(opts.stress) && opts.stress > 0) {
|
||||||
if (this.addStress) this.addStress(opts.stress, { threshold: opts.stressThreshold ?? 8, duration: opts.stressDuration ?? 4.2 });
|
global.TarinaiNeedSystem?.addNeedShock?.(this, { safety: opts.stress }, threat);
|
||||||
else this.stress = clamp((this.stress || 0) + opts.stress, 0, 130);
|
|
||||||
}
|
}
|
||||||
if (opts.bubble) this.bubble?.(opts.bubble, opts.bubbleCooldown ?? 0.9, opts.bubbleColor || "rgba(84,66,86,0.80)");
|
if (opts.bubble) this.bubble?.(opts.bubble, opts.bubbleCooldown ?? 0.9, opts.bubbleColor || "rgba(84,66,86,0.80)");
|
||||||
this.lastPanicCause = opts.cause || opts.reason || this.thought || "panic";
|
this.lastPanicCause = opts.cause || opts.reason || this.thought || "panic";
|
||||||
|
|
|
||||||
|
|
@ -263,10 +263,7 @@
|
||||||
if (colonyMoodId === "zunda_party" || colonyMoodId === "ball_party") this.stress = clamp((this.stress || 0) - dt * 0.34, 0, 130);
|
if (colonyMoodId === "zunda_party" || colonyMoodId === "ball_party") this.stress = clamp((this.stress || 0) - dt * 0.34, 0, 130);
|
||||||
if (colonyMoodId === "ant_overrun" && this.state !== "panic") {
|
if (colonyMoodId === "ant_overrun" && this.state !== "panic") {
|
||||||
const antSeen = (this.world?.nearbyAnts?.(this.x, this.y, 110, true) || []).some(a => a && !a.dead);
|
const antSeen = (this.world?.nearbyAnts?.(this.x, this.y, 110, true) || []).some(a => a && !a.dead);
|
||||||
if (antSeen) {
|
if (antSeen) window.TarinaiNeedSystem?.addNeedShock?.(this, { safety: 18 }, null);
|
||||||
if (this.enterPanic) this.enterPanic({ target: null, reason: "アリだ!", fear: 1.1, wake: true, cause: "colony_ant_overrun" });
|
|
||||||
else { this.setActionState?.("panic", { target: null, reason: "アリだ!", wake: true }); this.fearTimer = Math.max(this.fearTimer || 0, 1.1 * this.personalityProfile().fear); }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const wasFighting = this.fightTimer > 0.04;
|
const wasFighting = this.fightTimer > 0.04;
|
||||||
this.fightTimer = Math.max(0, this.fightTimer - dt);
|
this.fightTimer = Math.max(0, this.fightTimer - dt);
|
||||||
|
|
@ -378,6 +375,7 @@
|
||||||
if (this.world.resolveFenceCollision) this.world.resolveFenceCollision(this);
|
if (this.world.resolveFenceCollision) this.world.resolveFenceCollision(this);
|
||||||
const sleepingAtFrameEnd = this.state === "sleep" || this.sleeping;
|
const sleepingAtFrameEnd = this.state === "sleep" || this.sleeping;
|
||||||
if (wasSleepingAtFrameStart && !sleepingAtFrameEnd && !this.dead) this.awakeLockTimer = Math.max(this.awakeLockTimer || 0, 10);
|
if (wasSleepingAtFrameStart && !sleepingAtFrameEnd && !this.dead) this.awakeLockTimer = Math.max(this.awakeLockTimer || 0, 10);
|
||||||
|
if (this.needsInitialized && window.TarinaiNeedSystem?.deriveStressFromNeeds) this.stress = window.TarinaiNeedSystem.deriveStressFromNeeds(this.needs || {});
|
||||||
this.checkLife(dt);
|
this.checkLife(dt);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -586,13 +584,11 @@
|
||||||
const pin = this.currentLodgedPin?.() || null;
|
const pin = this.currentLodgedPin?.() || null;
|
||||||
const pinBehavior = this.currentLodgedPinBehavior?.() || null;
|
const pinBehavior = this.currentLodgedPinBehavior?.() || null;
|
||||||
if (pin && pinBehavior?.panicOnAttach) {
|
if (pin && pinBehavior?.panicOnAttach) {
|
||||||
if (this.enterPanic) this.enterPanic({ threat: pin, reason: "画鋲が刺さってパニックになっている", fear: 0.60, hurtTimer: 0.24, awakeLockTimer: 1.8, bubble: "!!", bubbleColor: "rgba(168,72,72,0.82)", cause: "pushpin_stuck" });
|
window.TarinaiNeedSystem?.addNeedShock?.(this, { safety: 45, health: 20 }, pin);
|
||||||
else { this.setActionState?.("panic", { target: this.panicDestination(pin), reason: "画鋲が刺さってパニックになっている", wake: true }); this.fearTimer = Math.max(this.fearTimer || 0, 0.60); }
|
|
||||||
this.hurtTimer = Math.max(this.hurtTimer || 0, 0.24);
|
this.hurtTimer = Math.max(this.hurtTimer || 0, 0.24);
|
||||||
this.awakeLockTimer = Math.max(this.awakeLockTimer || 0, 1.8);
|
this.awakeLockTimer = Math.max(this.awakeLockTimer || 0, 1.8);
|
||||||
this.bubble("!!", 0.9, "rgba(168,72,72,0.82)");
|
this.bubble("!!", 0.9, "rgba(168,72,72,0.82)");
|
||||||
this.thought = "\u753b\u92f2\u304c\u523a\u3055\u3063\u3066\u30d1\u30cb\u30c3\u30af\u306b\u306a\u3063\u3066\u3044\u308b";
|
this.thought = "\u753b\u92f2\u304c\u523a\u3055\u3063\u3066\u3044\u308b";
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
this.stuckPushpinId = null;
|
this.stuckPushpinId = null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -213,6 +213,7 @@ function renderSelected() {
|
||||||
const itemEffectSummary = t.activeItemEffectSummary ? t.activeItemEffectSummary() : [];
|
const itemEffectSummary = t.activeItemEffectSummary ? t.activeItemEffectSummary() : [];
|
||||||
const snapshot = [
|
const snapshot = [
|
||||||
t.id, t.type, t.name, generationDisplay, t.state, t.thought, targetLabel(t.target),
|
t.id, t.type, t.name, generationDisplay, t.state, t.thought, targetLabel(t.target),
|
||||||
|
JSON.stringify(t.needs || {}), JSON.stringify(t.intent || {}),
|
||||||
fmt(t.age), fmt(t.lifeSpan), fmt(t.hunger), fmt(t.loneliness),
|
fmt(t.age), fmt(t.lifeSpan), fmt(t.hunger), fmt(t.loneliness),
|
||||||
fmt(t.energy), fmt(t.stress), fmt(t.mood),
|
fmt(t.energy), fmt(t.stress), fmt(t.mood),
|
||||||
t.parentNames?.join("+") || "", t.children?.length || 0, fmt(t.lack),
|
t.parentNames?.join("+") || "", t.children?.length || 0, fmt(t.lack),
|
||||||
|
|
@ -259,8 +260,6 @@ function renderSelected() {
|
||||||
const basicHtml = `
|
const basicHtml = `
|
||||||
<div class="info-row"><span>\u4e16\u4ee3</span><strong>${escapeHtml(generationDisplay || "\u4e0d\u660e")}</strong></div>
|
<div class="info-row"><span>\u4e16\u4ee3</span><strong>${escapeHtml(generationDisplay || "\u4e0d\u660e")}</strong></div>
|
||||||
<div class="info-row"><span>\u72b6\u614b</span><strong>${escapeHtml(stateLabel(t.state))}</strong></div>
|
<div class="info-row"><span>\u72b6\u614b</span><strong>${escapeHtml(stateLabel(t.state))}</strong></div>
|
||||||
<div class="info-row"><span>\u3044\u307e</span><strong>${escapeHtml(t.intent?.actionLabel || stateLabel(t.state))}</strong></div>
|
|
||||||
<div class="info-row"><span>\u7406\u7531</span><strong>${escapeHtml(t.intent?.reasonText || reasonLabel(t))}</strong></div>
|
|
||||||
<div class="info-row"><span>\u5bfe\u8c61</span><strong>${escapeHtml(targetLabel(t.target))}</strong></div>
|
<div class="info-row"><span>\u5bfe\u8c61</span><strong>${escapeHtml(targetLabel(t.target))}</strong></div>
|
||||||
<div class="info-row"><span>\u5e74\u9f62</span><strong>${fmt(t.age)} / ${fmt(t.lifeSpan)}</strong></div>
|
<div class="info-row"><span>\u5e74\u9f62</span><strong>${fmt(t.age)} / ${fmt(t.lifeSpan)}</strong></div>
|
||||||
<div class="info-row"><span>\u6700\u5927\u5bff\u547d</span><strong>${geneticPercentText(t, "life")}</strong></div>
|
<div class="info-row"><span>\u6700\u5927\u5bff\u547d</span><strong>${geneticPercentText(t, "life")}</strong></div>
|
||||||
|
|
@ -268,7 +267,11 @@ function renderSelected() {
|
||||||
<div class="info-row"><span>\u79fb\u52d5\u901f\u5ea6</span><strong>${geneticPercentText(t, "speed")}</strong></div>
|
<div class="info-row"><span>\u79fb\u52d5\u901f\u5ea6</span><strong>${geneticPercentText(t, "speed")}</strong></div>
|
||||||
<div class="info-row"><span>\u30b5\u30a4\u30ba</span><strong>${geneticSizeText(t)}</strong></div>
|
<div class="info-row"><span>\u30b5\u30a4\u30ba</span><strong>${geneticSizeText(t)}</strong></div>
|
||||||
`;
|
`;
|
||||||
const healthHtml = selectedNeedRowsHtml(t) + selectedInfoRowHtml("\u30b9\u30c8\u30ec\u30b9", fmt(t.stress), "stress");
|
const needsHtml = `
|
||||||
|
${selectedNeedRowsHtml(t)}
|
||||||
|
<div class="info-row"><span>\u3044\u307e</span><strong>${escapeHtml(t.intent?.actionLabel || stateLabel(t.state))}</strong></div>
|
||||||
|
<div class="info-row"><span>\u7406\u7531</span><strong>${escapeHtml(t.intent?.reasonText || reasonLabel(t))}</strong></div>
|
||||||
|
`;
|
||||||
const itemEffectHtml = itemEffectSummary.length
|
const itemEffectHtml = itemEffectSummary.length
|
||||||
? itemEffectSummary.map(e => `<div class="info-row"><span>${escapeHtml(e.label)}</span><strong>${escapeHtml(e.detail)}</strong></div>`).join("")
|
? itemEffectSummary.map(e => `<div class="info-row"><span>${escapeHtml(e.label)}</span><strong>${escapeHtml(e.detail)}</strong></div>`).join("")
|
||||||
: `<div class="info-row"><span>\u30a2\u30a4\u30c6\u30e0\u52b9\u679c</span><strong>\u306a\u3057</strong></div>`;
|
: `<div class="info-row"><span>\u30a2\u30a4\u30c6\u30e0\u52b9\u679c</span><strong>\u306a\u3057</strong></div>`;
|
||||||
|
|
@ -288,7 +291,7 @@ function renderSelected() {
|
||||||
${effectBadges.length ? `<div class="selected-effects">${effectBadges.join("")}</div>` : ""}
|
${effectBadges.length ? `<div class="selected-effects">${effectBadges.join("")}</div>` : ""}
|
||||||
<div class="selected-data-groups">
|
<div class="selected-data-groups">
|
||||||
${selectedDataCategoryHtml("basic", "\u57fa\u672c", basicHtml)}
|
${selectedDataCategoryHtml("basic", "\u57fa\u672c", basicHtml)}
|
||||||
${selectedDataCategoryHtml("health", "\u4f53\u8abf", healthHtml)}
|
${selectedDataCategoryHtml("needs", "\u30cb\u30fc\u30ba", needsHtml)}
|
||||||
${selectedDataCategoryHtml("effects", "\u30a2\u30a4\u30c6\u30e0\u52b9\u679c", itemEffectHtml)}
|
${selectedDataCategoryHtml("effects", "\u30a2\u30a4\u30c6\u30e0\u52b9\u679c", itemEffectHtml)}
|
||||||
${selectedDataCategoryHtml("personality", "\u6027\u683c", personalityHtml)}
|
${selectedDataCategoryHtml("personality", "\u6027\u683c", personalityHtml)}
|
||||||
${selectedDataCategoryHtml("relation", "\u95a2\u4fc2", relationHtml)}
|
${selectedDataCategoryHtml("relation", "\u95a2\u4fc2", relationHtml)}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue