Files
pixelheros/assets/script/game/common/config/GameSet.ts
pan 5fe961846f feat(victory): add defeat reward gate by clear time and kill ratio
Defeat rewards now require surviving 15s and killing at least one
monster. Qualified defeats grant a fixed survive reward plus a
kill-ratio-scaled bonus; unqualified defeats yield nothing.
Victory rewards remain unchanged.
2026-09-11 15:57:21 +08:00

257 lines
8.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Color } from "cc";
/** 碰撞分组 */
export enum BoxSet {
//物理碰撞tag
SKILL_TAG = 8,
ATK_RANGE = 4,
//group
DEFAULT = 1,
MONSTER = 2,
HERO = 4,
//地图边界
LETF_END = -320,
RIGHT_END = 320,
//游戏地平线
GAME_LINE = 10,
/** 技能/装备各自独立的上限 */
BOX_MAX = 6,
}
export enum FacSet {
HERO = 0,
MON = 1,
}
export enum FightSet {
/** 英雄三排出生/编队基准 x(y 均为 BoxSet.GAME_LINE):前排迎敌、中排、后排靠左 */
HERO_ROW_FRONT_X = -200, // 前排(最靠右迎敌):坦克 / 战士
HERO_ROW_MID_X = -260, // 中排:刺客 / 射手
HERO_ROW_BACK_X = -320, // 后排(最靠左):法师 / 辅助
/** 怪物三排出生/编队基准 x(y 均为 BoxSet.GAME_LINE):前排迎敌、中排、后排靠右 */
MON_ROW_FRONT_X = 200, // 前排(最靠左迎敌):近战 / 重型 / 近战Boss
MON_ROW_MID_X = 260, // 中排:远程 / 刺客 / 远程Boss
MON_ROW_BACK_X = 320, // 后排(最靠右):辅助 / 召唤师
WAVE_COIN_BASE = 7, // 回合金币基础奖励
WAVE_COIN_GROW = 2, // 回合金币递增值
WAVE_COIN_MAX = 17, // 回合金币最大基础奖励
CRIT_DAMAGE = 50,//暴击伤害
MORE_RC = 10,//更多次数 广告获取的次数
HEARTPOS = -320,//基地位置
/** 场上英雄编制数:由开局 3 次三选一固定,玩家无法扩充 */
HERO_FIELD_NUM = 3,
/** 英雄可升级到的最高等级(通过升级卡提升),99 近似无限升级 */
HERO_MAX_LV = 99,
/** 英雄技能等级上限(无限升级下技能 5 级封顶,超出等级只长属性) */
HERO_SKILL_MAX_LV = 5,
/** 英雄属性随等级成长的倍率(ap/hp = base * MULTIPLIER^(lv-1)) */
HERO_LV_MULTIPLIER = 2,
// BACK_RANG=30,//后退范围
BACK_RANG = 20,//后退范围
FiIGHT_TIME = 30,//战斗时间
FROST_TIME = 3,//冰冻时间
STUN_TIME = 1,//击晕时间(短控:施加瞬间 CD 削减,期间 CD 停止增长)
/** 麻痹持续时间(秒) */
PARALYZE_TIME = 5,
/** 麻痹对技能 CD 增长的基础减速量(百分点,可被麻痹强化 buff 提升,达 100 则停止增长) */
PARALYZE_CD_SLOW = 50,
/** 击晕施加瞬间的技能 CD 削减量(百分点,20 表示 ccd × 0.8) */
STUN_CD_CUT = 20,
SKILL_CAST_DELAY = 0.15,
/** 多发/召唤技能每次实例化之间的间隔(秒),首个立即执行 */
SUMMON_INTERVAL = 0.12,
CSKILL_START_X = -340,
CSKILL_START_Y = 30,
/** 护盾数值上限(数值减免型:1 点护盾吸收 1 点伤害) */
SHIELD_MAX = 5,
/** 防御减伤平衡常数:减伤率 = defense / (defense + DEFENSE_K),K 越大每点防御收益越低 */
DEFENSE_K = 500,
WAVE_HEAL_RATE = 0.4, // 回合结束时所有英雄恢复最大生命值的比例(与 DDA 放水兜底分层:回血保节奏,放水防崩盘)
PUNCTURE_DOWN = 50,
/** 穿透伤害衰减系数:单体技能命中第2个及以后目标时按此比例折算伤害 */
PUNCTURE_DMG_RATIO = 0.5,
REFRESH_COST = 2,
BASE_COST = 5,
INIT_COIN = 7, // 初始金币数
/** 单次刷新卡牌消耗的银币数量 */
SILVER_REFRESH_COST = 1,
/** 全局默认闪避率(百分点),heroSet 未配置时生效 */
DEFAULT_DODGE = 15,
/** 全局默认命中率(百分点),heroSet 未配置时生效 */
DEFAULT_ACCURACY = 10,
}
/**
* 英雄局外等级升级所需碎片数量(key 为目标等级)。
* 查询方式:HERO_UPGRADE_NEED_FRAGMENTS[growth.lv + 1],即升到下一级所需的碎片数。
* 局外等级独立于局内战斗等级,持久化保存于 smc.data.hero_growth。
*/
export const HERO_UPGRADE_NEED_FRAGMENTS: Record<number, number> = {
2: 10,
3: 30,
4: 50,
5: 70,
6: 90,
7: 110,
8: 130,
9: 150,
10: 170,
11: 190,
12: 210,
13: 230,
14: 250,
15: 270,
16: 290,
};
/**
* 技能卡牌出现的回合配置(单一数据源)。
* 数组索引 i 对应卡牌档位 rarity = i + 1:
* - 第 1 个回合 → LV1 档(基础强度)
* - 第 2 个回合 → LV2 档(强度 ×2)
* - 第 3 个回合 → LV3 档(强度 ×3)
* 需与 CardSet.SkillCardData 的 wave 字段严格对齐,否则抽卡时池子为空。
*/
export const SKILL_CARD_WAVES: number[] = [1, 5, 8];
export const laneIdx = {
2: [-180, 90],
1: [-180, 0],
3: [-180, -90],
5: [-280, 90],
4: [-280, 0],
6: [-280, -90],
}
export enum IndexSet {
/** 英雄基础层级 */
HERO = -2000,
/** 一线怪物基础层级(y=120) - 层级较低,在后面 */
MON1 = 1000,
/** 二线怪物基础层级(y=80) - 层级较高,在前面 */
MON2 = -3000,
/** 每个怪物的层级增量,确保后生成的在前面 */
MON_INCREMENT = 1,
SLILL = 4000,
BOSS = 2100,
}
export const TooltipTypes = {
life: 1,
health: 2,
skill: 3,
crit: 4,
uskill: 5,
lvup: 6,
apup: 7,
hpup: 8,
addmp: 9,
shield: 10,
miss: 11,
/** 通用文字飘字(闪避/格挡/免疫等),文字与颜色由调用方传入 */
tip: 12,
}
/** 数字格式化工具函数 */
export class NumberFormatter {
/**
* 将数字转换为易读格式
* @param num 要转换的数字
* @returns 格式化后的字符串
* 例如:1234 -> "1.2k", 1234567 -> "1.2M", 1234567890 -> "1.2B"
*/
static formatNumber(num: number): string {
if (num < 1000) {
return num.toString();
} else if (num < 1000000) {
// 5位数用k表示 (1000-999999)
return (num / 1000).toFixed(1).replace(/\.0$/, '') + 'k';
} else if (num < 1000000000) {
// 7位数用M表示 (1000000-999999999)
return (num / 1000000).toFixed(1).replace(/\.0$/, '') + 'M';
} else if (num < 1000000000000) {
// 10位数用B表示 (1000000000-999999999999)
return (num / 1000000000).toFixed(1).replace(/\.0$/, '') + 'B';
} else {
// 更大的数字用T表示
return (num / 1000000000000).toFixed(1).replace(/\.0$/, '') + 'T';
}
}
/**
* 将数字转换为中文格式
* @param num 要转换的数字
* @returns 中文格式的字符串
* 例如:1234 -> "1.2千", 1234567 -> "1.2百万"
*/
static formatNumberChinese(num: number): string {
if (num < 10000) {
return num.toString();
} else if (num < 100000000) {
// 万级别
return (num / 10000).toFixed(1).replace(/\.0$/, '') + '万';
} else if (num < 1000000000000) {
// 亿级别
return (num / 100000000).toFixed(1).replace(/\.0$/, '') + '亿';
} else {
// 万亿级别
return (num / 1000000000000).toFixed(1).replace(/\.0$/, '') + '万亿';
}
}
}
export function getLvColor(lv: number): Color {
switch (lv) {
case 2: return new Color("#2ECC71");
case 3: return new Color("#3498DB");
case 4: return new Color("#9B59B6");
case 5: return new Color("#F1C40F");
case 6: return new Color("#E74C3C");
default: return Color.WHITE;
}
}
/**
* rarity → 背景颜色节点名映射:1=green 2=blue 3=purple 4=yellow 5=red
* 用于 BG_node 下子节点的显隐切换
*/
export const RARITY_BG_COLORS: string[] = ["green", "blue", "purple", "yellow", "red"];
/**
* 战斗结算奖励配置(每局结束后发放:英雄碎片 + 金币 + 天赋经验)。
* 数值均为"失败基准",胜利时整体乘以 victory_multiplier。
*/
export const VICTORY_REWARD_SET = {
/** 金币:base + wave_win_count × per_wave */
gold: { base: 100, per_wave: 50 },
/** 天赋经验:base + wave_win_count × per_wave */
talent_exp: { base: 20, per_wave: 10 },
/** 每个出场英雄保底碎片数 */
played_fragment: 1,
/** 随机英雄碎片数量(发放给随机抽中的 1 个英雄) */
random_fragment: 2,
/** 银币:固定发放,不分输赢 */
silver: 3,
/** 钻石:按输赢在 [min, max] 闭区间内随机(不参与 victory_multiplier) */
diamond: {
victory: { min: 5, max: 10 },
defeat: { min: 1, max: 3 },
},
/** 胜利加成系数(失败 1.0) */
victory_multiplier: 1.2,
/**
* 失败奖励限制(不影响胜利):
* 坚持 < defeat_time_threshold 秒或本节一只怪未杀 → 无任何奖励;
* 达标后 = 坚持奖励(固定)+ 击杀比例奖励(基数 × 本节击杀比例)
*/
defeat: {
/** 坚持时间门槛(秒) */
time_threshold: 15,
/** 超门槛固定奖励("超 15 秒奖励") */
survive: { gold: 50, talent_exp: 10 },
/** 击杀比例奖励基数(本节怪物全灭时全额发放) */
kill: { gold: 150, talent_exp: 30 },
},
};