This commit is contained in:
2026-09-28 20:58:29 +08:00
parent c3e83a700a
commit 8045e3c63f
49 changed files with 4582 additions and 441 deletions
+14
View File
@@ -0,0 +1,14 @@
import liubeiOpening, { openingRewards } from "./stories/liubei-opening.js";
import actMap from "./map.js";
import { rewardPools } from "./rewards.js";
import forestAmbush from "./stories/forest-ambush.js";
export default {
map: actMap,
nodeContents: {
[forestAmbush.id]: forestAmbush,
[liubeiOpening.id]: liubeiOpening,
},
rewardPools,
rewards: openingRewards,
};
+20
View File
@@ -0,0 +1,20 @@
const act1Map = {
id: "act1",
name: "第一关·初梦",
floorNodes: [1, 4, 4, 4, 1],
minFloorNodes: [1, 3, 3, 3, 1],
nodeWeights: { battle: 65, event: 15, rest: 10, shop: 10 },
fixedNodes: [
{
floor: 0,
position: "start",
type: "battle",
contentId: "act1.battle.liubeiOpening",
},
],
enemies: ["re_xiahoudun", "re_zhangliao", "re_xuzhu"],
boss: "re_lvbu",
baseGold: 20,
};
export default act1Map;
+16
View File
@@ -0,0 +1,16 @@
export const rewardPools = {
"act1.pool.story.scoutGift": [
"shared.reward.support.scout",
"shared.reward.card.sha",
"shared.reward.card.tao",
"shared.reward.card.upgrade",
"shared.reward.item.handCharm",
],
"act1.pool.story.ambushLoot": [
"shared.reward.card.sha",
"shared.reward.card.tao",
"shared.reward.card.upgrade",
"shared.reward.heal",
"shared.reward.item.handCharm",
],
};
@@ -0,0 +1,112 @@
const forestAmbush = {
id: "act1.story.forestAmbush",
kind: "dialogue",
name: "林中伏兵",
mapName: "林中伏兵",
description: "你在密林中遇到一名负伤的斥候。他声称前方有伏兵,并请求你决定下一步行动。",
dialogue: [
{
type: "narrator",
text: "暮色压进密林,归巢的鸟雀忽然一齐噤声。",
},
{
type: "sound",
speaker: "林间异响",
text: "沙沙……咔嚓!",
speed: 45,
},
{
type: "character",
character: "re_zhangliao",
speaker: "负伤斥候",
text: "且慢!前方埋伏着一队精兵。我侥幸逃出,已无力再探。",
},
{
type: "character",
character: "$player",
speaker: "$player",
text: "先把你知道的情形说清楚,我再决定如何行动。",
},
],
choices: [
{
id: "listen_and_leave",
name: "听完警告后离开",
description: "结束对话,不发生战斗,也不获得奖励。",
outcome: {
result: "你记下了斥候的警告,绕开了危险区域。",
dialogue: [
{ type: "narrator", text: "你记下警告,沿着一条隐蔽的小径绕开了危险区域。" },
],
flags: {
"story.act1.heardAmbushWarning": true,
"story.act1.ambushResult": "left",
},
},
},
{
id: "help_scout",
name: "帮助斥候处理伤势",
description: "不进入战斗,从随机出现的三个谢礼中选择一个。",
outcome: {
result: "斥候恢复了行动能力,并拿出随身物资作为谢礼。",
dialogue: [
{
type: "character",
character: "re_zhangliao",
speaker: "负伤斥候",
text: "多谢相助。这些随身物资,请务必收下。",
},
],
rewardPool: "act1.pool.story.scoutGift",
rewardTitle: "斥候的谢礼(三选一)",
flags: {
"story.act1.helpedScout": true,
"story.act1.ambushResult": "helped",
},
},
},
{
id: "hunt_ambushers",
name: "主动追击伏兵",
description: "迎战两名伏兵,第 3 轮还有敌军增援;胜利后获得金币并选择战利品。",
outcome: {
result: "你循着林间留下的痕迹追了上去。",
dialogue: [
{ type: "character", character: "$player", speaker: "$player", text: "与其绕路,不如趁他们尚未察觉,先发制人。" },
{ type: "sound", text: "刀剑出鞘之声划破寂静。" },
],
battle: {
enemies: ["re_xiahoudun", "re_zhangliao", "re_xuzhu"],
gold: 30,
// Two initial enemies; a third-round reinforcement demonstrates the rule system.
battlePlan: {
units: [
{ id: "captain", character: "re_xiahoudun", camp: "enemy", hand: 4 },
{ id: "guard", character: "re_xuzhu", camp: "enemy", hand: 2 },
],
rules: [
{ id: "enemy_reinforcement", name: "伏兵增援", blocksVictory: true, when: { event: "roundStart", round: 3 },
effects: [{ type: "spawn", unit: { id: "reinforcement", character: "re_zhangliao", camp: "enemy", hand: 3 } }] },
{ id: "captain_rally", name: "困兽犹斗", when: { event: "state", all: [
{ unit: "captain", field: "alive", value: true }, { unit: "captain", field: "hp", op: "lte", value: 2 },
] }, effects: [{ type: "draw", target: "captain", amount: 2 }] },
{ id: "player_supply", name: "临阵补给", when: { event: "state", all: [
{ unit: "player", field: "hand", op: "lte", value: 1 },
] }, effects: [{ type: "draw", target: "player", amount: 2 }] },
],
},
rewardPool: "act1.pool.story.ambushLoot",
rewardTitle: "伏兵战利品(三选一)",
description: "击败伏兵后,从随机出现的三个奖励中选择一个。",
},
flags: {
"story.act1.huntedAmbushers": true,
"story.act1.ambushResult": "fought",
},
},
},
],
};
export default forestAmbush;
@@ -0,0 +1,72 @@
export const openingDialogue = [
{ type: "narrator", text: "你是21世纪的一名普通牛马。" },
{ type: "narrator", text: "某天你晚上9点照常下班,刚出公司大门,就撞大运了。" },
{ type: "narrator", text: "等你睁开眼发现自己竟已身在三国,成为桃园结义后的刘备了。" },
{ type: "character", character: "$player", text: "(内心)我叫刘备。眼前这两位,便是与我结为兄弟的关羽和张飞。此刻,三弟正与二弟谈论黄巾之乱。" },
{ type: "character", character: "zhangfei", text: "大哥!如今黄巾作乱,官府正在招募义兵。俺们既已结为兄弟,何不召集乡勇,起兵讨伐黄巾贼?" },
{ type: "character", character: "guanyu", text: "三弟所言有理。只是起兵讨贼,须备足钱粮、兵器,方能成事。此事如何安排,还请大哥定夺。" },
{
type: "choice", text: "还好我历史满分!但是我不想干活啊。", flag: "story.act1.liubeiOpening.reply", defaultChoice: "gather", choices: [
{ id: "gather", text: "眼下先召集乡亲,整备人手,再从长计议。待我上山巡视一番,说不定有一张SSR呢。" },
]
},
{ type: "character", character: "zhangfei", text: "SSR为何物?" },
{ type: "narrator", text: "你不等张飞吐槽,转身拂袖而去。" },
{ type: "narrator", text: "乡间小道之上,忽听前方有人高声喝道:“黄巾军押运辎重,闲人速速避让,莫要挡路!”" },
{ type: "narrator", text: "只见一人一马疾驰而来。" },
{ type: "character", character: "$player", text: "(内心)这就开始刷怪了?白送的物资来了。" },
{ type: "narrator", text: "只见你伸腿一拦,只见对方勒马拔剑,进入战斗。" },
];
export const reinforcementDialogue = [
{ type: "character", character: "$player", text: "(内心)我靠,对面有马我没马啊。" },
{ type: "character", character: "mengsan_sushuang_zhangshiping_shuying", text: "将军莫急,我等前来助战。" },
];
export const victoryDialogue = [
{ type: "character", character: "$player", text: "方才多谢二位出手相助,尚未请教二位尊姓大名?" },
{ type: "character", character: "mengsan_sushuang_zhangshiping_shuying", text: "在下苏双,这位是张世平。我二人皆是中山商贾。" },
{ type: "character", character: "$player", text: "原来是苏兄、张兄。不知二位为何来到此处?" },
{ type: "character", character: "mengsan_sushuang_zhangshiping_shuying", text: "我二人贩马经商,途经涿郡。久闻玄德素有豪侠之名,特来拜会。" },
{ type: "character", character: "mengsan_sushuang_zhangshiping_shuying", text: "入城打听之时,恰遇张壮士。听闻玄德正在此处,我二人便一路寻来。" },
{ type: "character", character: "mengsan_sushuang_zhangshiping_shuying", text: "不料刚到此地,便见玄德与黄巾贼交战。今日一见,果然名不虚传。" },
{ type: "character", character: "$player", text: "二位过誉了。既然远道而来,不如随我回寒舍一叙?" },
{ type: "character", character: "mengsan_sushuang_zhangshiping_shuying", text: "玄德盛情,我二人心领了。只是商队不日便要启程,实不便久留。" },
{ type: "character", character: "mengsan_sushuang_zhangshiping_shuying", text: "听闻玄德正欲招募乡勇、讨伐黄巾。我二人虽是商贾,也愿略尽绵薄之力。" },
{ type: "character", character: "mengsan_sushuang_zhangshiping_shuying", text: "我二人常年贩马,别的或许帮不上忙,良马倒有一些,愿赠与玄德,助义兵一臂之力。" },
{ type: "character", character: "mengsan_sushuang_zhangshiping_shuying", text: "至于甲胄兵器,我二人并不经营。听闻蜀郡有一年轻匠人,名唤蒲元,颇善锻造,如今在刘焉麾下。玄德若欲寻他,不妨前往投靠刘焉。" }
];
export const openingRewards = {
"act1.reward.dilu": {
id: "act1.reward.dilu", name: "的卢", description: "+1坐骑,加入本次征程的个人牌库。",
card: { name: "dilu", suit: "club", number: 5, nature: null },
},
};
export default {
id: "act1.battle.liubeiOpening", kind: "battle", name: "刘备初始剧情", mapName: "初识的卢",
requiredCharacter: "mengsan_liubei_shuying",
enemies: ["mengsan_soldier_shuying"], gold: 20,
skipRandomReward: true, fixedRewards: ["act1.reward.dilu"], openingDialogue, victoryDialogue,
battlePlan: {
units: [{
id: "soldier", character: "mengsan_soldier_shuying", camp: "enemy",
inheritSkills: false, skills: [], hand: 4, hp: 24, maxHp: 24,
equipment: [{ name: "dilu", suit: "club", number: 5 }],
}],
rules: [{
id: "merchants_arrive", name: "苏双与张世平支援",
when: { event: "turnEnd", actor: "player", actorTurns: 4 },
effects: [
{ type: "dialogue", lines: reinforcementDialogue },
{
type: "spawn", unit: {
id: "merchants", character: "mengsan_sushuang_zhangshiping_shuying", camp: "ally",
after: "player", inheritSkills: false, skills: [], hand: 4, hp: 4, maxHp: 4,
}
},
{ type: "discardEquipment", target: "soldier", name: "dilu" },
],
}],
},
};
+8
View File
@@ -0,0 +1,8 @@
import actMap from "./map.js";
export default {
map: actMap,
nodeContents: {},
rewardPools: {},
rewards: {},
};
+13
View File
@@ -0,0 +1,13 @@
const act2Map = {
id: "act2",
name: "第二关·迷梦",
floorNodes: [1, 4, 4, 4, 4, 1],
minFloorNodes: [1, 3, 2, 3, 3, 1],
nodeWeights: { battle: 55, elite: 15, event: 12, rest: 9, shop: 9 },
enemies: ["re_ganning", "re_zhangfei", "re_huangzhong", "re_weiyan"],
eliteEnemies: ["re_guanyu", "dianwei"],
boss: "shen_guanyu",
baseGold: 30,
};
export default act2Map;
+8
View File
@@ -0,0 +1,8 @@
import actMap from "./map.js";
export default {
map: actMap,
nodeContents: {},
rewardPools: {},
rewards: {},
};
+13
View File
@@ -0,0 +1,13 @@
const act3Map = {
id: "act3",
name: "第三关·终梦",
floorNodes: [1, 4, 4, 4, 4, 4, 1],
minFloorNodes: [1, 3, 2, 3, 2, 3, 1],
nodeWeights: { battle: 45, elite: 20, event: 15, rest: 10, shop: 10 },
enemies: ["re_simayi", "re_sunben", "dongzhuo", "re_yuanshao"],
eliteEnemies: ["shen_zhaoyun", "shen_simayi"],
boss: "shen_caocao",
baseGold: 40,
};
export default act3Map;