Compare commits
6 Commits
73214dbb10
...
2c306ff21a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c306ff21a | ||
|
|
0c9818ca27 | ||
|
|
efe6cc0dd7 | ||
|
|
c5d521136d | ||
|
|
27cd20c70d | ||
|
|
1855bcec4c |
@@ -2692,8 +2692,8 @@
|
||||
"height": 81,
|
||||
"rawWidth": 185,
|
||||
"rawHeight": 81,
|
||||
"borderTop": 0,
|
||||
"borderBottom": 0,
|
||||
"borderTop": 40,
|
||||
"borderBottom": 35,
|
||||
"borderLeft": 92,
|
||||
"borderRight": 92,
|
||||
"packable": true,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -35,19 +35,22 @@
|
||||
},
|
||||
{
|
||||
"__id__": 50
|
||||
},
|
||||
{
|
||||
"__id__": 56
|
||||
}
|
||||
],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 56
|
||||
"__id__": 62
|
||||
},
|
||||
{
|
||||
"__id__": 58
|
||||
"__id__": 64
|
||||
}
|
||||
],
|
||||
"_prefab": {
|
||||
"__id__": 60
|
||||
"__id__": 66
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
@@ -87,7 +90,7 @@
|
||||
"__id__": 1
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_active": false,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 3
|
||||
@@ -266,7 +269,7 @@
|
||||
"__id__": 11
|
||||
}
|
||||
],
|
||||
"_active": true,
|
||||
"_active": false,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 17
|
||||
@@ -608,7 +611,7 @@
|
||||
"__id__": 1
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_active": false,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 27
|
||||
@@ -783,7 +786,7 @@
|
||||
"__id__": 1
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_active": false,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 35
|
||||
@@ -958,7 +961,7 @@
|
||||
"__id__": 1
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_active": false,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 43
|
||||
@@ -1126,7 +1129,7 @@
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Node",
|
||||
"_name": "Label",
|
||||
"_name": "icon",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": {
|
||||
@@ -1145,6 +1148,145 @@
|
||||
"_prefab": {
|
||||
"__id__": 55
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 35,
|
||||
"z": 0
|
||||
},
|
||||
"_lrot": {
|
||||
"__type__": "cc.Quat",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0,
|
||||
"w": 1
|
||||
},
|
||||
"_lscale": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0.9,
|
||||
"y": 0.9,
|
||||
"z": 1
|
||||
},
|
||||
"_mobility": 0,
|
||||
"_layer": 1073741824,
|
||||
"_euler": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.UITransform",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 50
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 52
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 78,
|
||||
"height": 78
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0.5,
|
||||
"y": 0.5
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "0elb3r0slJwbY2BNC1zTKn"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Sprite",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 50
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 54
|
||||
},
|
||||
"_customMaterial": null,
|
||||
"_srcBlendFactor": 2,
|
||||
"_dstBlendFactor": 4,
|
||||
"_color": {
|
||||
"__type__": "cc.Color",
|
||||
"r": 255,
|
||||
"g": 255,
|
||||
"b": 255,
|
||||
"a": 255
|
||||
},
|
||||
"_spriteFrame": {
|
||||
"__uuid__": "031877cb-0f3d-4e92-bc5d-e492a0d95a08@d17da",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
"_type": 0,
|
||||
"_fillType": 0,
|
||||
"_sizeMode": 0,
|
||||
"_fillCenter": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"_fillStart": 0,
|
||||
"_fillRange": 0,
|
||||
"_isTrimmedMode": true,
|
||||
"_useGrayscale": false,
|
||||
"_atlas": {
|
||||
"__uuid__": "031877cb-0f3d-4e92-bc5d-e492a0d95a08",
|
||||
"__expectedType__": "cc.SpriteAtlas"
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "075wC9BqZNpKBHWkkHGa0w"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
"root": {
|
||||
"__id__": 1
|
||||
},
|
||||
"asset": {
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "a33ReyWcpAoZY5ieotS6Ir",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Node",
|
||||
"_name": "Label",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 57
|
||||
},
|
||||
{
|
||||
"__id__": 59
|
||||
}
|
||||
],
|
||||
"_prefab": {
|
||||
"__id__": 61
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
@@ -1180,16 +1322,16 @@
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 50
|
||||
"__id__": 56
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 52
|
||||
"__id__": 58
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 21.90380859375,
|
||||
"height": 58.4
|
||||
"width": 15.123046875,
|
||||
"height": 54.4
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
@@ -1208,11 +1350,11 @@
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 50
|
||||
"__id__": 56
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 54
|
||||
"__id__": 60
|
||||
},
|
||||
"_customMaterial": null,
|
||||
"_srcBlendFactor": 2,
|
||||
@@ -1227,8 +1369,8 @@
|
||||
"_string": "9",
|
||||
"_horizontalAlign": 1,
|
||||
"_verticalAlign": 1,
|
||||
"_actualFontSize": 25,
|
||||
"_fontSize": 25,
|
||||
"_actualFontSize": 20,
|
||||
"_fontSize": 20,
|
||||
"_fontFamily": "Arial",
|
||||
"_lineHeight": 40,
|
||||
"_overflow": 0,
|
||||
@@ -1237,7 +1379,7 @@
|
||||
"_isSystemFontUsed": true,
|
||||
"_spacingX": 0,
|
||||
"_isItalic": false,
|
||||
"_isBold": true,
|
||||
"_isBold": false,
|
||||
"_isUnderline": false,
|
||||
"_underlineHeight": 2,
|
||||
"_cacheMode": 0,
|
||||
@@ -1249,7 +1391,7 @@
|
||||
"b": 0,
|
||||
"a": 255
|
||||
},
|
||||
"_outlineWidth": 4,
|
||||
"_outlineWidth": 2,
|
||||
"_enableShadow": false,
|
||||
"_shadowColor": {
|
||||
"__type__": "cc.Color",
|
||||
@@ -1293,7 +1435,7 @@
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 57
|
||||
"__id__": 63
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
@@ -1321,13 +1463,13 @@
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 59
|
||||
"__id__": 65
|
||||
},
|
||||
"icon_node": {
|
||||
"__id__": 11
|
||||
"__id__": 50
|
||||
},
|
||||
"info_label": {
|
||||
"__id__": 53
|
||||
"__id__": 59
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
|
||||
@@ -2,6 +2,7 @@ import * as exp from "constants"
|
||||
import { HeroInfo, HeroList, HType } from "./heroSet"
|
||||
import { FightSet } from "./GameSet"
|
||||
import { oops } from "db://oops-framework/core/Oops"
|
||||
import { SkillOverrides, TGroup } from "./SkillSet"
|
||||
|
||||
class I18nString {
|
||||
constructor(private key: string, private params?: any[]) { }
|
||||
@@ -51,6 +52,7 @@ export interface CardConfig {
|
||||
weight: number
|
||||
kind: CKind
|
||||
pool_lv: CardLV
|
||||
wave?: number // 针对技能卡:仅在指定波次(wave)才能抽到
|
||||
hero_lv?: number
|
||||
card_lv?: number
|
||||
base_pool_lv?: number
|
||||
@@ -62,6 +64,7 @@ export interface CardConfig {
|
||||
t_times?: number // 触发次数
|
||||
t_inv?: number // 触发间隔(秒)
|
||||
keep_waves?: number // 维持的波次数(-1表示持续到战斗结束,0或undefined表示仅本波次)
|
||||
overrides?: SkillOverrides // 技能参数覆写(如自定义伤害ap、buff值、金币数等)
|
||||
}
|
||||
export const CardsUpSet: Record<number, number> = {
|
||||
1: 50,
|
||||
@@ -127,14 +130,19 @@ HeroList.forEach(uuid => {
|
||||
// 添加非英雄卡牌 (技能、功能卡)
|
||||
CardPoolList.push(
|
||||
// 技能卡牌 (以增益/辅助为主,因为在备战期没有敌人)
|
||||
{ uuid: 6401, type: CardType.Skill, cost: 0, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6401"), info: t("skill_info_6401"), is_inst: true, t_times: 1, t_inv: 0, keep_waves:15},
|
||||
{ uuid: 6402, type: CardType.Skill, cost: 0, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6402"), info: t("skill_info_6402"), is_inst: true, t_times: 1, t_inv: 0, keep_waves:15 },
|
||||
{ uuid: 6403, type: CardType.Skill, cost: 0, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6403"), info: t("skill_info_6403"), is_inst: true, t_times: 1, t_inv: 0, keep_waves:15 },
|
||||
{ uuid: 6404, type: CardType.Skill, cost: 0, weight: 20, pool_lv: 1, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6404"), info: t("skill_info_6404"), is_inst: true, t_times: 1, t_inv: 0, keep_waves:15 },
|
||||
{ uuid: 6405, type: CardType.Skill, cost: 0, weight: 20, pool_lv: 2, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6405"), info: t("skill_info_6405"), is_inst: true, t_times: 1, t_inv: 0, keep_waves:15 },
|
||||
{ uuid: 6406, type: CardType.Skill, cost: 0, weight: 20, pool_lv: 2, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6406"), info: t("skill_info_6406"), is_inst: true, t_times: 1, t_inv: 0, keep_waves:15 },
|
||||
{ uuid: 6304, type: CardType.Skill, cost: 0, weight: 20, pool_lv: 3, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6304"), info: t("skill_info_6304"), is_inst: true, t_times: 1, t_inv: 0, keep_waves:15 },
|
||||
{ uuid: 6305, type: CardType.Skill, cost: 0, weight: 20, pool_lv: 3, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6305"), info: t("skill_info_6305"), is_inst: true, t_times: 1, t_inv: 0, keep_waves:15 },
|
||||
{ uuid: 6304, type: CardType.Skill, cost: 0, weight: 20, pool_lv: 1, wave: 1, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6304"), info: t("skill_info_6304"), is_inst: true, t_times: 1, t_inv: 0, keep_waves: 15 },
|
||||
{ uuid: 6305, type: CardType.Skill, cost: 0, weight: 20, pool_lv: 1, wave: 1, kind: CKind.Skill, card_lv: 1, name: t("skill_name_6305"), info: t("skill_info_6305"), is_inst: true, t_times: 1, t_inv: 0, keep_waves: 15 },
|
||||
// 自定义 overrides 示例卡牌
|
||||
{
|
||||
uuid: 6401, type: CardType.Skill, cost: 0, weight: 10, pool_lv: 1, wave: 1, kind: CKind.Skill, card_lv: 1,
|
||||
name: "超强攻击强化", info: "使场上英雄增加50点攻击力",
|
||||
is_inst: true, t_times: 1, t_inv: 0, keep_waves: 15, overrides: { ap: 50 }
|
||||
},
|
||||
{
|
||||
uuid: 6101, type: CardType.Skill, cost: 0, weight: 10, pool_lv: 1, wave: 1, kind: CKind.Skill, card_lv: 1,
|
||||
name: "持续天降火球", info: "战斗中每隔3秒释放一个火球,造成300%伤害,持续2波次",
|
||||
is_inst: false, t_times: 999, t_inv: 3, keep_waves: 15, overrides: { TGroup: TGroup.Enemy, ap: 300, hit_count: 2 }
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -266,6 +274,7 @@ export const drawCardsByRule = (
|
||||
heroType?: HType
|
||||
heroLv?: number
|
||||
targetPoolLv?: number
|
||||
wave?: number
|
||||
} = {}
|
||||
): CardConfig[] => {
|
||||
const count = Math.max(0, Math.floor(options.count ?? 4))
|
||||
@@ -293,6 +302,18 @@ export const drawCardsByRule = (
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
// 如果传入了波次并且是技能卡,则根据 wave 过滤
|
||||
if (options.wave !== undefined) {
|
||||
pool = pool.filter(card => {
|
||||
if (card.type === CardType.Skill) {
|
||||
// 只有 wave 值严格等于当前 wave 的技能卡才会留在池中
|
||||
return card.wave === options.wave;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
}
|
||||
|
||||
const picked = pickCards(pool, count)
|
||||
return picked
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
|
||||
// 卡牌技能直接触发
|
||||
if (args.isCardSkill) {
|
||||
this.forceCastCardSkill(args.s_uuid, args.card_lv || 1, args.targetPos || new Vec3(FightSet.CSKILL_START_X, FightSet.CSKILL_START_Y, 0));
|
||||
this.forceCastCardSkill(args.s_uuid, args.card_lv || 1, args.targetPos || new Vec3(FightSet.CSKILL_START_X, FightSet.CSKILL_START_Y, 0), args.overrides);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -70,9 +70,10 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
* 强制执行卡牌技能
|
||||
* 卡牌技能没有施法者主体,直接从指定坐标释放,或者对全体/随机友方生效
|
||||
*/
|
||||
public forceCastCardSkill(s_uuid: number, cardLv: number, spawnPos: Vec3) {
|
||||
const config = SkillSet[s_uuid];
|
||||
public forceCastCardSkill(s_uuid: number, cardLv: number, spawnPos: Vec3, overrides?: SkillOverrides) {
|
||||
let config = SkillSet[s_uuid];
|
||||
if (!config) return;
|
||||
config = mergeSkillParams(config, overrides);
|
||||
|
||||
// 如果是敌方目标,没有战斗时不释放
|
||||
const isEnemyTarget = !this.isSelfSkill(config.TGroup) && !this.isFriendlySkill(config.TGroup);
|
||||
@@ -111,24 +112,49 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
mockAttrs.freeze_chance = 0;
|
||||
mockAttrs.puncture_chance = 0;
|
||||
mockAttrs.fac = FacSet.HERO;
|
||||
mockAttrs.type = HType.Long; // 假定为远程,拥有较长索敌范围
|
||||
mockAttrs.dis = 2000; // 给予全屏以上的索敌范围
|
||||
|
||||
let targetPos: Vec3 | null = null;
|
||||
if (!isFriendly) {
|
||||
// 伪造一个 view 供找敌逻辑使用,位置为 spawnPos
|
||||
const mockView = {
|
||||
node: { position: spawnPos }
|
||||
} as any;
|
||||
// 获取全屏索敌范围
|
||||
const maxRange = this.resolveMaxCastRange(mockAttrs, mockAttrs.type as HType);
|
||||
const target = this.findNearestEnemyInRange(mockAttrs, mockView, maxRange);
|
||||
if (target && target.node) {
|
||||
targetPos = this.resolveEnemyCastTargetPos(config, mockAttrs, mockView, target, maxRange);
|
||||
}
|
||||
// 如果全屏都没找到敌人,直接放弃释放伤害技能
|
||||
if (!targetPos) {
|
||||
console.log("[SCastSystem] forceCastCardSkill: no enemy found for skill", s_uuid);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
console.log("[SCastSystem] forceCastCardSkill: casting skill", s_uuid, "castTimes", castTimes, "targetPos", targetPos);
|
||||
for (let i = 0; i < castTimes; i++) {
|
||||
if (isFriendly) {
|
||||
const friendlyTargets = this.resolveFriendlyTargets(targetEids, FacSet.HERO);
|
||||
if (friendlyTargets.length === 0) continue;
|
||||
this.applyFriendlySkillEffects(s_uuid, cardLv, config, null as any, mockAttrs, friendlyTargets, spawnPos);
|
||||
} else {
|
||||
const enemyTargetPos = this.resolveRepeatCastTargetPos(new Vec3(spawnPos.x + 300, spawnPos.y, spawnPos.z), i);
|
||||
this.createSkillEntityForCard(s_uuid, cardLv, mockAttrs, spawnPos, enemyTargetPos, i);
|
||||
const enemyTargetPos = this.resolveRepeatCastTargetPos(targetPos, i);
|
||||
this.createSkillEntityForCard(s_uuid, cardLv, mockAttrs, spawnPos, enemyTargetPos, i, overrides);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 专用于卡牌施放的技能实体生成 */
|
||||
private createSkillEntityForCard(s_uuid: number, skillLv: number, mockAttrs: HeroAttrsComp, startPos: Vec3, targetPos: Vec3 | null, castIndex: number = 0) {
|
||||
private createSkillEntityForCard(s_uuid: number, skillLv: number, mockAttrs: HeroAttrsComp, startPos: Vec3, targetPos: Vec3 | null, castIndex: number = 0, overrides?: SkillOverrides) {
|
||||
const scene = smc.map.MapView.scene;
|
||||
const parent = scene.entityLayer?.node?.getChildByName("SKILL");
|
||||
if (!parent || !targetPos) return;
|
||||
if (!parent || !targetPos) {
|
||||
console.log("[SCastSystem] createSkillEntityForCard failed: parent or targetPos missing", !!parent, !!targetPos);
|
||||
return;
|
||||
}
|
||||
|
||||
const skill = ecs.getEntity<Skill>(Skill);
|
||||
const actualStartPos = this.resolveRepeatCastStartPos(startPos, castIndex);
|
||||
@@ -140,7 +166,8 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
box_group: BoxSet.HERO
|
||||
} as any;
|
||||
|
||||
skill.load(actualStartPos, parent, s_uuid, targetPos.clone(), mockView, mockAttrs, skillLv, 0);
|
||||
skill.load(actualStartPos, parent, s_uuid, targetPos.clone(), mockView, mockAttrs, skillLv, 0, overrides);
|
||||
console.log("[SCastSystem] createSkillEntityForCard success for skill", s_uuid);
|
||||
}
|
||||
/** 空施法计划:用于“当前无可施法技能”时的统一返回 */
|
||||
private readonly emptyCastPlan = { skillId: 0, skillLv: 1, isFriendly: false, targetPos: null as Vec3 | null, targetEids: [] as number[], overrides: undefined as SkillOverrides | undefined };
|
||||
|
||||
@@ -24,10 +24,9 @@ import { mLogger } from "../common/Logger";
|
||||
import { _decorator, Node, Prefab, instantiate, Vec3 } from "cc";
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
||||
import { SkillBoxComp } from "./SkillBoxComp";
|
||||
import { SBox } from "./SBox";
|
||||
import { oops } from "db://oops-framework/core/Oops";
|
||||
import { GameEvent } from "../common/config/GameEvent";
|
||||
import { smc } from "../common/SingletonModuleComp";
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
/** 技能槽位数据结构 */
|
||||
@@ -64,16 +63,16 @@ export class MissSkillsComp extends CCComp {
|
||||
* 第 2 行 y=320:x = -320, -240, -160, -80, 0
|
||||
*/
|
||||
private slots: SkillBoxSlot[] = [
|
||||
{ x: -320, y: 240, used: false, node: null },
|
||||
{ x: -240, y: 240, used: false, node: null },
|
||||
{ x: -160, y: 240, used: false, node: null },
|
||||
{ x: -80, y: 240, used: false, node: null },
|
||||
{ x: 0, y: 240, used: false, node: null },
|
||||
{ x: -320, y: 320, used: false, node: null },
|
||||
{ x: -240, y: 320, used: false, node: null },
|
||||
{ x: -160, y: 320, used: false, node: null },
|
||||
{ x: -80, y: 320, used: false, node: null },
|
||||
{ x: 0, y: 320, used: false, node: null },
|
||||
{ x: -320, y: 340, used: false, node: null },
|
||||
{ x: -240, y: 340, used: false, node: null },
|
||||
{ x: -160, y: 340, used: false, node: null },
|
||||
{ x: -80, y: 340, used: false, node: null },
|
||||
{ x: 0, y: 340, used: false, node: null },
|
||||
{ x: -320, y: 420, used: false, node: null },
|
||||
{ x: -240, y: 420, used: false, node: null },
|
||||
{ x: -160, y: 420, used: false, node: null },
|
||||
{ x: -80, y: 420, used: false, node: null },
|
||||
{ x: 0, y: 420, used: false, node: null },
|
||||
];
|
||||
|
||||
/** 注册事件监听 */
|
||||
@@ -164,9 +163,6 @@ export class MissSkillsComp extends CCComp {
|
||||
* @param card_lv 技能卡等级
|
||||
*/
|
||||
addSkill(uuid: number, card_lv: number) {
|
||||
// 技能节点的父容器
|
||||
var parent = smc.map.MapView.scene.entityLayer!.node!.getChildByName("SKILL")!;
|
||||
|
||||
if (!this.skill_box) {
|
||||
mLogger.error(this.debugMode, "MissSkillsComp", "skill_box prefab not set");
|
||||
return;
|
||||
@@ -179,17 +175,13 @@ export class MissSkillsComp extends CCComp {
|
||||
return;
|
||||
}
|
||||
|
||||
// 实例化并放入槽位
|
||||
const node = instantiate(this.skill_box);
|
||||
node.parent = parent;
|
||||
node.setPosition(new Vec3(this.slots[emptyIndex].x, this.slots[emptyIndex].y, 0));
|
||||
// 使用 ECS 实体创建技能节点
|
||||
let sbox = ecs.getEntity<SBox>(SBox);
|
||||
let pos = new Vec3(this.slots[emptyIndex].x, this.slots[emptyIndex].y, 0);
|
||||
let node = sbox.load(uuid, card_lv, pos, this.skill_box);
|
||||
|
||||
this.slots[emptyIndex].used = true;
|
||||
this.slots[emptyIndex].node = node;
|
||||
|
||||
// 初始化技能效果组件
|
||||
const comp = node.getComponent(SkillBoxComp) || node.addComponent(SkillBoxComp);
|
||||
comp.init(uuid, card_lv);
|
||||
}
|
||||
|
||||
/** ECS 组件移除时销毁节点 */
|
||||
|
||||
@@ -778,12 +778,22 @@ export class MissionCardComp extends CCComp {
|
||||
|
||||
private buildSkillDrawCards(): CardConfig[] {
|
||||
const targetType = CardType.Skill;
|
||||
const cards = getCardsByLv(this.poolLv, targetType);
|
||||
const currentWave = this.getCurrentWave();
|
||||
// 使用明确规则的 drawCardsByRule,指定只要 3 张技能卡,并且过滤对应 wave
|
||||
const cards = drawCardsByRule(this.poolLv, {
|
||||
count: 3,
|
||||
type: targetType,
|
||||
wave: currentWave
|
||||
});
|
||||
|
||||
if (cards.length >= 3) return cards.slice(0, 3);
|
||||
const filled = [...cards];
|
||||
while (filled.length < 3) {
|
||||
const fallback = getCardsByLv(this.poolLv, targetType);
|
||||
const fallback = drawCardsByRule(this.poolLv, {
|
||||
count: 3,
|
||||
type: targetType,
|
||||
wave: currentWave
|
||||
});
|
||||
if (fallback.length === 0) break;
|
||||
filled.push(fallback[filled.length % fallback.length]);
|
||||
}
|
||||
|
||||
52
assets/script/game/map/SBox.ts
Normal file
52
assets/script/game/map/SBox.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { instantiate, Prefab, Vec3, Node } from "cc";
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { smc } from "../common/SingletonModuleComp";
|
||||
import { SkillBoxComp } from "./SkillBoxComp";
|
||||
|
||||
/** SBox 实体:负责技能卡效果节点创建、初始化与销毁流程 */
|
||||
@ecs.register(`SBox`)
|
||||
export class SBox extends ecs.Entity {
|
||||
/** 技能盒子视图和逻辑组件引用 */
|
||||
SkillBox!: SkillBoxComp;
|
||||
|
||||
protected init() {
|
||||
// 如果有纯逻辑数据组件可以在这里 addComponents
|
||||
}
|
||||
|
||||
/** 销毁实体并释放视图节点,防止残留 */
|
||||
destroy(): void {
|
||||
const view = this.get(SkillBoxComp);
|
||||
if (view && view.node && view.node.isValid) {
|
||||
view.node.destroy();
|
||||
}
|
||||
|
||||
this.remove(SkillBoxComp);
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载并初始化技能盒子
|
||||
* 1) 创建节点并挂到 SKILL 层
|
||||
* 2) 初始化表现与属性数据
|
||||
*/
|
||||
load(uuid: number, card_lv: number, pos: Vec3, prefab: Prefab): Node {
|
||||
let node = instantiate(prefab);
|
||||
let scene = smc.map.MapView.scene;
|
||||
|
||||
// 统一挂到实体显示层 SKILL 节点下
|
||||
let parent = scene.entityLayer!.node!.getChildByName("SKILL");
|
||||
if (parent) {
|
||||
node.parent = parent;
|
||||
}
|
||||
node.setPosition(pos);
|
||||
|
||||
// 获取并注册组件
|
||||
let sboxComp = node.getComponent(SkillBoxComp) || node.addComponent(SkillBoxComp);
|
||||
this.add(sboxComp);
|
||||
|
||||
// 初始化业务逻辑
|
||||
sboxComp.init(uuid, card_lv);
|
||||
|
||||
return node;
|
||||
}
|
||||
}
|
||||
9
assets/script/game/map/SBox.ts.meta
Normal file
9
assets/script/game/map/SBox.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "10240197-8f36-4350-88cb-e3eae9567f12",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ import { _decorator, Node, Prefab, Sprite, Label, Vec3, resources, SpriteAtlas }
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
||||
import { CardPoolList } from "../common/config/CardSet";
|
||||
import { SkillSet } from "../common/config/SkillSet";
|
||||
import { SkillSet, SkillOverrides } from "../common/config/SkillSet";
|
||||
import { oops } from "db://oops-framework/core/Oops";
|
||||
import { GameEvent } from "../common/config/GameEvent";
|
||||
import { smc } from "../common/SingletonModuleComp";
|
||||
@@ -70,6 +70,8 @@ export class SkillBoxComp extends CCComp {
|
||||
private trigger_interval: number = 0;
|
||||
/** 维持的波次数(-1表示直到战斗结束,0表示不跨波次,>0表示维持的具体波次数) */
|
||||
private keep_waves: number = 0;
|
||||
/** 技能覆写参数(自定义伤害、Buff等) */
|
||||
private overrides?: SkillOverrides;
|
||||
|
||||
// ======================== 运行时状态 ========================
|
||||
|
||||
@@ -125,6 +127,7 @@ export class SkillBoxComp extends CCComp {
|
||||
this.trigger_times = config.t_times ?? 1;
|
||||
this.trigger_interval = config.t_inv ?? 0;
|
||||
this.keep_waves = config.keep_waves ?? 0;
|
||||
this.overrides = config.overrides;
|
||||
}
|
||||
|
||||
this.current_trigger_times = 0;
|
||||
@@ -140,7 +143,11 @@ export class SkillBoxComp extends CCComp {
|
||||
if (this.keep_waves === 0 && this.current_trigger_times >= this.trigger_times) {
|
||||
// 次数已满且不跨波次维持 → 延迟 1 秒后销毁(保留短暂视觉反馈)
|
||||
this.scheduleOnce(() => {
|
||||
if (this.node && this.node.isValid) this.node.destroy();
|
||||
if (this.ent) {
|
||||
(this.ent as ecs.Entity).destroy();
|
||||
} else if (this.node && this.node.isValid) {
|
||||
this.node.destroy();
|
||||
}
|
||||
}, 1.0);
|
||||
}
|
||||
}
|
||||
@@ -209,7 +216,11 @@ export class SkillBoxComp extends CCComp {
|
||||
if (this.keep_waves > 0) {
|
||||
this.keep_waves--;
|
||||
if (this.keep_waves <= 0) {
|
||||
if (this.node && this.node.isValid) this.node.destroy();
|
||||
if (this.ent) {
|
||||
(this.ent as ecs.Entity).destroy();
|
||||
} else if (this.node && this.node.isValid) {
|
||||
this.node.destroy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -227,7 +238,11 @@ export class SkillBoxComp extends CCComp {
|
||||
// 默认逻辑:不跨波次维持
|
||||
if (!this.is_instant) {
|
||||
if (this.current_trigger_times >= this.trigger_times) {
|
||||
if (this.node && this.node.isValid) this.node.destroy();
|
||||
if (this.ent) {
|
||||
(this.ent as ecs.Entity).destroy();
|
||||
} else if (this.node && this.node.isValid) {
|
||||
this.node.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -235,7 +250,11 @@ export class SkillBoxComp extends CCComp {
|
||||
|
||||
/** 任务结束:强制销毁 */
|
||||
private onMissionEnd() {
|
||||
this.node.destroy();
|
||||
if (this.ent) {
|
||||
(this.ent as ecs.Entity).destroy();
|
||||
} else if (this.node && this.node.isValid) {
|
||||
this.node.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
// ======================== 帧更新 ========================
|
||||
@@ -261,7 +280,11 @@ export class SkillBoxComp extends CCComp {
|
||||
// 次数用完且不跨波次维持 → 延迟销毁
|
||||
if (this.keep_waves === 0 && this.current_trigger_times >= this.trigger_times) {
|
||||
this.scheduleOnce(() => {
|
||||
if (this.node && this.node.isValid) this.node.destroy();
|
||||
if (this.ent) {
|
||||
(this.ent as ecs.Entity).destroy();
|
||||
} else if (this.node && this.node.isValid) {
|
||||
this.node.destroy();
|
||||
}
|
||||
}, 0.5);
|
||||
}
|
||||
}
|
||||
@@ -285,12 +308,15 @@ export class SkillBoxComp extends CCComp {
|
||||
s_uuid: this.s_uuid,
|
||||
isCardSkill: true, // 标记为卡牌技能(区别于英雄自身技能)
|
||||
card_lv: this.card_lv,
|
||||
targetPos: targetPos
|
||||
targetPos: targetPos,
|
||||
overrides: this.overrides
|
||||
});
|
||||
}
|
||||
|
||||
/** ECS 组件移除时销毁节点 */
|
||||
reset() {
|
||||
this.node.destroy();
|
||||
if (this.node && this.node.isValid) {
|
||||
this.node.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,124 +109,135 @@ export class Skill extends ecs.Entity {
|
||||
}
|
||||
config = mergeSkillParams(config, overrides);
|
||||
|
||||
// 加载预制体
|
||||
const path = `game/skill/atk/${config.sp_name}`;
|
||||
const prefab:Prefab = oops.res.get(path, Prefab);
|
||||
if (!prefab) {
|
||||
mLogger.error(this.debugMode, 'Skill', "[Skill] 预制体加载失败:", path);
|
||||
return;
|
||||
}
|
||||
const node: Node = Skill.getFromPool(path) || instantiate(prefab);
|
||||
if (!node || !node.isValid) {
|
||||
mLogger.error(this.debugMode, 'Skill', "[Skill] 节点无效:", path);
|
||||
return;
|
||||
}
|
||||
|
||||
this.prefabPath = path;
|
||||
this.skillNode = node;
|
||||
|
||||
let skillParent: Node | null = null;
|
||||
if (smc.map && smc.map.MapView && smc.map.MapView.scene && smc.map.MapView.scene.entityLayer && smc.map.MapView.scene.entityLayer.node) {
|
||||
skillParent = smc.map.MapView.scene.entityLayer.node.getChildByName("SKILL");
|
||||
}
|
||||
if (!skillParent || !skillParent.isValid) {
|
||||
skillParent = parent;
|
||||
}
|
||||
|
||||
if (!skillParent || !skillParent.isValid) {
|
||||
mLogger.error(this.debugMode, 'Skill', "[Skill] 父节点无效");
|
||||
if(node.isValid) node.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
node.parent = skillParent;
|
||||
node.active = true;
|
||||
// 设置节点属性
|
||||
let face=caster.node.scale.x < 0 ? -1 : 1
|
||||
node.setScale(v3(Math.abs(node.scale.x)*face,node.scale.y,1))
|
||||
// 初始视图
|
||||
const SView = node.getComponent(SkillView);
|
||||
if (!SView) {
|
||||
mLogger.error(this.debugMode, 'Skill', "[Skill] SkillView 组件缺失:", path);
|
||||
if (node.isValid) node.destroy();
|
||||
return;
|
||||
}
|
||||
if(config.EType!=EType.collision){
|
||||
const collider=node.getComponent(BoxCollider2D);
|
||||
if(collider){
|
||||
collider.enabled=false
|
||||
const initSkillNode = (prefab: Prefab) => {
|
||||
const node: Node = Skill.getFromPool(path) || instantiate(prefab);
|
||||
if (!node || !node.isValid) {
|
||||
mLogger.error(this.debugMode, 'Skill', "[Skill] 节点无效:", path);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 只设置必要的运行时属性,配置信息通过 SkillSet[uuid] 访问
|
||||
// 核心标识
|
||||
SView.s_uuid= s_uuid
|
||||
SView.group= caster.box_group
|
||||
|
||||
this.add(SView);
|
||||
startPos.x=startPos.x+SView.atk_x*face
|
||||
startPos.y=startPos.y+SView.atk_y
|
||||
this.prefabPath = path;
|
||||
this.skillNode = node;
|
||||
|
||||
let skillParent: Node | null = null;
|
||||
if (smc.map && smc.map.MapView && smc.map.MapView.scene && smc.map.MapView.scene.entityLayer && smc.map.MapView.scene.entityLayer.node) {
|
||||
skillParent = smc.map.MapView.scene.entityLayer.node.getChildByName("SKILL");
|
||||
}
|
||||
if (!skillParent || !skillParent.isValid) {
|
||||
skillParent = parent;
|
||||
}
|
||||
|
||||
if (!skillParent || !skillParent.isValid) {
|
||||
mLogger.error(this.debugMode, 'Skill', "[Skill] 父节点无效");
|
||||
if(node.isValid) node.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
node.setPosition(startPos);
|
||||
node.parent = skillParent;
|
||||
node.active = true;
|
||||
// 设置节点属性
|
||||
let face=caster.node.scale.x < 0 ? -1 : 1
|
||||
node.setScale(v3(Math.abs(node.scale.x)*face,node.scale.y,1))
|
||||
// 初始视图
|
||||
const SView = node.getComponent(SkillView);
|
||||
if (!SView) {
|
||||
mLogger.error(this.debugMode, 'Skill', "[Skill] SkillView 组件缺失:", path);
|
||||
if (node.isValid) node.destroy();
|
||||
return;
|
||||
}
|
||||
if(config.EType!=EType.collision){
|
||||
const collider=node.getComponent(BoxCollider2D);
|
||||
if(collider){
|
||||
collider.enabled=false
|
||||
}
|
||||
}
|
||||
|
||||
// 只设置必要的运行时属性,配置信息通过 SkillSet[uuid] 访问
|
||||
// 核心标识
|
||||
SView.s_uuid= s_uuid
|
||||
SView.group= caster.box_group
|
||||
|
||||
// 初始化移动组件 - 从SkillView获取移动参数
|
||||
let sMoveCom = this.get(SMoveDataComp);
|
||||
if (!sMoveCom) {
|
||||
sMoveCom = this.add(SMoveDataComp);
|
||||
}
|
||||
sMoveCom.reset(); // 复用组件时重置状态
|
||||
sMoveCom.startPos.set(startPos);
|
||||
sMoveCom.targetPos.set(targetPos);
|
||||
sMoveCom.s_uuid = s_uuid;
|
||||
sMoveCom.scale = caster.node.scale.x < 0 ? -1 : 1;
|
||||
sMoveCom.runType = config.RType;
|
||||
sMoveCom.endType = config.EType;
|
||||
sMoveCom.bezierStartHeight = config.bezier_start_y ?? sMoveCom.bezierStartHeight;
|
||||
sMoveCom.bezierMidHeight = config.bezier_mid_y ?? sMoveCom.bezierMidHeight;
|
||||
sMoveCom.bezierArc = config.bezier_arc ?? sMoveCom.bezierArc;
|
||||
// 从SkillView获取移动参数,位置初始化由SMoveSystem统一处理
|
||||
sMoveCom.atk_x = SView.atk_x;
|
||||
sMoveCom.atk_y = SView.atk_y;
|
||||
this.add(SView);
|
||||
startPos.x=startPos.x+SView.atk_x*face
|
||||
startPos.y=startPos.y+SView.atk_y
|
||||
|
||||
if (config.EType === EType.timeEnd) {
|
||||
let sTimeCom = this.get(StimeDataComp);
|
||||
if (!sTimeCom) sTimeCom = this.add(StimeDataComp);
|
||||
sTimeCom.reset();
|
||||
sTimeCom.s_uuid = s_uuid;
|
||||
sTimeCom.totalTime = Math.max(1, config.time ?? 0);
|
||||
sTimeCom.hitInterval = Math.max(0.5, config.hitcd || 0);
|
||||
node.setPosition(startPos);
|
||||
|
||||
// 初始化移动组件 - 从SkillView获取移动参数
|
||||
let sMoveCom = this.get(SMoveDataComp);
|
||||
if (!sMoveCom) {
|
||||
sMoveCom = this.add(SMoveDataComp);
|
||||
}
|
||||
sMoveCom.reset(); // 复用组件时重置状态
|
||||
sMoveCom.startPos.set(startPos);
|
||||
sMoveCom.targetPos.set(targetPos);
|
||||
sMoveCom.s_uuid = s_uuid;
|
||||
sMoveCom.scale = caster.node.scale.x < 0 ? -1 : 1;
|
||||
sMoveCom.runType = config.RType;
|
||||
sMoveCom.endType = config.EType;
|
||||
sMoveCom.bezierStartHeight = config.bezier_start_y ?? sMoveCom.bezierStartHeight;
|
||||
sMoveCom.bezierMidHeight = config.bezier_mid_y ?? sMoveCom.bezierMidHeight;
|
||||
sMoveCom.bezierArc = config.bezier_arc ?? sMoveCom.bezierArc;
|
||||
// 从SkillView获取移动参数,位置初始化由SMoveSystem统一处理
|
||||
sMoveCom.atk_x = SView.atk_x;
|
||||
sMoveCom.atk_y = SView.atk_y;
|
||||
|
||||
if (config.EType === EType.timeEnd) {
|
||||
let sTimeCom = this.get(StimeDataComp);
|
||||
if (!sTimeCom) sTimeCom = this.add(StimeDataComp);
|
||||
sTimeCom.reset();
|
||||
sTimeCom.s_uuid = s_uuid;
|
||||
sTimeCom.totalTime = Math.max(1, config.time ?? 0);
|
||||
sTimeCom.hitInterval = Math.max(0.5, config.hitcd || 0);
|
||||
} else {
|
||||
const sTimeCom = this.get(StimeDataComp);
|
||||
if (sTimeCom) this.remove(StimeDataComp);
|
||||
}
|
||||
// 初始化数据组件
|
||||
let sDataCom = this.get(SDataCom);
|
||||
if (!sDataCom) {
|
||||
sDataCom = this.add(SDataCom);
|
||||
}
|
||||
sDataCom.reset();
|
||||
sDataCom.group=caster.box_group
|
||||
sDataCom.casterEid=caster.ent.eid
|
||||
sDataCom.Attrs = {};
|
||||
const SUp=SkillUpList[s_uuid] ? SkillUpList[s_uuid]:SkillUpList[1001];
|
||||
const sCrt = (config.crt ?? 0)+(SUp.crt*skill_lv);
|
||||
const sFrz = (config.frz ?? 0)+(SUp.frz*skill_lv);
|
||||
const sAp =config.ap+(SUp.ap*skill_lv);
|
||||
const sHit=config.hit_count+(SUp.hit_count*skill_lv);
|
||||
sDataCom.Attrs[Attrs.ap] = Math.floor(cAttrsComp.ap*sAp/100); //技能的ap是百分值 需要/100 而且需要再最终计算总ap时再/100,不然会出现ap为90%变0
|
||||
sDataCom.Attrs[Attrs.critical] = cAttrsComp.getRuntimeCritical() + sCrt;
|
||||
sDataCom.Attrs[Attrs.critical_damage] = cAttrsComp.getRuntimeCritDamageBonus();
|
||||
sDataCom.Attrs[Attrs.freeze_chance] = cAttrsComp.getRuntimeFreezeChance() + sFrz;
|
||||
sDataCom.Attrs[Attrs.knockback_chance] = cAttrsComp.knockback_chance || 0;
|
||||
sDataCom.Attrs[Attrs.knockback_distance] = cAttrsComp.knockback_distance || 0;
|
||||
sDataCom.Attrs[Attrs.puncture_chance] = cAttrsComp.getRuntimePunctureChance(); // 初始化携带施法者的穿透概率
|
||||
sDataCom.s_uuid=s_uuid
|
||||
sDataCom.skill_lv = Math.max(0, skill_lv);
|
||||
sDataCom.fac=cAttrsComp.fac
|
||||
sDataCom.ext_dmg=ext_dmg
|
||||
sDataCom.hit_count = 0
|
||||
sDataCom.max_hit_count = Math.max(1,sHit)
|
||||
SView.init();
|
||||
};
|
||||
|
||||
let prefab: Prefab = oops.res.get(path, Prefab);
|
||||
if (prefab) {
|
||||
initSkillNode(prefab);
|
||||
} else {
|
||||
const sTimeCom = this.get(StimeDataComp);
|
||||
if (sTimeCom) this.remove(StimeDataComp);
|
||||
oops.res.loadAsync(path, Prefab).then((res: Prefab) => {
|
||||
if (res) {
|
||||
initSkillNode(res);
|
||||
} else {
|
||||
mLogger.error(this.debugMode, 'Skill', "[Skill] 预制体加载失败:", path);
|
||||
}
|
||||
}).catch((err) => {
|
||||
mLogger.error(this.debugMode, 'Skill', "[Skill] 预制体加载异常:", path, err);
|
||||
});
|
||||
}
|
||||
// 初始化数据组件
|
||||
let sDataCom = this.get(SDataCom);
|
||||
if (!sDataCom) {
|
||||
sDataCom = this.add(SDataCom);
|
||||
}
|
||||
sDataCom.reset();
|
||||
sDataCom.group=caster.box_group
|
||||
sDataCom.casterEid=caster.ent.eid
|
||||
sDataCom.Attrs = {};
|
||||
const SUp=SkillUpList[s_uuid] ? SkillUpList[s_uuid]:SkillUpList[1001];
|
||||
const sCrt = (config.crt ?? 0)+(SUp.crt*skill_lv);
|
||||
const sFrz = (config.frz ?? 0)+(SUp.frz*skill_lv);
|
||||
const sAp =config.ap+(SUp.ap*skill_lv);
|
||||
const sHit=config.hit_count+(SUp.hit_count*skill_lv);
|
||||
sDataCom.Attrs[Attrs.ap] = Math.floor(cAttrsComp.ap*sAp/100); //技能的ap是百分值 需要/100 而且需要再最终计算总ap时再/100,不然会出现ap为90%变0
|
||||
sDataCom.Attrs[Attrs.critical] = cAttrsComp.getRuntimeCritical() + sCrt;
|
||||
sDataCom.Attrs[Attrs.critical_damage] = cAttrsComp.getRuntimeCritDamageBonus();
|
||||
sDataCom.Attrs[Attrs.freeze_chance] = cAttrsComp.getRuntimeFreezeChance() + sFrz;
|
||||
sDataCom.Attrs[Attrs.knockback_chance] = cAttrsComp.knockback_chance || 0;
|
||||
sDataCom.Attrs[Attrs.knockback_distance] = cAttrsComp.knockback_distance || 0;
|
||||
sDataCom.Attrs[Attrs.puncture_chance] = cAttrsComp.getRuntimePunctureChance(); // 初始化携带施法者的穿透概率
|
||||
sDataCom.s_uuid=s_uuid
|
||||
sDataCom.skill_lv = Math.max(0, skill_lv);
|
||||
sDataCom.fac=cAttrsComp.fac
|
||||
sDataCom.ext_dmg=ext_dmg
|
||||
sDataCom.hit_count = 0
|
||||
sDataCom.max_hit_count = Math.max(1,sHit)
|
||||
SView.init();
|
||||
}
|
||||
|
||||
/** 模块资源释放 */
|
||||
|
||||
Reference in New Issue
Block a user