Files
pixelheros/assets/script/game/hero/Hero.ts
panw 382f6d2b32 fix(技能): 修复技能等级计算错误,默认等级从1改为0
将技能相关计算的默认等级从1统一修正为0,确保等级计算逻辑的一致性。具体包括:
- HeroAttrsComp.getSkillLevel() 方法在无效技能ID时返回0
- Hero实体构建技能模型时使用Math.max确保最低等级为0
- SDataCom组件初始化skill_lv为0
- Skill实体加载时skill_lv参数默认值改为0,计算时使用Math.max(0, skill_lv)
2026-03-24 10:25:12 +08:00

155 lines
5.7 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 { instantiate, Node, Prefab, Vec3 ,v3,resources,SpriteFrame,Sprite,SpriteAtlas, BoxCollider2D, tween, Tween} from "cc";
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { smc } from "../common/SingletonModuleComp";
import { HeroAttrsComp } from "./HeroAttrsComp";
import { HeroViewComp } from "./HeroViewComp";
import { BoxSet, FacSet, FightSet, IndexSet } from "../common/config/GameSet";
import { HeroInfo, HeroPos, resolveFormationTargetX } from "../common/config/heroSet";
import { GameEvent } from "../common/config/GameEvent";
import { Attrs} from "../common/config/HeroAttrs";
import { MoveComp } from "./MoveComp";
import { mLogger } from "../common/Logger";
/** 角色实体 */
@ecs.register(`Hero`)
export class Hero extends ecs.Entity {
HeroModel!: HeroAttrsComp;
View!: HeroViewComp;
HeroMove!: MoveComp;
debugMode: boolean = false; // 是否启用调试模式
protected init() {
this.addComponents<ecs.Comp>(
MoveComp,
HeroAttrsComp,
);
}
destroy(): void {
// 销毁节点,防止视觉残留
const view = this.get(HeroViewComp);
if (view && view.node && view.node.isValid) {
view.node.destroy();
}
this.remove(HeroViewComp);
this.remove(HeroAttrsComp);
super.destroy();
}
/** 加载角色 */
load(pos: Vec3 = Vec3.ZERO,scale:number = 1,uuid:number=1001, dropToY:number = pos.y,hero_lv:number=1) {
scale = 1
if(hero_lv>3) hero_lv=3
// 查找空闲英雄槽位
let size=1+0.1*hero_lv
var path = "game/heros/"+HeroInfo[uuid].path;
var prefab: Prefab = oops.res.get(path, Prefab)!;
var node = instantiate(prefab);
var scene = smc.map.MapView.scene;
node.parent = scene.entityLayer!.node!.getChildByName("HERO")!;
const collider = node.getComponent(BoxCollider2D);
if (collider) collider.enabled = false; // 先禁用
node.setScale(size*node.scale.x,size*node.scale.y);
node.setPosition(pos)
// 🔥 设置初始 SiblingIndex - 英雄基础层级 + 位置偏移
mLogger.log(this.debugMode,"hero",node.getSiblingIndex());
var hv = node.getComponent(HeroViewComp)!;
const model = this.get(HeroAttrsComp);
let hero = HeroInfo[uuid]; // 共用英雄数据
// 设置 View 层属性(表现相关)
hv.scale = 1;
hv.box_group = BoxSet.HERO;
// 设置 Model 层属性(数据相关)
model.hero_uuid = uuid;
model.hero_name = hero.name;
model.lv = hero_lv;
model.type = hero.type;
model.fac = FacSet.HERO;
// 只有主角才挂载天赋组件
// ✅ 初始化技能数据(迁移到 HeroSkillsComp
// 设置基础属性
model.ap = hero.ap*model.lv;
model.hp= model.hp_max = hero.hp*model.lv;
model.speed = hero.speed;
model.skills = {};
for (const key in hero.skills) {
const skill = hero.skills[key];
if (!skill) continue;
//用于增量 计算最终技能等级英雄等级与技能初始等级均从1开始需各减1抵消故-2最低等级时0
model.skills[skill.uuid] = { ...skill, lv: Math.max(0,skill.lv + hero_lv - 2), ccd: skill.cd };
}
model.updateSkillDistanceCache();
// 初始化 buff/debuff 系统
model.initAttrs();
this.add(hv);
oops.message.dispatchEvent(GameEvent.MasterCalled,{uuid:uuid})
const move = this.get(MoveComp);
move.direction = 1; // 向右移动
move.targetX = resolveFormationTargetX(model.fac, model.type);
move.baseY = dropToY;
move.moving = false;
const dropDistance = Math.abs(pos.y - dropToY);
const dropDuration = Math.max(0.18, Math.min(0.38, dropDistance / 1200));
Tween.stopAllByTarget(node);
tween(node)
.to(dropDuration, { position: v3(pos.x, dropToY, 0) })
.call(() => {
if (!node || !node.isValid) return;
node.setPosition(pos.x, dropToY, 0);
hv.playEnd("down");
move.moving = true;
if (collider) {
collider.enabled = true;
collider.group = BoxSet.HERO;
collider.apply();
}
})
.start();
smc.vmdata.mission_data.hero_num++
}
reset() {
// 注: 自定义释放逻辑,视图层实现 ecs.IComp 接口的 ecs 组件需要手动释放
super.destroy();
}
}
@ecs.register('HeroLifecycleSystem')
export class HeroLifecycleSystem extends ecs.ComblockSystem
implements ecs.IEntityEnterSystem, ecs.IEntityRemoveSystem {
filter() {
return ecs.allOf(MoveComp);
}
entityEnter(e: ecs.Entity): void {
// 英雄实体创建时的特殊处理
const heroAttrs = e.get(HeroAttrsComp);
if (heroAttrs) {
mLogger.log(heroAttrs.debugMode, 'HeroLifecycle', `英雄进入世界: ${heroAttrs.hero_name}`);
} else {
mLogger.log(true, 'HeroLifecycle', `英雄进入世界: 实体ID ${e.eid}`);
}
}
entityRemove(e: ecs.Entity): void {
// 英雄实体销毁时的清理工作
const heroAttrs = e.get(HeroAttrsComp);
if (heroAttrs) {
mLogger.log(heroAttrs.debugMode, 'HeroLifecycle', `英雄离开世界: ${heroAttrs.hero_name}`);
} else {
mLogger.log(true, 'HeroLifecycle', `英雄离开世界: 实体ID ${e.eid}`);
}
}
}