y
This commit is contained in:
parent
61718e2981
commit
f657b6a4a4
94 changed files with 3970 additions and 1241 deletions
|
|
@ -4,13 +4,54 @@
|
|||
const Tarinai = global.Tarinai;
|
||||
if (!Tarinai) throw new Error("Tarinai is not available for mixin: tarinai_identity_social.js");
|
||||
|
||||
function relationIdSetFor(tarinai) {
|
||||
const ids = new Set(Object.keys(tarinai?.relationships || {}));
|
||||
for (const other of tarinai?.world?.tarinai || []) {
|
||||
if (!other || other === tarinai || !other.id) continue;
|
||||
if (other.relationships?.[tarinai.id]) ids.add(other.id);
|
||||
const relationPeerCache = new WeakMap();
|
||||
|
||||
function relationPeerEntry(tarinai) {
|
||||
const relationships = tarinai?.relationships || {};
|
||||
let entry = relationPeerCache.get(tarinai);
|
||||
if (!entry || entry.relationships !== relationships) {
|
||||
const keys = Object.keys(relationships);
|
||||
entry = { relationships, ids: new Set(keys), ownCount: keys.length, incomingBuilt: false };
|
||||
relationPeerCache.set(tarinai, entry);
|
||||
}
|
||||
return ids;
|
||||
return entry;
|
||||
}
|
||||
|
||||
function dropRelationPeerId(tarinai, id) {
|
||||
if (!tarinai || !id) return false;
|
||||
const relationships = tarinai.relationships && typeof tarinai.relationships === "object" ? tarinai.relationships : null;
|
||||
const entry = relationPeerCache.get(tarinai);
|
||||
let removed = false;
|
||||
if (relationships && Object.prototype.hasOwnProperty.call(relationships, id)) {
|
||||
delete relationships[id];
|
||||
removed = true;
|
||||
}
|
||||
if (entry) {
|
||||
entry.ids.delete(id);
|
||||
if (removed) entry.ownCount = Math.max(0, (entry.ownCount || 0) - 1);
|
||||
}
|
||||
if (removed) tarinai.relationCache = null;
|
||||
return removed;
|
||||
}
|
||||
|
||||
function lazyDropDeadRelationPeer(tarinai, id) {
|
||||
const pending = tarinai?.world?._deadTarinaiIdsPendingCleanup;
|
||||
if (!(pending instanceof Set) || pending.size === 0 || !pending.has(id)) return false;
|
||||
if (tarinai.world?.liveTarinaiById?.(id)) return false;
|
||||
dropRelationPeerId(tarinai, id);
|
||||
return true;
|
||||
}
|
||||
|
||||
function relationIdSetFor(tarinai) {
|
||||
const entry = relationPeerEntry(tarinai);
|
||||
if (!entry.incomingBuilt) {
|
||||
for (const other of tarinai?.world?.tarinai || []) {
|
||||
if (!other || other.dead || other === tarinai || !other.id) continue;
|
||||
if (other.relationships?.[tarinai.id]) entry.ids.add(other.id);
|
||||
}
|
||||
entry.incomingBuilt = true;
|
||||
}
|
||||
return entry.ids;
|
||||
}
|
||||
|
||||
Object.defineProperties(Tarinai.prototype, Object.getOwnPropertyDescriptors({
|
||||
|
|
@ -169,6 +210,7 @@
|
|||
this.surpriseTimer = Math.max(this.surpriseTimer || 0, 0.65);
|
||||
this.focusPulseTimer = Math.max(this.focusPulseTimer || 0, 1.0);
|
||||
if (boosted.length) this.recordChangeCause?.("\u305F\u308A\u306A\u3044\u738B\u8005", boosted.join("\u30FB"), { value: +1 });
|
||||
this.world?.syncTarinaiCountEntry?.(this);
|
||||
this.world?.recordFamily?.(this);
|
||||
return true;
|
||||
},
|
||||
|
|
@ -188,11 +230,30 @@
|
|||
|
||||
relationTo(id) {
|
||||
if (!id) return relationDefaults();
|
||||
const pendingDead = this.world?._deadTarinaiIdsPendingCleanup;
|
||||
if (pendingDead instanceof Set && pendingDead.size > 0 && pendingDead.has(id) && !this.world?.liveTarinaiById?.(id)) {
|
||||
dropRelationPeerId(this, id);
|
||||
return relationDefaults();
|
||||
}
|
||||
if (!this.relationships) this.relationships = {};
|
||||
if (!this.relationships[id]) this.relationships[id] = relationDefaults();
|
||||
if (!this.relationships[id]) {
|
||||
this.relationships[id] = relationDefaults();
|
||||
const entry = relationPeerEntry(this);
|
||||
entry.ids.add(id);
|
||||
entry.ownCount = (entry.ownCount || 0) + 1;
|
||||
const other = this.world?.liveTarinaiById?.(id) || null;
|
||||
if (other) relationPeerEntry(other).ids.add(this.id);
|
||||
}
|
||||
return this.relationships[id];
|
||||
},
|
||||
|
||||
pruneDeadRelationshipRefs(deadIds) {
|
||||
if (!(deadIds instanceof Set) || deadIds.size === 0) return 0;
|
||||
let removed = 0;
|
||||
for (const id of deadIds) if (dropRelationPeerId(this, id)) removed += 1;
|
||||
return removed;
|
||||
},
|
||||
|
||||
adjustRelation(other, affinityDelta = 0, fearDelta = 0, event = "") {
|
||||
if (!other || !other.id || other === this) return;
|
||||
const rel = this.relationTo(other.id);
|
||||
|
|
@ -217,9 +278,12 @@
|
|||
let bestId = null;
|
||||
let bestScore = kind === "fear" ? 5 : FRIEND_AFFINITY_THRESHOLD;
|
||||
for (const id of relationIdSetFor(this)) {
|
||||
const rel = this.relationships?.[id] || relationDefaults();
|
||||
if (liveOnly && (!this.world?.liveTarinaiById?.(id) || id === this.id)) continue;
|
||||
const other = this.world?.liveTarinaiById?.(id) || null;
|
||||
if (liveOnly && (!other || id === this.id)) {
|
||||
if (!other) lazyDropDeadRelationPeer(this, id);
|
||||
continue;
|
||||
}
|
||||
const rel = this.relationships?.[id] || relationDefaults();
|
||||
const reverse = kind === "fear" ? null : (other?.relationships?.[this.id] || null);
|
||||
const score = kind === "fear" ? (rel.fear || 0) : Math.max(rel.affinity || 0, reverse?.affinity || 0);
|
||||
if (score > bestScore) { bestId = id; bestScore = score; }
|
||||
|
|
@ -239,11 +303,14 @@
|
|||
if (this.relationCache?.friendCountKey === cacheKey && now < (this.relationCache.friendCountUntil || 0)) return this.relationCache.friendCount;
|
||||
let count = 0;
|
||||
for (const id of relationIdSetFor(this)) {
|
||||
const rel = this.relationships?.[id] || relationDefaults();
|
||||
const other = this.world?.liveTarinaiById?.(id) || null;
|
||||
if (liveOnly && (!other || id === this.id)) {
|
||||
if (!other) lazyDropDeadRelationPeer(this, id);
|
||||
continue;
|
||||
}
|
||||
const rel = this.relationships?.[id] || relationDefaults();
|
||||
const reverse = other?.relationships?.[this.id] || null;
|
||||
if (Math.max(rel.affinity || 0, reverse?.affinity || 0) <= minScore) continue;
|
||||
if (liveOnly && (!other || id === this.id)) continue;
|
||||
count += 1;
|
||||
}
|
||||
this.relationCache = { ...(this.relationCache || {}), friendCountKey: cacheKey, friendCount: count, friendCountUntil: now + 1.4 };
|
||||
|
|
@ -264,12 +331,15 @@
|
|||
}
|
||||
let best = null, bestScore = minScore;
|
||||
for (const id of relationIdSetFor(this)) {
|
||||
const rel = this.relationships?.[id] || relationDefaults();
|
||||
const t = this.world.liveTarinaiById?.(id) || null;
|
||||
if (!t) {
|
||||
lazyDropDeadRelationPeer(this, id);
|
||||
continue;
|
||||
}
|
||||
const rel = this.relationships?.[id] || relationDefaults();
|
||||
const reverse = t?.relationships?.[this.id] || null;
|
||||
const score = Math.max(rel.affinity || 0, reverse?.affinity || 0);
|
||||
if (score <= bestScore) continue;
|
||||
if (!t) continue;
|
||||
if (Number.isFinite(maxDist) && dist(this, t) > maxDist) continue;
|
||||
best = t;
|
||||
bestScore = score;
|
||||
|
|
@ -286,7 +356,10 @@
|
|||
if (this.world.time - when > maxAge) continue;
|
||||
if (!(event.includes("fight") || event.includes("\u55a7\u5629") || (rel.fightsWon || 0) || (rel.fightsLost || 0))) continue;
|
||||
const t = this.world.liveTarinaiById?.(id) || null;
|
||||
if (!t) continue;
|
||||
if (!t) {
|
||||
lazyDropDeadRelationPeer(this, id);
|
||||
continue;
|
||||
}
|
||||
if (Number.isFinite(maxDist) && dist(this, t) > maxDist) continue;
|
||||
if (when > bestT) { best = t; bestT = when; }
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue