@kevin5251984/guild 0.2.12 → 0.2.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +10 -8
- package/src/catalog/subagents.ts +1 -2
- package/src/chat-parts.ts +1 -6
- package/src/generate.ts +27 -55
- package/src/handlers.ts +6 -183
- package/src/harness.ts +8 -21
- package/src/image-gen.ts +1 -2
- package/src/llm.ts +7 -14
- package/src/mention.ts +12 -63
- package/src/oauth.ts +27 -131
- package/src/public/chat.css +7 -102
- package/src/public/chat.html +48 -190
- package/src/public/i18n.js +6 -18
- package/src/public/index.html +46 -1
- package/src/public/settings.html +1 -2
- package/src/public/skills-add.html +0 -8
- package/src/public/studio.html +117 -171
- package/src/public/style.css +77 -249
- package/src/public/subagents-add.html +0 -8
- package/src/router.ts +0 -11
- package/src/store.ts +0 -14
- package/src/subagent.ts +6 -203
- package/src/tools.ts +18 -117
- package/src/trajectory.ts +5 -51
- package/src/usage.ts +0 -10
- package/vendor/protocol/src/index.ts +1 -4
- package/src/public/buddy.js +0 -432
|
@@ -95,12 +95,7 @@
|
|
|
95
95
|
return;
|
|
96
96
|
}
|
|
97
97
|
const button = document.getElementById("ai-generate");
|
|
98
|
-
if (button.disabled || button.getAttribute("aria-busy") === "true") return;
|
|
99
98
|
button.disabled = true;
|
|
100
|
-
button.setAttribute("aria-busy", "true");
|
|
101
|
-
button.classList.add("is-busy");
|
|
102
|
-
const idle = button.textContent;
|
|
103
|
-
button.textContent = t("studio.generating");
|
|
104
99
|
try {
|
|
105
100
|
const response = await fetch("/generate", {
|
|
106
101
|
method: "POST",
|
|
@@ -120,9 +115,6 @@
|
|
|
120
115
|
);
|
|
121
116
|
} finally {
|
|
122
117
|
button.disabled = false;
|
|
123
|
-
button.removeAttribute("aria-busy");
|
|
124
|
-
button.classList.remove("is-busy");
|
|
125
|
-
button.textContent = idle;
|
|
126
118
|
}
|
|
127
119
|
});
|
|
128
120
|
|
package/src/public/studio.html
CHANGED
|
@@ -51,32 +51,24 @@
|
|
|
51
51
|
</div>
|
|
52
52
|
<div class="rpg-scene is-inn" id="scene-inn" hidden>
|
|
53
53
|
<div class="inn-map">
|
|
54
|
-
<div class="inn-wall">
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
<div class="inn-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
</div>
|
|
64
|
-
<div class="inn-nook inn-nook-r">
|
|
65
|
-
<div class="inn-bar"></div>
|
|
66
|
-
<div class="inn-bottles" id="inn-bottles"></div>
|
|
67
|
-
</div>
|
|
54
|
+
<div class="inn-wall"></div>
|
|
55
|
+
<div class="inn-rail"></div>
|
|
56
|
+
<div class="inn-bar"></div>
|
|
57
|
+
<div class="inn-bottles" id="inn-bottles"></div>
|
|
58
|
+
<div class="inn-table t1"></div>
|
|
59
|
+
<div class="inn-table t2"></div>
|
|
60
|
+
<div class="inn-barrel b1"></div>
|
|
61
|
+
<div class="inn-barrel b2"></div>
|
|
62
|
+
<div class="inn-hearth"></div>
|
|
68
63
|
<div class="inn-actors" id="inn-actors"></div>
|
|
69
64
|
</div>
|
|
70
65
|
<button type="button" class="rpg-exit" id="leave-inn" data-i18n="studio.leave">出門</button>
|
|
71
66
|
</div>
|
|
72
67
|
<div class="rpg-dialog" id="rpg-dialog">
|
|
73
68
|
<div class="rpg-dialog-inner">
|
|
74
|
-
<
|
|
75
|
-
<
|
|
76
|
-
|
|
77
|
-
<p class="rpg-line" id="rpg-line">夜晚的編制還開著。點那扇門進去。</p>
|
|
78
|
-
<div class="rpg-acts" id="rpg-acts"></div>
|
|
79
|
-
</div>
|
|
69
|
+
<div class="rpg-name" id="rpg-name">酒館</div>
|
|
70
|
+
<p class="rpg-line" id="rpg-line">夜晚的編制還開著。點那扇門進去。</p>
|
|
71
|
+
<div class="rpg-acts" id="rpg-acts"></div>
|
|
80
72
|
</div>
|
|
81
73
|
</div>
|
|
82
74
|
</div>
|
|
@@ -96,7 +88,6 @@
|
|
|
96
88
|
<input name="oneLiner" placeholder="這名冒險者在編制裡做什麼" data-i18n-placeholder="studio.oneLinerPh" />
|
|
97
89
|
<div class="card-foot">
|
|
98
90
|
<button type="button" class="ghost danger" id="delete-bot" hidden data-i18n="bot.delete">請這名冒險者離席</button>
|
|
99
|
-
<button type="button" class="ghost" id="gen-look" hidden data-i18n="studio.genLook">生成形象</button>
|
|
100
91
|
<div class="save-row">
|
|
101
92
|
<p class="block-flash" hidden></p>
|
|
102
93
|
<button type="button" class="save-md" data-save="identity" hidden>儲存名字</button>
|
|
@@ -192,7 +183,7 @@
|
|
|
192
183
|
let openId = "";
|
|
193
184
|
let activeTags = new Set();
|
|
194
185
|
let showAllSkills = false;
|
|
195
|
-
let rpgTalk = { name: "", line: "", acts: ""
|
|
186
|
+
let rpgTalk = { name: "", line: "", acts: "" };
|
|
196
187
|
const PICKED = "__picked__";
|
|
197
188
|
const REST_CAP = 12;
|
|
198
189
|
|
|
@@ -206,8 +197,6 @@
|
|
|
206
197
|
document.title = t("studio.editDocTitle");
|
|
207
198
|
submit.hidden = true;
|
|
208
199
|
document.getElementById("delete-bot").hidden = false;
|
|
209
|
-
document.getElementById("gen-look").hidden = false;
|
|
210
|
-
document.getElementById("gen-look").textContent = t("studio.genLook");
|
|
211
200
|
mdSaves.forEach((btn) => {
|
|
212
201
|
btn.hidden = false;
|
|
213
202
|
const kind = btn.getAttribute("data-save");
|
|
@@ -223,7 +212,6 @@
|
|
|
223
212
|
submit.hidden = false;
|
|
224
213
|
submit.textContent = t("studio.seat");
|
|
225
214
|
document.getElementById("delete-bot").hidden = true;
|
|
226
|
-
document.getElementById("gen-look").hidden = true;
|
|
227
215
|
document.title = t("title.studio");
|
|
228
216
|
mdSaves.forEach((btn) => {
|
|
229
217
|
btn.hidden = true;
|
|
@@ -250,24 +238,6 @@
|
|
|
250
238
|
function setBlockFlash(block, kind, text) {
|
|
251
239
|
setNodeFlash(block && block.querySelector(".gen-row .block-flash"), kind, text);
|
|
252
240
|
}
|
|
253
|
-
function beginBusy(button, label) {
|
|
254
|
-
if (!button || button.disabled || button.getAttribute("aria-busy") === "true") {
|
|
255
|
-
return false;
|
|
256
|
-
}
|
|
257
|
-
button.dataset.idleLabel = button.textContent;
|
|
258
|
-
button.disabled = true;
|
|
259
|
-
button.setAttribute("aria-busy", "true");
|
|
260
|
-
button.classList.add("is-busy");
|
|
261
|
-
if (label) button.textContent = label;
|
|
262
|
-
return true;
|
|
263
|
-
}
|
|
264
|
-
function endBusy(button, label) {
|
|
265
|
-
if (!button) return;
|
|
266
|
-
button.disabled = false;
|
|
267
|
-
button.removeAttribute("aria-busy");
|
|
268
|
-
button.classList.remove("is-busy");
|
|
269
|
-
button.textContent = label || button.dataset.idleLabel || button.textContent;
|
|
270
|
-
}
|
|
271
241
|
function saveFlashEl(kind) {
|
|
272
242
|
const btn = document.querySelector('.save-md[data-save="' + kind + '"]');
|
|
273
243
|
return btn && btn.parentElement ? btn.parentElement.querySelector(".block-flash") : null;
|
|
@@ -577,7 +547,8 @@
|
|
|
577
547
|
setNodeFlash(flashEl, "error", t("studio.emptyLib"));
|
|
578
548
|
return;
|
|
579
549
|
}
|
|
580
|
-
|
|
550
|
+
button.disabled = true;
|
|
551
|
+
button.textContent = t("studio.picking");
|
|
581
552
|
try {
|
|
582
553
|
const response = await fetch("/generate/skills", {
|
|
583
554
|
method: "POST",
|
|
@@ -626,7 +597,8 @@
|
|
|
626
597
|
} catch (err) {
|
|
627
598
|
setNodeFlash(flashEl, "error", err.message);
|
|
628
599
|
} finally {
|
|
629
|
-
|
|
600
|
+
button.disabled = false;
|
|
601
|
+
button.textContent = t("studio.pickSkills");
|
|
630
602
|
}
|
|
631
603
|
});
|
|
632
604
|
document.getElementById("skill-search").addEventListener("input", () => {
|
|
@@ -716,7 +688,8 @@
|
|
|
716
688
|
setBlockFlash(block, "error", t("studio.needPrompt", { kind: kind }));
|
|
717
689
|
return;
|
|
718
690
|
}
|
|
719
|
-
|
|
691
|
+
button.disabled = true;
|
|
692
|
+
button.textContent = t("studio.generating");
|
|
720
693
|
try {
|
|
721
694
|
const response = await fetch("/generate", {
|
|
722
695
|
method: "POST",
|
|
@@ -756,7 +729,8 @@
|
|
|
756
729
|
} catch (err) {
|
|
757
730
|
setBlockFlash(block, "error", err.message);
|
|
758
731
|
} finally {
|
|
759
|
-
|
|
732
|
+
button.disabled = false;
|
|
733
|
+
button.textContent = t("studio.genMd");
|
|
760
734
|
}
|
|
761
735
|
});
|
|
762
736
|
});
|
|
@@ -913,29 +887,80 @@
|
|
|
913
887
|
const roster = await fetch("/bots").then((r) => r.json());
|
|
914
888
|
renderBar(Array.isArray(roster) ? roster : []);
|
|
915
889
|
setScene("inn");
|
|
916
|
-
talk(body.name, t("studio.hireToast"), npcActs(body)
|
|
890
|
+
talk(body.name, t("studio.hireToast"), npcActs(body));
|
|
917
891
|
});
|
|
918
892
|
|
|
893
|
+
function seedOf(key) {
|
|
894
|
+
let n = 0;
|
|
895
|
+
for (const ch of key) n = (n + ch.charCodeAt(0) * 17) % 997;
|
|
896
|
+
return n;
|
|
897
|
+
}
|
|
898
|
+
function shirtColor(key) {
|
|
899
|
+
return COLORS[seedOf(key) % COLORS.length];
|
|
900
|
+
}
|
|
901
|
+
function px(ctx, x, y, w, h, color) {
|
|
902
|
+
ctx.fillStyle = color;
|
|
903
|
+
ctx.fillRect(x, y, w, h);
|
|
904
|
+
}
|
|
905
|
+
function drawBuddy(canvas, shirt, seed) {
|
|
906
|
+
const ctx = canvas.getContext("2d");
|
|
907
|
+
canvas.width = 16;
|
|
908
|
+
canvas.height = 24;
|
|
909
|
+
ctx.imageSmoothingEnabled = false;
|
|
910
|
+
const skin = ["#f0c8a0", "#e2b184", "#c68642", "#8d5524"][seed % 4];
|
|
911
|
+
const hair = ["#2a1c12", "#c4a35a", "#1a1a1a", "#6b2d3c", "#3c4a6e"][seed % 5];
|
|
912
|
+
const outline = "#1b1510";
|
|
913
|
+
const pants = "#2a3140";
|
|
914
|
+
const style = seed % 3;
|
|
915
|
+
px(ctx, 4, 12, 8, 7, outline);
|
|
916
|
+
px(ctx, 5, 13, 6, 5, shirt);
|
|
917
|
+
px(ctx, 3, 13, 2, 5, shirt);
|
|
918
|
+
px(ctx, 11, 13, 2, 5, shirt);
|
|
919
|
+
px(ctx, 3, 18, 2, 1, skin);
|
|
920
|
+
px(ctx, 11, 18, 2, 1, skin);
|
|
921
|
+
px(ctx, 4, 4, 8, 8, outline);
|
|
922
|
+
px(ctx, 5, 5, 6, 6, skin);
|
|
923
|
+
px(ctx, 6, 7, 1, 1, outline);
|
|
924
|
+
px(ctx, 9, 7, 1, 1, outline);
|
|
925
|
+
if (style === 0) {
|
|
926
|
+
px(ctx, 4, 3, 8, 3, hair);
|
|
927
|
+
px(ctx, 4, 5, 2, 3, hair);
|
|
928
|
+
px(ctx, 10, 5, 2, 3, hair);
|
|
929
|
+
} else if (style === 1) {
|
|
930
|
+
px(ctx, 4, 2, 8, 4, hair);
|
|
931
|
+
px(ctx, 3, 5, 2, 4, hair);
|
|
932
|
+
px(ctx, 11, 5, 2, 4, hair);
|
|
933
|
+
} else {
|
|
934
|
+
px(ctx, 5, 2, 6, 2, hair);
|
|
935
|
+
px(ctx, 4, 4, 8, 2, hair);
|
|
936
|
+
px(ctx, 7, 1, 2, 2, hair);
|
|
937
|
+
}
|
|
938
|
+
px(ctx, 5, 19, 3, 4, pants);
|
|
939
|
+
px(ctx, 8, 19, 3, 4, pants);
|
|
940
|
+
px(ctx, 5, 23, 3, 1, outline);
|
|
941
|
+
px(ctx, 8, 23, 3, 1, outline);
|
|
942
|
+
}
|
|
943
|
+
const SPOTS = [
|
|
944
|
+
[22, 38],
|
|
945
|
+
[36, 34],
|
|
946
|
+
[50, 40],
|
|
947
|
+
[64, 36],
|
|
948
|
+
[26, 54],
|
|
949
|
+
[42, 58],
|
|
950
|
+
[58, 52],
|
|
951
|
+
[74, 56],
|
|
952
|
+
];
|
|
919
953
|
let barBots = [];
|
|
920
954
|
function setScene(name) {
|
|
921
955
|
document.getElementById("scene-street").hidden = name !== "street";
|
|
922
956
|
document.getElementById("scene-inn").hidden = name !== "inn";
|
|
923
957
|
document.getElementById("rpg-screen").setAttribute("data-scene", name);
|
|
924
958
|
}
|
|
925
|
-
function talk(name, line, acts
|
|
926
|
-
rpgTalk = { name: name, line: line, acts: acts || ""
|
|
959
|
+
function talk(name, line, acts) {
|
|
960
|
+
rpgTalk = { name: name, line: line, acts: acts || "" };
|
|
927
961
|
document.getElementById("rpg-name").textContent = name;
|
|
928
962
|
document.getElementById("rpg-line").textContent = line;
|
|
929
963
|
document.getElementById("rpg-acts").innerHTML = acts || "";
|
|
930
|
-
const img = document.getElementById("rpg-face");
|
|
931
|
-
const url = String(face || "").trim();
|
|
932
|
-
if (url) {
|
|
933
|
-
img.hidden = false;
|
|
934
|
-
img.src = url;
|
|
935
|
-
} else {
|
|
936
|
-
img.removeAttribute("src");
|
|
937
|
-
img.hidden = true;
|
|
938
|
-
}
|
|
939
964
|
}
|
|
940
965
|
function npcActs(bot) {
|
|
941
966
|
return (
|
|
@@ -950,69 +975,6 @@
|
|
|
950
975
|
"</a>"
|
|
951
976
|
);
|
|
952
977
|
}
|
|
953
|
-
function npcSprite(bot) {
|
|
954
|
-
if (bot.portrait) {
|
|
955
|
-
return (
|
|
956
|
-
'<img class="npc-bust" alt="" src="' +
|
|
957
|
-
esc(bot.portrait) +
|
|
958
|
-
'">'
|
|
959
|
-
);
|
|
960
|
-
}
|
|
961
|
-
return (
|
|
962
|
-
'<span class="npc-blank" aria-hidden="true">' +
|
|
963
|
-
esc(initials(bot.name || bot.handle)) +
|
|
964
|
-
"</span>"
|
|
965
|
-
);
|
|
966
|
-
}
|
|
967
|
-
const lookBusy = new Set();
|
|
968
|
-
async function requestLook(id) {
|
|
969
|
-
const bot = barBots.find((item) => item.id === id);
|
|
970
|
-
if (!bot || lookBusy.has(id)) return;
|
|
971
|
-
const formBtn = document.getElementById("gen-look");
|
|
972
|
-
if (formBtn && EDIT_ID === id && !beginBusy(formBtn, t("studio.genLookBusy"))) {
|
|
973
|
-
return;
|
|
974
|
-
}
|
|
975
|
-
lookBusy.add(id);
|
|
976
|
-
const npc = document.querySelector('.rpg-npc[data-id="' + id + '"]');
|
|
977
|
-
if (npc) npc.classList.add("drawing");
|
|
978
|
-
talk(bot.name, t("studio.genLookBusy"), npcActs(bot), bot.portrait);
|
|
979
|
-
const idFlash = document.querySelector("#create-bot > .card .block-flash");
|
|
980
|
-
if (idFlash && EDIT_ID === id) {
|
|
981
|
-
setNodeFlash(idFlash, "muted", t("studio.genLookBusy"));
|
|
982
|
-
}
|
|
983
|
-
try {
|
|
984
|
-
const response = await fetch("/bots/" + encodeURIComponent(id) + "/look", {
|
|
985
|
-
method: "POST",
|
|
986
|
-
});
|
|
987
|
-
const body = await response.json();
|
|
988
|
-
if (!response.ok) {
|
|
989
|
-
talk(bot.name, body.error || t("studio.genLookFail"), npcActs(bot), bot.portrait);
|
|
990
|
-
if (idFlash && EDIT_ID === id) {
|
|
991
|
-
setNodeFlash(idFlash, "error", body.error || t("studio.genLookFail"));
|
|
992
|
-
}
|
|
993
|
-
return;
|
|
994
|
-
}
|
|
995
|
-
const i = barBots.findIndex((item) => item.id === id);
|
|
996
|
-
if (i >= 0) barBots[i] = Object.assign({}, barBots[i], body);
|
|
997
|
-
await renderBar(barBots);
|
|
998
|
-
document.querySelectorAll(".rpg-npc").forEach((el) => {
|
|
999
|
-
el.classList.toggle("on", el.getAttribute("data-id") === id);
|
|
1000
|
-
});
|
|
1001
|
-
talk(body.name || bot.name, t("studio.genLookDone"), npcActs(body), body.portrait);
|
|
1002
|
-
if (idFlash && EDIT_ID === id) {
|
|
1003
|
-
setNodeFlash(idFlash, "health", t("studio.genLookDone"));
|
|
1004
|
-
}
|
|
1005
|
-
} catch (err) {
|
|
1006
|
-
talk(bot.name, t("studio.genLookFail"), npcActs(bot), bot.portrait);
|
|
1007
|
-
if (idFlash && EDIT_ID === id) {
|
|
1008
|
-
setNodeFlash(idFlash, "error", t("studio.genLookFail"));
|
|
1009
|
-
}
|
|
1010
|
-
} finally {
|
|
1011
|
-
lookBusy.delete(id);
|
|
1012
|
-
if (npc) npc.classList.remove("drawing");
|
|
1013
|
-
if (formBtn && EDIT_ID === id) endBusy(formBtn, t("studio.genLook"));
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1016
978
|
function renderSideRoster(bots) {
|
|
1017
979
|
const hire = document.getElementById("side-hire");
|
|
1018
980
|
const box = document.getElementById("side-roster");
|
|
@@ -1035,55 +997,48 @@
|
|
|
1035
997
|
})
|
|
1036
998
|
.join("");
|
|
1037
999
|
}
|
|
1038
|
-
|
|
1000
|
+
function renderBar(bots) {
|
|
1039
1001
|
barBots = bots || [];
|
|
1040
1002
|
renderSideRoster(barBots);
|
|
1041
1003
|
const bottles = ["#c44", "#4a8", "#c84", "#48c", "#a4c", "#cc8", "#844", "#4cc"];
|
|
1042
1004
|
document.getElementById("inn-bottles").innerHTML = bottles
|
|
1043
1005
|
.map((c) => '<span style="background:' + c + '"></span>')
|
|
1044
1006
|
.join("");
|
|
1045
|
-
const
|
|
1046
|
-
|
|
1047
|
-
const
|
|
1048
|
-
(space.live || []).forEach((row) => {
|
|
1049
|
-
if (row && row.botId) diving[row.botId] = true;
|
|
1050
|
-
});
|
|
1051
|
-
} catch {
|
|
1052
|
-
/* roster still renders if live is down */
|
|
1053
|
-
}
|
|
1054
|
-
const station = (inner) =>
|
|
1055
|
-
'<div class="inn-station"><span class="inn-desk" aria-hidden="true"><span class="inn-monitor"></span></span>' +
|
|
1056
|
-
inner +
|
|
1057
|
-
"</div>";
|
|
1058
|
-
const nodes = barBots.map((bot) => {
|
|
1007
|
+
const roster = barBots.slice(0, SPOTS.length - 1);
|
|
1008
|
+
const nodes = roster.map((bot, i) => {
|
|
1009
|
+
const spot = SPOTS[i];
|
|
1059
1010
|
const on = EDIT_ID === bot.id ? " on" : "";
|
|
1060
|
-
|
|
1061
|
-
return station(
|
|
1011
|
+
return (
|
|
1062
1012
|
'<button type="button" class="rpg-npc' +
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1013
|
+
on +
|
|
1014
|
+
'" style="left:' +
|
|
1015
|
+
spot[0] +
|
|
1016
|
+
"%;top:" +
|
|
1017
|
+
spot[1] +
|
|
1018
|
+
'%" data-id="' +
|
|
1019
|
+
bot.id +
|
|
1020
|
+
'"><canvas class="buddy" data-handle="' +
|
|
1021
|
+
bot.handle +
|
|
1022
|
+
'"></canvas><span class="tag">' +
|
|
1023
|
+
esc(bot.name) +
|
|
1024
|
+
"</span></button>"
|
|
1075
1025
|
);
|
|
1076
1026
|
});
|
|
1027
|
+
const hireSpot = SPOTS[Math.min(roster.length, SPOTS.length - 1)];
|
|
1077
1028
|
nodes.push(
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1029
|
+
'<button type="button" class="rpg-npc vacant" style="left:' +
|
|
1030
|
+
hireSpot[0] +
|
|
1031
|
+
"%;top:" +
|
|
1032
|
+
hireSpot[1] +
|
|
1033
|
+
'%" data-id="hire"><canvas class="buddy" data-handle="recruit"></canvas><span class="tag">' +
|
|
1034
|
+
t("studio.hireChip") +
|
|
1035
|
+
"</span></button>",
|
|
1085
1036
|
);
|
|
1086
1037
|
document.getElementById("inn-actors").innerHTML = nodes.join("");
|
|
1038
|
+
document.querySelectorAll("#inn-actors canvas.buddy").forEach((canvas) => {
|
|
1039
|
+
const handle = canvas.getAttribute("data-handle") || "";
|
|
1040
|
+
drawBuddy(canvas, shirtColor(handle), seedOf(handle));
|
|
1041
|
+
});
|
|
1087
1042
|
}
|
|
1088
1043
|
document.getElementById("enter-inn").addEventListener("click", () => {
|
|
1089
1044
|
setScene("inn");
|
|
@@ -1107,16 +1062,11 @@
|
|
|
1107
1062
|
}
|
|
1108
1063
|
const bot = barBots.find((item) => item.id === id);
|
|
1109
1064
|
if (!bot) return;
|
|
1110
|
-
talk(bot.name, bot.oneLiner || t("studio.drink"), npcActs(bot)
|
|
1065
|
+
talk(bot.name, bot.oneLiner || t("studio.drink"), npcActs(bot));
|
|
1111
1066
|
});
|
|
1112
1067
|
document.getElementById("rpg-acts").addEventListener("click", (event) => {
|
|
1113
1068
|
const link = event.target.closest('a[href="#hire"]');
|
|
1114
1069
|
if (link) document.getElementById("hire").hidden = false;
|
|
1115
|
-
const look = event.target.closest("[data-look]");
|
|
1116
|
-
if (look) requestLook(look.getAttribute("data-look"));
|
|
1117
|
-
});
|
|
1118
|
-
document.getElementById("gen-look").addEventListener("click", () => {
|
|
1119
|
-
if (EDIT_ID) requestLook(EDIT_ID);
|
|
1120
1070
|
});
|
|
1121
1071
|
|
|
1122
1072
|
async function boot() {
|
|
@@ -1137,11 +1087,7 @@
|
|
|
1137
1087
|
}
|
|
1138
1088
|
allSkills = mergeSkills(guild, host);
|
|
1139
1089
|
const bots = await fetch("/bots").then((r) => r.json());
|
|
1140
|
-
|
|
1141
|
-
if (location.hash === "#inn") {
|
|
1142
|
-
setScene("inn");
|
|
1143
|
-
talk(t("studio.keeper"), t("studio.keeperLine"), "");
|
|
1144
|
-
}
|
|
1090
|
+
renderBar(Array.isArray(bots) ? bots : []);
|
|
1145
1091
|
if (EDIT_ID) {
|
|
1146
1092
|
const response = await fetch("/bots/" + encodeURIComponent(EDIT_ID));
|
|
1147
1093
|
const bot = await response.json();
|
|
@@ -1161,7 +1107,7 @@
|
|
|
1161
1107
|
selected = new Set(bot.skillIds || []);
|
|
1162
1108
|
setFlash("muted", t("studio.editing", { handle: bot.handle }));
|
|
1163
1109
|
setScene("inn");
|
|
1164
|
-
talk(bot.name, bot.oneLiner || t("studio.drink"), npcActs(bot)
|
|
1110
|
+
talk(bot.name, bot.oneLiner || t("studio.drink"), npcActs(bot));
|
|
1165
1111
|
} else {
|
|
1166
1112
|
setScene("street");
|
|
1167
1113
|
document.getElementById("hire").hidden = true;
|
|
@@ -1173,7 +1119,7 @@
|
|
|
1173
1119
|
applyStudioCopy();
|
|
1174
1120
|
render();
|
|
1175
1121
|
renderBar(barBots);
|
|
1176
|
-
if (rpgTalk.name) talk(rpgTalk.name, rpgTalk.line, rpgTalk.acts
|
|
1122
|
+
if (rpgTalk.name) talk(rpgTalk.name, rpgTalk.line, rpgTalk.acts);
|
|
1177
1123
|
});
|
|
1178
1124
|
boot().catch((err) => setFlash("error", err.message));
|
|
1179
1125
|
</script>
|