Fix reconnect issue.
This commit is contained in:
parent
3a12b6a4ab
commit
3325c63631
@ -83,6 +83,7 @@ export abstract class MD2Base {
|
|||||||
}
|
}
|
||||||
abstract refreshUI();
|
abstract refreshUI();
|
||||||
handleSignalRCallback(message: SignalRMessage): void {
|
handleSignalRCallback(message: SignalRMessage): void {
|
||||||
|
console.log('handleSignalRCallback', message);
|
||||||
if (message.from) {
|
if (message.from) {
|
||||||
if (message.from.isGroup) {
|
if (message.from.isGroup) {
|
||||||
if (!this.isHeroDashboard) return;
|
if (!this.isHeroDashboard) return;
|
||||||
@ -146,6 +147,8 @@ export abstract class MD2Base {
|
|||||||
break;
|
break;
|
||||||
case 'update':
|
case 'update':
|
||||||
if (this.isHeroDashboard) {
|
if (this.isHeroDashboard) {
|
||||||
|
//Before update game info check the current Hero level
|
||||||
|
let playerHeroLevel = this.md2Service.playerHero?.level;
|
||||||
this.md2Service.info = new MD2GameInfo(JSON.parse(message.parameters['gameInfo']) as MD2GameInfo);
|
this.md2Service.info = new MD2GameInfo(JSON.parse(message.parameters['gameInfo']) as MD2GameInfo);
|
||||||
let playerHero = this.md2Service.heros.find(h => h.playerInfo.tabId == this.stateService.loginUserService.sessionTabId);
|
let playerHero = this.md2Service.heros.find(h => h.playerInfo.tabId == this.stateService.loginUserService.sessionTabId);
|
||||||
if (playerHero) {
|
if (playerHero) {
|
||||||
@ -154,6 +157,13 @@ export abstract class MD2Base {
|
|||||||
playerHero.playerInfo.isDisconnected = false;
|
playerHero.playerInfo.isDisconnected = false;
|
||||||
this.md2Service.playerHero = playerHero;
|
this.md2Service.playerHero = playerHero;
|
||||||
this.md2Service.broadcastMyHeroInfo();
|
this.md2Service.broadcastMyHeroInfo();
|
||||||
|
//When fetch game info, if the hero level is changed, show the level up message
|
||||||
|
if (playerHeroLevel && playerHeroLevel != playerHero.level) {
|
||||||
|
//do i--
|
||||||
|
for (let i = playerHero.level; i > playerHeroLevel; i--) {
|
||||||
|
this.md2Service.msgBoxService.show(`Level Up Lv.${i}`, { text: 'Please do a skill level up!', icon: ADIcon.INFO });
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.detectChanges();
|
this.detectChanges();
|
||||||
}
|
}
|
||||||
@ -172,9 +182,11 @@ export abstract class MD2Base {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'sendJoinInfo':
|
case 'sendJoinInfo':
|
||||||
|
//When hero join the game, or reconnect to the game will receive this message
|
||||||
if (this.isHeroDashboard && this.md2Service.playerHero) {
|
if (this.isHeroDashboard && this.md2Service.playerHero) {
|
||||||
this.md2Service.playerHero.playerInfo.signalRClientId = message.parameters['signalrconnid'];
|
this.md2Service.playerHero.playerInfo.signalRClientId = message.parameters['signalrconnid'];
|
||||||
this.md2Service.broadcastMyHeroInfo();
|
//Send fetch game info to the hero
|
||||||
|
this.md2Service.broadcastFetchGameInfo();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { Component, OnInit, Input } from '@angular/core';
|
|||||||
import { NbDialogRef } from '@nebular/theme';
|
import { NbDialogRef } from '@nebular/theme';
|
||||||
import { GameBundle } from '../massive-darkness2.db.model';
|
import { GameBundle } from '../massive-darkness2.db.model';
|
||||||
import { MD2Service } from '../../../services/MD2/md2.service';
|
import { MD2Service } from '../../../services/MD2/md2.service';
|
||||||
|
import { StringUtils } from '../../../utilities/string-utils';
|
||||||
|
|
||||||
export interface GameInitConfig {
|
export interface GameInitConfig {
|
||||||
enabledBundles: GameBundle[];
|
enabledBundles: GameBundle[];
|
||||||
@ -23,12 +24,7 @@ export class GameInitDlgComponent implements OnInit {
|
|||||||
enableMobSpecialRule: boolean = false;
|
enableMobSpecialRule: boolean = false;
|
||||||
enableHeroBetrayal: boolean = false;
|
enableHeroBetrayal: boolean = false;
|
||||||
|
|
||||||
bundleOptions = [
|
bundleOptions = [];
|
||||||
{ value: GameBundle.CoreGame, label: 'Core Game' },
|
|
||||||
{ value: GameBundle.HeavenFallen, label: 'Heaven Fallen' },
|
|
||||||
{ value: GameBundle.Zombiecide, label: 'Zombiecide' },
|
|
||||||
{ value: GameBundle.ZombiecideWhiteDeath, label: 'Zombiecide White Death' }
|
|
||||||
];
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private dlgRef: NbDialogRef<GameInitDlgComponent>,
|
private dlgRef: NbDialogRef<GameInitDlgComponent>,
|
||||||
@ -36,6 +32,10 @@ export class GameInitDlgComponent implements OnInit {
|
|||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
//For each GameBundle, create a new option
|
||||||
|
this.bundleOptions = Object.values(GameBundle).filter(b => !isNaN(Number(b))).map(b => ({
|
||||||
|
value: b as GameBundle, label: StringUtils.camelToTitle(GameBundle[b as GameBundle] as string)
|
||||||
|
}));
|
||||||
// Initialize from context if provided
|
// Initialize from context if provided
|
||||||
if (this.initialConfig) {
|
if (this.initialConfig) {
|
||||||
this.enabledBundles = [...this.initialConfig.enabledBundles];
|
this.enabledBundles = [...this.initialConfig.enabledBundles];
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import { HeroClass, MD2HeroInfo, MD2HeroProfile, MD2Icon } from '../massive-dark
|
|||||||
import { MD2Base } from '../MD2Base';
|
import { MD2Base } from '../MD2Base';
|
||||||
import { MD2HeroProfileService } from '../service/massive-darkness2.service';
|
import { MD2HeroProfileService } from '../service/massive-darkness2.service';
|
||||||
import { SignalRService } from '../../../services/signal-r.service';
|
import { SignalRService } from '../../../services/signal-r.service';
|
||||||
|
import { NbToastrService } from '@nebular/theme';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ngx-hero-dashboard',
|
selector: 'ngx-hero-dashboard',
|
||||||
@ -46,7 +47,9 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
heroUpdateDebounceTimer = new DebounceTimer(1000, () => { this.broadcastHeroInfo(); })
|
heroUpdateDebounceTimer = new DebounceTimer(1000, () => {
|
||||||
|
this.broadcastHeroInfo();
|
||||||
|
})
|
||||||
|
|
||||||
classOptions: DropDownOption[] = [
|
classOptions: DropDownOption[] = [
|
||||||
new DropDownOption(HeroClass.Berserker, 'Berserker'),
|
new DropDownOption(HeroClass.Berserker, 'Berserker'),
|
||||||
@ -92,7 +95,8 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
|
|||||||
protected route: ActivatedRoute,
|
protected route: ActivatedRoute,
|
||||||
protected cdRef: ChangeDetectorRef,
|
protected cdRef: ChangeDetectorRef,
|
||||||
private msgBoxService: MsgBoxService,
|
private msgBoxService: MsgBoxService,
|
||||||
private signalRService: SignalRService
|
private signalRService: SignalRService,
|
||||||
|
private toastrService: NbToastrService
|
||||||
) {
|
) {
|
||||||
super(md2Service, stateService, route, cdRef);
|
super(md2Service, stateService, route, cdRef);
|
||||||
this.isHeroDashboard = true;
|
this.isHeroDashboard = true;
|
||||||
@ -109,9 +113,10 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
|
|||||||
this.gameRoomService.joinGameRoom(this.roomId);
|
this.gameRoomService.joinGameRoom(this.roomId);
|
||||||
//this.fetchGameInfo();
|
//this.fetchGameInfo();
|
||||||
this.signalRService.signalRMessageConnSubject.subscribe(state => {
|
this.signalRService.signalRMessageConnSubject.subscribe(state => {
|
||||||
if (state.status == 'connected') {
|
//fetchGameInfo is called in MD2Base.handleSignalRCallback sendJoinInfo message
|
||||||
this.fetchGameInfo();
|
// if (state.status == 'connected') {
|
||||||
}
|
// this.fetchGameInfo();
|
||||||
|
// }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,7 +289,6 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
|
|||||||
this.hero.uiActivating = false;
|
this.hero.uiActivating = false;
|
||||||
}
|
}
|
||||||
this.broadcastHeroInfo();
|
this.broadcastHeroInfo();
|
||||||
|
|
||||||
}
|
}
|
||||||
endActivation() {
|
endActivation() {
|
||||||
if (this.hero.remainActions > 0) {
|
if (this.hero.remainActions > 0) {
|
||||||
|
|||||||
@ -57,7 +57,9 @@
|
|||||||
({{md2Service.highestPlayerLevel}})</label>
|
({{md2Service.highestPlayerLevel}})</label>
|
||||||
</div> -->
|
</div> -->
|
||||||
<div class="col-12" *ngFor="let hero of md2Service.heros">
|
<div class="col-12" *ngFor="let hero of md2Service.heros">
|
||||||
<label class='label mr-1'>{{hero.playerInfo.name}} ({{heroClassName(hero)}} -
|
<label class='label mr-1'
|
||||||
|
(click)="adjustHeroValue(hero,'remainActions')">{{hero.playerInfo.name}}
|
||||||
|
({{heroClassName(hero)}} -
|
||||||
{{hero.name}})</label>
|
{{hero.name}})</label>
|
||||||
<span class="badge badge-primary mr-1"
|
<span class="badge badge-primary mr-1"
|
||||||
(click)="adjustHeroValue(hero,'level')">Lv.:{{hero.level}}</span>
|
(click)="adjustHeroValue(hero,'level')">Lv.:{{hero.level}}</span>
|
||||||
|
|||||||
@ -112,7 +112,7 @@ export class MassiveDarkness2Component extends MD2Base implements OnInit {
|
|||||||
inputType: 'number',
|
inputType: 'number',
|
||||||
inputValue: hero[value].toString()
|
inputValue: hero[value].toString()
|
||||||
}).pipe(first()).subscribe(result => {
|
}).pipe(first()).subscribe(result => {
|
||||||
if (result) {
|
if (![false, null, undefined].includes(result)) {
|
||||||
hero[value] = Number.parseInt(result);
|
hero[value] = Number.parseInt(result);
|
||||||
this.md2Service.broadcastHeroInfoToAll(hero, true);
|
this.md2Service.broadcastHeroInfoToAll(hero, true);
|
||||||
this.detectChanges();
|
this.detectChanges();
|
||||||
|
|||||||
@ -8,6 +8,7 @@ export enum MobSkillTarget {
|
|||||||
HighestHp = 70,
|
HighestHp = 70,
|
||||||
HighestMp = 80,
|
HighestMp = 80,
|
||||||
LowestLevel = 90,
|
LowestLevel = 90,
|
||||||
|
HighestLevel = 100,
|
||||||
MostExtraToken = 200,
|
MostExtraToken = 200,
|
||||||
LeastExtraToken,
|
LeastExtraToken,
|
||||||
MostExtraToken2,
|
MostExtraToken2,
|
||||||
@ -17,8 +18,9 @@ export enum MobSkillTarget {
|
|||||||
export enum GameBundle {
|
export enum GameBundle {
|
||||||
CoreGame,
|
CoreGame,
|
||||||
HeavenFallen,
|
HeavenFallen,
|
||||||
Zombiecide,
|
Zombicide,
|
||||||
ZombiecideWhiteDeath
|
ZombicideWhiteDeath,
|
||||||
|
DarkBringerPack
|
||||||
}
|
}
|
||||||
export interface MD2MobInfo {
|
export interface MD2MobInfo {
|
||||||
id: string;
|
id: string;
|
||||||
@ -48,7 +50,10 @@ export interface MD2MobLevelInfo {
|
|||||||
defenceInfo: MD2DiceSet;
|
defenceInfo: MD2DiceSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MD2MobSkill {
|
export class MD2MobSkill {
|
||||||
|
constructor(config: Partial<MD2MobSkill> = {}) {
|
||||||
|
Object.assign(this, config);
|
||||||
|
}
|
||||||
id: string;
|
id: string;
|
||||||
seq: number;
|
seq: number;
|
||||||
level: number;
|
level: number;
|
||||||
|
|||||||
@ -21,7 +21,7 @@ export class MD2Logic {
|
|||||||
break;
|
break;
|
||||||
case MobSkillTarget.LeastMp:
|
case MobSkillTarget.LeastMp:
|
||||||
let lowestMp = Math.min(...heros.map(h => h.mp));
|
let lowestMp = Math.min(...heros.map(h => h.mp));
|
||||||
beenAttackedHero = heros.filter(h => h.hp == lowestMp);
|
beenAttackedHero = heros.filter(h => h.mp == lowestMp);
|
||||||
//this.otherAttackTarget = 'attacking the other <b>Lowest HP</b> hero.';
|
//this.otherAttackTarget = 'attacking the other <b>Lowest HP</b> hero.';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -36,10 +36,15 @@ export class MD2Logic {
|
|||||||
//this.otherAttackTarget = 'attacking the other <b>Highest Mp</b> hero.';
|
//this.otherAttackTarget = 'attacking the other <b>Highest Mp</b> hero.';
|
||||||
break;
|
break;
|
||||||
case MobSkillTarget.LowestLevel:
|
case MobSkillTarget.LowestLevel:
|
||||||
let lowestLevel = Math.max(...heros.map(h => h.level));
|
let lowestLevel = Math.min(...heros.map(h => h.level));
|
||||||
beenAttackedHero = heros.filter(h => h.level == lowestLevel);
|
beenAttackedHero = heros.filter(h => h.level == lowestLevel);
|
||||||
//this.otherAttackTarget = 'attacking the other <b>Lowest Level</b> hero.';
|
//this.otherAttackTarget = 'attacking the other <b>Lowest Level</b> hero.';
|
||||||
break;
|
break;
|
||||||
|
case MobSkillTarget.HighestLevel:
|
||||||
|
let highestLevel = Math.max(...heros.map(h => h.level));
|
||||||
|
beenAttackedHero = heros.filter(h => h.level == highestLevel);
|
||||||
|
//this.otherAttackTarget = 'attacking the other <b>Lowest Level</b> hero.';
|
||||||
|
break;
|
||||||
case MobSkillTarget.LeastExtraToken:
|
case MobSkillTarget.LeastExtraToken:
|
||||||
|
|
||||||
let leastExtraToken = Math.min(...heros.map(h => h.extraToken));
|
let leastExtraToken = Math.min(...heros.map(h => h.extraToken));
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { ObjectUtils } from "../../utilities/object-utils";
|
|||||||
import { GamePlayer } from "../games.model";
|
import { GamePlayer } from "../games.model";
|
||||||
import { MD2Clone } from "./factorys/md2-clone";
|
import { MD2Clone } from "./factorys/md2-clone";
|
||||||
import { MobSkill } from "./massive-darkness2.model.boss";
|
import { MobSkill } from "./massive-darkness2.model.boss";
|
||||||
import { BossFightProfile, MD2DiceSet, MD2MobSkill } from "./massive-darkness2.db.model";
|
import { BossFightProfile, GameBundle, MD2DiceSet, MD2MobSkill } from "./massive-darkness2.db.model";
|
||||||
|
|
||||||
const MD2_IMG_URL = (id: string = null) => { return `${environment.apiUrl}/Files/Images/MD2/${(id ? `${encodeURI(id)}` : '')}` }
|
const MD2_IMG_URL = (id: string = null) => { return `${environment.apiUrl}/Files/Images/MD2/${(id ? `${encodeURI(id)}` : '')}` }
|
||||||
export enum MobDlgType {
|
export enum MobDlgType {
|
||||||
@ -307,6 +307,8 @@ export class MobInfo implements IDrawingItem {
|
|||||||
this.drawingWeight = 1;
|
this.drawingWeight = 1;
|
||||||
this.unitRemainHp = config.hp
|
this.unitRemainHp = config.hp
|
||||||
}
|
}
|
||||||
|
id: string;
|
||||||
|
from: GameBundle;
|
||||||
type: MobType = MobType.Mob;
|
type: MobType = MobType.Mob;
|
||||||
imageUrl: string
|
imageUrl: string
|
||||||
standUrl: string
|
standUrl: string
|
||||||
@ -429,7 +431,7 @@ export class MD2HeroInfo {
|
|||||||
uiShowExtraToken2 = false;
|
uiShowExtraToken2 = false;
|
||||||
uiBossFight = false;
|
uiBossFight = false;
|
||||||
uiShowAttackBtn = false;
|
uiShowAttackBtn = false;
|
||||||
|
uiBetrayal = false;
|
||||||
public get heroFullName(): string {
|
public get heroFullName(): string {
|
||||||
return `${this.playerInfo.name} (${HeroClass[this.class]} - ${this.name})`
|
return `${this.playerInfo.name} (${HeroClass[this.class]} - ${this.name})`
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,10 +18,11 @@ export class MD2HeroProfileMaintenanceComponent implements OnInit {
|
|||||||
MD2Icon = MD2Icon;
|
MD2Icon = MD2Icon;
|
||||||
public gridData: GridDataResult = { data: [], total: 0 };
|
public gridData: GridDataResult = { data: [], total: 0 };
|
||||||
private allData: MD2HeroProfile[] = [];
|
private allData: MD2HeroProfile[] = [];
|
||||||
|
private lastSelectedHero: MD2HeroProfile;
|
||||||
private lastSelectedHeroClass: HeroClass;
|
private lastSelectedHeroClass: HeroClass;
|
||||||
public gridState: State = {
|
public gridState: State = {
|
||||||
skip: 0,
|
skip: 0,
|
||||||
take: 10,
|
take: 1000,
|
||||||
sort: [{
|
sort: [{
|
||||||
field: 'title',
|
field: 'title',
|
||||||
dir: 'asc'
|
dir: 'asc'
|
||||||
@ -77,6 +78,11 @@ export class MD2HeroProfileMaintenanceComponent implements OnInit {
|
|||||||
|
|
||||||
public addHandler(): void {
|
public addHandler(): void {
|
||||||
const editorData = { heroClass: this.lastSelectedHeroClass || HeroClass.Berserker } as MD2HeroProfile;
|
const editorData = { heroClass: this.lastSelectedHeroClass || HeroClass.Berserker } as MD2HeroProfile;
|
||||||
|
if (this.lastSelectedHero) {
|
||||||
|
editorData.heroClass = this.lastSelectedHero.heroClass;
|
||||||
|
editorData.skillHtml = this.lastSelectedHero.skillHtml;
|
||||||
|
editorData.shadowSkillHtml = this.lastSelectedHero.shadowSkillHtml;
|
||||||
|
}
|
||||||
const dialogRef = this.dialogService.open({
|
const dialogRef = this.dialogService.open({
|
||||||
title: 'Add New Hero Profile',
|
title: 'Add New Hero Profile',
|
||||||
content: MD2HeroProfileEditorComponent,
|
content: MD2HeroProfileEditorComponent,
|
||||||
@ -95,6 +101,7 @@ export class MD2HeroProfileMaintenanceComponent implements OnInit {
|
|||||||
|
|
||||||
dialogRef.result.subscribe((result: MD2HeroProfile) => {
|
dialogRef.result.subscribe((result: MD2HeroProfile) => {
|
||||||
if (result) {
|
if (result) {
|
||||||
|
this.lastSelectedHero = result;
|
||||||
this.lastSelectedHeroClass = result.heroClass;
|
this.lastSelectedHeroClass = result.heroClass;
|
||||||
this.loadData();
|
this.loadData();
|
||||||
}
|
}
|
||||||
@ -108,7 +115,7 @@ export class MD2HeroProfileMaintenanceComponent implements OnInit {
|
|||||||
width: '90vw',
|
width: '90vw',
|
||||||
height: 600
|
height: 600
|
||||||
});
|
});
|
||||||
|
this.lastSelectedHero = dataItem;
|
||||||
const editor = dialogRef.content.instance;
|
const editor = dialogRef.content.instance;
|
||||||
editor.isAdding = false;
|
editor.isAdding = false;
|
||||||
editor.data = JSON.parse(JSON.stringify(dataItem));
|
editor.data = JSON.parse(JSON.stringify(dataItem));
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import { StringUtils } from '../../../utilities/string-utils';
|
|||||||
import { DrawingBag, DrawingItem, MD2Icon, MobDlgType, MobInfo, TreasureType } from '../massive-darkness2.model';
|
import { DrawingBag, DrawingItem, MD2Icon, MobDlgType, MobInfo, TreasureType } from '../massive-darkness2.model';
|
||||||
import { MD2Base, MD2ComponentBase } from '../MD2Base';
|
import { MD2Base, MD2ComponentBase } from '../MD2Base';
|
||||||
import { SpawnMobDlgComponent } from './spawn-mob-dlg/spawn-mob-dlg.component';
|
import { SpawnMobDlgComponent } from './spawn-mob-dlg/spawn-mob-dlg.component';
|
||||||
|
import { GameBundle } from '../massive-darkness2.db.model';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'md2-mobs',
|
selector: 'md2-mobs',
|
||||||
@ -89,21 +90,23 @@ export class MobsComponent extends MD2ComponentBase implements OnInit {
|
|||||||
|
|
||||||
spawnSpecificMob() {
|
spawnSpecificMob() {
|
||||||
let mobOptions = this.isRoamingMonster ?
|
let mobOptions = this.isRoamingMonster ?
|
||||||
this.md2Service.allRoamingMonsterInfos.map(f => new DropDownOption(f.name, f.name)) :
|
this.md2Service.allRoamingMonsterInfos.map(f => new DropDownOption(f.id, `${StringUtils.camelToTitle(GameBundle[f.from])} - ${f.name}`)) :
|
||||||
this.md2Service.allMobInfos.map(f => new DropDownOption(f.name, f.name));
|
this.md2Service.allMobInfos.map(f => new DropDownOption(f.id, `${StringUtils.camelToTitle(GameBundle[f.from])} - ${f.name}`));
|
||||||
|
mobOptions = mobOptions.sort((a, b) => a.value1.localeCompare(b.value1));
|
||||||
|
|
||||||
this.msgBoxService.showInputbox('Spawn', '',
|
this.msgBoxService.showInputbox('Spawn', '',
|
||||||
{
|
{
|
||||||
inputType: 'dropdown', dropDownOptions: mobOptions,
|
inputType: 'dropdown', dropDownOptions: mobOptions,
|
||||||
buttons: ADButtons.YesNoCancel,
|
buttons: ADButtons.YesNoCancel,
|
||||||
confirmButtonText: 'Spawn',
|
confirmButtonText: 'Spawn',
|
||||||
cancelButtonText: 'Random'
|
cancelButtonText: 'Random'
|
||||||
}).pipe(first()).subscribe(mobName => {
|
}).pipe(first()).subscribe(mobId => {
|
||||||
|
|
||||||
|
|
||||||
if (mobName || mobName === false) {
|
if (mobId || mobId === false) {
|
||||||
|
|
||||||
if (!mobName) { mobName = null; }
|
if (!mobId) { mobId = null; }
|
||||||
let result = this.md2Service.spawnMob(this.isRoamingMonster, mobName);
|
let result = this.md2Service.spawnMob(this.isRoamingMonster, mobId);
|
||||||
let titleText = result.exitingMob == null ? `${result.mob.description} Shows Up` : `${result.mob.description} Activate One Action Now!`;
|
let titleText = result.exitingMob == null ? `${result.mob.description} Shows Up` : `${result.mob.description} Activate One Action Now!`;
|
||||||
let actType = result.exitingMob == null ? MobDlgType.Spawn : MobDlgType.Activating;
|
let actType = result.exitingMob == null ? MobDlgType.Spawn : MobDlgType.Activating;
|
||||||
let mob = result.exitingMob == null ? result.mob : result.exitingMob;
|
let mob = result.exitingMob == null ? result.mob : result.exitingMob;
|
||||||
|
|||||||
@ -12,7 +12,8 @@ import { MD2ComponentBase } from '../../MD2Base';
|
|||||||
import { ADButtons, ADIcon } from '../../../../ui/alert-dlg/alert-dlg.model';
|
import { ADButtons, ADIcon } from '../../../../ui/alert-dlg/alert-dlg.model';
|
||||||
import { MobSkillType } from '../../massive-darkness2.model.boss';
|
import { MobSkillType } from '../../massive-darkness2.model.boss';
|
||||||
import { Observable, from, of } from 'rxjs';
|
import { Observable, from, of } from 'rxjs';
|
||||||
import { MD2MobSkill } from '../../massive-darkness2.db.model';
|
import { MD2MobSkill, MobSkillTarget } from '../../massive-darkness2.db.model';
|
||||||
|
import { MD2Logic } from '../../massive-darkness2.logic';
|
||||||
|
|
||||||
type SkillResolutionResult = { result: boolean; skill: MD2MobSkill | null };
|
type SkillResolutionResult = { result: boolean; skill: MD2MobSkill | null };
|
||||||
|
|
||||||
@ -31,7 +32,7 @@ export class SpawnMobDlgComponent extends MD2ComponentBase implements OnInit {
|
|||||||
MD2Icon = MD2Icon;
|
MD2Icon = MD2Icon;
|
||||||
mob: MobInfo;
|
mob: MobInfo;
|
||||||
actionInfoHtml: string;
|
actionInfoHtml: string;
|
||||||
beenAttackedHero = [] as MD2HeroInfo[];
|
beenAttackedHero = null as MD2HeroInfo;
|
||||||
attackTarget: string;
|
attackTarget: string;
|
||||||
otherAttackTarget: string;
|
otherAttackTarget: string;
|
||||||
constructor(
|
constructor(
|
||||||
@ -157,50 +158,45 @@ export class SpawnMobDlgComponent extends MD2ComponentBase implements OnInit {
|
|||||||
if (this.mode == MobDlgType.Spawn) {
|
if (this.mode == MobDlgType.Spawn) {
|
||||||
htmlText = `${this.mob.description} Shows Up`;
|
htmlText = `${this.mob.description} Shows Up`;
|
||||||
} else if (this.mode == MobDlgType.Activating) {
|
} else if (this.mode == MobDlgType.Activating) {
|
||||||
let targetType = null as AttackTarget;
|
let targetType = null as MobSkillTarget;
|
||||||
let randomAttack = Math.random() * AttackTarget.LowestLevel;
|
let randomAttack = Math.random() * MobSkillTarget.HighestLevel;
|
||||||
const values = Object.values(AttackTarget);
|
const values = Object.values(MobSkillTarget);
|
||||||
|
|
||||||
const stringKeys = Object
|
const stringKeys = Object
|
||||||
.keys(AttackTarget)
|
.keys(MobSkillTarget)
|
||||||
.filter((v) => isNaN(Number(v)))
|
.filter((v) => isNaN(Number(v)))
|
||||||
for (let i = 0; i < stringKeys.length; i++) {
|
for (let i = 0; i < stringKeys.length; i++) {
|
||||||
const element = AttackTarget[stringKeys[i]];
|
const element = MobSkillTarget[stringKeys[i]];
|
||||||
|
|
||||||
if (element >= randomAttack) {
|
if (element >= randomAttack) {
|
||||||
targetType = element;
|
targetType = element;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.beenAttackedHero = MD2Logic.getTargetHeroByFilter(this.md2Service.heros, targetType);
|
||||||
switch (targetType) {
|
switch (targetType) {
|
||||||
case AttackTarget.LeastHp:
|
case MobSkillTarget.LeastHp:
|
||||||
let lowestHp = Math.min(...this.md2Service.heros.map(h => h.hp));
|
this.otherAttackTarget = 'attacking the other <b>Lowest HP</b> hero.';
|
||||||
this.beenAttackedHero = this.md2Service.heros.filter(h => h.hp == lowestHp);
|
|
||||||
//this.otherAttackTarget = 'attacking the other <b>Lowest HP</b> hero.';
|
|
||||||
break;
|
break;
|
||||||
case AttackTarget.HighestHp:
|
case MobSkillTarget.HighestHp:
|
||||||
let highestHp = Math.max(...this.md2Service.heros.map(h => h.hp));
|
this.otherAttackTarget = 'attacking the other <b>Highest HP</b> hero.';
|
||||||
this.beenAttackedHero = this.md2Service.heros.filter(h => h.hp == highestHp);
|
|
||||||
//this.otherAttackTarget = 'attacking the other <b>Highest HP</b> hero.';
|
|
||||||
break;
|
break;
|
||||||
case AttackTarget.HighestMp:
|
case MobSkillTarget.HighestMp:
|
||||||
let highestMp = Math.max(...this.md2Service.heros.map(h => h.mp));
|
this.otherAttackTarget = 'attacking the other <b>Highest Mana</b> hero.';
|
||||||
this.beenAttackedHero = this.md2Service.heros.filter(h => h.mp == highestMp);
|
|
||||||
//this.otherAttackTarget = 'attacking the other <b>Highest Mp</b> hero.';
|
|
||||||
break;
|
break;
|
||||||
case AttackTarget.LowestLevel:
|
case MobSkillTarget.LowestLevel:
|
||||||
let lowestLevel = Math.max(...this.md2Service.heros.map(h => h.level));
|
this.otherAttackTarget = 'attacking the other <b>Lowest Level</b> hero.';
|
||||||
this.beenAttackedHero = this.md2Service.heros.filter(h => h.level == lowestLevel);
|
|
||||||
//this.otherAttackTarget = 'attacking the other <b>Lowest Level</b> hero.';
|
|
||||||
break;
|
break;
|
||||||
case AttackTarget.Random:
|
case MobSkillTarget.HighestLevel:
|
||||||
|
this.otherAttackTarget = 'attacking the other <b>Highest Level</b> hero.';
|
||||||
|
break;
|
||||||
|
case MobSkillTarget.Random:
|
||||||
default:
|
default:
|
||||||
this.beenAttackedHero = [this.md2Service.heros[Math.round(Math.random() * (this.md2Service.heros.length - 1))]];
|
this.otherAttackTarget = 'Just act like normal.';
|
||||||
//this.otherAttackTarget = 'Just act like normal.';
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let attackedHeros = StringUtils.makeCommaSeparatedString(this.beenAttackedHero.map(h => this.md2Service.heroFullName(h)), true, true);
|
//let attackedHeros = StringUtils.makeCommaSeparatedString(this.beenAttackedHero.map(h => this.md2Service.heroFullName(h)), true, true);
|
||||||
this.attackTarget = `Attacking <b>${attackedHeros}</b> first if possible.`;
|
this.attackTarget = `Attacking <b>${this.beenAttackedHero.heroFullName}</b> first if possible, otherwise ${this.otherAttackTarget}`;
|
||||||
htmlText = `${this.title}`;
|
htmlText = `${this.title}`;
|
||||||
} else {
|
} else {
|
||||||
htmlText = `${this.mob.description}`;
|
htmlText = `${this.mob.description}`;
|
||||||
|
|||||||
@ -38,10 +38,10 @@ export class MD2InitService {
|
|||||||
const levelInfo = mobInfo.mobLevelInfos[j];
|
const levelInfo = mobInfo.mobLevelInfos[j];
|
||||||
switch (mobInfo.type) {
|
switch (mobInfo.type) {
|
||||||
case MobType.Mob:
|
case MobType.Mob:
|
||||||
this.md2Service.mobDeck.AddItem(new MobInfo({ name: mobInfo.name, level: levelInfo.level, drawingWeight: 1 }));
|
this.md2Service.mobDeck.AddItem(new MobInfo({ id: mobInfo.id, name: mobInfo.name, from: mobInfo.from, level: levelInfo.level, drawingWeight: 1 }));
|
||||||
break;
|
break;
|
||||||
case MobType.RoamingMonster:
|
case MobType.RoamingMonster:
|
||||||
this.md2Service.roamingMobDeck.AddItem(new MobInfo({ name: mobInfo.name, level: levelInfo.level, drawingWeight: 1 }));
|
this.md2Service.roamingMobDeck.AddItem(new MobInfo({ id: mobInfo.id, name: mobInfo.name, from: mobInfo.from, level: levelInfo.level, drawingWeight: 1 }));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import { GameBundle, MD2DiceSet, MD2MobInfo, MD2MobSkill, MobSkillTarget } from
|
|||||||
import { environment } from '../../../environments/environment';
|
import { environment } from '../../../environments/environment';
|
||||||
import { RollingBlackDice } from '../../games/massive-darkness2/massive-darkness2.model.dice';
|
import { RollingBlackDice } from '../../games/massive-darkness2/massive-darkness2.model.dice';
|
||||||
import { BossActivationComponent } from '../../games/massive-darkness2/boss-fight/boss-activation/boss-activation.component';
|
import { BossActivationComponent } from '../../games/massive-darkness2/boss-fight/boss-activation/boss-activation.component';
|
||||||
|
import { NbToastrService } from '@nebular/theme';
|
||||||
|
|
||||||
|
|
||||||
const MD2_IMG_URL = (id: string = null) => { return `${environment.apiUrl}/Files/Images/MD2/Mobs${(id ? `${encodeURI(id)}` : '')}` };
|
const MD2_IMG_URL = (id: string = null) => { return `${environment.apiUrl}/Files/Images/MD2/Mobs${(id ? `${encodeURI(id)}` : '')}` };
|
||||||
@ -79,7 +80,8 @@ export class MD2Service {
|
|||||||
public loginUserService: LoginUserService,
|
public loginUserService: LoginUserService,
|
||||||
public signalRService: SignalRService,
|
public signalRService: SignalRService,
|
||||||
public dlgService: NbDialogService,
|
public dlgService: NbDialogService,
|
||||||
public themeService: NbThemeService
|
public themeService: NbThemeService,
|
||||||
|
public toastrService: NbToastrService
|
||||||
) {
|
) {
|
||||||
this.darknessPhaseRule = new CoreGameDarknessPhaseRule();
|
this.darknessPhaseRule = new CoreGameDarknessPhaseRule();
|
||||||
this.info = new MD2GameInfo();
|
this.info = new MD2GameInfo();
|
||||||
@ -133,6 +135,18 @@ export class MD2Service {
|
|||||||
this.info.roundPhase = RoundPhase.HeroPhase;
|
this.info.roundPhase = RoundPhase.HeroPhase;
|
||||||
if (!this.info.isBossFight) {
|
if (!this.info.isBossFight) {
|
||||||
this.info.round++;
|
this.info.round++;
|
||||||
|
if (this.info.round == 5 && this.info.enableHeroBetrayal) {
|
||||||
|
let betrayalHero = this.getTargetHerosByFilter(MobSkillTarget.LowestLevel, true)[0];
|
||||||
|
this.sendMsgboxMsg(betrayalHero.playerInfo.signalRClientId,
|
||||||
|
{
|
||||||
|
title: 'Dark Lord’s Invitation', text: 'Child of light… why pretend?<br>' +
|
||||||
|
'I have seen the hunger within you, the one your allies fear you will one day unleash.<br>' +
|
||||||
|
'Serve me openly, and the world shall kneel before you.<br>' +
|
||||||
|
'One act of betrayal—one moment of truth—and you will become the legend the others only pretend to be.', icon: ADIcon.WARNING
|
||||||
|
});
|
||||||
|
betrayalHero.uiBetrayal = true;
|
||||||
|
this.broadcastGameInfo();
|
||||||
|
}
|
||||||
if (this.darknessPhaseRule.runDarknessPhase()) {
|
if (this.darknessPhaseRule.runDarknessPhase()) {
|
||||||
this.msgBoxService.show(`${NumberUtils.Ordinal(this.info.round)} Hero Phase`, { icon: ADIcon.INFO });
|
this.msgBoxService.show(`${NumberUtils.Ordinal(this.info.round)} Hero Phase`, { icon: ADIcon.INFO });
|
||||||
}
|
}
|
||||||
@ -144,7 +158,7 @@ export class MD2Service {
|
|||||||
//this.runNextPhase();
|
//this.runNextPhase();
|
||||||
}
|
}
|
||||||
|
|
||||||
public spawnMob(isRoamingMonster: boolean, mobName: string = null) {
|
public spawnMob(isRoamingMonster: boolean, mobId: string = null) {
|
||||||
let mobDeck = null as DrawingBag<MobInfo>;
|
let mobDeck = null as DrawingBag<MobInfo>;
|
||||||
let level = 1;
|
let level = 1;
|
||||||
if (this.highestPlayerLevel < 3) {
|
if (this.highestPlayerLevel < 3) {
|
||||||
@ -159,17 +173,17 @@ export class MD2Service {
|
|||||||
mobDeck = this.mobDeck;
|
mobDeck = this.mobDeck;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mobDeck.drawingItems.filter(m => (m as MobInfo).level == level)
|
if (mobDeck.drawingItems.filter(m => (m as MobInfo).level == level && this.info.enabledBundles.includes((m as MobInfo).from))
|
||||||
.map(d => d.drawingWeight).reduce((a, b) => a + b, 0) == 0) {
|
.map(d => d.drawingWeight).reduce((a, b) => a + b, 0) == 0) {
|
||||||
mobDeck.RestoreRemoveItems();
|
mobDeck.RestoreRemoveItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
let newSpawnMob = null as MobInfo;
|
let newSpawnMob = null as MobInfo;
|
||||||
|
|
||||||
if (mobName) {
|
if (mobId) {
|
||||||
newSpawnMob = new MobInfo(mobDeck.DrawAndRemove(1, m => m.level == level && m.name == mobName)[0]);
|
newSpawnMob = new MobInfo(mobDeck.DrawAndRemove(1, m => m.level == level && m.id == mobId)[0]);
|
||||||
} else {
|
} else {
|
||||||
newSpawnMob = new MobInfo(mobDeck.DrawAndRemove(1, m => m.level == level)[0]);
|
newSpawnMob = new MobInfo(mobDeck.DrawAndRemove(1, m => m.level == level && this.info.enabledBundles.includes(m.from))[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let exitingMob = isRoamingMonster ? this.roamingMonsters.find(m => m.name == newSpawnMob.name) : this.mobs.find(m => m.name == newSpawnMob.name);
|
let exitingMob = isRoamingMonster ? this.roamingMonsters.find(m => m.name == newSpawnMob.name) : this.mobs.find(m => m.name == newSpawnMob.name);
|
||||||
@ -224,15 +238,15 @@ export class MD2Service {
|
|||||||
mobInfo.skills = mobInfo.skills.sort((a, b) => b.seq - a.seq);
|
mobInfo.skills = mobInfo.skills.sort((a, b) => b.seq - a.seq);
|
||||||
switch (dbMobInfo.type) {
|
switch (dbMobInfo.type) {
|
||||||
case MobType.Mob:
|
case MobType.Mob:
|
||||||
mobInfo.leaderImgUrl = !!mobInfo.leaderImgUrl ? MD2_IMG_URL(mobInfo.leaderImgUrl) : MD2_IMG_URL(`/${GameBundle[dbMobInfo.from]}/Mobs/${mobInfo.name}/Leader.png`);
|
mobInfo.leaderImgUrl = !!dbMobInfo.leaderImgUrl ? this.imgUrl(dbMobInfo.leaderImgUrl) : MD2_IMG_URL(`/${GameBundle[dbMobInfo.from]}/Mobs/${mobInfo.name}/Leader.png`);
|
||||||
mobInfo.minionImgUrl = !!mobInfo.minionImgUrl ? MD2_IMG_URL(mobInfo.minionImgUrl) : MD2_IMG_URL(`/${GameBundle[dbMobInfo.from]}/Mobs/${mobInfo.name}/Minion.png`);
|
mobInfo.minionImgUrl = !!dbMobInfo.minionImgUrl ? this.imgUrl(dbMobInfo.minionImgUrl) : MD2_IMG_URL(`/${GameBundle[dbMobInfo.from]}/Mobs/${mobInfo.name}/Minion.png`);
|
||||||
break;
|
break;
|
||||||
case MobType.RoamingMonster:
|
case MobType.RoamingMonster:
|
||||||
mobInfo.leaderImgUrl = !!mobInfo.leaderImgUrl ? MD2_IMG_URL(mobInfo.leaderImgUrl) : MD2_IMG_URL(`/${GameBundle[dbMobInfo.from]}/RoamingMonsters/${mobInfo.name}/Stand.png`);
|
mobInfo.leaderImgUrl = !!dbMobInfo.leaderImgUrl ? this.imgUrl(dbMobInfo.leaderImgUrl) : MD2_IMG_URL(`/${GameBundle[dbMobInfo.from]}/RoamingMonsters/${mobInfo.name}/Stand.png`);
|
||||||
mobInfo.minionImgUrl = null;
|
mobInfo.minionImgUrl = null;
|
||||||
break;
|
break;
|
||||||
case MobType.Boss:
|
case MobType.Boss:
|
||||||
mobInfo.leaderImgUrl = !!mobInfo.leaderImgUrl ? MD2_IMG_URL(mobInfo.leaderImgUrl) : MD2_IMG_URL(`/Boss/${mobInfo.name}-Stand.png`);
|
mobInfo.leaderImgUrl = !!dbMobInfo.leaderImgUrl ? this.imgUrl(dbMobInfo.leaderImgUrl) : this.imgUrl(`/Boss/${mobInfo.name}-Stand.png`);
|
||||||
mobInfo.minionImgUrl = null;
|
mobInfo.minionImgUrl = null;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -632,7 +646,6 @@ export class MD2Service {
|
|||||||
actionName: actionName,
|
actionName: actionName,
|
||||||
parameters: parameters
|
parameters: parameters
|
||||||
} as SignalRMessage;
|
} as SignalRMessage;
|
||||||
|
|
||||||
if (sessionId == null) {
|
if (sessionId == null) {
|
||||||
message.receiver = { isGroup: true, connectionId: this.gameRoomService.gameRoomId } as SignalRClient
|
message.receiver = { isGroup: true, connectionId: this.gameRoomService.gameRoomId } as SignalRClient
|
||||||
} else {
|
} else {
|
||||||
@ -698,7 +711,9 @@ export class MD2Service {
|
|||||||
let actionHtml = '';
|
let actionHtml = '';
|
||||||
let beenAttackedHero = [] as MD2HeroInfo[];
|
let beenAttackedHero = [] as MD2HeroInfo[];
|
||||||
let bossAction: MD2MobSkill;
|
let bossAction: MD2MobSkill;
|
||||||
bossAction = this.info.boss.skills.find(s => s.type == MobSkillType.ActiveSkill && s.skillRoll == actionResult.claws);
|
bossAction = new MD2MobSkill(this.info.boss.skills.find(s => s.type == MobSkillType.ActiveSkill && s.skillRoll == actionResult.claws));
|
||||||
|
|
||||||
|
bossAction.description = this.skillParse(bossAction.description, bossAction.skillTarget);
|
||||||
|
|
||||||
return this.dlgService.open(BossActivationComponent, { context: { boss: this.info.boss, bossAction: bossAction, currentAction: this.bossActivatedTimes, allActions: this.info.boss.actions } }).onClose;
|
return this.dlgService.open(BossActivationComponent, { context: { boss: this.info.boss, bossAction: bossAction, currentAction: this.bossActivatedTimes, allActions: this.info.boss.actions } }).onClose;
|
||||||
|
|
||||||
@ -790,7 +805,6 @@ export class MD2Service {
|
|||||||
|
|
||||||
// Use the first hero as targetHero for replacements
|
// Use the first hero as targetHero for replacements
|
||||||
const targetHero = targetHeros[0];
|
const targetHero = targetHeros[0];
|
||||||
let result = skillHtmlContent;
|
|
||||||
|
|
||||||
// Replace targetHero properties
|
// Replace targetHero properties
|
||||||
result = result.replace(/\btargetHero\.name\b/g, String(targetHero?.heroFullName || 0));
|
result = result.replace(/\btargetHero\.name\b/g, String(targetHero?.heroFullName || 0));
|
||||||
@ -824,7 +838,7 @@ export class MD2Service {
|
|||||||
// Check if expression still contains letters (variables that weren't replaced)
|
// Check if expression still contains letters (variables that weren't replaced)
|
||||||
if (/[a-zA-Z_]/.test(sanitizedExpression)) {
|
if (/[a-zA-Z_]/.test(sanitizedExpression)) {
|
||||||
// Variables weren't replaced, return original match
|
// Variables weren't replaced, return original match
|
||||||
return match;
|
return match.replace('${', '').replace('}', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate expression contains only safe mathematical characters
|
// Validate expression contains only safe mathematical characters
|
||||||
|
|||||||
@ -26,7 +26,6 @@ p {
|
|||||||
}
|
}
|
||||||
|
|
||||||
button,
|
button,
|
||||||
a,
|
|
||||||
input {
|
input {
|
||||||
touch-action: manipulation;
|
touch-action: manipulation;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user