hm
This commit is contained in:
parent
129c07183a
commit
5ed977788c
49 changed files with 1084 additions and 392 deletions
71
js/health.js
71
js/health.js
|
|
@ -11,6 +11,9 @@ const HEALTH = (() => {
|
|||
poke: "\u3064\u3064\u304b\u308c\u3059\u304e",
|
||||
firecracker: "\u7206\u7af9",
|
||||
genkotsu: "\u3052\u3093\u3053\u3064",
|
||||
shooting: "射撃",
|
||||
stoneCrush: "石に潰された",
|
||||
weakness: "衰弱",
|
||||
poisonBlock: "毒ブロック",
|
||||
accident: "\u4e8b\u6545",
|
||||
collision: "\u885d\u7a81",
|
||||
|
|
@ -30,6 +33,10 @@ const HEALTH = (() => {
|
|||
const text = String(reason || "");
|
||||
if (!text) return "";
|
||||
if (text.includes(WEAKENED_SUFFIX)) return text.replace(/\u3067\u8870\u5f31.*$/, "");
|
||||
if (/射撃|shoot/.test(text)) return CAUSES.shooting;
|
||||
if (/石に潰された|石.*潰|stone.*crush|crushed.*stone/.test(text)) return CAUSES.stoneCrush;
|
||||
const collisionWith = text.match(/([^、。\s]+)に衝突/);
|
||||
if (collisionWith) return `${collisionWith[1]}に衝突`;
|
||||
if (/\u55a7\u5629|fight|headbutt/.test(text)) return CAUSES.fight;
|
||||
if (/\u3052\u3093\u3053\u3064|genkotsu/.test(text)) return CAUSES.genkotsu;
|
||||
if (/毒ブロック|poison.?block/.test(text)) return CAUSES.poisonBlock;
|
||||
|
|
@ -37,7 +44,7 @@ const HEALTH = (() => {
|
|||
if (/\u77ee\u5c0f\u85ac|dwarf/.test(text)) return CAUSES.dwarfDrug;
|
||||
if (/\u7206\u7af9|firecracker|explosion/.test(text)) return CAUSES.firecracker;
|
||||
if (/\u4ed5\u69d8\u306b\u3088\u308a\u753b\u9762\u5916\u3067\u524a\u9664|\u753b\u9762\u5916\u3067\u524a\u9664|out.*bounds|offscreen/.test(text)) return CAUSES.outOfBounds;
|
||||
if (/\u885d\u7a81|collision/.test(text)) return CAUSES.collision;
|
||||
if (/\u885d\u7a81|collision|急激な速度変化/.test(text)) return CAUSES.collision;
|
||||
if (/\u3064\u3064\u304b\u308c|\u3064\u3064\u304d|poke/.test(text)) return CAUSES.poke;
|
||||
if (/\u306d\u3080\u308a\u75c5|sleep.*disease/.test(text)) return CAUSES.sleepDisease;
|
||||
if (/\u7206\u767a\u75c5|explosion.*disease/.test(text)) return CAUSES.explosionDisease;
|
||||
|
|
@ -50,7 +57,8 @@ const HEALTH = (() => {
|
|||
}
|
||||
if (/\u98e2|\u7a7a\u8179|\u98df\u3079\u7269|hunger/.test(text)) return CAUSES.hunger;
|
||||
if (/\u30b9\u30c8\u30ec\u30b9|stress/.test(text)) return CAUSES.stress;
|
||||
if (/\u30dc\u30fc\u30eb|\u843d\u3061|\u843d\u4e0b|\u77f3|\u9053\u5177|\u4e8b\u6545|\u5f53\u305f|ball|drop|stone|accident/.test(text)) return CAUSES.accident;
|
||||
if (/\u77f3|stone/.test(text)) return CAUSES.stoneCrush;
|
||||
if (/\u30dc\u30fc\u30eb|\u843d\u3061|\u843d\u4e0b|\u9053\u5177|\u4e8b\u6545|\u5f53\u305f|ball|drop|accident/.test(text)) return CAUSES.accident;
|
||||
if (/\u5bff\u547d|\u5929\u5bff/.test(text)) return CAUSES.lifespan;
|
||||
return "";
|
||||
}
|
||||
|
|
@ -96,24 +104,33 @@ const HEALTH = (() => {
|
|||
const recentMajor = hasRecentMajorDamage(t);
|
||||
const recent = recentDamageCause(t, 20);
|
||||
const fighting = isFightingContext(t, recent);
|
||||
if (recentMajor && t.lastMajorDamageCause === CAUSES.collision) return CAUSES.collision;
|
||||
if (recentMajor && (!direct || direct === t.lastMajorDamageCause || opts.fromDamage || t.energy <= 18 || t.mood <= 16 || t.stress >= 124 || t.hunger >= 112)) {
|
||||
|
||||
// Direct damage death: use the immediate/direct source, not a weakened suffix.
|
||||
if (opts.fromDamage) {
|
||||
if (direct) return direct;
|
||||
if (recentMajor && t.lastMajorDamageCause) return t.lastMajorDamageCause;
|
||||
if (recent) return recent;
|
||||
return CAUSES.accident;
|
||||
}
|
||||
|
||||
if (recentMajor && t.lastMajorDamageCause === CAUSES.collision && !(t.energy <= 20 || t.mood <= 16 || t.stress >= 124 || t.hunger >= 112)) return CAUSES.collision;
|
||||
if (recentMajor && (!direct || direct === t.lastMajorDamageCause || t.energy <= 18 || t.mood <= 16 || t.stress >= 124 || t.hunger >= 112)) {
|
||||
return weakenedDeathReasonFor(t.lastMajorDamageCause);
|
||||
}
|
||||
const weakenedTrace = recentDamageCause(t, WEAKENED_TRACE_WINDOW);
|
||||
const traceCanWeaken = weakenedTrace && weakenedTrace !== CAUSES.stress && weakenedTrace !== CAUSES.hunger && weakenedTrace !== CAUSES.lifespan && weakenedTrace !== CAUSES.outOfBounds;
|
||||
if (traceCanWeaken && (!direct || direct === CAUSES.stress || direct === CAUSES.hunger || direct === weakenedTrace || opts.fromDamage) && (t.energy <= 20 || t.mood <= 16 || t.stress >= 124 || t.hunger >= 114)) {
|
||||
if (traceCanWeaken && (!direct || direct === CAUSES.stress || direct === CAUSES.hunger || direct === weakenedTrace) && (t.energy <= 20 || t.mood <= 16 || t.stress >= 124 || t.hunger >= 114)) {
|
||||
return weakenedDeathReasonFor(weakenedTrace);
|
||||
}
|
||||
if (direct && direct !== CAUSES.stress) return direct;
|
||||
if (t.zunchiDisease && ((t.zunchiDiseaseSeverity || 0) >= 0.30 || /\u75c5|zunchi/.test(text))) return CAUSES.zunchiDisease;
|
||||
if (t.hunger >= 108 || (t.hunger >= 94 && t.energy <= 26) || /\u98e2|\u7a7a\u8179|hunger/.test(text)) return CAUSES.hunger;
|
||||
if (fighting && (t.energy <= 44 || t.stress >= 112 || t.mood <= 22 || opts.fromDamage)) return CAUSES.fight;
|
||||
if (recent && recent !== CAUSES.stress && (t.energy <= 22 || t.mood <= 14 || t.stress >= 126 || opts.fromDamage)) return weakenedDeathReasonFor(recent);
|
||||
if (fighting && (t.energy <= 44 || t.stress >= 112 || t.mood <= 22)) return CAUSES.fight;
|
||||
if (recent && recent !== CAUSES.stress && (t.energy <= 22 || t.mood <= 14 || t.stress >= 126)) return weakenedDeathReasonFor(recent);
|
||||
if (text.includes(CAUSES.lifespan) || text.includes("\u5bff\u547d")) return CAUSES.lifespan;
|
||||
if (direct) return direct;
|
||||
if (t.stress >= 118 || /\u30b9\u30c8\u30ec\u30b9|stress|\u6c17\u5206/.test(text)) return CAUSES.stress;
|
||||
if (t.energy <= 0.5) return CAUSES.accident;
|
||||
if (opts.lowHealth || t.energy <= 0.5) return CAUSES.weakness;
|
||||
return "";
|
||||
}
|
||||
|
||||
|
|
@ -122,11 +139,42 @@ const HEALTH = (() => {
|
|||
if (text.includes(WEAKENED_SUFFIX)) return text;
|
||||
const cause = dominantDeathCause(t, text, opts) || CAUSES.accident;
|
||||
if (cause.includes(WEAKENED_SUFFIX)) return cause;
|
||||
const canWeaken = cause && !cause.endsWith("\u75c5") && cause !== CAUSES.hunger && cause !== CAUSES.stress && cause !== CAUSES.lifespan && cause !== CAUSES.outOfBounds && cause !== CAUSES.collision && cause !== CAUSES.genkotsu;
|
||||
if (opts.fromDamage) return cause;
|
||||
const canWeaken = cause && !cause.endsWith("\u75c5") && cause !== CAUSES.hunger && cause !== CAUSES.stress && cause !== CAUSES.lifespan && cause !== CAUSES.outOfBounds && cause !== CAUSES.collision && cause !== CAUSES.genkotsu && cause !== CAUSES.weakness;
|
||||
if (canWeaken && (opts.weakened || (hasRecentMajorDamage(t) && cause === t.lastMajorDamageCause))) return weakenedDeathReasonFor(cause);
|
||||
return cause;
|
||||
}
|
||||
|
||||
|
||||
function maybeReleaseZunchiFromDamage(t, actualLoss = 0, cause = "") {
|
||||
if (!t || !t.world || t.dead) return false;
|
||||
const loss = Math.max(0, Number(actualLoss) || 0);
|
||||
if (loss <= 0.1) return false;
|
||||
const now = t.world.time || 0;
|
||||
if (now < Number(t.nextDamageZunchiAt || -999)) return false;
|
||||
const probability = Math.max(0.06, Math.min(0.82, 0.06 + loss / 48));
|
||||
if (Math.random() >= probability) return false;
|
||||
t.nextDamageZunchiAt = now + Math.max(0.55, 1.55 - Math.min(0.9, loss / 38));
|
||||
if (t.hasLodgedPinEffect?.("blocksZunchi")) {
|
||||
t.oshiriByoZunchiStock = Math.min(24, Math.max(0, t.oshiriByoZunchiStock || 0) + 1);
|
||||
t.thought = "ダメージでずんちを我慢している";
|
||||
return false;
|
||||
}
|
||||
const side = t.facingDir ? t.facingDir() : (t.facing || 1);
|
||||
const jitter = (Math.random() - 0.5) * Math.max(4, (t.radius || 22) * 0.25);
|
||||
const x = t.x - side * (t.radius || 22) * (0.72 + Math.random() * 0.24);
|
||||
const y = t.y + (t.radius || 22) * (0.24 + Math.random() * 0.25) + jitter;
|
||||
t.world.spawnZunchi?.(x, y, t);
|
||||
t.poopCount = (t.poopCount || 0) + 1;
|
||||
t.digest = Math.max(0, Number(t.digest || 0) - 1.0);
|
||||
t.nextPoopBubbleAt = now + 2.0;
|
||||
t.bubble?.("ぶりゅっ", 1.1, "rgba(74,91,50,0.78)", { force: true });
|
||||
if (now > Number(t.nextDamageZunchiLogAt || -999)) {
|
||||
t.nextDamageZunchiLogAt = now + 10;
|
||||
t.world.log?.(`${t.name}はダメージでずんちを放出した。`, "accident", { participants: [t] });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function applyDamage(t, amount, reason = "") {
|
||||
const maxEnergy = typeof tarinaiMaxEnergy === "function" ? tarinaiMaxEnergy(t) : (Number(t.maxEnergy) || 100);
|
||||
t.maxEnergy = maxEnergy;
|
||||
|
|
@ -142,14 +190,14 @@ const HEALTH = (() => {
|
|||
if (plushie && actualLoss >= 1) plushie.damage(actualLoss, t.world, null);
|
||||
if (cause === CAUSES.fight || /\u55a7\u5629|fight/.test(String(reason || ""))) t.recordBleedExposure();
|
||||
audio.damage?.(actualLoss);
|
||||
maybeReleaseZunchiFromDamage(t, actualLoss, cause || reason);
|
||||
if (t.sleepDisease) t.recoverSleepDisease("\u30c0\u30e1\u30fc\u30b8\u3067\u306d\u3080\u308a\u75c5\u304c\u6cbb\u3063\u305f");
|
||||
if (t.wakeFromDamage) t.wakeFromDamage(cause || reason);
|
||||
if (t.maybeBecomeTimidAfterDamage) t.maybeBecomeTimidAfterDamage(cause || reason);
|
||||
t.showHpBar();
|
||||
}
|
||||
if (t.energy <= 0.5) {
|
||||
const majorNow = actualLoss >= Math.max(10, before * 0.42);
|
||||
t.die(normalizeDeathReason(t, reason || cause, { fromDamage: true, weakened: majorNow }));
|
||||
t.die(normalizeDeathReason(t, reason || cause, { fromDamage: true }));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -172,6 +220,7 @@ const HEALTH = (() => {
|
|||
normalizeDeathReason,
|
||||
applyDamage,
|
||||
briefDeathReason,
|
||||
maybeReleaseZunchiFromDamage,
|
||||
});
|
||||
})();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue