c.tianPoints -= it.cost; var res = { ok: true, item: it, txt: '' }; switch (it.id) { case 'trib': pc.tribSkip = (pc.tribSkip || 0) + 1; pc.tribMult *= 1.2; res.txt = '下一次突破不降天劫。但你欠天道的这一次,会在下一次连本带利收回来(天劫强度 +20%)。'; break; case 'monitor': { if (pc.monitor <= 0) { pc.tianPoints += it.cost; return { ok: false, msg: '你现在是 L0,没什么可降的。' }; } pc.monitor--; pc.monitorGrace = this.turn + 30; res.txt = '天道暂时不看你(→' + D.MONITOR[pc.monitor].lv + ')。三十回合内若再犯禁忌,直接跳两级——它记得你耍过它。'; break; } case 'wash': { var ks = this.karmas.filter(function (k) { return k.status === 'active' && k.strength > 3; }); if (!ks.length) { pc.tianPoints += it.cost; return { ok: false, msg: '没有需要压制的因果线。' }; } var k = ks.sort(function (a, b) { return b.strength - a.strength; })[0]; k.strength = 1; k.washed = true; res.txt = '【' + k.name + '】强度压到 1。它不会消失,只是暂时不疼——而你很清楚它会回来。'; break; } case 'chance': pc.forceSuccess = (pc.forceSuccess || 0) + 1; res.txt = '下一次掷骰强制成功。但这次机缘会有人来抢,且抢的人比你强。'; break; case 'life': pc.lifeMax += 20; res.txt = '寿元 +20 年。垫进来的是谁的时间,你不会知道,也不该去查。'; break; case 'heal': { var ts = D.INJURY_TYPES.filter(function (t) { return pc.injury[t] > 0; }); if (!ts.length) { pc.tianPoints += it.cost; return { ok: false, msg: '你身上没有道伤可清。' }; } var t2 = ts.sort(function (a, b) { return pc.injury[b] - pc.injury[a]; })[0]; pc.injury[t2]--; /* 代价转移 */ var others = D.INJURY_TYPES.filter(function (x) { return x !== t2; }); var to = others[Math.floor(Math.random() * others.length)]; pc.injury[to] = E.clamp((pc.injury[to] || 0) + 1, 0, 5); pc.combat = this.calcPower(pc); res.txt = t2 + '道伤降一级(→' + D.INJURY_LEVELS[pc.injury[t2]] + ')。降下来的那部分没有消失,它转移到了' + to + '(→' + D.INJURY_LEVELS[pc.injury[to]] + ')。'; break; } case 'clean': { if (pc.pollution <= 0) { pc.tianPoints += it.cost; return { ok: false, msg: '你的道心是干净的,没什么可净化。' }; } var before = pc.pollution; pc.pollution--; pc.cleanDebt = (pc.cleanDebt || 0) + 1; res.txt = '道心从「' + D.POLLUTION[before].name + '」退到「' + D.POLLUTION[pc.pollution].name + '」。被清掉的东西记着你,它会回来。'; break; } case 'reveal': { var hid = this.karmas.filter(function (k) { return !k.realRevealed && k.surface; }); if (!hid.length) { pc.tianPoints += it.cost; return { ok: false, msg: '没有被隐藏的因果线了。' }; } var hk = hid[Math.floor(Math.random() * hid.length)]; hk.realRevealed = true; hk.surface = null; res.txt = '【' + hk.name + '】的真相:' + (hk.desc || '它比你以为的更近,也更旧。') + ' 知道之后就回不去了。'; break; } case 'escape': pc.autoEscape = (pc.autoEscape || 0) + 1; res.txt = '下一次致命危机你会活下来。活下来的方式可能不好看。'; break; case 'dao': { var keys = Object.keys(pc.bp || {}); if (!keys.length) { pc.tianPoints += it.cost; return { ok: false, msg: '你还没有任何道途可以推。' }; } var top = keys.sort(function (a, b) { return pc.bp[b] - pc.bp[a]; })[0]; pc.bpStage[top] = Math.min(5, (pc.bpStage[top] || 0) + 1); pc.bpHollow = (pc.bpHollow || 0) + 1; res.txt = '【' + top + '】阶跃推到' + D.BP_STAGE_NAMES[pc.bpStage[top] - 1] + '。跳过的积累不会补回来——境界是虚的,你自己知道。'; break; } case 'ascend': pc.forcedAscend = true; res.txt = '你跳过了四项证道条件。天道认为这是欺诈。它会认账,因为它必须认账——但它会用别的方式找回平衡。'; break; case 'six': { var key = extra || '根骨'; var fr = this.forgeSix(key); if (!fr.ok) { pc.tianPoints += it.cost; return { ok: false, msg: fr.msg }; } res.txt = fr.msg; break; } } return res; }; /* ============================================================ SECTION: curses 命途缺陷周期性发作 ============================================================ */ Game.prototype.activeFlaws = function () { var pc = this.pc; pc.flaws = pc.flaws || []; var out = []; pc.flaws.forEach(function (f) { out.push(f); }); /* 出身自带缺陷 */ if (pc.origin && pc.origin.flaw) { var fd = D.FLAWS.filter(function (x) { return x.id === pc.origin.flaw; })[0]; if (fd && !out.some(function (x) { return x.id === fd.id; })) out.push(fd); } /* 天赋中的负面 */ (pc.talents || []).forEach(function (t) { if (t.cost < 0 && !out.some(function (x) { return x.id === t.id; })) { out.push({ id: t.id, name: t.name, desc: t.desc, fx: {} }); } }); return out; }; Game.prototype.curseTick = function () { var pc = this.pc, r = this.rng; var flaws = this.activeFlaws(); var out = []; flaws.forEach(function (f) { var fx = f.fx || {}; if (!fx.curse) return; var bank = D.CURSE_EVENTS[fx.curse]; if (!bank || !bank.length) return; /* 周期性发作概率 */ var rate = { blood: 0.16, countdown: 0.22, lonestar: 0.12, blind: 0.14, mute: 0.12, onearm: 0.1, amnesia: 0.13, wanted: 0.2, debt: 0.18, nemeses: 0.17, sickly: 0.16, impure: 0.1, ugly: 0.1, heartdemon: 0.2, karmahole: 0.15, jealous: 0.14, nameless: 0.08, slave: 0.16, medicine: 0.15, scapegoat: 0.16, nofire: 0.1, yinborn: 0.15, possessed: 0.18, daodebt: 0.2, luckdebt: 0.14, numb: 0.12, marked: 0.18, cracked: 0.16 }[fx.curse] || 0.1; /* 周期性强制发作 */ if (fx.curse === 'blood' && this.turn % 8 === 0) rate = 1; if (fx.curse === 'debt' && this.turn > 0 && this.turn % 20 === 0) rate = 1; if (fx.curse === 'daodebt' && this.turn % 50 === 0 && this.turn > 0) rate = 1; if (fx.curse === 'countdown' && this.turn % 20 === 0) rate = 1; if (r() >= rate) return; var txt = bank[Math.floor(r() * bank.length)]; var effects = []; switch (fx.curse) { case 'blood': pc.hp = Math.max(1, pc.hp - Math.round(pc.hpMax * 0.25)); pc.pollution = E.clamp(pc.pollution + (r() < 0.3 ? 1 : 0), 0, 4); effects.push('气血 -25%'); break; case 'countdown': pc.age += 1; effects.push('寿元 -1 年'); break; case 'lonestar': { var near = this.npcs.filter(function (n) { return n.alive && n.met && (n.bond || 0) >= 2; }); if (near.length) { var v = near[Math.floor(r() * near.length)]; this.npcDeathCheck(v, '孤星命格所致——不是你的错,但你在场'); effects.push(v.fullName + ' 出事了'); this.pendingDeathNote = this.deathNarrative(v); } break; } case 'wanted': { var d = this.dice(0.4, { attr: '气运' }); if (d.result === 'fail' || d.result === 'greatfail') { pc.hp = Math.max(1, pc.hp - Math.round(pc.hpMax * 0.3)); pc.money = Math.max(0, pc.money * 0.7); effects.push('被截住,气血 -30%,灵石被搜走三成'); } else effects.push('你提前察觉了,绕开了'); break; } case 'debt': { var debt = (fx.debt || 3000) * (1 + Math.floor(this.turn / 20) * 0.2); if (pc.money >= debt) { pc.money -= debt; effects.push('被迫还了 ' + Math.round(debt) + ' 灵石'); } else { this.addInjury('肉身', Math.min(5, pc.injury['肉身'] + 1), '还不上债'); pc.reputation = E.clamp(pc.reputation - 8, -100, 100); effects.push('还不上,他们用了别的方式收'); } break; } case 'nemeses': { var alive = this.npcs.filter(function (n) { return n.alive; }); if (alive.length) { var foe = alive.sort(function (a, b) { return b.power - a.power; })[Math.floor(r() * Math.min(3, alive.length))]; this.npcAttitude(foe, '仇恨', 45, '宿敌'); foe.nemesis = true; effects.push(foe.fullName + ' 到了(战力 ' + foe.power + ',你 ' + pc.combat + ')'); this.pendingAmbush = foe; } break; } case 'sickly': pc.hp = Math.max(1, pc.hp - Math.round(pc.hpMax * 0.15)); effects.push('气血 -15%'); break; case 'heartdemon': { if (r() < 0.5) { pc.burstTurns = (pc.burstTurns || 0) + 2; effects.push('心魔接管,接下来两回合战力 ×2'); } else { pc.pollution = E.clamp(pc.pollution + 1, 0, 4); effects.push('污染 +1 阶'); } break; } case 'karmahole': { var nk = D.KARMA_POOL[Math.floor(r() * D.KARMA_POOL.length)]; this.karmas.push({ id: 'kh' + this.turn, name: nk.name, level: nk.level, power: Math.round(nk.power * 1.5), strength: Math.round(nk.power * 1.5), trigger: nk.trigger, endings: nk.endings, desc: nk.desc, realRevealed: true, status: 'active', createdTurn: this.turn, unbreakable: true }); effects.push('新增不可斩断因果:' + nk.name); break; } case 'jealous': { pc.hp = Math.max(1, pc.hp - Math.round(pc.hpMax * 0.2)); this.addInjury('肉身', Math.min(5, pc.injury['肉身'] + 1), '无妄天劫'); effects.push('无妄之劫,气血 -20%,肉身道伤 +1'); break; } case 'slave': { var d2 = this.dice(0.45, { attr: '心性' }); if (d2.result === 'fail' || d2.result === 'greatfail') { pc.hp = Math.max(1, pc.hp - Math.round(pc.hpMax * 0.35)); this.addInjury('神魂', Math.min(5, pc.injury['神魂'] + 1), '契约反噬'); effects.push('抗命失败,契约反噬'); } else effects.push('你抗住了这一次,但契约会再来'); break; } case 'medicine': { pc.money += Math.round(300 + r() * 900); pc.hp = Math.max(1, pc.hp - Math.round(pc.hpMax * 0.2)); effects.push('被人抽了血,换了一笔灵石'); break; } case 'possessed': { pc.possessedTurn = this.turn; var acts = ['他杀了一个人,用的是你的手', '他去见了某个你不认识的人,谈了很久', '他把你的东西送给了别人', '他把你藏起来的秘密说出去了']; effects.push(acts[Math.floor(r() * acts.length)]); pc.reputation = E.clamp(pc.reputation - 12, -100, 100); if (r() < 0.4) { var an = this.npcs.filter(function (n) { return n.alive; })[0]; if (an) { this.npcAttitude(an, '仇恨', 60, '残识接管期间做的事'); effects.push(an.fullName + ' 现在恨你,且理由充分'); } } break; } case 'daodebt': { var td = this.dice(0.4, { attr: '心性' }); if (td.result === 'fail' || td.result === 'greatfail') { pc.hp = Math.max(1, pc.hp - Math.round(pc.hpMax * 0.4)); this.addInjury('道基', Math.min(5, pc.injury['道基'] + 1), '天道催收'); effects.push('催收失败,道基受损'); } else effects.push('你扛过了这次催收。本金没动。'); break; } case 'luckdebt': pc.money = Math.max(0, pc.money * 0.9); effects.push('又损失了一点东西,说不清是什么'); break; case 'numb': if (pc.hp < pc.hpMax * 0.3 && r() < 0.5) { pc.hp = Math.max(1, pc.hp - Math.round(pc.hpMax * 0.15)); effects.push('你才发现伤口有多深'); } break; case 'amnesia': { if (r() < 0.35) { var p = this.npcs.filter(function (n) { return n.alive; })[Math.floor(r() * Math.max(1, this.npcs.filter(function (n) { return n.alive; }).length))]; if (p) { this.npcRemember(p, '过往', '他自称是你师父,而你完全不认识他', '关系待定', '因果级'); p.claimsPast = true; effects.push(p.fullName + ' 自称认识你'); this.pendingPast = p; } } break; } case 'blind': case 'mute': case 'onearm': case 'impure': case 'ugly': case 'nofire': case 'yinborn': case 'nameless': case 'scapegoat': effects.push('这个缺陷今天又拦了你一次'); if (r() < 0.3) { pc.energy = Math.max(0, pc.energy - 15); } break; case 'marked': { /* 被天道标记:监察缓慢累积,突破时天劫必至 */ if (r() < 0.4 && pc.monitor < 5) { var mm = this.raiseMonitor(pc.monitor + 1, '被天道标记'); if (mm.raised) effects.push('天道监察升至 ' + D.MONITOR[mm.to].lv + '(成功率 -' + Math.round(mm.to ? D.MONITOR[mm.to].pen * 100 : 0) + '%)'); } else effects.push('你被记了一笔。这一笔暂时没结算,但它记下了。'); break; } case 'cracked': { /* 道基残缺:道蕴从裂缝漏损,偶有异力渗出 */ var leak = Math.round(Math.min(pc.daoyun, 8 + r() * 20)); pc.daoyun = Math.max(0, pc.daoyun - leak); if (r() < 0.2) { pc.daoyun += leak * 2; effects.push('裂缝里渗出一点不属于你的力量,道蕴 +' + leak + '(净得)'); } else effects.push('道蕴从裂缝漏掉 ' + leak + ' 点'); break; } } out.push({ flaw: f.name, curse: fx.curse, txt: txt, effects: effects }); }, this); return out; }; /* ============================================================ SECTION: options-ext 扩展行动类别(极度自由) ============================================================ */ var _origMakeOptions = Game.prototype.makeOptions; Game.prototype.makeOptions = function (scene) { var opts = _origMakeOptions.call(this, scene); if (scene === 'opening') return opts; /* 防止同一类行动连续出现:玩家不该连着三回合被问"要不要建势力" */ if (this._lastAct && opts.length > 3) { var filtered = opts.filter(function (o) { return o.act !== this._lastAct || o.free; }, this); if (filtered.length >= 3) opts = filtered; } var r = this.rng, pc = this.pc; var free = opts.pop(); /* 摘出自由输入项,最后再放回 */ var R = function (risk) { return { '低': 'low', '中': 'mid', '高': 'high', '必死': 'dead', '未知': 'unk' }[risk] || 'mid'; }; var extra = []; /* 作恶 */ if (r() < 0.55) { var targets = ['一个落单的散修', '一队没有护卫的商队', '一座只剩老人孩子的村子', '一个受了重伤正在疗伤的人']; extra.push({ id: 'evil', text: '去做一件天道不喜欢的事:' + targets[Math.floor(r() * targets.length)] + ',把他们的东西拿过来', risk: '中', gain: ['资源', '修为'], cost: ['因果', '道心污染', '天道监察'], act: 'evil', riskCls: R('中'), tag: '支线行动', evil: true }); } /* 建立势力:需要冷却与一点本钱,不能每回合都来一次 */ if (r() < 0.5 && (!this._foundAt || this.turn - this._foundAt > 6)) { extra.push({ id: 'found', text: '开始建立属于自己的势力:招人、立规矩、占一处地盘,从此有人以你的话为准', risk: '中', gain: ['人脉', '资源', '道心'], cost: ['时间', '因果', '资源'], act: 'found', riskCls: R('中'), tag: '主线抉择', main: true }); } /* 躺平 */ if (r() < 0.45) { extra.push({ id: 'idle', text: '什么都不做:找个角落待着,看这一天过去,让世界自己转', risk: '低', gain: ['道心', '安全'], cost: ['时间', '寿元'], act: 'idle', riskCls: R('低'), tag: '支线行动' }); } /* 天道点交易:核心机制,始终可达(承受道伤/污染/寿元等本就不需要先有缺陷) */ if (r() < 0.4 || (pc.tianPoints || 0) > 0 || (this.activeFlaws && this.activeFlaws().length)) { extra.push({ id: 'tian', text: '与天道做一笔交易:用自己身上的一部分(道伤、污染、寿元、名声、羁绊、百艺)换天道点,再用天道点买抵消天劫、降监察、洗因果、续命', risk: '未知', gain: ['天道点'], cost: ['道伤', '道心污染', '寿元', '因果'], act: 'tian', riskCls: R('未知'), tag: '支线行动' }); } /* 极端:主动引发大事件 */ if (r() < 0.2) { extra.push({ id: 'provoke', text: '主动引爆一件大事:把那条你已经知道的大事件预告公开,让所有人提前入场', main: true, risk: '高', gain: ['情报', '人脉', '道心'], cost: ['因果', '道伤', '天道监察'], act: 'provoke', riskCls: R('高'), tag: '主线抉择' }); } /* 远行:换一块天地。灵石是路费,时间是税,因果是随行的行李 */ if (this.pc.plane === 'lower' && r() < 0.4 && D.START_WORLDS && D.START_WORLDS.length > 1) { var others = D.START_WORLDS.filter(function (w) { return w.id !== pc.world.id; }); var destW0 = others[Math.floor(r() * others.length)]; extra.push({ id: 'travel', text: '远行:离开' + pc.world.name + ',往' + destW0.name + '去(' + destW0.tag + ',灵气×' + destW0.qi + ')', risk: '中', gain: ['情报', '资源'], cost: ['时间', '灵石', '因果'], act: 'travel', dest: destW0.id, riskCls: R('中'), tag: '支线行动' }); } /* 飞升:此界已容不下你 */ var planeIsUpper = this.pc.plane && this.pc.plane.indexOf('upper:') === 0; if (this.pc.plane === 'lower' && this.pc.realmIdx >= 8) { extra.push({ id: 'ascend', text: '飞升:此界已容不下你,破开界壁去上界', main: true, risk: '高', gain: ['道心', '修为', '因果'], cost: ['道伤', '寿元', '因果'], act: 'ascend', riskCls: R('高'), tag: '主线抉择' }); } else if (planeIsUpper && this.pc.realmIdx >= 10) { extra.push({ id: 'ascend', text: '飞升:从上界再进一步,往太虚之上的位面去', main: true, risk: '必死', gain: ['道心', '因果'], cost: ['道伤', '寿元', '因果'], act: 'ascend', riskCls: 'dead', tag: '主线抉择' }); } /* 随机插入 1~2 个 */ extra.sort(function () { return r() - 0.5; }); var insert = extra.slice(0, 2); /* 保证总数不超过 5(含自由输入) */ var keep = opts.slice(0, Math.max(2, 4 - insert.length)); var out = keep.concat(insert); out.push(free); return out; }; /* ============================================================ SECTION: doaction-ext 扩展行为执行 ============================================================ */ var _origDoAction = Game.prototype.doAction; Game.prototype.doAction = function (opt, freeText) { var act = opt && opt.act; this._lastAct = act; if (act === 'found') this._foundAt = this.turn; if (['evil', 'found', 'idle', 'tian', 'provoke', 'travel', 'ascend'].indexOf(act) < 0) { var res0 = _origDoAction.call(this, opt, freeText); this._applyCurseTick(res0); return res0; } /* 扩展行为:先执行,再走通用回合流程 */ var pc = this.pc, r = this.rng; var parts = [], settle = { karma: [], npc: [], world: [], daoyun: 0, injury: [], bp: [], arts: [] }; var kind = 'social', mainTxt = '', costTxt = '', baideObj = null; if (act === 'evil') { kind = 'battle'; var d = this.dice(0.6, { attr: '气运' }); var victim = ['一个落单的散修', '一队商队', '一座村子', '一个伤者'][Math.floor(r() * 4)]; var got = 0; if (d.result === 'great' || d.result === 'ok') { got = Math.round((200 + r() * 1500) * (1 + this.stage * 0.15)); pc.money += got; mainTxt = '你动手了。' + victim + '没能阻止你——' + (d.result === 'great' ? '他们甚至没能看清你的脸。' : '他们看清了你的脸,这会比较麻烦。'); mainTxt += ' 你拿走了 ' + got + ' 灵石和一些别的东西。'; this.addBp('杀', d.result === 'great' ? 3.0 : 2.2, '作恶'); settle.bp.push('杀 行为 +' + (d.result === 'great' ? 3.0 : 2.2) + ' BP(重大抉择级)'); } else if (d.result === 'barely') { got = Math.round(80 + r() * 300); pc.money += got; pc.hp = Math.max(1, pc.hp - Math.round(pc.hpMax * 0.2)); mainTxt = '你做成了,但做得不干净。有人跑了,或者有人记住了你。你只拿到 ' + got + ' 灵石。'; this.addBp('杀', 1.8, '作恶'); } else { pc.hp = Math.max(1, pc.hp - Math.round(pc.hpMax * (d.result === 'greatfail' ? 0.55 : 0.3))); this.addInjury('肉身', Math.min(5, pc.injury['肉身'] + 1), '作恶失手'); mainTxt = d.result === 'greatfail' ? '你失手了,而且失手得很彻底。' + victim + '里有一个人比你想的强得多。你现在在跑,跑的时候还在流血。' : '没做成。' + victim + '反抗了,反抗得比你预料的激烈。你退出来的时候少了点东西。'; settle.injury.push('肉身道伤 → ' + D.INJURY_LEVELS[pc.injury['肉身']]); } /* 必然代价(代价守恒) */ pc.pollution = E.clamp(pc.pollution + 1, 0, 4); pc.reputation = E.clamp(pc.reputation - (d.result === 'great' ? 10 : 18), -100, 100); var mk = this.raiseMonitor(Math.max(1, pc.monitor), '作恶'); if (mk.raised) parts.push({ cls: 'monitor', html: '

【天道监察 → ' + D.MONITOR[mk.to].lv + '】' + mk.txt + '

' }); var nk = D.KARMA_POOL.filter(function (k) { return ['血海深仇', '夺宝之恨', '未救之人', '一起做过坏事', '见证者'].indexOf(k.name) >= 0; }); var kk = nk[Math.floor(r() * nk.length)]; this.karmas.push({ id: 'ev' + this.turn, name: kk.name, level: kk.level, power: kk.power, strength: Math.max(3, Math.round(kk.power * 0.8)), trigger: '你抢了不该抢的', endings: kk.endings, desc: kk.desc, realRevealed: true, status: 'active', createdTurn: this.turn }); settle.karma.push('新增因果:' + kk.name + '(' + kk.level + ')'); settle.injury.push('道心污染 → ' + D.POLLUTION[pc.pollution].name); costTxt = this.addCost(2, '作恶'); settle.world.push('声誉 ' + pc.reputation + ' | 灵石 +' + got); baideObj = '手上还没干的血'; /* 口碑传播:恶名也是名 */ parts.push({ cls: 'sys', html: '

【口碑网】这件事会传开。传开的速度取决于' + victim + '里有没有人活着走出去,以及活着的人认识多少人。

' }); pc.energy = Math.max(0, pc.energy - 35); } else if (act === 'found') { kind = 'social'; var followers = this.npcs.filter(function (n) { return n.alive && n.met && ((n.att['敬畏'] || 0) >= 30 || (n.att['感恩'] || 0) >= 30 || (n.att['利用'] || 0) >= 40); }); if (followers.length < 1) { mainTxt = '你想立起来一点东西,但没人跟你。不是他们看不起你,是他们各自都有自己要活的方式。招人这件事,比你想象的更需要本钱。'; parts.push({ cls: 'sys', html: '

建立势力需要至少一位愿意跟你的人。先去见人、去救人、去让人怕你。

' }); } else { var cost = Math.min(pc.money, 500); pc.money -= cost; var d2 = this.dice(0.5 + followers.length * 0.06, { attr: '魅力' }); if (d2.result === 'great' || d2.result === 'ok' || d2.result === 'barely') { var base = this.place(); this.myForce = this.myForce || { name: null, base: base, members: [], rules: [], turn: this.turn, power: 0 }; var f0 = followers[Math.floor(r() * followers.length)]; if (this.myForce.members.indexOf(f0.id) < 0) this.myForce.members.push(f0.id); if (!this.myForce.name) { var pre = D.TITLE_PRE[Math.floor(r() * D.TITLE_PRE.length)]; var post = ['堂', '社', '会', '盟', '阁', '司', '局', '寨'][Math.floor(r() * 8)]; this.myForce.name = pre + post; } this.myForce.power += 10 + Math.round(f0.power * 0.02); this.myForce.rules.push(['不许问为什么', '账目公开', '叛者不留', '弱者先走', '不碰凡人'][Math.floor(r() * 5)]); mainTxt = '你在' + base + '立起了「' + this.myForce.name + '」。第一批人只有 ' + this.myForce.members.length + ' 个,规矩定了 ' + this.myForce.rules.length + ' 条。' + '立规矩的那天没人反对,这比有人反对更让人不安。'; mainTxt += ' 花掉 ' + cost + ' 灵石。'; f0.factionName = this.myForce.name; this.addBp('谋', 3.0, '建立势力'); settle.bp.push('谋 行为 +3.0 BP(重大抉择级)'); settle.world.push('新势力「' + this.myForce.name + '」成立于' + base + ',成员 ' + this.myForce.members.length + ' 人'); /* 其他势力会注意到 */ var notice = this.factions[Math.floor(r() * this.factions.length)]; if (notice) { notice.relation['myforce'] = -20; mainTxt += '
' + notice.name + '注意到了你。他们没有表态,但他们记下了。'; settle.world.push(notice.name + ' 对「' + this.myForce.name + '」态度:警惕'); } pc.reputation = E.clamp(pc.reputation + 6, -100, 100); if (d2.result === 'barely') { mainTxt += '
过程不太顺。有人来了又走了,走的时候没说明原因。'; } } else { mainTxt = '你试了,没成。' + (d2.result === 'greatfail' ? '不仅没成,还让原来愿意跟你的人也犹豫了。立势这种事,失败一次要缓很久。' : '人来了,看了看,又走了。你没留他们,因为你知道留下来也没用。'); pc.reputation = E.clamp(pc.reputation - 4, -100, 100); } } pc.energy = Math.max(0, pc.energy - 30); baideObj = '那张写了名字的纸'; } else if (act === 'idle') { kind = 'time'; var y = r() < 0.3 ? 1 : 0; mainTxt = '你什么都没做。这件事比听起来难——你需要抵抗住"应该做点什么"的冲动,而坐在那里,看时间过去。'; pc.energy = Math.min(pc.energyMax, pc.energy + 35); pc.hp = Math.min(pc.hpMax, pc.hp + Math.round(pc.hpMax * 0.15)); if (pc.pollution > 0 && r() < 0.35) { pc.pollution--; mainTxt += '
识海里那点东西淡了一些。不是清了,是你没喂它。'; } if (pc.costLevel > 0 && r() < 0.3) { pc.costLevel--; mainTxt += '
身上那笔代价松动了一级。'; } this.addBp('无', 0.4, '什么都不做'); settle.bp.push('无 行为 +0.4 BP(日常级:扫地、做饭、走路也是道)'); if (y) { var yl = this.passYears(y, '虚度'); if (yl.length) mainTxt += '
' + yl.join('
'); } mainTxt += '
精力 +35,气血恢复 15%。世界照常转了' + (y ? '一年' : '一天') + ',没有等你,也没有针对你。'; /* 躺平的代价:时间在走 */ pc.age += y; baideObj = '窗外那棵什么都没变的树'; } else if (act === 'travel') { kind = 'explore'; var destW = D.WORLDS.filter(function (w) { return w.id === (opt && opt.dest); })[0] || D.WORLDS[0]; var fromW = pc.world; var fare = Math.round(80 + r() * 160); pc.money = Math.max(0, pc.money - fare); var yrs = 1 + Math.floor(r() * 2); var mishap = r() < 0.3; pc.world = destW; pc.worldQi = destW.qi; pc.lastPlace = null; mainTxt = '你把能卖的都卖了,凑出 ' + fare + ' 枚灵石做路费。离开' + fromW.name + '的那天没有人送——' + '在这里,你本来也没留下什么值得送的东西。'; mainTxt += '
' + [ '路走了' + yrs + '年。中间换了三次车,两次船,最后一次是徒步。', '走了' + yrs + '年。' + yrs + '年里你学会了一件事:地图上画得越清楚的地方,到了越不像。', '走了' + yrs + '年。你数过路上的桥,数到第十一座就不数了。' ][Math.floor(r() * 3)]; if (mishap) { var lost = Math.round(pc.money * 0.4); pc.money = Math.max(0, pc.money - lost); pc.hp = Math.max(1, pc.hp - Math.round(pc.hpMax * 0.18)); mainTxt += '
半路上出了事。货丢了,人也伤了。等你爬到' + destW.name + ',身上只剩 ' + pc.money + ' 枚灵石。'; settle.injury.push('肉身磨损(长途跋涉)'); } mainTxt += '
你到了' + destW.name + '。' + destW.desc; mainTxt += '
这里的天比原来的低,灵气浓度是原来的 ' + destW.qi + ' 倍。你站在城门口,先做的事是记路——' + '在陌生的地方,记路比记人有用。'; var yl2 = this.passYears(yrs, '远行'); if (yl2.length) mainTxt += '
' + yl2.join('
'); this.addBp('无', 0.8, '远行'); settle.bp.push('无 行为 +0.8 BP(远行也是修行)'); settle.world.push('界域变更:' + fromW.name + ' → ' + destW.name + '(灵气×' + destW.qi + ')'); pc.energy = Math.max(0, pc.energy - 30); baideObj = '客栈门口那块被踩得发亮的路石'; } else if (act === 'ascend') { kind = 'weird'; if (pc.plane === 'lower') { var cands = D.upperRealmsFor(pc.world.upperOf || pc.world.id); var own = cands.filter(function (u) { return u.systemId === pc.systemId; })[0]; var others = cands.filter(function (u) { return u.systemId !== pc.systemId; }); var dest = (r() < 0.55 && own) ? own : (others.length ? others[Math.floor(r() * others.length)] : own); var fromName = pc.world.name; pc.plane = 'upper:' + dest.id; pc.world = dest; pc.worldQi = dest.qi; pc.lastPlace = null; mainTxt = '你破开了界壁。' + fromName + '的天在你身后合拢,像什么也没发生过。'; mainTxt += '
你落在' + dest.name + '。' + dest.desc; mainTxt += '
这里的灵气浓得发涩,压得你经脉发疼。上界不是福地,是另一套更硬的规矩——能上来的,没有一个是靠运气。'; var upYears = 1 + Math.floor(r() * 3); var uyl = this.passYears(upYears, '飞升'); if (uyl.length) mainTxt += '
' + uyl.join('
'); pc.daoyun += 100; settle.daoyun += 100; this.addBp('无', 3.0, '飞升'); settle.bp.push('无 行为 +3.0 BP(飞升)'); settle.world.push('位面变更:' + fromName + ' → ' + dest.name + '(' + D.systemById(dest.systemId).name + '上界)'); pc.energy = 30; baideObj = '脚下这块比下界更硬的石板'; } else { var fromName2 = pc.world.name; pc.plane = 'top'; pc.world = D.TOP_PLANE; pc.worldQi = D.TOP_PLANE.qi; pc.lastPlace = null; mainTxt = '你从' + fromName2 + '再往上走了一层。' + D.TOP_PLANE.desc; mainTxt += '
这里没有路标,也没有人告诉你下一步该做什么。你只看见远处有几个人站着,谁也不看谁。'; pc.daoyun += 200; settle.daoyun += 200; this.addBp('无', 4.0, '飞升位面'); settle.bp.push('无 行为 +4.0 BP(飞升位面)'); settle.world.push('位面变更:' + fromName2 + ' → ' + D.TOP_PLANE.name); pc.energy = 20; baideObj = '远处那几个互不看对方的人'; } } else if (act === 'tian') { kind = 'karma'; mainTxt = '你坐下来,开始清点自己身上还剩什么可以卖。这件事做多了会熟练,熟练了就可悲。'; parts.push({ cls: 'sys', html: '

【天道点交易】当前持有 ' + (pc.tianPoints || 0) + ' 点。请在右侧「天道点」面板中选择承受什么、兑换什么。天道不劝你,也不拦你——它只是记账。

' }); this.pendingTianPanel = true; pc.energy = Math.max(0, pc.energy - 10); baideObj = '自己那双开始习惯这件事的手'; } else if (act === 'provoke') { kind = 'weird'; var be = this.bigEvents.filter(function (e) { return !e.done; })[0]; if (!be) { mainTxt = '你想引爆一件大事,但手上没有可用的引子。你知道的还不够多。'; } else { var d3 = this.dice(0.4, { attr: '悟性' }); be.turn = Math.max(this.turn + 1, Math.round(be.turn * 0.5)); mainTxt = '你把那件事说了出去。说得很有技巧,让三方都以为是另外两方说的。'; if (d3.result === 'great') { mainTxt += '
效果比你想的好。原本还有几个月的事,现在被压到了第 ' + be.turn + ' 回合。而且所有人都以为自己是主动入场的。'; pc.daoyun += 80; this.addBp('谋', 4.5, '操纵局势'); settle.daoyun += 80; settle.bp.push('谋 行为 +4.5 BP(重大抉择级)'); pc.reputation = E.clamp(pc.reputation + 15, -100, 100); } else if (d3.result === 'ok' || d3.result === 'barely') { mainTxt += '
事情提前了,但有人开始查是谁说的。查到你会需要时间,而你不确定自己有多少时间。'; this.addBp('谋', 3.0, '操纵局势'); this.karmas.push({ id: 'pv' + this.turn, name: '见证者', level: '个人级', power: 6, strength: 6, trigger: '你把消息放了出去', endings: ['没人查到', '被查到', '被灭口'], desc: '有人开始查是谁把消息捅出来的。你做得不干净。', realRevealed: true, status: 'active', createdTurn: this.turn }); settle.karma.push('新增因果:见证者(有人在查你)'); } else { mainTxt += '
你失算了。事情确实提前了,但提前到了对你最不利的那一刻——你还没准备好,而所有人都已经就位。'; var m2 = this.raiseMonitor(Math.max(pc.monitor, 2), '操纵局势'); if (m2.raised) parts.push({ cls: 'monitor', html: '

【天道监察 → ' + D.MONITOR[m2.to].lv + '】' + m2.txt + '

' }); pc.hp = Math.max(1, pc.hp - Math.round(pc.hpMax * 0.25)); this.addCost(3, '操纵局势失败'); costTxt = this.addCost(3, '操纵局势失败'); } } pc.energy = Math.max(0, pc.energy - 40); baideObj = '那句说出去就收不回来的话'; } /* ---- 通用回合收尾 ---- */ this.turn++; pc.timeLeft = 3; if (pc.age >= pc.lifeMax && !this.over) { this.die('寿元耗尽'); } if (pc.hp <= 0 && !this.over) { if ((pc.autoEscape || 0) > 0) { pc.autoEscape--; pc.hp = Math.round(pc.hpMax * 0.2); parts.push({ cls: 'break', html: '

【必定逃脱】你本该死在这里。有什么东西把你拽了出去,拽的方式不好看,但你活着。

' }); } else this.die('重伤不治'); } var ticks = this.worldTick(); if (this.turn % 10 === 0) { var rm = N.makeRumor(this); this.rumors.unshift(rm); var big = N.makeBigForecast(this); this.rumors.unshift(big); this.bigEvents.push({ id: 'bep' + this.turn, kind: big.eventType, turn: big.dueTurn, desc: big.text, done: false, weight: big.weight }); this.bigEvents.sort(function (a, b) { return a.turn - b.turn; }); var priceReason = this.updatePrices(); var compress = this.compressMemory(); var rumorPush = [big, rm]; } var dueF = this.checkForeshadow(); this.advanceStage(); this.checkBigEvents(); var stageUp = this.takeStages(), bigFired = this.takeBigEvents(); this.decayMemory(); var decayLog = this.decayBp(); var daoTitle = this.grantDaoTitle(); pc.energy = Math.min(pc.energyMax, pc.energy + 12); /* 余炽线 */ var ember = null; if (kind === 'battle' || (stageUp && stageUp.length) || (bigFired && bigFired.length)) { this.emberDue = 1 + Math.floor(r() * 3); this.highStreak = 0; } else this.highStreak++; if (this.emberDue > 0) { ember = N.ember(this, this.emberDue); this.emberDue--; } if (this.highStreak >= 3 && this.emberDue === 0) { ember = N.ember(this, 1); this.highStreak = 0; } if (!settle.world.length && ticks.length) settle.world.push('世界 TICK:' + ticks.length + ' 件后台事件'); this.settlements.unshift({ turn: this.turn, s: settle }); if (this.settlements.length > 300) { this.settleArchive = this.settleArchive || []; this.settlements.splice(300).forEach(function (rec) { var bits = []; ['karma', 'npc', 'world', 'injury', 'bp', 'arts'].forEach(function (k) { if (rec.s[k] && rec.s[k].length) bits.push(rec.s[k].length + '项'); }); this.settleArchive.unshift({ turn: rec.turn, brief: bits.join(',') || '无显著变化' }); }, this); this.settleArchive = this.settleArchive.slice(0, 2000); } /* 岁月史书 */ var ctx = { kind: kind, subject: null, place: pc.lastPlace || (pc.lastPlace = this.place()), timeStr: ['子时', '丑时', '寅时', '卯时', '辰时', '黄昏', '入夜', '五更'][this.turn % 8], sensePool: this.sensePool(), usedSenses: this.usedSenses, goldenCache: this.goldenCache, rng_i: this.turn * 17 + 3, baideObj: baideObj, resultTxt: mainTxt ? mainTxt.replace(/
/g, '

') : null, costTxt: costTxt, blank: null, echo: ticks.filter(function (t) { return !t.hidden; }).slice(0, 2).map(function (t) { return t.text; }).join(' '), event: null }; var ch = N.chronicle(ctx); var res = { turn: this.turn, parts: parts, settlement: settle, options: [], ticks: ticks, chronicle: ch, ember: ember, stageUp: stageUp, bigFired: bigFired, dueForesight: dueF, compress: compress, decayLog: decayLog, daoTitle: daoTitle, priceReason: priceReason, rumorPush: rumorPush, over: this.over, deathForms: this.over ? D.DEATH_FORMS : null, showTian: !!this.pendingTianPanel }; this.pendingTianPanel = false; res.parts.push({ cls: 'chronicle', html: ch.html }); if (ember) res.parts.push({ cls: 'ember', html: ember }); if (stageUp && stageUp.length) stageUp.forEach(function (s) { res.parts.push({ cls: 'stage', html: '

【大劫推进·' + s.name + '】

' + s.desc + '

' }); }); if (bigFired && bigFired.length) { var self = this; bigFired.forEach(function (e) { res.parts.push({ cls: 'world', html: N.worldNarrative(self, e) }); }); } if (daoTitle) res.parts.push({ cls: 'title', html: '

【道号凝结】「' + daoTitle.title + '」已录入万古道碑。
' + daoTitle.deed + '

' }); if (dueF && dueF.length) dueF.forEach(function (f) { if (!f.discarded) res.parts.push({ cls: 'foresight', html: '

【伏笔到期】' + f.text + '

' }); }); this._applyCurseTick(res); res.options = this.over ? [] : this.makeOptions(); return res; }; /* 缺陷发作注入到任意回合结果 */ Game.prototype._applyCurseTick = function (res) { if (!res || !this.pc) return; var curses = this.curseTick(); if (!curses.length) return; res.curses = curses; var html = curses.map(function (c) { return '

【' + c.flaw + '·发作】' + c.txt + (c.effects.length ? '
' + c.effects.map(function (e) { return '· ' + e; }).join('
') + '
' : '') + '

'; }).join(''); res.parts.push({ cls: 'curse', html: html }); if (this.pendingDeathNote) { res.parts.push({ cls: 'death', html: '

' + this.pendingDeathNote + '

' }); this.pendingDeathNote = null; } if (this.pendingAmbush) { var foe = this.pendingAmbush; this.pendingAmbush = null; res.parts.push({ cls: 'threat', html: '

【宿敌临门】' + foe.fullName + ' 就在外面。战力 ' + foe.power + ',你 ' + this.pc.combat + '。你可以打、可以跑、也可以试着谈——他可能听,也可能不听。

' }); res.ambush = foe.id; } if (this.pendingPast) { var p = this.pendingPast; this.pendingPast = null; res.parts.push({ cls: 'foresight', html: '

【过去找上门】' + p.fullName + ' 说认识你。他说得很具体,具体到你无法用"认错人了"打发他。

' }); } if (this.pc.hp <= 0 && !this.over) { if ((this.pc.autoEscape || 0) > 0) { this.pc.autoEscape--; this.pc.hp = Math.round(this.pc.hpMax * 0.2); res.parts.push({ cls: 'break', html: '

【必定逃脱】你本该死在这里。你活着,方式不好看。

' }); } else { this.die('死于命途缺陷'); res.over = true; res.deathForms = D.DEATH_FORMS; } } }; /* ============================================================ SECTION: openfile-ext 开档时挂载缺陷与天道点 ============================================================ */ var _origOpenFile = Game.prototype.openFile; Game.prototype.openFile = function (cfg) { var o = _origOpenFile.call(this, cfg); var pc = this.pc; pc.tianPoints = 0; pc.flaws = (cfg.flaws || []).map(function (f) { return { id: f.id, name: f.name, desc: f.desc, fx: f.fx || {} }; }); /* 缺陷效果落地 */ pc.flaws.forEach(function (f) { var fx = f.fx || {}; if (fx.pollution) pc.pollution = Math.max(pc.pollution, fx.pollution); if (fx.monitor) pc.monitor = Math.max(pc.monitor, fx.monitor); if (fx.life) pc.lifeMax = Math.min(pc.lifeMax, fx.life); if (fx.cultMult) pc.cultMult *= fx.cultMult; if (fx.breakMult) pc.breakMult *= fx.breakMult; if (fx.tribMult) pc.tribMult *= fx.tribMult; if (fx.powerMult) pc.powerMult = (pc.powerMult || 1) * fx.powerMult; if (fx.hpMult) pc.hpMult = (pc.hpMult || 1) * fx.hpMult; if (fx.luckFlat) pc.luckFlat = (pc.luckFlat || 0) + fx.luckFlat; if (fx.luckMult) pc.luckMult = (pc.luckMult || 1) * fx.luckMult; if (fx.bondCap != null) pc.bondCap = Math.min(pc.bondCap, fx.bondCap + 1); if (fx.charmMin) pc.six['魅力'] = Math.min(pc.six['魅力'], fx.charmMin); if (fx.injury) pc.injury[fx.injury[0]] = Math.max(pc.injury[fx.injury[0]] || 0, fx.injury[1]); if (fx.daoBonus) pc.daoBonus = (pc.daoBonus || 0) + fx.daoBonus; if (fx.mindShield) pc.mindShield = true; if (fx.evilRep) pc.reputation = (pc.reputation || 0) - fx.evilRep * 0.5; if (fx.reputation) pc.reputation = (pc.reputation || 0) + fx.reputation; if (fx.debt) pc.debt = (pc.debt || 0) + fx.debt; if (fx.nemeses) { /* 生成宿敌 */ var self = this; for (var i = 0; i < fx.nemeses && i < this.npcs.length; i++) { var cand = this.npcs.filter(function (n) { return n.alive && !n.nemesis; }); if (!cand.length) break; var foe = cand[Math.floor(Math.random() * cand.length)]; foe.nemesis = true; foe.met = false; this.npcAttitude(foe, '仇恨', 70, '宿敌(开局即存在)'); } } if (fx.pastDue) { this.foreshadow.push({ id: 'past' + this.turn, text: '你的过去会找上门', level: '因果级', trigger: '某个自称认识你的人出现', dueTurn: 15 + Math.floor(Math.random() * 30), createdTurn: 0, resolved: false }); } }, this); /* 出身/天赋自带缺陷合并 */ if (pc.origin && pc.origin.flaw) { var of = D.FLAWS.filter(function (x) { return x.id === pc.origin.flaw; })[0]; if (of && !pc.flaws.some(function (f) { return f.id === of.id; })) { pc.flaws.push({ id: of.id, name: of.name, desc: of.desc, fx: of.fx || {} }); } } (pc.talents || []).forEach(function (t) { if (t.cost >= 0) return; if (!pc.flaws.some(function (f) { return f.id === t.id; })) pc.flaws.push({ id: t.id, name: t.name, desc: t.desc, fx: t.effect || {} }); }); /* 灵根负面效果 */ if (pc.linggen) { if (pc.linggen.pollution) pc.pollution = Math.max(pc.pollution, pc.linggen.pollution); if (pc.linggen.tribMult) pc.tribMult *= pc.linggen.tribMult; if (pc.linggen.breakMult) pc.breakMult *= pc.linggen.breakMult; if (pc.linggen.hpMult) pc.hpMult = (pc.hpMult || 1) * pc.linggen.hpMult; if (pc.linggen.daoInjury) for (var dk in pc.linggen.daoInjury) pc.injury[dk] = Math.max(pc.injury[dk] || 0, pc.linggen.daoInjury[dk]); if (pc.linggen.karma) { var lk = D.KARMA_POOL.filter(function (k) { return k.name === pc.linggen.karma; })[0]; if (lk && !this.karmas.some(function (k) { return k.name === lk.name; })) { this.karmas.push({ id: 'lg' + lk.id, name: lk.name, level: lk.level, power: lk.power, strength: lk.power, trigger: lk.trigger, endings: lk.endings, desc: lk.desc, surface: lk.hidden ? this._surfaceMask(lk) : null, realRevealed: !lk.hidden, status: 'active', createdTurn: 0 }); } } } /* 出身声誉/缺陷 */ if (pc.origin) { if (pc.origin.grant && pc.origin.grant.reputation) pc.reputation = (pc.reputation || 0) + pc.origin.grant.reputation; if (pc.origin.polarity === 'neg') pc.reputation = (pc.reputation || 0) - 5; } /* 天赋扩展效果 */ (pc.talents || []).forEach(function (t) { var e = t.effect || {}; if (e.hpMult) pc.hpMult = (pc.hpMult || 1) * e.hpMult; if (e.powerFlat) pc.powerFlat = (pc.powerFlat || 0) + e.powerFlat; if (e.pollutionHalf) pc.pollutionHalf = true; if (e.desperateHalf) pc.desperateHalf = true; if (e.talkBonus) pc.talkBonus = (pc.talkBonus || 0) + e.talkBonus; if (e.tradeBonus) pc.tradeBonus = (pc.tradeBonus || 0) + e.tradeBonus; if (e.artBonus) { pc.artBonus = pc.artBonus || {}; if (typeof e.artBonus === 'number') pc.artBonus[t.effect.art || 'all'] = (pc.artBonus[t.effect.art || 'all'] || 0) + e.artBonus; else for (var ak in e.artBonus) pc.artBonus[ak] = (pc.artBonus[ak] || 0) + e.artBonus[ak]; } if (e.bpMult) { pc.bpMult = pc.bpMult || {}; for (var bk in e.bpMult) pc.bpMult[bk] = (pc.bpMult[bk] || 1) * e.bpMult[bk]; } if (e.reputation) pc.reputation = (pc.reputation || 0) + e.reputation; if (e.startRealm) { /* 已在基础流程处理 */ } if (e.wantedBy) { pc.wantedBy = true; } if (e.bondCap) pc.bondCap = Math.min(pc.bondCap, e.bondCap); if (e.dao && !pc.daoBias) pc.daoBias = e.dao; }); /* 应用体质倍率 */ if (pc.hpMult) { pc.hpMax = Math.round(pc.hpMax * pc.hpMult); pc.hp = pc.hpMax; } if (pc.powerFlat) pc.powerFlatBonus = pc.powerFlat; pc.combat = this.calcPower(pc); /* 缺陷写入开档信息 */ o.flaws = pc.flaws.slice(); return o; }; /* 战力计算叠加天赋/缺陷修正 */ var _origCalcPower = Game.prototype.calcPower; Game.prototype.calcPower = function (pc) { var p = _origCalcPower.call(this, pc); if (pc.powerMult) p *= pc.powerMult; if (pc.powerFlatBonus) p *= (1 + pc.powerFlatBonus); if (pc.burstTurns > 0) p *= 2; if (pc.bpHollow) p *= (1 - pc.bpHollow * 0.04); return Math.max(1, Math.round(p)); }; /* 掷骰支持强制成功 / 气运倍率 / 缺陷惩罚 */ var _origDice = Game.prototype.dice; Game.prototype.dice = function (baseRate, opts) { var d = _origDice.call(this, baseRate, opts); var pc = this.pc; if (pc.luckMult) d.rate = E.clamp(d.rate * pc.luckMult, 0.02, 0.98); if (pc.flaws && pc.flaws.some(function (f) { return f.fx && f.fx.curse === 'luckdebt'; })) d.rate = E.clamp(d.rate * 0.88, 0.02, 0.98); if ((pc.forceSuccess || 0) > 0) { pc.forceSuccess--; d.result = 'great'; d.forced = true; } return d; }; /* 突破支持抵消天劫 */ var _origBreak = Game.prototype.tryBreakthrough; Game.prototype.tryBreakthrough = function () { var pc = this.pc; if ((pc.tribSkip || 0) > 0) { pc.tribSkip--; var savedNoTrib = pc.noTrib; pc.noTrib = true; var r = _origBreak.call(this); pc.noTrib = savedNoTrib; if (r && r.txt) r.txt = '【天道点·抵消天劫】' + r.txt + '
你欠天道的这一次,会在下一次连本带利收回来。'; return r; } return _origBreak.call(this); }; /* 岁月流逝扣减爆发回合 */ var _origPassYears = Game.prototype.passYears; Game.prototype.passYears = function (years, reason) { if (this.pc && this.pc.burstTurns) this.pc.burstTurns = 0; return _origPassYears.call(this, years, reason); }; /* 存档包含新增字段 */ var _origSave = Game.prototype.makeSaveCode; Game.prototype.makeSaveCode = function () { var r = _origSave.call(this); if (r.payload) { r.payload.tianPoints = this.pc.tianPoints || 0; r.payload.flaws = (this.pc.flaws || []).map(function (f) { return f.id; }); r.payload.myForce = this.myForce || null; r.payload.poolSeed = this.poolSeed || null; } if (r.code) { try { r.code = 'DDWJ21-' + btoa(encodeURIComponent(JSON.stringify(r.payload)).replace(/%([0-9A-F]{2})/g, function (_, p1) { return String.fromCharCode(parseInt(p1, 16)); })); } catch (e) { /* 保留原码 */ } } return r; }; var _origLoad = Game.loadFromCode; Game.loadFromCode = function (code) { var g = _origLoad(code); if (g && g.pc) { var p = null; try { var raw = String(code).replace(/^DDWJ21-/, ''); p = JSON.parse(decodeURIComponent(Array.prototype.map.call(atob(raw), function (c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }).join(''))); } catch (e) { p = null; } g.pc.tianPoints = (p && p.tianPoints) || 0; var fids = (p && p.flaws) || []; g.pc.flaws = fids.map(function (id) { var f = D.FLAWS.filter(function (x) { return x.id === id; })[0] || D.TALENTS.filter(function (x) { return x.id === id; })[0]; return f ? { id: f.id, name: f.name, desc: f.desc, fx: f.fx || f.effect || {} } : { id: id, name: id, desc: '', fx: {} }; }); g.myForce = (p && p.myForce) || null; g.poolSeed = (p && p.poolSeed) || null; g.pc.burstTurns = 0; pc_sync(g); } return g; }; function pc_sync(g) { if (g && g.pc) g.pc.combat = g.calcPower(g.pc); } /* ============================================================ SECTION: api ============================================================ */ return { Pool: Pool, buildSemiCandidates: buildSemiCandidates, buildFullRandom: buildFullRandom, keywordAnchors: keywordAnchors, IDENTITY_TYPES: D.IDENTITY_TYPES, TIAN_SHOP: D.TIAN_SHOP, TIAN_EARN: D.TIAN_EARN }; })();