消消方块阵换皮表情
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

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);
}
}