You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
212 lines
6.7 KiB
212 lines
6.7 KiB
import { _decorator, Component, Node, UITransform, Vec3 } from 'cc';
|
|
import { EDITOR } from 'cc/env';
|
|
import { Monster, MonsterTag } from '../Monster';
|
|
import { IWeaponProperty } from '../BattleDataManager';
|
|
import { Skill } from './Skill';
|
|
import { GEvent } from 'db://assets/mx/module/event/GEvent';
|
|
const { ccclass, property, executeInEditMode } = _decorator;
|
|
|
|
@ccclass('LaserLine')
|
|
@executeInEditMode
|
|
export class LaserLine extends Component {
|
|
|
|
startNode: Node = null;
|
|
endNode: Node = null;
|
|
line: Node = null;
|
|
|
|
|
|
Data: IWeaponProperty = null;
|
|
index: number = 0;
|
|
private _curentTarget: Monster = null;
|
|
private _time = 10;
|
|
private _cd = 0;
|
|
private _weaponId = 0;
|
|
private _findTargetDis = 200;
|
|
private _tetriLevel = 1;
|
|
|
|
private _lineUiTransform: UITransform | null = null;
|
|
private _lineWidth = 1;
|
|
|
|
protected onLoad() {
|
|
this.startNode = this.node.getChildByName("起点");
|
|
this.endNode = this.node.getChildByName("末点");
|
|
this.line = this.node.getChildByName("line");
|
|
this._lineUiTransform = this.line.getComponent(UITransform);
|
|
this._lineWidth = this._lineUiTransform?.width || 1;
|
|
this.updateLine();
|
|
}
|
|
|
|
protected onEnable(): void {
|
|
GEvent.Ins.on(GEvent.BattleWarnTimeStart, this._onWarnTimeStart, this);
|
|
}
|
|
|
|
protected onDisable(): void {
|
|
GEvent.Ins.off(GEvent.BattleWarnTimeStart, this._onWarnTimeStart, this);
|
|
}
|
|
|
|
private _onWarnTimeStart() {
|
|
this.unschedule(this._warnRemoveScheduled);
|
|
this.scheduleOnce(this._warnRemoveScheduled, 0);
|
|
}
|
|
|
|
private _warnRemoveScheduled = () => {
|
|
if (this.node?.isValid) {
|
|
this.remove();
|
|
}
|
|
};
|
|
|
|
setData(weaponId: number, data: IWeaponProperty, index: number = 0, tetriLevel: number = 1) {
|
|
this.index = index;
|
|
this.Data = data;
|
|
this._cd = 0;
|
|
this._findTargetDis = 0;
|
|
this._weaponId = weaponId;
|
|
this._tetriLevel = Number.isFinite(tetriLevel as any) && (tetriLevel as any) > 0 ? (tetriLevel as any) : 1;
|
|
this._time = this.Data.weaponContinueTime;
|
|
this.getOneLaserAtkTarget(index);
|
|
}
|
|
|
|
protected update(dt: number): void {
|
|
if (EDITOR) {
|
|
// 编辑器模式下更新线
|
|
this.updateLine();
|
|
return;
|
|
}
|
|
|
|
const battle = gg.game?.CurentBattle;
|
|
if (!battle) {
|
|
return;
|
|
}
|
|
// 普通关卡:预警会 pause,canUpdateFrame 为 false 时 _time 不走、事件也可能早于本帧执行顺序漏掉。
|
|
// Boss 关预警不 pause,不在这里清激光(仍允许攻击)。
|
|
if (battle.IsWarnTimeActive && battle.IsGamePause) {
|
|
this.remove();
|
|
return;
|
|
}
|
|
|
|
if (!battle.canUpdateFrame()) {
|
|
return;
|
|
}
|
|
|
|
if (this._time < 0) {
|
|
this.remove();
|
|
return;
|
|
}
|
|
|
|
this._cd -= dt * gg.game.CurentBattle.TimeScale;
|
|
this._time -= dt * gg.game.CurentBattle.TimeScale;
|
|
if (this._cd < 0) {
|
|
this.atk();
|
|
}
|
|
|
|
if (this._curentTarget
|
|
&& this._curentTarget.checkTag(MonsterTag.IS_BE_ATTACKED_BY_LASER + this.index)
|
|
&& this._curentTarget.node
|
|
&& this._curentTarget.node.isValid
|
|
&& this._curentTarget.node.active) {
|
|
this.endNode.worldPosition = this._curentTarget.node.worldPosition;
|
|
this.updateLine();
|
|
} else {
|
|
if (this._curentTarget) {
|
|
this._curentTarget.setTag(MonsterTag.IS_BE_ATTACKED_BY_LASER + this.index, false);
|
|
this._curentTarget = null;
|
|
}
|
|
this.startNode.active = false;
|
|
this.endNode.active = false;
|
|
this.line.active = false;
|
|
this.getOneLaserAtkTarget(this.index);
|
|
}
|
|
}
|
|
|
|
/**设置目标坐标(世界坐标) */
|
|
setTargetPos(pos: Vec3) {
|
|
this.endNode.worldPosition = pos;
|
|
this.updateLine();
|
|
}
|
|
|
|
private updateLine() {
|
|
if(!this.Data){
|
|
return
|
|
}
|
|
this.startNode.active = true;
|
|
this.endNode.active = true;
|
|
this.line.active = true;
|
|
let startPos = this.startNode.worldPosition;
|
|
let endPos = this.endNode.worldPosition;
|
|
const dx = startPos.x - endPos.x;
|
|
const dy = startPos.y - endPos.y;
|
|
const dz = startPos.z - endPos.z;
|
|
const disSq = dx * dx + dy * dy + dz * dz;
|
|
if (disSq < 1e-8) {
|
|
return
|
|
}
|
|
|
|
const dis = Math.sqrt(disSq);
|
|
const invDis = 1 / dis;
|
|
const dirX = dx * invDis;
|
|
const dirY = dy * invDis;
|
|
|
|
const scole = dis / this._lineWidth;
|
|
|
|
// Vec3.angle((-1,0,0), dir) 等价于 acos(dot);ref 向量长度为 1,因此 dot = (-1)*dirX = -dirX
|
|
let dot = -dirX;
|
|
if (dot > 1) dot = 1;
|
|
else if (dot < -1) dot = -1;
|
|
let angle = Math.acos(dot) * 180 / Math.PI;
|
|
if (dirY > 0) angle = -angle;
|
|
|
|
this.line.setWorldPosition(startPos.x, startPos.y, startPos.z);
|
|
this.line.setScale(scole, 1, 1);
|
|
this.line.angle = angle;
|
|
|
|
let index = 0;
|
|
// if (this.Data.isHavePurpleSkill) index = 1;
|
|
// if (this.Data.isHaveOrangeSkill) index = 2;
|
|
// for (let i = 0; i < this.line.children.length; i++) {
|
|
// this.line.children[i].active = false;
|
|
// }
|
|
this.line.children[index].active = true;
|
|
}
|
|
|
|
private getOneLaserAtkTarget(index: number = 0) {
|
|
const skill = this.node.getComponent(Skill);
|
|
|
|
if (!skill) return;
|
|
|
|
const findNode = skill.pickNearestMonsterByIndex(index);
|
|
|
|
if (!findNode || !findNode.isValid) return;
|
|
|
|
const monster = findNode.getComponent(Monster);
|
|
//console.log('monster+++++++++===1111', monster)
|
|
if (!monster || monster.IsDead || !monster.node || !monster.node.isValid) return;
|
|
|
|
//console.log('monster+++++++++===222', monster)
|
|
this._curentTarget = monster;
|
|
this._curentTarget.setTag(MonsterTag.IS_BE_ATTACKED_BY_LASER + index, true);
|
|
this.setTargetPos(this._curentTarget.node.worldPosition);
|
|
this._findTargetDis = 2000;
|
|
}
|
|
|
|
atk() {
|
|
if (this._curentTarget && !this._curentTarget.IsDead) {
|
|
this._curentTarget.attackByWeapon(this._weaponId, undefined, this._tetriLevel);
|
|
}
|
|
this._cd = this.Data.damageInterval;
|
|
}
|
|
|
|
remove() {
|
|
if (!this.isValid) {
|
|
return;
|
|
}
|
|
this.unscheduleAllCallbacks();
|
|
|
|
if (this._curentTarget) {
|
|
this._curentTarget.setTag(MonsterTag.IS_BE_ATTACKED_BY_LASER + this.index, false);
|
|
this._curentTarget = null;
|
|
}
|
|
gg.res.putNode(this.node);
|
|
}
|
|
}
|
|
|
|
|
|
|