0.2.4-dev: round-29 community fixes and the official shared card pool
- Shared card pool and item stock as in the official mode (the owner's request, from the 路标档案馆 video and public notes): solo low-tier exceptions, co-op operators x2, shared item stock with special-item exceptions, normal / advanced occupancy 1 / 2, re-check on buy, 机变 exhaustion, release on consume / destroy / elimination; 整备 never exceeds stock; invariant held <= cap. - 突袭: one taunt-first reselect right after a revive (the owner's rule); ordinary polls and redeploys keep the 0.2.3 rule; a revive on an enemy's tile stays. #475: online boss / hidden-boss Raid may land on the empty half (owner-limited scope). - 浊心斯卡蒂 S1 x 坚守 no longer bounce redirected damage, and the two shares conserve the hit (idea of PR #464 by @HappyTanuki). - Operator fixes adapted from PRs by @Xinglan233 (#459 哈洛德 S2 elemental trigger, #460 涤火杰西卡 shield on the four adjacent tiles, #461 家族徽章 first hit after stealth, #462 松果 S2 regrow per deploy); 克莱门莎 S2 splash 1.1 / 100% ATK and air auto-trigger (#467); 白面 copying 歌蕾蒂娅 / 余 skips the three-member condition (#473, the owner's video). - 香槟炸弹 is not chosen by friendly auras / heals (PR #468 / #476 by @Siornya); 琳琅诗怀雅 coin balance (PR #450 by @IceCodeNew); Touch prep display (PR #451 by @YinqiMargatroid); lobby header (PR #471 by @YuriRestia); Japanese UI terms (PR #448 by @scutkane). - AI-only boss countdown grace, render-failure cache / recovery without restarting a battle, device units kept on a same-field re-entry, DIY detail / skill previews, large-text result buttons. - golden: battle families equal 0.2.3 except diy-135 / diy-136 (克莱门莎); all 18 release matches move through the shared pool, every flip named in docs/history/0.2.4.md §29.12; two coverage scenarios added.
This commit is contained in:
1 parent
1db8e51023
commit
6bfc08270c
129 files changed
+3477
-1011
No files matched your search
+10
-7
@@ -136,12 +136,12 @@ function itemCard(gd, id) {
|
||||
* Build the draft cards for an SP round.
|
||||
* @returns {{ family: string, name: string, desc: string, eventId: string|null, cards: object[] } | null}
|
||||
*/
|
||||
export function generateDraft(gd, rng, round, { stageId = null, bondAvailable = null } = {}) {
|
||||
export function generateDraft(gd, rng, round, { stageId = null, bondAvailable = null, itemAvailable = null } = {}) {
|
||||
const sch = scheduleFor(gd, round);
|
||||
const fams = Array.isArray(sch.families) && sch.families.length ? sch.families.map((f) => [f.family, f.weight]) : [['supply', 1]];
|
||||
let family = weightedPick(rng, fams) || 'supply';
|
||||
const n = Number.isInteger(sch.cards) && sch.cards > 0 ? Math.min(sch.cards, 6) : formatCount(gd);
|
||||
const opts = { stageId, bondAvailable, round };
|
||||
const opts = { stageId, bondAvailable, round, itemAvailable };
|
||||
let cards = buildCards(gd, rng, family, n, sch, opts);
|
||||
if (!cards.length && family !== 'supply') { family = 'supply'; cards = buildCards(gd, rng, family, n, sch, opts); }
|
||||
if (!cards.length) return null;
|
||||
@@ -328,16 +328,17 @@ function bountyDraftCards(gd, rng, n, sch, round) {
|
||||
* the nearest lower one, then any) — so one item can fill two slots. Positions shuffled; `n` < the slots (solo) keeps
|
||||
* `n` of them. Null without a usable `shopDraft` or at a round its `rounds` (when given) does not list.
|
||||
*/
|
||||
export function shopDraftCards(gd, rng, n, round = null) {
|
||||
export function shopDraftCards(gd, rng, n, round = null, itemAvailable = null) {
|
||||
const spec = gd.choices.shopDraft;
|
||||
const slots = spec && Array.isArray(spec.slots) ? spec.slots.filter((x) => x && typeof x === 'object') : [];
|
||||
if (!slots.length) return null;
|
||||
if (Array.isArray(spec.rounds) && !spec.rounds.includes(round)) return null;
|
||||
const w = spec.itemWeights && typeof spec.itemWeights === 'object' ? spec.itemWeights : {};
|
||||
const coin = typeof spec.coin === 'string' && gd.item(spec.coin) ? spec.coin : null;
|
||||
const free = list => itemAvailable ? list.filter(itemAvailable) : list;
|
||||
const ofTier = (t) => {
|
||||
for (let k = t; k >= 1; k--) if ((gd.shopItemsByTier[k] || []).length) return gd.shopItemsByTier[k];
|
||||
return eligibleItems(gd, 1, 6);
|
||||
for (let k = t; k >= 1; k--) { const list = free(gd.shopItemsByTier[k] || []); if (list.length) return list; }
|
||||
return free(eligibleItems(gd, 1, 6));
|
||||
};
|
||||
const out = [];
|
||||
for (const slot of slots) {
|
||||
@@ -382,10 +383,10 @@ export function tacticDraftCards(gd, rng, n, { stageId = null, bondAvailable = n
|
||||
return out;
|
||||
}
|
||||
|
||||
function buildCards(gd, rng, family, n, sch, { stageId = null, bondAvailable = null, round = 1 } = {}) {
|
||||
function buildCards(gd, rng, family, n, sch, { stageId = null, bondAvailable = null, round = 1, itemAvailable = null } = {}) {
|
||||
if (family === 'bounty') return bountyDraftCards(gd, rng, n, sch, round);
|
||||
if (family === 'shop') {
|
||||
const cards = shopDraftCards(gd, rng, n, round);
|
||||
const cards = shopDraftCards(gd, rng, n, round, itemAvailable);
|
||||
if (cards) return cards;
|
||||
}
|
||||
if (family === 'supply' || family === 'shop') {
|
||||
@@ -393,7 +394,9 @@ function buildCards(gd, rng, family, n, sch, { stageId = null, bondAvailable = n
|
||||
let hi = 6;
|
||||
if (family === 'supply' && Array.isArray(sch.supplyTiers) && sch.supplyTiers.length === 2) [lo, hi] = sch.supplyTiers;
|
||||
let list = eligibleItems(gd, lo, hi);
|
||||
if (itemAvailable) list = list.filter(itemAvailable);
|
||||
if (!list.length) list = eligibleItems(gd, 1, 6);
|
||||
if (itemAvailable) list = list.filter(itemAvailable);
|
||||
const out = [];
|
||||
for (let i = 0; i < n && list.length; i++) out.push(itemCard(gd, list[Math.floor(rng() * list.length)]));
|
||||
return out;
|
||||
|
||||
Reference in new issue
Block a user