mirror of
https://github.com/Shu-Ying/noname-shuying.git
synced 2026-10-11 03:20:01 +08:00
243 lines
11 KiB
JavaScript
243 lines
11 KiB
JavaScript
import { createCardData } from "../cards/card-data.js";
|
|
|
|
// 梦三怪物规则只作用于敌方单位;子类可覆盖构造参数或 createDeck()。
|
|
const TIER_RULES = Object.freeze({
|
|
normal: Object.freeze({ draw: 1, handLimit: 3, energy: 2 }),
|
|
elite: Object.freeze({ draw: 2, handLimit: 5, energy: 3 }),
|
|
boss: Object.freeze({ draw: 3, handLimit: 7, energy: 4 }),
|
|
});
|
|
|
|
const BASE_DECKS = Object.freeze({
|
|
normal: Object.freeze(["sha", "sha", "sha", "sha", "shan", "shan", "tao", "jiu", "sha"]),
|
|
elite: Object.freeze(["sha", "sha", "sha", "sha", "shan", "shan", "shan", "tao", "jiu", "juedou", "wuzhong", "guohe"]),
|
|
boss: Object.freeze(["sha", "sha", "sha", "sha", "sha", "shan", "shan", "shan", "tao", "jiu", "juedou", "wuzhong", "guohe"]),
|
|
});
|
|
|
|
const HEALTH = Object.freeze({
|
|
mengsan_soldier_shuying: 24,
|
|
mengsan_flyconid_shuying: 48,
|
|
mengsan_fogmog_shuying: 74, mengsan_eye_with_teeth_shuying: 6,
|
|
mengsan_mawler_shuying: 72,
|
|
mengsan_vine_shambler_shuying: 61,
|
|
mengsan_nibbit_shuying: 44,
|
|
mengsan_cubex_construct_shuying: 65,
|
|
mengsan_byrdonis_shuying: 82,
|
|
mengsan_bygone_effigy_shuying: 127,
|
|
mengsan_vantom_shuying: 173,
|
|
mengsan_ceremonial_beast_shuying: 252,
|
|
mengsan_kin_priest_shuying: 190, mengsan_kin_follower_shuying: 59,
|
|
mengsan_phrog_parasite_shuying: 62,
|
|
mengsan_wriggler_shuying: 19,
|
|
mengsan_shrinker_beetle_shuying: 39,
|
|
mengsan_twig_slime_m_shuying: 27,
|
|
mengsan_twig_slime_s_shuying: 9,
|
|
mengsan_leaf_slime_m_shuying: 34,
|
|
mengsan_leaf_slime_s_shuying: 13,
|
|
mengsan_slithering_strangler_shuying: 54,
|
|
mengsan_snapping_jaxfruit_shuying: 32,
|
|
mengsan_inklet_shuying: 14,
|
|
mengsan_fuzzy_wurm_crawler_shuying: 56,
|
|
mengsan_raider_brute_shuying: 32,
|
|
mengsan_raider_assassin_shuying: 21,
|
|
mengsan_raider_axe_shuying: 21,
|
|
mengsan_raider_crossbow_shuying: 20,
|
|
mengsan_raider_tracker_shuying: 23,
|
|
re_xiahoudun: 30, re_zhangliao: 28, re_xuzhu: 34, re_lvbu: 120,
|
|
re_ganning: 39, re_zhangfei: 42, re_huangzhong: 37, re_weiyan: 40,
|
|
re_guanyu: 65, dianwei: 62, shen_guanyu: 165,
|
|
re_simayi: 47, re_sunben: 49, dongzhuo: 55, re_yuanshao: 52,
|
|
shen_zhaoyun: 76, shen_simayi: 80, shen_caocao: 210,
|
|
});
|
|
const validDeckCard = entry => typeof entry === "string" ? Boolean(entry) : Boolean(entry &&
|
|
typeof entry.name === "string" && entry.name &&
|
|
(entry.suit == null || ["spade", "heart", "club", "diamond"].includes(entry.suit)) &&
|
|
(entry.number == null || Number.isInteger(entry.number) && entry.number >= 1 && entry.number <= 13));
|
|
|
|
export class Monster {
|
|
constructor({ character, tier = "normal", hp, deck, draw, handLimit, energy } = {}) {
|
|
if (!TIER_RULES[tier]) throw new Error("梦三怪物阶级无效:" + tier);
|
|
if (typeof character !== "string" || !character) throw new Error("梦三怪物缺少武将ID");
|
|
const defaults = TIER_RULES[tier];
|
|
this.character = character;
|
|
this.tier = tier;
|
|
this.hp = hp ?? HEALTH[character] ?? (tier === "boss" ? 110 : tier === "elite" ? 60 : 32);
|
|
this.draw = draw ?? defaults.draw;
|
|
this.handLimit = handLimit ?? defaults.handLimit;
|
|
this.energy = energy ?? defaults.energy;
|
|
this.deck = deck || BASE_DECKS[tier];
|
|
if (![this.hp, this.draw, this.handLimit, this.energy].every(value => Number.isInteger(value) && value > 0)) throw new Error("梦三怪物数值无效");
|
|
if (!Array.isArray(this.deck) || !this.deck.length || this.deck.some(entry => !validDeckCard(entry))) throw new Error("梦三怪物牌堆无效");
|
|
}
|
|
|
|
createDeck(prefix) {
|
|
return this.deck.map((entry, index) => {
|
|
const card = typeof entry === "string" ? { name: entry } : entry;
|
|
return createCardData({
|
|
id: `${prefix}_${index}`, name: card.name,
|
|
suit: card.suit || ["spade", "heart", "club", "diamond"][index % 4],
|
|
number: card.number || index % 13 + 1,
|
|
nature: card.nature || null, affixes: Array.isArray(card.affixes) ? card.affixes.slice() : [], upgrade: card.upgrade || 0,
|
|
}, { enemy: true });
|
|
});
|
|
}
|
|
}
|
|
|
|
// 专属怪物示例:以后可在子类中覆写任意默认行为。
|
|
export class OpeningSoldier extends Monster {
|
|
constructor(options = {}) { super({ character: "mengsan_soldier_shuying", tier: "normal", hp: 24, ...options }); }
|
|
}
|
|
export class Flyconid extends Monster {
|
|
constructor(options = {}) { super({ ...options, character: "mengsan_flyconid_shuying", tier: "normal", hp: 48 }); }
|
|
}
|
|
export class FuzzyWurmCrawler extends Monster {
|
|
constructor(options = {}) {
|
|
super({ ...options, character: "mengsan_fuzzy_wurm_crawler_shuying", tier: "normal", hp: options.hp ?? 56 });
|
|
}
|
|
}
|
|
export class Inklet extends Monster {
|
|
constructor(options = {}) {
|
|
super({ ...options, character: "mengsan_inklet_shuying", tier: "normal", hp: options.hp ?? 14 });
|
|
}
|
|
}
|
|
export class SnappingJaxfruit extends Monster {
|
|
constructor(options = {}) {
|
|
super({ ...options, character: "mengsan_snapping_jaxfruit_shuying", tier: "normal", hp: options.hp ?? 32 });
|
|
}
|
|
}
|
|
export class SlitheringStrangler extends Monster {
|
|
constructor(options = {}) {
|
|
super({ ...options, character: "mengsan_slithering_strangler_shuying", tier: "normal", hp: options.hp ?? 54 });
|
|
}
|
|
}
|
|
export class LeafSlimeSmall extends Monster {
|
|
constructor(options = {}) {
|
|
super({ ...options, character: "mengsan_leaf_slime_s_shuying", tier: "normal", hp: options.hp ?? 13 });
|
|
}
|
|
}
|
|
export class LeafSlimeMedium extends Monster {
|
|
constructor(options = {}) {
|
|
super({ ...options, character: "mengsan_leaf_slime_m_shuying", tier: "normal", hp: options.hp ?? 34 });
|
|
}
|
|
}
|
|
export class TwigSlimeSmall extends Monster {
|
|
constructor(options = {}) {
|
|
super({ ...options, character: "mengsan_twig_slime_s_shuying", tier: "normal", hp: options.hp ?? 9 });
|
|
}
|
|
}
|
|
export class TwigSlimeMedium extends Monster {
|
|
constructor(options = {}) {
|
|
super({ ...options, character: "mengsan_twig_slime_m_shuying", tier: "normal", hp: options.hp ?? 27 });
|
|
}
|
|
}
|
|
export class ShrinkerBeetle extends Monster {
|
|
constructor(options = {}) {
|
|
super({ ...options, character: "mengsan_shrinker_beetle_shuying", tier: "normal", hp: options.hp ?? 39 });
|
|
}
|
|
}
|
|
export class PhrogParasite extends Monster {
|
|
constructor(options = {}) { super({ ...options, character: "mengsan_phrog_parasite_shuying", tier: "elite", hp: options.hp ?? 62 }); }
|
|
}
|
|
export class Wriggler extends Monster {
|
|
constructor(options = {}) { super({ ...options, character: "mengsan_wriggler_shuying", tier: "elite", hp: options.hp ?? 19 }); }
|
|
}
|
|
export class CeremonialBeast extends Monster {
|
|
constructor(options = {}) { super({ ...options, character: "mengsan_ceremonial_beast_shuying", tier: "boss", hp: options.hp ?? 252 }); }
|
|
}
|
|
export class KinPriest extends Monster {
|
|
constructor(options = {}) { super({ ...options, character: "mengsan_kin_priest_shuying", tier: "boss", hp: options.hp ?? 190 }); }
|
|
}
|
|
export class KinFollower extends Monster {
|
|
constructor(options = {}) { super({ ...options, character: "mengsan_kin_follower_shuying", tier: "normal", hp: options.hp ?? 59 }); }
|
|
}
|
|
export class Vantom extends Monster {
|
|
constructor(options = {}) {
|
|
super({ ...options, character: "mengsan_vantom_shuying", tier: "boss", hp: options.hp ?? 173 });
|
|
}
|
|
}
|
|
export class BygoneEffigy extends Monster {
|
|
constructor(options = {}) {
|
|
super({ ...options, character: "mengsan_bygone_effigy_shuying", tier: "elite", hp: options.hp ?? 127 });
|
|
}
|
|
}
|
|
export class Byrdonis extends Monster {
|
|
constructor(options = {}) {
|
|
super({ ...options, character: "mengsan_byrdonis_shuying", tier: "elite", hp: options.hp ?? 82 });
|
|
}
|
|
}
|
|
export class CubexConstruct extends Monster {
|
|
constructor(options = {}) {
|
|
super({ ...options, character: "mengsan_cubex_construct_shuying", tier: "normal", hp: options.hp ?? 65 });
|
|
}
|
|
}
|
|
export class Nibbit extends Monster {
|
|
constructor(options = {}) {
|
|
super({ ...options, character: "mengsan_nibbit_shuying", tier: "normal", hp: options.hp ?? 44 });
|
|
}
|
|
}
|
|
export class VineShambler extends Monster {
|
|
constructor(options = {}) {
|
|
super({ ...options, character: "mengsan_vine_shambler_shuying", tier: "normal", hp: options.hp ?? 61 });
|
|
}
|
|
}
|
|
export class Mawler extends Monster {
|
|
constructor(options = {}) { super({ ...options, character: "mengsan_mawler_shuying", tier: "normal", hp: 72 }); }
|
|
}
|
|
export class Fogmog extends Monster {
|
|
constructor(options = {}) { super({ ...options, character: "mengsan_fogmog_shuying", tier: "normal", hp: 74 }); }
|
|
}
|
|
export class EyeWithTeeth extends Monster {
|
|
constructor(options = {}) {
|
|
super({ ...options, character: "mengsan_eye_with_teeth_shuying", tier: "normal", hp: 6, energy: 1, handLimit: 1 });
|
|
this.draw = 0;
|
|
}
|
|
createDeck() { return []; } // 爪牙仅发动牵制,不额外抽取或打出三国杀牌。
|
|
}
|
|
const raiderClass = (character, hp) => class extends Monster {
|
|
constructor(options = {}) { super({ ...options, character, tier: "normal", hp }); }
|
|
};
|
|
export const RaiderBrute = raiderClass("mengsan_raider_brute_shuying", 32);
|
|
export const RaiderAssassin = raiderClass("mengsan_raider_assassin_shuying", 21);
|
|
export const RaiderAxe = raiderClass("mengsan_raider_axe_shuying", 21);
|
|
export const RaiderCrossbow = raiderClass("mengsan_raider_crossbow_shuying", 20);
|
|
export const RaiderTracker = raiderClass("mengsan_raider_tracker_shuying", 23);
|
|
|
|
// 新怪物子类在这里注册,未注册的角色使用 Monster 的阶级默认值。
|
|
export const MONSTER_TYPES = Object.freeze({
|
|
mengsan_soldier_shuying: OpeningSoldier,
|
|
mengsan_flyconid_shuying: Flyconid,
|
|
mengsan_fogmog_shuying: Fogmog,
|
|
mengsan_mawler_shuying: Mawler,
|
|
mengsan_vine_shambler_shuying: VineShambler,
|
|
mengsan_nibbit_shuying: Nibbit,
|
|
mengsan_cubex_construct_shuying: CubexConstruct,
|
|
mengsan_byrdonis_shuying: Byrdonis,
|
|
mengsan_bygone_effigy_shuying: BygoneEffigy,
|
|
mengsan_vantom_shuying: Vantom,
|
|
mengsan_ceremonial_beast_shuying: CeremonialBeast,
|
|
mengsan_kin_priest_shuying: KinPriest, mengsan_kin_follower_shuying: KinFollower,
|
|
mengsan_phrog_parasite_shuying: PhrogParasite,
|
|
mengsan_wriggler_shuying: Wriggler,
|
|
mengsan_shrinker_beetle_shuying: ShrinkerBeetle,
|
|
mengsan_twig_slime_m_shuying: TwigSlimeMedium,
|
|
mengsan_twig_slime_s_shuying: TwigSlimeSmall,
|
|
mengsan_leaf_slime_m_shuying: LeafSlimeMedium,
|
|
mengsan_leaf_slime_s_shuying: LeafSlimeSmall,
|
|
mengsan_slithering_strangler_shuying: SlitheringStrangler,
|
|
mengsan_snapping_jaxfruit_shuying: SnappingJaxfruit,
|
|
mengsan_inklet_shuying: Inklet,
|
|
mengsan_fuzzy_wurm_crawler_shuying: FuzzyWurmCrawler,
|
|
mengsan_eye_with_teeth_shuying: EyeWithTeeth,
|
|
mengsan_raider_brute_shuying: RaiderBrute,
|
|
mengsan_raider_assassin_shuying: RaiderAssassin,
|
|
mengsan_raider_axe_shuying: RaiderAxe,
|
|
mengsan_raider_crossbow_shuying: RaiderCrossbow,
|
|
mengsan_raider_tracker_shuying: RaiderTracker,
|
|
});
|
|
|
|
export function createMonster(spec) {
|
|
const Type = Object.hasOwn(MONSTER_TYPES, spec.character) ? MONSTER_TYPES[spec.character] : Monster;
|
|
return new Type(spec);
|
|
}
|
|
|
|
export { TIER_RULES, BASE_DECKS };
|