2025-11-14 13:09:09 -08:00

217 lines
7.7 KiB
TypeScript

import { Component, Input, OnInit, ViewChild } from '@angular/core';
import { DialogRef, DialogContentBase, DialogService } from '@progress/kendo-angular-dialog';
import { GridComponent, GridDataResult } from '@progress/kendo-angular-grid';
import { State } from '@progress/kendo-data-query';
import { first } from 'rxjs/operators';
import { BossFightProfile, BossFightPhaseBuff } from '../../massive-darkness2.db.model';
import { MobSkillType } from '../../massive-darkness2.model.boss';
import { MD2BossFightProfileService, MD2PhaseBuffService } from '../../service/massive-darkness2.service';
import { MsgBoxService } from '../../../../services/msg-box.service';
import { MD2PhaseBuffEditorComponent } from '../md2-phase-buff-editor/md2-phase-buff-editor.component';
import { MD2IconPickerDlgComponent } from '../../md2-html-editor/md2-icon-picker-dlg.component';
@Component({
selector: 'ngx-md2-boss-fight-editor',
templateUrl: './md2-boss-fight-editor.component.html',
styleUrls: ['./md2-boss-fight-editor.component.scss']
})
export class MD2BossFightEditorComponent extends DialogContentBase implements OnInit {
@Input() public data: BossFightProfile;
@Input() public mobInfoId: string;
@ViewChild('phaseBuffsGrid') phaseBuffsGrid: GridComponent;
public model: BossFightProfile;
public phaseBuffs: BossFightPhaseBuff[] = [];
public phaseBuffsData: GridDataResult = { data: [], total: 0 };
public phaseBuffsState: State = {
skip: 0,
take: 10,
sort: [],
filter: {
logic: 'and',
filters: []
}
};
public isLoading: boolean = false;
public processing: boolean = false;
constructor(
public dialog: DialogRef,
private dialogService: DialogService,
private bossFightProfileService: MD2BossFightProfileService,
private phaseBuffService: MD2PhaseBuffService,
private msgBoxService: MsgBoxService
) {
super(dialog);
}
ngOnInit(): void {
this.initializeModel();
}
public initializeModel(): void {
this.model = {
id: this.data?.id || '',
mobInfoId: this.mobInfoId || this.data?.mobInfoId || '',
prerequisite: this.data?.prerequisite || '',
objective: this.data?.objective || '',
specialRules: this.data?.specialRules || '',
extraTokenName: this.data?.extraTokenName || '',
extraTokenHtml: this.data?.extraTokenHtml || '',
extraTokenName2: this.data?.extraTokenName2 || '',
extraTokenHtml2: this.data?.extraTokenHtml2 || '',
phaseBuffs: this.data?.phaseBuffs || []
};
this.phaseBuffs = this.model.phaseBuffs || [];
this.loadPhaseBuffs();
}
public loadPhaseBuffs(): void {
this.phaseBuffsData = {
data: this.phaseBuffs.sort((a, b) => a.phase - b.phase),
total: this.phaseBuffs.length
};
}
public addPhaseBuffHandler(): void {
if (!this.model) return;
const lastPhaseBuff = this.phaseBuffs.length > 0
? this.phaseBuffs.reduce((prev, current) => (prev.phase > current.phase) ? prev : current)
: null;
const nextPhase = lastPhaseBuff ? lastPhaseBuff.phase + 1 : 1;
const newPhaseBuff: BossFightPhaseBuff = {
id: this.generatePhaseBuffId(),
bossFightProfileId: this.model.id,
phase: nextPhase,
extraAction: 0,
extraAttackDice: { type: MobSkillType.Attack, yellow: null, orange: null, red: null, blue: null, green: null, black: null },
extraDefenceDice: { type: MobSkillType.Defense, yellow: null, orange: null, red: null, blue: null, green: null, black: null },
extraHp: 0,
extraTokenCount: 0,
extraTokenCount2: 0,
enableExtraBuffDescription: false,
extraBuffDescription: ''
};
this.openPhaseBuffEditor(newPhaseBuff, true);
}
public editPhaseBuffHandler(dataItem: BossFightPhaseBuff): void {
if (!this.model) return;
const phaseBuffCopy: BossFightPhaseBuff = JSON.parse(JSON.stringify(dataItem));
this.openPhaseBuffEditor(phaseBuffCopy, false);
}
private openPhaseBuffEditor(phaseBuff: BossFightPhaseBuff, isNew: boolean): void {
if (!this.model) return;
const dialogRef = this.dialogService.open({
title: isNew ? 'Add New Phase Buff' : 'Edit Phase Buff',
content: MD2PhaseBuffEditorComponent,
width: '80vw',
height: 700
});
const editor = dialogRef.content.instance as MD2PhaseBuffEditorComponent;
editor.isAdding = isNew;
editor.data = phaseBuff;
editor.bossFightProfileId = this.model.id;
setTimeout(() => {
editor.initializeModel();
}, 0);
dialogRef.result.subscribe(result => {
if (result && typeof result === 'object' && 'id' in result) {
this.handlePhaseBuffSaved(result as BossFightPhaseBuff, isNew);
}
});
}
private handlePhaseBuffSaved(result: BossFightPhaseBuff, isNew: boolean): void {
if (!this.model) return;
if (isNew) {
if (!this.phaseBuffs) {
this.phaseBuffs = [];
}
this.phaseBuffs.push(result);
} else {
const index = this.phaseBuffs.findIndex(p => p.id === result.id);
if (index !== -1) {
this.phaseBuffs[index] = result;
}
}
this.model.phaseBuffs = this.phaseBuffs;
this.loadPhaseBuffs();
}
public removePhaseBuffHandler({ dataItem }: { dataItem: BossFightPhaseBuff }): void {
this.msgBoxService.showConfirmDeleteBox().pipe(first()).subscribe(answer => {
if (answer === true) {
this.isLoading = true;
this.phaseBuffService.delete(dataItem.id).pipe(first()).subscribe(result => {
const index = this.phaseBuffs.findIndex(p => p.id === dataItem.id);
if (index !== -1) {
this.phaseBuffs.splice(index, 1);
this.model.phaseBuffs = this.phaseBuffs;
this.loadPhaseBuffs();
}
this.isLoading = false;
});
}
});
}
private generatePhaseBuffId(): string {
return 'phasebuff_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
}
public close(): void {
this.dialog.close();
}
public save(): void {
if (!this.processing && this.model) {
this.processing = true;
this.model.phaseBuffs = this.phaseBuffs;
this.model.mobInfoId = this.mobInfoId || this.model.mobInfoId;
this.bossFightProfileService.createOrUpdate(this.model).pipe(first()).subscribe(result => {
this.processing = false;
this.dialog.close(result);
}, error => {
this.processing = false;
console.error('Error saving boss fight profile:', error);
});
}
}
showInsertMD2Icon(attributeName: string) {
this.dialogService.open({
title: 'Select MD2 Icon',
content: MD2IconPickerDlgComponent,
width: '800px',
height: 600
}).result.subscribe((html: string) => {
if (html && typeof html === 'string') {
this.model[attributeName] = html;
} else {
this.model[attributeName] = '';
}
});
}
public get isValid(): boolean {
if (!this.model) {
return false;
}
return this.model.mobInfoId !== '';
}
}