Update boss fight
This commit is contained in:
parent
6a031ca478
commit
d486fe9594
@ -70,6 +70,10 @@ const socialLinks = [
|
|||||||
NbChatModule.forRoot({
|
NbChatModule.forRoot({
|
||||||
messageGoogleMapKey: 'AIzaSyA_wNuCzia92MAmdLRemailRGvCF7wCZPY',
|
messageGoogleMapKey: 'AIzaSyA_wNuCzia92MAmdLRemailRGvCF7wCZPY',
|
||||||
}),
|
}),
|
||||||
|
NbDialogModule.forRoot({
|
||||||
|
closeOnBackdropClick: false,
|
||||||
|
closeOnEsc: false
|
||||||
|
}),
|
||||||
NgxMaskModule.forRoot(maskConfig),
|
NgxMaskModule.forRoot(maskConfig),
|
||||||
NbDateFnsDateModule.forRoot({ format: 'MM/dd/yyyy' }),
|
NbDateFnsDateModule.forRoot({ format: 'MM/dd/yyyy' }),
|
||||||
CoreModule.forRoot(),
|
CoreModule.forRoot(),
|
||||||
|
|||||||
@ -32,6 +32,7 @@ import { BossActivationComponent } from './massive-darkness2/boss-fight/boss-act
|
|||||||
import { MobAttackInfoComponent } from './massive-darkness2/mobs/mob-detail-info/mob-attack-info/mob-attack-info.component';
|
import { MobAttackInfoComponent } from './massive-darkness2/mobs/mob-detail-info/mob-attack-info/mob-attack-info.component';
|
||||||
import { MobDefInfoComponent } from './massive-darkness2/mobs/mob-detail-info/mob-def-info/mob-def-info.component';
|
import { MobDefInfoComponent } from './massive-darkness2/mobs/mob-detail-info/mob-def-info/mob-def-info.component';
|
||||||
import { MobCombatInfoComponent } from './massive-darkness2/mobs/mob-detail-info/mob-combat-info/mob-combat-info.component';
|
import { MobCombatInfoComponent } from './massive-darkness2/mobs/mob-detail-info/mob-combat-info/mob-combat-info.component';
|
||||||
|
import { MobStandInfoComponent } from './massive-darkness2/mobs/mob-stand-info/mob-stand-info.component';
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@ -58,7 +59,8 @@ import { MobCombatInfoComponent } from './massive-darkness2/mobs/mob-detail-info
|
|||||||
BossActivationComponent,
|
BossActivationComponent,
|
||||||
MobAttackInfoComponent,
|
MobAttackInfoComponent,
|
||||||
MobDefInfoComponent,
|
MobDefInfoComponent,
|
||||||
MobCombatInfoComponent
|
MobCombatInfoComponent,
|
||||||
|
MobStandInfoComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
|
|||||||
@ -37,6 +37,9 @@ export abstract class MD2Base {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
this.md2Service.refreshUI$.pipe(takeUntil(this.destroy$)).subscribe(result => {
|
||||||
|
this.cdRef.detectChanges();
|
||||||
});
|
});
|
||||||
this.stateService.loginUserService.signalRInitialized.pipe(first()).subscribe(result => {
|
this.stateService.loginUserService.signalRInitialized.pipe(first()).subscribe(result => {
|
||||||
console.log('signalRInitialized');
|
console.log('signalRInitialized');
|
||||||
@ -78,9 +81,15 @@ export abstract class MD2Base {
|
|||||||
}
|
}
|
||||||
abstract refreshUI();
|
abstract refreshUI();
|
||||||
handleSignalRCallback(message: SignalRMessage): void {
|
handleSignalRCallback(message: SignalRMessage): void {
|
||||||
|
if (message.from.isGroup) {
|
||||||
|
if (!this.isHeroDashboard) return;
|
||||||
|
} else {
|
||||||
|
if (this.isHeroDashboard && this.md2Service.playerHero.playerInfo.signalRClientId == message.from.sessionId) return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (message.actionType) {
|
switch (message.actionType) {
|
||||||
case 'hero':
|
case 'hero':
|
||||||
let heroInfo = JSON.parse(message.parameters['hero']) as MD2HeroInfo;
|
let heroInfo = new MD2HeroInfo(JSON.parse(message.parameters['hero']));
|
||||||
switch (message.actionName) {
|
switch (message.actionName) {
|
||||||
case 'join':
|
case 'join':
|
||||||
this.md2Service.heros.push(heroInfo);
|
this.md2Service.heros.push(heroInfo);
|
||||||
@ -88,26 +97,43 @@ export abstract class MD2Base {
|
|||||||
case 'update':
|
case 'update':
|
||||||
let exitingHero = this.md2Service.heros.find(h => h.playerInfo.signalRClientId == heroInfo.playerInfo.signalRClientId);
|
let exitingHero = this.md2Service.heros.find(h => h.playerInfo.signalRClientId == heroInfo.playerInfo.signalRClientId);
|
||||||
if (exitingHero) {
|
if (exitingHero) {
|
||||||
Object.keys(heroInfo).forEach(key => exitingHero[key] = heroInfo[key]);
|
let activateBoss = exitingHero.uiActivating && !heroInfo.uiActivating;
|
||||||
|
|
||||||
|
this.md2Service.heros[this.md2Service.heros.indexOf(exitingHero)] = heroInfo;
|
||||||
|
if (this.isHeroDashboard && this.md2Service.stateService.playerHero.playerInfo.tabId == heroInfo.playerInfo.tabId) {
|
||||||
|
this.md2Service.stateService.playerHero = heroInfo;
|
||||||
|
}
|
||||||
|
if (!this.isHeroDashboard && this.md2Service.info.isBossFight && activateBoss) {
|
||||||
|
this.md2Service.activateBoss();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.md2Service.heros.push(heroInfo);
|
this.md2Service.heros.push(heroInfo);
|
||||||
}
|
}
|
||||||
if (!this.isHeroDashboard) {
|
if (!this.isHeroDashboard) {
|
||||||
if (this.gameInfo.roundPhase == RoundPhase.HeroPhase) {
|
if (this.gameInfo.roundPhase == RoundPhase.HeroPhase) {
|
||||||
if (!this.md2Service.heros.some(h => h.remainActions > 0)) {
|
if (!this.md2Service.heros.some(h => h.remainActions > 0) && !this.md2Service.heros.some(h => h.uiActivating)) {
|
||||||
if (this.md2Service.mobs.length > 0 || this.md2Service.roamingMonsters.length > 0) {
|
if (!this.md2Service.info.isBossFight) {
|
||||||
this.md2Service.msgBoxService.show('Enemy Phase', { icon: ADIcon.WARNING }).pipe(first()).subscribe(result => {
|
if (this.md2Service.mobs.length > 0 || this.md2Service.roamingMonsters.length > 0) {
|
||||||
|
this.md2Service.msgBoxService.show('Enemy Phase', { icon: ADIcon.WARNING }).pipe(first()).subscribe(result => {
|
||||||
|
this.md2Service.runNextPhase();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
this.md2Service.runNextPhase();
|
this.md2Service.runNextPhase();
|
||||||
});
|
}
|
||||||
} else {
|
|
||||||
this.md2Service.runNextPhase();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Object.assign(heroInfo, exitingHero);
|
//Object.assign(heroInfo, exitingHero);
|
||||||
|
break;
|
||||||
|
case 'updateMyHero':
|
||||||
|
if (this.isHeroDashboard) {
|
||||||
|
this.md2Service.stateService.playerHero = heroInfo;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -126,6 +152,12 @@ export abstract class MD2Base {
|
|||||||
this.detectChanges();
|
this.detectChanges();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'phase':
|
||||||
|
if (this.isHeroDashboard) {
|
||||||
|
this.md2Service.info.roundPhase = JSON.parse(message.parameters['phase']);
|
||||||
|
this.detectChanges();
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -160,17 +192,21 @@ export abstract class MD2Base {
|
|||||||
break;
|
break;
|
||||||
case 'heroAction':
|
case 'heroAction':
|
||||||
if (!this.isHeroDashboard) {
|
if (!this.isHeroDashboard) {
|
||||||
this.gameInfo.currentActivateHero = this.md2Service.heros.find(h => h.playerInfo.tabId == message.parameters['tabId']);
|
//this.md2Service.currentActivateHero = this.md2Service.heros.find(h => h.playerInfo.tabId == message.parameters['tabId']);
|
||||||
switch (message.actionName) {
|
switch (message.actionName) {
|
||||||
case 'attackAction':
|
case 'attackAction':
|
||||||
this.gameInfo.showAttackBtn = true;
|
if (this.gameInfo.isBossFight) {
|
||||||
|
this.md2Service.heroAttackingSubject.next(this.md2Service.currentActivateHero);
|
||||||
|
} else {
|
||||||
|
this.gameInfo.showAttackBtn = true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'openDoor':
|
case 'openDoor':
|
||||||
//Door component listen for it
|
//Door component listen for it
|
||||||
break;
|
break;
|
||||||
case 'tradeAction':
|
case 'tradeAction':
|
||||||
this.md2Service.msgBoxService.show('Trade and Equip', {
|
this.md2Service.msgBoxService.show('Trade and Equip', {
|
||||||
text: `every one in the <b>same zone</b> with ${this.md2Service.heroFullName(this.gameInfo.currentActivateHero)} may freely trade and
|
text: `every one in the <b>same zone with <b>${this.md2Service.heroFullName(this.md2Service.currentActivateHero)}</b> may freely trade and
|
||||||
equip items!`,
|
equip items!`,
|
||||||
icon: ADIcon.INFO
|
icon: ADIcon.INFO
|
||||||
});
|
});
|
||||||
@ -179,7 +215,7 @@ export abstract class MD2Base {
|
|||||||
//this.md2Service.roundPhase = Number.parseInt(message.parameters['phase']);
|
//this.md2Service.roundPhase = Number.parseInt(message.parameters['phase']);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this.heroAction(this.gameInfo.currentActivateHero, message.actionName);
|
this.heroAction(this.md2Service.currentActivateHero, message.actionName);
|
||||||
this.detectChanges();
|
this.detectChanges();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -227,4 +263,15 @@ export abstract class MD2ComponentBase {
|
|||||||
iconHtml(icon: MD2Icon, cssClass = '') {
|
iconHtml(icon: MD2Icon, cssClass = '') {
|
||||||
return this.md2Service.stateService.iconHtml(icon, cssClass);
|
return this.md2Service.stateService.iconHtml(icon, cssClass);
|
||||||
}
|
}
|
||||||
|
detectChanges() {
|
||||||
|
if (!this.cdRef['destroyed']) {
|
||||||
|
this.cdRef.detectChanges();
|
||||||
|
this.refreshUI();
|
||||||
|
this.md2Service.refreshUI$.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
refreshUI() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,25 +1,31 @@
|
|||||||
<nb-card>
|
<nb-card>
|
||||||
|
|
||||||
<nb-card-body>
|
<nb-card-body class="g-overflow-hidden">
|
||||||
<div class="row form-group" style="
|
<div class="row form-group">
|
||||||
height: 53vh;
|
<div class="col-md-5 g-height-700px">
|
||||||
overflow: auto;
|
<md2-mob-stand-info [mob]="boss.info" [mode]="mode"></md2-mob-stand-info>
|
||||||
">
|
|
||||||
<div class="col-md-5">
|
|
||||||
<img src="{{boss.standUrl}}" class="img-fluid">
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-7">
|
<div class="col-md-7">
|
||||||
<label class="MD2text g-font-size-40 mt-5" [innerHtml]="bossAction.skillName">
|
<label class="MD2text g-font-size-40 mt-4" [innerHtml]="bossAction.name">
|
||||||
|
|
||||||
</label>
|
</label>
|
||||||
<label class="g-font-size-20 mt-3" [innerHtml]="bossAction.skillDescription">
|
<label class="mt-2 g-font-size-20 my-3 MD2IconContainer-lg" [innerHtml]="bossAction.description">
|
||||||
|
|
||||||
</label>
|
</label>
|
||||||
|
<hr>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
|
||||||
|
<md2-mob-attack-info [mob]="boss.info"></md2-mob-attack-info>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8 MD2IconContainer-lg">
|
||||||
|
|
||||||
|
<md2-mob-combat-info [mob]="boss.info"></md2-mob-combat-info>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<md2-mob-attack-info [mob]="boss.info">
|
|
||||||
</md2-mob-attack-info>
|
|
||||||
<md2-mob-combat-info [mob]="boss.info"></md2-mob-combat-info>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nb-card-body>
|
</nb-card-body>
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
|
import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { NbDialogRef } from '@nebular/theme';
|
import { NbDialogRef } from '@nebular/theme';
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
import { MD2Service } from '../../../../services/MD2/md2.service';
|
import { MD2Service } from '../../../../services/MD2/md2.service';
|
||||||
import { MsgBoxService } from '../../../../services/msg-box.service';
|
import { MsgBoxService } from '../../../../services/msg-box.service';
|
||||||
import { StateService } from '../../../../services/state.service';
|
import { StateService } from '../../../../services/state.service';
|
||||||
import { MobDlgType, MD2Icon, MD2HeroInfo } from '../../massive-darkness2.model';
|
import { MobDlgType, MD2Icon, MD2HeroInfo, RoundPhase } from '../../massive-darkness2.model';
|
||||||
import { MobSkill, IBossFight } from '../../massive-darkness2.model.boss';
|
import { MobSkill, IBossFight } from '../../massive-darkness2.model.boss';
|
||||||
import { MD2ComponentBase } from '../../MD2Base';
|
import { MD2ComponentBase } from '../../MD2Base';
|
||||||
import { SpawnMobDlgComponent } from '../../mobs/spawn-mob-dlg/spawn-mob-dlg.component';
|
import { SpawnMobDlgComponent } from '../../mobs/spawn-mob-dlg/spawn-mob-dlg.component';
|
||||||
@ -14,12 +16,13 @@ import { SpawnMobDlgComponent } from '../../mobs/spawn-mob-dlg/spawn-mob-dlg.com
|
|||||||
templateUrl: './boss-activation.component.html',
|
templateUrl: './boss-activation.component.html',
|
||||||
styleUrls: ['./boss-activation.component.scss']
|
styleUrls: ['./boss-activation.component.scss']
|
||||||
})
|
})
|
||||||
export class BossActivationComponent extends MD2ComponentBase implements OnInit {
|
export class BossActivationComponent implements OnInit {
|
||||||
boss: IBossFight;
|
boss: IBossFight;
|
||||||
bossAction: MobSkill;
|
bossAction: MobSkill;
|
||||||
|
currentAction: number;
|
||||||
|
allActions: number;
|
||||||
MobDlgType = MobDlgType;
|
MobDlgType = MobDlgType;
|
||||||
mode: MobDlgType;
|
mode: MobDlgType = MobDlgType.Activating;
|
||||||
|
|
||||||
title: string;
|
title: string;
|
||||||
titleHtml: string;
|
titleHtml: string;
|
||||||
@ -31,16 +34,29 @@ export class BossActivationComponent extends MD2ComponentBase implements OnInit
|
|||||||
otherAttackTarget: string;
|
otherAttackTarget: string;
|
||||||
constructor(
|
constructor(
|
||||||
private dlgRef: NbDialogRef<SpawnMobDlgComponent>,
|
private dlgRef: NbDialogRef<SpawnMobDlgComponent>,
|
||||||
private msgBoxService: MsgBoxService,
|
|
||||||
public md2Service: MD2Service,
|
public md2Service: MD2Service,
|
||||||
protected stateService: StateService,
|
protected stateService: StateService,
|
||||||
protected route: ActivatedRoute,
|
protected route: ActivatedRoute,
|
||||||
protected cdRef: ChangeDetectorRef,
|
protected cdRef: ChangeDetectorRef,
|
||||||
) {
|
) {
|
||||||
super(md2Service, stateService, route, cdRef);
|
this.md2Service.refreshUI$.pipe(takeUntil(this.destroy$)).subscribe(result => {
|
||||||
|
if (!this.cdRef['destroyed']) {
|
||||||
|
this.cdRef.detectChanges();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
private destroy$: Subject<void> = new Subject<void>();
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.destroy$.next();
|
||||||
|
this.destroy$.complete();
|
||||||
|
}
|
||||||
|
ngOnInit(): void {
|
||||||
|
|
||||||
}
|
}
|
||||||
close() {
|
close() {
|
||||||
this.boss.standUrl
|
//this.boss.standUrl
|
||||||
|
this.md2Service.info.roundPhase = RoundPhase.HeroPhase;
|
||||||
this.dlgRef.close();
|
this.dlgRef.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<nb-card>
|
<nb-card>
|
||||||
<nb-card-header>
|
<nb-card-header class="MD2text g-font-size-28">
|
||||||
{{boss.name}}
|
{{boss.name}}
|
||||||
<button nbButton hero status="primary" (click)="activate()">Action</button>
|
<button nbButton hero status="primary" (click)="activate()">Action</button>
|
||||||
</nb-card-header>
|
</nb-card-header>
|
||||||
@ -9,13 +9,24 @@
|
|||||||
<img src="{{boss.standUrl}}" class="w-100 g-max-height-80vh">
|
<img src="{{boss.standUrl}}" class="w-100 g-max-height-80vh">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-7">
|
<div class="col-md-7">
|
||||||
<md2-mob-detail-info [mob]="boss.info">
|
<div class="row">
|
||||||
</md2-mob-detail-info>
|
<div class="col-md">
|
||||||
|
<adj-number-input name="mob{{boss.info.name}}" [(ngModel)]="boss.info.unitRemainHp" minimum="0"
|
||||||
|
class="mb-3" title="Boss HP" (hitMinimum)="WIN()">
|
||||||
|
</adj-number-input>
|
||||||
|
<md2-mob-attack-info [mob]="boss.info">
|
||||||
|
</md2-mob-attack-info>
|
||||||
|
<md2-mob-def-info [mob]="boss.info"></md2-mob-def-info>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-9 h6" *ngIf="boss.extraRules">
|
||||||
|
<div [innerHtml]="boss.extraRules"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<adj-number-input name="mob{{boss.info.name}}" [(ngModel)]="boss.info.unitRemainHp" minimum="0"
|
</div>
|
||||||
title="Boss HP" (hitMinimum)="WIN()">
|
|
||||||
</adj-number-input>
|
<md2-mob-combat-info [mob]="boss.info"></md2-mob-combat-info>
|
||||||
<button nbButton hero status="danger" size="small" (click)="attack(boss.info)">Attack It</button>
|
<!--
|
||||||
|
<button nbButton hero status="danger" size="small" (click)="attack(boss.info)">Attack It</button> -->
|
||||||
|
|
||||||
<!-- <label class="MD2Text mt-3" [innerHtml]="boss.info.combatSkill.skillName">
|
<!-- <label class="MD2Text mt-3" [innerHtml]="boss.info.combatSkill.skillName">
|
||||||
</label>
|
</label>
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
|
|||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { NbDialogService } from '@nebular/theme';
|
import { NbDialogService } from '@nebular/theme';
|
||||||
import { Subject, Observable } from 'rxjs';
|
import { Subject, Observable } from 'rxjs';
|
||||||
import { first } from 'rxjs/operators';
|
import { first, takeUntil } from 'rxjs/operators';
|
||||||
import { MD2Service } from '../../../services/MD2/md2.service';
|
import { MD2Service } from '../../../services/MD2/md2.service';
|
||||||
import { MsgBoxService } from '../../../services/msg-box.service';
|
import { MsgBoxService } from '../../../services/msg-box.service';
|
||||||
import { StateService } from '../../../services/state.service';
|
import { StateService } from '../../../services/state.service';
|
||||||
@ -37,7 +37,16 @@ export class BossFightComponent extends MD2ComponentBase {
|
|||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
super.ngOnInit();
|
super.ngOnInit();
|
||||||
|
this.md2Service.heroAttackingSubject.pipe(takeUntil(this.destroy$)).subscribe(result => {
|
||||||
|
if (this.md2Service.info.isBossFight) {
|
||||||
|
this.attack(this.boss.info);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.destroy$.next();
|
||||||
|
this.destroy$.complete();
|
||||||
}
|
}
|
||||||
activate() {
|
activate() {
|
||||||
this.boss.activating();
|
this.boss.activating();
|
||||||
|
|||||||
@ -58,7 +58,7 @@ export class DoorEventsComponent extends MD2ComponentBase implements OnInit {
|
|||||||
this.msgBoxService.show('', { text: `<img src="${door.imageUrl}" class="g-height-70vh g-max-width-80vw">`, buttons: ADButtons.YesNo, confirmButtonText: 'Keep It', cancelButtonText: 'Discard' })
|
this.msgBoxService.show('', { text: `<img src="${door.imageUrl}" class="g-height-70vh g-max-width-80vw">`, buttons: ADButtons.YesNo, confirmButtonText: 'Keep It', cancelButtonText: 'Discard' })
|
||||||
.pipe(first()).subscribe(result => {
|
.pipe(first()).subscribe(result => {
|
||||||
if (result) {
|
if (result) {
|
||||||
door.name = this.md2Service.heroFullName(this.md2Service.info.currentActivateHero);
|
door.name = this.md2Service.heroFullName(this.md2Service.currentActivateHero);
|
||||||
this.drawDoorEvents.push(door);
|
this.drawDoorEvents.push(door);
|
||||||
}
|
}
|
||||||
this.cdRef.detectChanges();
|
this.cdRef.detectChanges();
|
||||||
|
|||||||
20
src/app/games/massive-darkness2/factorys/md2-clone.ts
Normal file
20
src/app/games/massive-darkness2/factorys/md2-clone.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { ObjectUtils } from "../../../utilities/object-utils";
|
||||||
|
import { IDrawingItem, MobInfo, TreasureItem } from "../massive-darkness2.model";
|
||||||
|
|
||||||
|
export class MD2Clone {
|
||||||
|
|
||||||
|
public static CloneDrawingItem(obj: IDrawingItem) {
|
||||||
|
let type = obj.constructor.name;
|
||||||
|
let cloneObj = null;
|
||||||
|
switch (type) {
|
||||||
|
case "TreasureItem":
|
||||||
|
return new TreasureItem(obj['type'], 1);
|
||||||
|
break;
|
||||||
|
case "MobInfo":
|
||||||
|
return new MobInfo(obj);
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return ObjectUtils.CloneValue(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -37,6 +37,7 @@ const CORE_GAME_MOB_LEVEL = [
|
|||||||
{ name: 'Satyrs', level: 5, hp: 6, rewardTokens: 2, defBlue: 4 }]
|
{ name: 'Satyrs', level: 5, hp: 6, rewardTokens: 2, defBlue: 4 }]
|
||||||
|
|
||||||
export abstract class MobFactory implements IMobFactory {
|
export abstract class MobFactory implements IMobFactory {
|
||||||
|
abstract mobName: string;
|
||||||
abstract generate(level: number): MobInfo
|
abstract generate(level: number): MobInfo
|
||||||
protected mob: MobInfo;
|
protected mob: MobInfo;
|
||||||
protected loadLevelInfo(mobName: string, level: number) {
|
protected loadLevelInfo(mobName: string, level: number) {
|
||||||
@ -46,11 +47,11 @@ export abstract class MobFactory implements IMobFactory {
|
|||||||
name: mobName, hp: levelInfo.hp, level: level, rewardTokens: levelInfo.rewardTokens,
|
name: mobName, hp: levelInfo.hp, level: level, rewardTokens: levelInfo.rewardTokens,
|
||||||
defenseInfo: new DefenseInfo(levelInfo.defBlue)
|
defenseInfo: new DefenseInfo(levelInfo.defBlue)
|
||||||
});
|
});
|
||||||
this.mob.leaderImgUrl = MD2_IMG_URL(`CoreGame/Mobs/${encodeURI(this.mob.name)}/Leader.png`);
|
this.mob.leaderImgUrl = MD2_IMG_URL(`/CoreGame/Mobs/${this.mob.name}/Leader.png`);
|
||||||
this.mob.minionImgUrl = MD2_IMG_URL(`CoreGame/Mobs/${encodeURI(this.mob.name)}/Minion.png`);
|
this.mob.minionImgUrl = MD2_IMG_URL(`/CoreGame/Mobs/${this.mob.name}/Minion.png`);
|
||||||
|
|
||||||
}
|
}
|
||||||
iconHtml(icon: MD2Icon, cssClass = '') {
|
iconHtml(icon: MD2Icon, cssClass = 'g-font-size-24') {
|
||||||
if (icon == MD2Icon.Fire) {
|
if (icon == MD2Icon.Fire) {
|
||||||
cssClass += ' g-color-google-plus ';
|
cssClass += ' g-color-google-plus ';
|
||||||
}
|
}
|
||||||
@ -68,6 +69,7 @@ export abstract class MobFactory implements IMobFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
export class MobDemonsFactory extends MobFactory {
|
export class MobDemonsFactory extends MobFactory {
|
||||||
|
mobName: string = 'Demons';
|
||||||
generate(level: number): MobInfo {
|
generate(level: number): MobInfo {
|
||||||
this.loadLevelInfo('Demons', level);
|
this.loadLevelInfo('Demons', level);
|
||||||
this.mob.combatSkill = new MobSkill(
|
this.mob.combatSkill = new MobSkill(
|
||||||
@ -80,8 +82,9 @@ export class MobDemonsFactory extends MobFactory {
|
|||||||
|
|
||||||
}
|
}
|
||||||
export class MobFallenAngelFactory extends MobFactory {
|
export class MobFallenAngelFactory extends MobFactory {
|
||||||
|
mobName: string = 'Fallen Angels';
|
||||||
generate(level: number): MobInfo {
|
generate(level: number): MobInfo {
|
||||||
this.loadLevelInfo('FallenAngels', level);
|
this.loadLevelInfo('Fallen Angels', level);
|
||||||
this.mob.combatSkill = new MobSkill(
|
this.mob.combatSkill = new MobSkill(
|
||||||
{
|
{
|
||||||
description: `Defender -${level == 1 ? 1 : 2} ${this.iconHtml(MD2Icon.Defense)}`,
|
description: `Defender -${level == 1 ? 1 : 2} ${this.iconHtml(MD2Icon.Defense)}`,
|
||||||
@ -93,6 +96,7 @@ export class MobFallenAngelFactory extends MobFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class MobFireEntitiesFactory extends MobFactory {
|
export class MobFireEntitiesFactory extends MobFactory {
|
||||||
|
mobName: string = 'Fire Entities';
|
||||||
generate(level: number): MobInfo {
|
generate(level: number): MobInfo {
|
||||||
this.loadLevelInfo('Fire Entities', level);
|
this.loadLevelInfo('Fire Entities', level);
|
||||||
this.mob.combatSkill = new MobSkill(
|
this.mob.combatSkill = new MobSkill(
|
||||||
@ -106,6 +110,7 @@ export class MobFireEntitiesFactory extends MobFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class MobGargoylesFactory extends MobFactory {
|
export class MobGargoylesFactory extends MobFactory {
|
||||||
|
mobName: string = 'Gargoyles';
|
||||||
generate(level: number): MobInfo {
|
generate(level: number): MobInfo {
|
||||||
this.loadLevelInfo('Gargoyles', level);
|
this.loadLevelInfo('Gargoyles', level);
|
||||||
this.mob.combatSkill = new MobSkill(
|
this.mob.combatSkill = new MobSkill(
|
||||||
@ -118,6 +123,7 @@ export class MobGargoylesFactory extends MobFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
export class MobInfernalImpsFactory extends MobFactory {
|
export class MobInfernalImpsFactory extends MobFactory {
|
||||||
|
mobName: string = 'Infernal Imps';
|
||||||
generate(level: number): MobInfo {
|
generate(level: number): MobInfo {
|
||||||
this.loadLevelInfo('Infernal Imps', level);
|
this.loadLevelInfo('Infernal Imps', level);
|
||||||
let damage = 1;
|
let damage = 1;
|
||||||
@ -148,6 +154,7 @@ export class MobInfernalImpsFactory extends MobFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
export class MobSatyrsFactory extends MobFactory {
|
export class MobSatyrsFactory extends MobFactory {
|
||||||
|
mobName: string = 'Satyrs';
|
||||||
generate(level: number): MobInfo {
|
generate(level: number): MobInfo {
|
||||||
this.loadLevelInfo('Satyrs', level);
|
this.loadLevelInfo('Satyrs', level);
|
||||||
this.mob.combatSkill = new MobSkill(
|
this.mob.combatSkill = new MobSkill(
|
||||||
@ -161,6 +168,7 @@ export class MobSatyrsFactory extends MobFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class MobSkeletonsFactory extends MobFactory {
|
export class MobSkeletonsFactory extends MobFactory {
|
||||||
|
mobName: string = 'Skeletons';
|
||||||
generate(level: number): MobInfo {
|
generate(level: number): MobInfo {
|
||||||
this.loadLevelInfo('Skeletons', level);
|
this.loadLevelInfo('Skeletons', level);
|
||||||
this.mob.combatSkill = new MobSkill(
|
this.mob.combatSkill = new MobSkill(
|
||||||
@ -175,6 +183,7 @@ export class MobSkeletonsFactory extends MobFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class MobUndeadFactory extends MobFactory {
|
export class MobUndeadFactory extends MobFactory {
|
||||||
|
mobName: string = 'Undead';
|
||||||
generate(level: number): MobInfo {
|
generate(level: number): MobInfo {
|
||||||
this.loadLevelInfo('Undead', level);
|
this.loadLevelInfo('Undead', level);
|
||||||
|
|
||||||
@ -195,6 +204,7 @@ export class MobUndeadFactory extends MobFactory {
|
|||||||
type: MobSkillType.Attack
|
type: MobSkillType.Attack
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
this.mob.drawingWeight = 1;
|
||||||
return this.mob;
|
return this.mob;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,53 +1,111 @@
|
|||||||
|
import { Subject } from "rxjs";
|
||||||
|
import { first, map } from "rxjs/operators";
|
||||||
import { environment } from "../../../../../environments/environment";
|
import { environment } from "../../../../../environments/environment";
|
||||||
import { DefenseInfo, IMobFactory, MD2Icon, MobInfo } from "../../massive-darkness2.model";
|
import { ADButtons, ADIcon } from "../../../../ui/alert-dlg/alert-dlg.model";
|
||||||
|
import { MD2Logic } from "../../massive-darkness2.logic";
|
||||||
|
import { AttackInfo, AttackTarget, DefenseInfo, IMobFactory, MD2Icon, MobInfo, MobType, TreasureItem, TreasureType } from "../../massive-darkness2.model";
|
||||||
import { MobSkill, MobSkillType } from "../../massive-darkness2.model.boss";
|
import { MobSkill, MobSkillType } from "../../massive-darkness2.model.boss";
|
||||||
|
|
||||||
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)}` : '')}` }
|
||||||
const CORE_GAME_MOB_LEVEL = [
|
const CORE_GAME_MOB_LEVEL = [
|
||||||
{ name: 'Gargoyles', level: 1, hp: 2, rewardTokens: 1, defBlue: 1 },
|
|
||||||
{ name: 'Gargoyles', level: 3, hp: 3, rewardTokens: 1, defBlue: 2 },
|
|
||||||
{ name: 'Gargoyles', level: 5, hp: 6, rewardTokens: 2, defBlue: 3 },
|
|
||||||
|
|
||||||
{ name: 'Demons', level: 1, hp: 3, rewardTokens: 1, defBlue: 1 },
|
new MobInfo({
|
||||||
{ name: 'Demons', level: 3, hp: 4, rewardTokens: 1, defBlue: 2 },
|
name: 'Andra', level: 1, hp: 5,
|
||||||
{ name: 'Demons', level: 5, hp: 6, rewardTokens: 2, defBlue: 4 },
|
|
||||||
|
|
||||||
{ name: 'Undead', level: 1, hp: 4, rewardTokens: 1, defBlue: 1 },
|
attackInfos: [new AttackInfo(MD2Icon.Melee, 1, 0, 0, 1), new AttackInfo(MD2Icon.Range, 1, 0, 0, 1)],
|
||||||
{ name: 'Undead', level: 3, hp: 5, rewardTokens: 1, defBlue: 1 },
|
defenseInfo: new DefenseInfo(2, 1),
|
||||||
{ name: 'Undead', level: 5, hp: 8, rewardTokens: 2, defBlue: 1 },
|
}),
|
||||||
|
new MobInfo({
|
||||||
|
name: 'Andra', level: 3, hp: 7,
|
||||||
|
|
||||||
{ name: 'Fire Entities', level: 1, hp: 3, rewardTokens: 1, defBlue: 1 },
|
attackInfos: [new AttackInfo(MD2Icon.Melee, 1, 1, 0, 1), new AttackInfo(MD2Icon.Range, 1, 1, 0, 1)],
|
||||||
{ name: 'Fire Entities', level: 3, hp: 4, rewardTokens: 1, defBlue: 2 },
|
defenseInfo: new DefenseInfo(3, 1),
|
||||||
{ name: 'Fire Entities', level: 5, hp: 7, rewardTokens: 2, defBlue: 3 },
|
}),
|
||||||
|
new MobInfo({
|
||||||
|
name: 'Andra', level: 5, hp: 5,
|
||||||
|
attackInfos: [new AttackInfo(MD2Icon.Melee, 1, 2, 0, 1), new AttackInfo(MD2Icon.Range, 1, 2, 0, 1)],
|
||||||
|
defenseInfo: new DefenseInfo(5, 1),
|
||||||
|
}),
|
||||||
|
|
||||||
{ name: 'Fallen Angels', level: 1, hp: 2, rewardTokens: 1, defBlue: 2 },
|
new MobInfo({
|
||||||
{ name: 'Fallen Angels', level: 3, hp: 3, rewardTokens: 1, defBlue: 3 },
|
name: 'Ytheria, Undead Queen', level: 1, hp: 4,
|
||||||
{ name: 'Fallen Angels', level: 5, hp: 5, rewardTokens: 2, defBlue: 5 },
|
attackInfos: [new AttackInfo(MD2Icon.Melee, 1), new AttackInfo(MD2Icon.Range, 2, 0, 0, 1)],
|
||||||
|
defenseInfo: new DefenseInfo(1, 1),
|
||||||
|
|
||||||
{ name: 'Infernal Imps', level: 1, hp: 3, rewardTokens: 1, defBlue: 1 },
|
}),
|
||||||
{ name: 'Infernal Imps', level: 3, hp: 4, rewardTokens: 1, defBlue: 1 },
|
new MobInfo({
|
||||||
{ name: 'Infernal Imps', level: 5, hp: 5, rewardTokens: 2, defBlue: 3 },
|
name: 'Ytheria, Undead Queen', level: 3, hp: 6,
|
||||||
|
attackInfos: [new AttackInfo(MD2Icon.Melee, 0, 1), new AttackInfo(MD2Icon.Range, 1, 1, 0, 1)],
|
||||||
|
defenseInfo: new DefenseInfo(2, 1),
|
||||||
|
|
||||||
{ name: 'Skeletons', level: 1, hp: 2, rewardTokens: 1, defBlue: 1 },
|
}),
|
||||||
{ name: 'Skeletons', level: 3, hp: 3, rewardTokens: 1, defBlue: 2 },
|
new MobInfo({
|
||||||
{ name: 'Skeletons', level: 5, hp: 5, rewardTokens: 2, defBlue: 4 },
|
name: 'Ytheria, Undead Queen', level: 5, hp: 8,
|
||||||
|
attackInfos: [new AttackInfo(MD2Icon.Melee, 2, 1), new AttackInfo(MD2Icon.Range, 2, 1, 0, 1)],
|
||||||
|
defenseInfo: new DefenseInfo(4, 1),
|
||||||
|
}),
|
||||||
|
|
||||||
{ name: 'Satyrs', level: 1, hp: 3, rewardTokens: 1, defBlue: 1 },
|
new MobInfo({
|
||||||
{ name: 'Satyrs', level: 3, hp: 4, rewardTokens: 1, defBlue: 2 },
|
name: 'Lyidan, Incubus Lord', level: 1, hp: 7,
|
||||||
{ name: 'Satyrs', level: 5, hp: 6, rewardTokens: 2, defBlue: 4 }]
|
attackInfos: [new AttackInfo(MD2Icon.Melee, 0, 1, 0, 2)],
|
||||||
|
defenseInfo: new DefenseInfo(2, 1),
|
||||||
|
}),
|
||||||
|
new MobInfo({
|
||||||
|
name: 'Lyidan, Incubus Lord', level: 3, hp: 10,
|
||||||
|
attackInfos: [new AttackInfo(MD2Icon.Melee, 0, 2, 0, 1)],
|
||||||
|
defenseInfo: new DefenseInfo(2, 1),
|
||||||
|
}),
|
||||||
|
new MobInfo({
|
||||||
|
name: 'Lyidan, Incubus Lord', level: 5, hp: 12,
|
||||||
|
attackInfos: [new AttackInfo(MD2Icon.Melee, 2, 2, 0, 1)],
|
||||||
|
defenseInfo: new DefenseInfo(4, 1),
|
||||||
|
}),
|
||||||
|
|
||||||
export abstract class MobFactory implements IMobFactory {
|
new MobInfo({
|
||||||
|
name: 'The Ghoul', level: 1, hp: 5,
|
||||||
|
attackInfos: [new AttackInfo(MD2Icon.Melee, 0, 1, 0, 1)],
|
||||||
|
defenseInfo: new DefenseInfo(2, 1),
|
||||||
|
}),
|
||||||
|
new MobInfo({
|
||||||
|
name: 'The Ghoul', level: 3, hp: 8,
|
||||||
|
attackInfos: [new AttackInfo(MD2Icon.Melee, 0, 2, 0, 2)],
|
||||||
|
defenseInfo: new DefenseInfo(3, 1),
|
||||||
|
}),
|
||||||
|
new MobInfo({
|
||||||
|
name: 'The Ghoul', level: 5, hp: 10,
|
||||||
|
attackInfos: [new AttackInfo(MD2Icon.Melee, 0, 3, 0, 3)],
|
||||||
|
defenseInfo: new DefenseInfo(4, 1),
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
|
||||||
|
export abstract class CoreGameRMFactory implements IMobFactory {
|
||||||
|
abstract mobName: string;
|
||||||
abstract generate(level: number): MobInfo
|
abstract generate(level: number): MobInfo
|
||||||
protected mob: MobInfo;
|
protected mob: MobInfo;
|
||||||
protected loadLevelInfo(mobName: string, level: number) {
|
protected loadLevelInfo(mobName: string, level: number) {
|
||||||
let levelInfo = CORE_GAME_MOB_LEVEL.find(m => m.name == mobName && level >= m.level);
|
let levelInfo = CORE_GAME_MOB_LEVEL.find(m => m.name == mobName && level >= m.level);
|
||||||
|
|
||||||
this.mob = new MobInfo({
|
this.mob = new MobInfo({
|
||||||
name: mobName, hp: levelInfo.hp, level: level, rewardTokens: levelInfo.rewardTokens,
|
type: MobType.RoamingMonster,
|
||||||
defenseInfo: new DefenseInfo(levelInfo.defBlue)
|
name: mobName, hpPerHero: levelInfo.hp, level: level, rewardTokens: levelInfo.rewardTokens,
|
||||||
|
attackInfos: levelInfo.attackInfos,
|
||||||
|
defenseInfo: levelInfo.defenseInfo,
|
||||||
|
actionSubject: new Subject<string>()
|
||||||
});
|
});
|
||||||
this.mob.leaderImgUrl = MD2_IMG_URL(`CoreGame/Mobs/${encodeURI(this.mob.name)}/Leader.png`);
|
this.mob.leaderImgUrl = MD2_IMG_URL(`/CoreGame/RoamingMonsters/${this.mob.name}/Stand.png`);
|
||||||
this.mob.minionImgUrl = MD2_IMG_URL(`CoreGame/Mobs/${encodeURI(this.mob.name)}/Minion.png`);
|
//this.mob.minionImgUrl = MD2_IMG_URL(`CoreGame/Mobs/${encodeURI(this.mob.name)}/Minion.png`);
|
||||||
|
|
||||||
|
|
||||||
|
if (level < 3) {
|
||||||
|
this.mob.rewardTokens = 2;
|
||||||
|
this.mob.fixedCarriedTreasure = [new TreasureItem(TreasureType.Rare)];
|
||||||
|
} else if (level < 5) {
|
||||||
|
this.mob.rewardTokens = 2;
|
||||||
|
this.mob.fixedCarriedTreasure = [new TreasureItem(TreasureType.Epic)];
|
||||||
|
} else {
|
||||||
|
this.mob.rewardTokens = 0;
|
||||||
|
this.mob.fixedCarriedTreasure = [new TreasureItem(TreasureType.Epic, 3)];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
iconHtml(icon: MD2Icon, cssClass = '') {
|
iconHtml(icon: MD2Icon, cssClass = '') {
|
||||||
@ -67,146 +125,213 @@ export abstract class MobFactory implements IMobFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export class MobDemonsFactory extends MobFactory {
|
export class RMUndeadQueenFactory extends CoreGameRMFactory {
|
||||||
|
mobName: string = 'Ytheria, Undead Queen';
|
||||||
generate(level: number): MobInfo {
|
generate(level: number): MobInfo {
|
||||||
this.loadLevelInfo('Demons', level);
|
this.loadLevelInfo('Ytheria, Undead Queen', level);
|
||||||
this.mob.combatSkill = new MobSkill(
|
|
||||||
{
|
this.mob.activateFunction = (mob, msgBoxService, heros) => {
|
||||||
description: `Attacking or defending Hero discards 1 ${this.iconHtml(MD2Icon.Mana)}`
|
let actionResult = '';
|
||||||
}
|
|
||||||
)
|
msgBoxService.show('Is There more than 1 Hero in LoS of Undead Queen?', {
|
||||||
return this.mob;
|
icon: ADIcon.QUESTION,
|
||||||
}
|
buttons: ADButtons.YesNo
|
||||||
|
}).pipe(first()).subscribe(result => {
|
||||||
|
if (result) {
|
||||||
|
mob.actions = 0;
|
||||||
|
mob.actionSubject.next(
|
||||||
|
`Undead Queen attacks each Hero in LoS(resolve each attack separately).`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
msgBoxService.show('Is There any Hero in LoS of Undead Queen?', {
|
||||||
|
icon: ADIcon.QUESTION,
|
||||||
|
buttons: ADButtons.YesNo
|
||||||
|
}).pipe(first()).subscribe(result => {
|
||||||
|
if (result) {
|
||||||
|
if (level < 3) {
|
||||||
|
actionResult = `Undead Queen +1 ${this.iconHtml(MD2Icon.YellowDice)} when attack`;
|
||||||
|
} else if (level < 5) {
|
||||||
|
actionResult = `Undead Queen +1 ${this.iconHtml(MD2Icon.YellowDice)} 1 ${this.iconHtml(MD2Icon.OrangeDice)} when attack`;
|
||||||
|
} else {
|
||||||
|
actionResult = `Undead Queen +2 ${this.iconHtml(MD2Icon.OrangeDice)} when attack`;
|
||||||
|
}
|
||||||
|
mob.actions = 0;
|
||||||
|
mob.actionSubject.next(
|
||||||
|
actionResult
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
mob.actions = 2;
|
||||||
|
mob.actionSubject.next(
|
||||||
|
`Undead Queen Gains 2 Actions`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
export class MobFallenAngelFactory extends MobFactory {
|
|
||||||
generate(level: number): MobInfo {
|
|
||||||
this.loadLevelInfo('FallenAngels', level);
|
|
||||||
this.mob.combatSkill = new MobSkill(
|
this.mob.combatSkill = new MobSkill(
|
||||||
{
|
{
|
||||||
description: `Defender -${level == 1 ? 1 : 2} ${this.iconHtml(MD2Icon.Defense)}`,
|
description: `Add 1 Minion to each Mob in the Dungeon, if possible.`,
|
||||||
type: MobSkillType.Attack
|
type: MobSkillType.Attack
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return this.mob;
|
return this.mob;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
export class RMAndraFactory extends CoreGameRMFactory {
|
||||||
export class MobFireEntitiesFactory extends MobFactory {
|
mobName: string = 'Andra';
|
||||||
generate(level: number): MobInfo {
|
generate(level: number): MobInfo {
|
||||||
this.loadLevelInfo('Fire Entities', level);
|
this.loadLevelInfo('Andra', level);
|
||||||
|
let damage = 2;
|
||||||
|
|
||||||
|
if (level < 3) {
|
||||||
|
damage = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mob.activateFunction = (mob, msgBoxService, heros) => {
|
||||||
|
let actionResult = '';
|
||||||
|
|
||||||
|
mob.actions = 0;
|
||||||
|
msgBoxService.show('Is Andra in the Dungeon?', {
|
||||||
|
icon: ADIcon.QUESTION,
|
||||||
|
buttons: ADButtons.YesNo
|
||||||
|
}).pipe(first()).subscribe(result => {
|
||||||
|
if (result) {
|
||||||
|
mob.actions = 0;
|
||||||
|
mob.actionSubject.next(
|
||||||
|
`Undead Queen attacks each Hero in LoS(resolve each attack separately).`
|
||||||
|
);
|
||||||
|
|
||||||
|
msgBoxService.show('Is Any Hero in the LoS of Andra?', {
|
||||||
|
icon: ADIcon.QUESTION,
|
||||||
|
buttons: ADButtons.YesNo
|
||||||
|
}).pipe(first()).subscribe(result => {
|
||||||
|
if (result) {
|
||||||
|
|
||||||
|
mob.actionSubject.next(
|
||||||
|
`Andra attack the Hero with the lowest HP in LoS.<br>then Put Andra to out side of Dungeon.(Hero is not reachable but not dead)`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
mob.actions = 0;
|
||||||
|
mob.actionSubject.next(
|
||||||
|
`Put Andra to out side of Dungeon.(Hero is not reachable but not dead)`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
let beenAttackHero = MD2Logic.getTargetHerosByFilter(heros, AttackTarget.LeastHp, true)[0];
|
||||||
|
mob.actionSubject.next(
|
||||||
|
`Place Andra in the same zone of ${MD2Logic.heroFullName(beenAttackHero)} and attack that Hero.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this.mob.combatSkill = new MobSkill(
|
this.mob.combatSkill = new MobSkill(
|
||||||
{
|
{
|
||||||
description: `Add 1 ${this.iconHtml(MD2Icon.Fire)} to the attacking or defending Hero.`,
|
description: `Deal ${damage} wound to another Hero with the lowest HP in LoS`,
|
||||||
type: MobSkillType.Combat
|
type: MobSkillType.Combat
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return this.mob;
|
return this.mob;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
export class RMTheGhoulFactory extends CoreGameRMFactory {
|
||||||
export class MobGargoylesFactory extends MobFactory {
|
mobName: string = 'The Ghoul';
|
||||||
generate(level: number): MobInfo {
|
generate(level: number): MobInfo {
|
||||||
this.loadLevelInfo('Gargoyles', level);
|
this.loadLevelInfo('The Ghoul', level);
|
||||||
this.mob.combatSkill = new MobSkill(
|
let health = 2;
|
||||||
{
|
|
||||||
description: `+ ${level < 5 ? 1 : 2} ${this.iconHtml(MD2Icon.Defense)}`,
|
|
||||||
type: MobSkillType.Defense
|
|
||||||
}
|
|
||||||
)
|
|
||||||
return this.mob;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export class MobInfernalImpsFactory extends MobFactory {
|
|
||||||
generate(level: number): MobInfo {
|
|
||||||
this.loadLevelInfo('Infernal Imps', level);
|
|
||||||
let damage = 1;
|
|
||||||
switch (level) {
|
|
||||||
case 1:
|
|
||||||
case 2:
|
|
||||||
damage = 1;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
case 4:
|
|
||||||
damage = 2;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
damage = 3;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
damage = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
this.mob.combatSkill = new MobSkill(
|
|
||||||
{
|
|
||||||
description: `Kill 1 Imp, then deal ${damage} Wound to each Hero in the attacker's Zone(once per roll).`,
|
|
||||||
type: MobSkillType.Defense
|
|
||||||
}
|
|
||||||
)
|
|
||||||
return this.mob;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export class MobSatyrsFactory extends MobFactory {
|
|
||||||
generate(level: number): MobInfo {
|
|
||||||
this.loadLevelInfo('Satyrs', level);
|
|
||||||
this.mob.combatSkill = new MobSkill(
|
|
||||||
{
|
|
||||||
description: `+ ${level < 3 ? 1 : 2} ${this.iconHtml(MD2Icon.Attack)}`,
|
|
||||||
type: MobSkillType.Attack
|
|
||||||
}
|
|
||||||
)
|
|
||||||
return this.mob;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class MobSkeletonsFactory extends MobFactory {
|
|
||||||
generate(level: number): MobInfo {
|
|
||||||
this.loadLevelInfo('Skeletons', level);
|
|
||||||
this.mob.combatSkill = new MobSkill(
|
|
||||||
{
|
|
||||||
description: `Add 1 minion to this Mob(if possible) unless the Hero discards ${level < 5 ? 1 : 2} ${this.iconHtml(MD2Icon.Mana)}.`,
|
|
||||||
type: MobSkillType.Defense,
|
|
||||||
skillRoll: 2
|
|
||||||
}
|
|
||||||
)
|
|
||||||
return this.mob;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class MobUndeadFactory extends MobFactory {
|
|
||||||
generate(level: number): MobInfo {
|
|
||||||
this.loadLevelInfo('Undead', level);
|
|
||||||
|
|
||||||
let skillDesc = '';
|
|
||||||
if (level < 3) {
|
if (level < 3) {
|
||||||
skillDesc = `+1 ${this.iconHtml(MD2Icon.YellowDice)}`;
|
health = 5;
|
||||||
} else if (level < 5) {
|
} else if (level < 5) {
|
||||||
skillDesc = `+2 ${this.iconHtml(MD2Icon.YellowDice)}`;
|
health = 8;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
skillDesc = `+1 ${this.iconHtml(MD2Icon.YellowDice)} 1 ${this.iconHtml(MD2Icon.OrangeDice)}`;
|
health = 10;
|
||||||
|
|
||||||
}
|
}
|
||||||
skillDesc += ' and this Mob takes 2 wounds';
|
|
||||||
|
this.mob.activateFunction = (mob, msgBoxService, heros) => {
|
||||||
|
let actionResult = '';
|
||||||
|
|
||||||
|
mob.actions = 0;
|
||||||
|
msgBoxService.show('Is there any <b>Mob with minion</b> in The Ghoul zone?', {
|
||||||
|
icon: ADIcon.QUESTION,
|
||||||
|
buttons: ADButtons.YesNo
|
||||||
|
}).pipe(first()).subscribe(result => {
|
||||||
|
if (result) {
|
||||||
|
mob.unitRemainHp += health;
|
||||||
|
mob.actionSubject.next(
|
||||||
|
`Kill 1 minion in The Ghoul zone(player choose), The Ghoul heals ${health}.`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
mob.actionSubject.next(
|
||||||
|
`The Ghoul moves 3 Zones toward the closest Hero and attack him/her, if possible.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this.mob.combatSkill = new MobSkill(
|
this.mob.combatSkill = new MobSkill(
|
||||||
{
|
{
|
||||||
description: skillDesc,
|
description: `Move the closest <b>Mob with minion</b> 1 Zone toward The Ghoul.`,
|
||||||
|
type: MobSkillType.Combat
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return this.mob;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export class RMLyidanIncubusLordFactory extends CoreGameRMFactory {
|
||||||
|
mobName: string = 'Lyidan, Incubus Lord';
|
||||||
|
generate(level: number): MobInfo {
|
||||||
|
this.loadLevelInfo('Lyidan, Incubus Lord', level);
|
||||||
|
this.mob.activateFunction = (mob, msgBoxService, heros) => {
|
||||||
|
let actionResult = '';
|
||||||
|
|
||||||
|
mob.actions = 0;
|
||||||
|
msgBoxService.show('Is Incubus Lord in a Light Zone?', {
|
||||||
|
icon: ADIcon.QUESTION,
|
||||||
|
buttons: ADButtons.YesNo
|
||||||
|
}).pipe(first()).subscribe(result => {
|
||||||
|
if (result) {
|
||||||
|
mob.unitRemainHp -= 3;
|
||||||
|
mob.actionSubject.next(
|
||||||
|
`The Incubus Lord got 3 Wounds, Move it to the closest Shadow Zone.`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
msgBoxService.show('Is there a Herp up to 3 Zones away(regardless of LoS) from The Incubus Lord?', {
|
||||||
|
icon: ADIcon.QUESTION,
|
||||||
|
buttons: ADButtons.YesNo
|
||||||
|
}).pipe(first()).subscribe(result => {
|
||||||
|
if (result) {
|
||||||
|
mob.actionSubject.next(
|
||||||
|
`Place The Incubus Lord in the zone of furthest Hero up to 3 Zones away.<br>` +
|
||||||
|
`Add 1 ${this.iconHtml(MD2Icon.Fire)} to that Hero and attack him/her.`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
mob.actions = 2;
|
||||||
|
mob.actionSubject.next(
|
||||||
|
`The Incubus Lord 2 Actions`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mob.combatSkill = new MobSkill(
|
||||||
|
{
|
||||||
|
description: `After combat, resolve all ${this.iconHtml(MD2Icon.Fire)} on the defending Hero(once per combat).`,
|
||||||
type: MobSkillType.Attack
|
type: MobSkillType.Attack
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return this.mob;
|
return this.mob;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
export const CoreGameRMFactories = [
|
||||||
|
new RMUndeadQueenFactory(),
|
||||||
export const CoreGameMobFactories = [
|
new RMAndraFactory(),
|
||||||
new MobDemonsFactory(),
|
new RMTheGhoulFactory(),
|
||||||
new MobFallenAngelFactory(),
|
new RMLyidanIncubusLordFactory(),
|
||||||
new MobFireEntitiesFactory(),
|
|
||||||
new MobGargoylesFactory(),
|
|
||||||
new MobInfernalImpsFactory(),
|
|
||||||
new MobSatyrsFactory(),
|
|
||||||
new MobSkeletonsFactory(),
|
|
||||||
new MobUndeadFactory(),
|
|
||||||
];
|
];
|
||||||
@ -1,9 +1,9 @@
|
|||||||
<nb-card *ngIf="!md2Service.playerHero">
|
<nb-card *ngIf="!hero">
|
||||||
<nb-card-body>
|
<nb-card-body>
|
||||||
<button nbButton hero status="primary" fullWidth (click)="initHero()">Choose Hero</button>
|
<button nbButton hero status="primary" fullWidth (click)="initHero()">Choose Hero</button>
|
||||||
</nb-card-body>
|
</nb-card-body>
|
||||||
</nb-card>
|
</nb-card>
|
||||||
<div *ngIf="md2Service.playerHero">
|
<div *ngIf="hero">
|
||||||
<div class="row no-gutters">
|
<div class="row no-gutters">
|
||||||
<div class="col-12 col-sm-7">
|
<div class="col-12 col-sm-7">
|
||||||
<div class="tp-wrapper mb-2">
|
<div class="tp-wrapper mb-2">
|
||||||
@ -11,24 +11,26 @@
|
|||||||
[@flipState]="flip">
|
[@flipState]="flip">
|
||||||
<div class="tp-box__side tp-box__front ">
|
<div class="tp-box__side tp-box__front ">
|
||||||
|
|
||||||
<img class="MD2HeroCard " src="{{md2Service.playerHero.imgUrl}}">
|
<img class="MD2HeroCard " src="{{hero.imgUrl}}">
|
||||||
</div>
|
</div>
|
||||||
<div class="tp-box__side tp-box__back">
|
<div class="tp-box__side tp-box__back">
|
||||||
|
|
||||||
|
|
||||||
<img class="MD2HeroCard " src="{{imgUrl('Heros/Guide/'+className+'.jpg')}}">
|
<img class="MD2HeroCard " src="{{imgUrl('Heros/Guide/'+className+'.jpg')}}">
|
||||||
|
|
||||||
|
<img class="MD2HeroCard " src="{{imgUrl('Sets/Shadowbane/'+className+'.png')}}">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="g-max-height-80vh mb-2">
|
<!-- <div class="g-max-height-80vh mb-2">
|
||||||
<img class="MD2HeroCard" src="{{md2Service.playerHero.imgUrl}}">
|
<img class="MD2HeroCard" src="{{hero.imgUrl}}">
|
||||||
<div class="MD2HeroCard">
|
<div class="MD2HeroCard">
|
||||||
<span class="MD2text MD2Name">{{md2Service.playerHero.name}}</span>
|
<span class="MD2text MD2Name">{{hero.name}}</span>
|
||||||
<span class="MD2text MD2Hp">{{md2Service.playerHero.hpMaximum}}</span>
|
<span class="MD2text MD2Hp">{{hero.hpMaximum}}</span>
|
||||||
<span class="MD2text MD2Mp">{{md2Service.playerHero.mpMaximum}}</span>
|
<span class="MD2text MD2Mp">{{hero.mpMaximum}}</span>
|
||||||
</div>
|
</div>
|
||||||
<img class="MD2HeroCard" src="{{md2Service.playerHero.imgUrl}}">
|
<img class="MD2HeroCard" src="{{hero.imgUrl}}">
|
||||||
<img class="MD2HeroCard HpMpBar" src="{{imgUrl('/Heros/Template/Border.png')}}">
|
<img class="MD2HeroCard HpMpBar" src="{{imgUrl('/Heros/Template/Border.png')}}">
|
||||||
</div> -->
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
@ -39,63 +41,57 @@
|
|||||||
<div class="row no-gutters">
|
<div class="row no-gutters">
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
|
|
||||||
<!-- <adj-number-input name="heroHP" [(ngModel)]="md2Service.playerHero.hp"
|
<!-- <adj-number-input name="heroHP" [(ngModel)]="hero.hp"
|
||||||
[maximum]="md2Service.playerHero.hpMaximum" minimum="0"
|
[maximum]="hero.hpMaximum" minimum="0"
|
||||||
title="{{iconHtml(MD2Icon.HP,'g-color-google-plus mr-1 g-font-size-18')}}HP" showMaximum
|
title="{{iconHtml(MD2Icon.HP,'g-color-google-plus mr-1 g-font-size-18')}}HP" showMaximum
|
||||||
(blur)="heroUpdateDebounceTimer.resetTimer()" (hitDecreasing)="increaseRage()">
|
(blur)="heroUpdateDebounceTimer.resetTimer()" (hitDecreasing)="increaseRage()">
|
||||||
</adj-number-input> -->
|
</adj-number-input> -->
|
||||||
|
|
||||||
|
|
||||||
<adj-number-input name="heroHP" [(ngModel)]="md2Service.playerHero.hp"
|
<adj-number-input name="heroHP" [(ngModel)]="hero.hp" [maximum]="hero.hpMaximum" minimum="0"
|
||||||
[maximum]="md2Service.playerHero.hpMaximum" minimum="0"
|
|
||||||
title="{{imgHtml('HpIcon.png','g-height-25 mr-1')}}HP" showMaximum
|
title="{{imgHtml('HpIcon.png','g-height-25 mr-1')}}HP" showMaximum
|
||||||
(blur)="heroUpdateDebounceTimer.resetTimer()" (hitDecreasing)="increaseRage()">
|
(blur)="heroUpdateDebounceTimer.resetTimer()" (hitDecreasing)="increaseRage()">
|
||||||
</adj-number-input>
|
</adj-number-input>
|
||||||
<adj-number-input name="heroMana" [(ngModel)]="md2Service.playerHero.mp"
|
<adj-number-input name="heroMana" [(ngModel)]="hero.mp" [maximum]="hero.mpMaximum"
|
||||||
[maximum]="md2Service.playerHero.mpMaximum" minimum="0"
|
minimum="0" title="{{imgHtml('HeroIcon.png','g-height-25 mr-1')}}Mana" showMaximum
|
||||||
title="{{imgHtml('HeroIcon.png','g-height-25 mr-1')}}Mana" showMaximum
|
|
||||||
(blur)="heroUpdateDebounceTimer.resetTimer()">
|
(blur)="heroUpdateDebounceTimer.resetTimer()">
|
||||||
</adj-number-input>
|
</adj-number-input>
|
||||||
|
|
||||||
<adj-number-input name="heroFire" [(ngModel)]="md2Service.playerHero.fireToken" minimum="0"
|
<adj-number-input name="heroFire" [(ngModel)]="hero.fireToken" minimum="0"
|
||||||
title="{{iconHtml(MD2Icon.Fire,'g-color-google-plus mr-1 g-font-size-18')}}Fire Token"
|
title="{{iconHtml(MD2Icon.Fire,'g-color-google-plus mr-1 g-font-size-18')}}Fire Token"
|
||||||
(blur)="heroUpdateDebounceTimer.resetTimer()">
|
(blur)="heroUpdateDebounceTimer.resetTimer()">
|
||||||
</adj-number-input>
|
</adj-number-input>
|
||||||
<adj-number-input name="heroFire" [(ngModel)]="md2Service.playerHero.frozenToken"
|
<adj-number-input name="heroFire" [(ngModel)]="hero.frozenToken" minimum="0"
|
||||||
minimum="0"
|
|
||||||
title="{{iconHtml(MD2Icon.Frost,'g-color-aqua mr-1 g-font-size-18')}}Frozen Token"
|
title="{{iconHtml(MD2Icon.Frost,'g-color-aqua mr-1 g-font-size-18')}}Frozen Token"
|
||||||
(blur)="heroUpdateDebounceTimer.resetTimer()">
|
(blur)="heroUpdateDebounceTimer.resetTimer()">
|
||||||
</adj-number-input>
|
</adj-number-input>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
|
|
||||||
<adj-number-input name="remainActions" [(ngModel)]="md2Service.playerHero.remainActions"
|
<adj-number-input name="remainActions" [(ngModel)]="hero.remainActions" minimum="0"
|
||||||
minimum="0" title="Remain Actions" (blur)="heroUpdateDebounceTimer.resetTimer()"
|
title="Remain Actions" (blur)="heroUpdateDebounceTimer.resetTimer()" hideIncreaseBtn
|
||||||
hideIncreaseBtn>
|
*ngIf="hero.uiActivating">
|
||||||
</adj-number-input>
|
</adj-number-input>
|
||||||
<adj-number-input name="heroLevel" [(ngModel)]="md2Service.playerHero.level" minimum="1"
|
<adj-number-input name="heroLevel" [(ngModel)]="hero.level" minimum="1" maximum="5"
|
||||||
maximum="5" title="Level" (blur)="heroUpdateDebounceTimer.resetTimer()">
|
title="Level" (blur)="heroUpdateDebounceTimer.resetTimer()">
|
||||||
</adj-number-input>
|
</adj-number-input>
|
||||||
<adj-number-input name="heroExp" [(ngModel)]="md2Service.playerHero.exp" minimum="0"
|
<adj-number-input name="heroExp" [(ngModel)]="hero.exp" minimum="0" title="Exp"
|
||||||
title="Exp" (blur)="heroUpdateDebounceTimer.resetTimer()">
|
(blur)="heroUpdateDebounceTimer.resetTimer()">
|
||||||
</adj-number-input>
|
</adj-number-input>
|
||||||
<adj-number-input name="heroRage" [(ngModel)]="md2Service.playerHero.rage" minimum="0"
|
<adj-number-input name="heroRage" [(ngModel)]="hero.rage" minimum="0" maximum="7"
|
||||||
maximum="7"
|
|
||||||
title="{{iconHtml(MD2Icon.Rage,'g-color-google-plus mr-1 g-font-size-18')}}Rage"
|
title="{{iconHtml(MD2Icon.Rage,'g-color-google-plus mr-1 g-font-size-18')}}Rage"
|
||||||
(blur)="heroUpdateDebounceTimer.resetTimer()"
|
(blur)="heroUpdateDebounceTimer.resetTimer()" *ngIf="hero.class==HeroClass.Berserker">
|
||||||
*ngIf="md2Service.playerHero.class==HeroClass.Berserker">
|
|
||||||
</adj-number-input>
|
</adj-number-input>
|
||||||
<adj-number-input name="heroCorruption" [(ngModel)]="md2Service.playerHero.corruptionToken"
|
<adj-number-input name="heroCorruption" [(ngModel)]="hero.corruptionToken" minimum="0"
|
||||||
minimum="0" title="{{imgHtml('Tokens/CorruptToken.png','g-height-18')}} Corruption"
|
title="{{imgHtml('Tokens/CorruptToken.png','g-height-18')}} Corruption"
|
||||||
(blur)="heroUpdateDebounceTimer.resetTimer()"
|
(blur)="heroUpdateDebounceTimer.resetTimer()" *ngIf="hero.uiShowCorruptionToken">
|
||||||
*ngIf="md2Service.playerHero.corruptionToken>0">
|
|
||||||
</adj-number-input>
|
</adj-number-input>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="md2Service.info.isBossFight"></div>
|
<div *ngIf="md2Service.info.isBossFight"></div>
|
||||||
<div *ngIf="md2Service.playerHero.remainActions>0">
|
<div *ngIf="hero.uiActivating&&hero.remainActions>0">
|
||||||
<button nbButton hero class="mr-2" status="info" (click)="moveAction()"
|
<button nbButton hero class="mr-2" status="info" (click)="moveAction()"
|
||||||
*ngIf="!showMoveAction">Move</button>
|
*ngIf="!showMoveAction">Move</button>
|
||||||
<button nbButton hero class="mr-2" status="info" (click)="moveActionEnd()"
|
<button nbButton hero class="mr-2" status="info" (click)="moveActionEnd()"
|
||||||
@ -109,8 +105,14 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<button nbButton hero fullWidth status="info" *ngIf="allowStartAction"
|
||||||
|
(click)="startActivation()">Start Activation</button>
|
||||||
|
|
||||||
<button nbButton hero status="info" class="mt-2" (click)="openDoor()" *ngIf="showMoveAction">Open
|
<button nbButton hero status="info" class="mt-2" (click)="openDoor()" *ngIf="showMoveAction">Open
|
||||||
Door</button>
|
Door</button>
|
||||||
|
<button nbButton hero fullWidth status="warning" class="mt-3" *ngIf="hero.uiActivating"
|
||||||
|
(click)="endActivation()">End
|
||||||
|
Activation</button>
|
||||||
|
|
||||||
</nb-card-body>
|
</nb-card-body>
|
||||||
</nb-card>
|
</nb-card>
|
||||||
@ -121,7 +123,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- <nb-flip-card *ngIf="md2Service.playerHero">
|
<!-- <nb-flip-card *ngIf="hero">
|
||||||
<nb-card-front>
|
<nb-card-front>
|
||||||
<nb-card>
|
<nb-card>
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { MD2Service } from '../../../services/MD2/md2.service';
|
|||||||
import { MsgBoxService } from '../../../services/msg-box.service';
|
import { MsgBoxService } from '../../../services/msg-box.service';
|
||||||
import { StateService } from '../../../services/state.service';
|
import { StateService } from '../../../services/state.service';
|
||||||
import { ADButtonColor, ADButtons } from '../../../ui/alert-dlg/alert-dlg.model';
|
import { ADButtonColor, ADButtons } from '../../../ui/alert-dlg/alert-dlg.model';
|
||||||
|
import { ArrayUtils } from '../../../utilities/array-utils';
|
||||||
import { StringUtils } from '../../../utilities/string-utils';
|
import { StringUtils } from '../../../utilities/string-utils';
|
||||||
import { DebounceTimer } from '../../../utilities/timer-utils';
|
import { DebounceTimer } from '../../../utilities/timer-utils';
|
||||||
import { HeroClass, MD2HeroInfo } from '../massive-darkness2.model';
|
import { HeroClass, MD2HeroInfo } from '../massive-darkness2.model';
|
||||||
@ -51,6 +52,7 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
|
|||||||
new DropDownOption(HeroClass.Rogue, 'Rogue'),
|
new DropDownOption(HeroClass.Rogue, 'Rogue'),
|
||||||
new DropDownOption(HeroClass.Wizard, 'Wizard'),
|
new DropDownOption(HeroClass.Wizard, 'Wizard'),
|
||||||
new DropDownOption(HeroClass.Shaman, 'Shaman'),
|
new DropDownOption(HeroClass.Shaman, 'Shaman'),
|
||||||
|
new DropDownOption(HeroClass.Druid, 'Druid'),
|
||||||
];
|
];
|
||||||
heros = [] as MD2HeroInfo[];
|
heros = [] as MD2HeroInfo[];
|
||||||
wizards: MD2HeroInfo[] = [
|
wizards: MD2HeroInfo[] = [
|
||||||
@ -76,7 +78,7 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public get allowAttack(): boolean {
|
public get allowAttack(): boolean {
|
||||||
return (!!this.md2Service.mobs && this.md2Service.mobs.length > 0) || (!!this.md2Service.roamingMonsters && this.md2Service.roamingMonsters.length > 0);
|
return this.md2Service.playerHero.uiBossFight || (!!this.md2Service.mobs && this.md2Service.mobs.length > 0) || (!!this.md2Service.roamingMonsters && this.md2Service.roamingMonsters.length > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
@ -130,7 +132,7 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
|
|||||||
class: heroClass
|
class: heroClass
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
this.heros = this.heros.sort((a, b) => StringUtils.compareSemVer(a.name, b.name));
|
this.heros = ArrayUtils.Shuffle(this.heros);//.sort((a, b) => StringUtils.compareSemVer(a.name, b.name));
|
||||||
this.showHeroList(heroClass, 0);
|
this.showHeroList(heroClass, 0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -157,16 +159,16 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
broadcastHeroInfo() {
|
broadcastHeroInfo() {
|
||||||
this.md2Service.broadcastMyHeroInfo();
|
this.md2Service.broadcastService.broadcastMyHeroInfo();
|
||||||
this.heroUpdateDebounceTimer.clearOut();
|
this.heroUpdateDebounceTimer.clearOut();
|
||||||
}
|
}
|
||||||
increaseRage() {
|
increaseRage() {
|
||||||
if (this.md2Service.playerHero.rage < 7) {
|
if (this.hero.rage < 7) {
|
||||||
this.md2Service.playerHero.rage++;
|
this.hero.rage++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
openDoor() {
|
openDoor() {
|
||||||
this.md2Service.broadcastHeroAction('openDoor');
|
this.md2Service.broadcastService.broadcastHeroAction('openDoor');
|
||||||
this.showMoveAction = false;
|
this.showMoveAction = false;
|
||||||
this.detectChanges();
|
this.detectChanges();
|
||||||
}
|
}
|
||||||
@ -183,17 +185,19 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
|
|||||||
this.showMoveAction = false;
|
this.showMoveAction = false;
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case 'recoveryAction':
|
case 'recoveryAction':
|
||||||
this.msgBoxService.show('Recovery', { text: 'takes the Recover action may gain up to 2 Health or Mana in any combination (either 2 Health, 2 Mana, or 1 of each).' })
|
this.msgBoxService.show('Recovery', { text: 'takes the Recover action may gain up to 2 Health or Mana in any combination (either 2 Health, 2 Mana, or 1 of each).' });
|
||||||
|
break;
|
||||||
|
case 'attackAction':
|
||||||
|
this.msgBoxService.show('Attacking', { text: 'Please process attacking action in Dashboard.' });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this.md2Service.broadcastHeroAction(action);
|
this.md2Service.broadcastService.broadcastHeroAction(action);
|
||||||
this.reduceAction();
|
this.reduceAction();
|
||||||
}
|
}
|
||||||
reduceAction() {
|
reduceAction() {
|
||||||
this.md2Service.playerHero.remainActions -= 1;
|
this.hero.remainActions -= 1;
|
||||||
this.detectChanges();
|
this.detectChanges();
|
||||||
this.broadcastHeroInfo();
|
this.broadcastHeroInfo();
|
||||||
}
|
}
|
||||||
@ -202,4 +206,30 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
|
|||||||
toggleFlip() {
|
toggleFlip() {
|
||||||
this.flip = (this.flip == 'inactive') ? 'active' : 'inactive';
|
this.flip = (this.flip == 'inactive') ? 'active' : 'inactive';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get allowStartAction() {
|
||||||
|
return !this.md2Service.heros.some(h => h.uiActivating) && !this.hero.uiActivating && this.hero.remainActions > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get hero() {
|
||||||
|
return this.md2Service.playerHero;
|
||||||
|
}
|
||||||
|
startActivation() {
|
||||||
|
this.hero.uiActivating = true;
|
||||||
|
this.broadcastHeroInfo();
|
||||||
|
}
|
||||||
|
endActivation() {
|
||||||
|
if (this.hero.remainActions > 0) {
|
||||||
|
this.msgBoxService.show('Are you sure?', { text: `End Activation will lose ${this.hero.remainActions} remaining actions.`, buttons: ADButtons.YesNo }).pipe(first()).subscribe(result => {
|
||||||
|
if (result) {
|
||||||
|
this.hero.remainActions = 0;
|
||||||
|
this.endActivation();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.hero.uiActivating = false;
|
||||||
|
this.broadcastHeroInfo();
|
||||||
|
this.detectChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,7 +24,7 @@
|
|||||||
</nb-card-header>
|
</nb-card-header>
|
||||||
<nb-card-body>
|
<nb-card-body>
|
||||||
|
|
||||||
<div class="row" *ngIf="md2Service.heros.length==0">
|
<div class="row" *ngIf="md2Service.heros.length==0&& false">
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
|
|
||||||
<adj-number-input name="heroLevel" [(ngModel)]="md2Service.playerAmount" [maximum]="6"
|
<adj-number-input name="heroLevel" [(ngModel)]="md2Service.playerAmount" [maximum]="6"
|
||||||
@ -59,9 +59,10 @@
|
|||||||
<span class="badge badge-success mr-1">Exp: {{hero.exp}}</span>
|
<span class="badge badge-success mr-1">Exp: {{hero.exp}}</span>
|
||||||
<span class="badge badge-danger mr-1" *ngIf="hero.fireToken">Fire:{{hero.fireToken}}</span>
|
<span class="badge badge-danger mr-1" *ngIf="hero.fireToken">Fire:{{hero.fireToken}}</span>
|
||||||
<span class="badge badge-info mr-1" *ngIf="hero.frozenToken">Frozen:{{hero.frozenToken}}</span>
|
<span class="badge badge-info mr-1" *ngIf="hero.frozenToken">Frozen:{{hero.frozenToken}}</span>
|
||||||
<span class="badge badge-light mr-1" *ngIf="hero.remainActions==0">Inactive</span>
|
|
||||||
<span class="badge badge-success mr-1" *ngIf="hero.remainActions>0">Remain
|
<span class="badge badge-success mr-1" *ngIf="hero.remainActions>0">Remain
|
||||||
Actions: {{hero.remainActions}}</span>
|
Actions: {{hero.remainActions}}</span>
|
||||||
|
<span class="badge badge-light mr-1" *ngIf=" !hero.uiActivating">Inactive</span>
|
||||||
|
<span class="badge badge-primary mr-1" *ngIf="hero.uiActivating">Activating</span>
|
||||||
<!-- <span class="badge badge-success mr-1">{{hero.playerInfo.signalRClientId}}</span> -->
|
<!-- <span class="badge badge-success mr-1">{{hero.playerInfo.signalRClientId}}</span> -->
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import { QRCodeService } from '../../services/qrcode.service';
|
|||||||
import { StringUtils } from '../../utilities/string-utils';
|
import { StringUtils } from '../../utilities/string-utils';
|
||||||
import { SpawnMobDlgComponent } from './mobs/spawn-mob-dlg/spawn-mob-dlg.component';
|
import { SpawnMobDlgComponent } from './mobs/spawn-mob-dlg/spawn-mob-dlg.component';
|
||||||
import { BossMicheal } from './massive-darkness2.model.boss';
|
import { BossMicheal } from './massive-darkness2.model.boss';
|
||||||
|
import { MD2InitService } from '../../services/MD2/md2-init.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ngx-massive-darkness2',
|
selector: 'ngx-massive-darkness2',
|
||||||
@ -26,6 +27,7 @@ export class MassiveDarkness2Component extends MD2Base implements OnInit {
|
|||||||
HeroClass: HeroClass
|
HeroClass: HeroClass
|
||||||
constructor(
|
constructor(
|
||||||
private fileService: FileService,
|
private fileService: FileService,
|
||||||
|
private initService: MD2InitService,
|
||||||
private msgBoxService: MsgBoxService,
|
private msgBoxService: MsgBoxService,
|
||||||
private qrCodeService: QRCodeService,
|
private qrCodeService: QRCodeService,
|
||||||
public gameRoomService: GameRoomService,
|
public gameRoomService: GameRoomService,
|
||||||
@ -42,7 +44,8 @@ export class MassiveDarkness2Component extends MD2Base implements OnInit {
|
|||||||
this.md2Service.enemyPhaseSubject.pipe(takeUntil(this.destroy$)).subscribe(result => {
|
this.md2Service.enemyPhaseSubject.pipe(takeUntil(this.destroy$)).subscribe(result => {
|
||||||
this.showEnemyPhaseAction(0);
|
this.showEnemyPhaseAction(0);
|
||||||
});
|
});
|
||||||
|
this.initService.initMobDecks();
|
||||||
|
this.initService.initTreasureBag();
|
||||||
}
|
}
|
||||||
override signalRInitialized() {
|
override signalRInitialized() {
|
||||||
|
|
||||||
@ -64,7 +67,7 @@ export class MassiveDarkness2Component extends MD2Base implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
showEnemyPhaseAction(index: number) {
|
showEnemyPhaseAction(index: number) {
|
||||||
let mob = new MobInfo(this.md2Service.enemyPhaseMobs[index]);
|
let mob = this.md2Service.enemyPhaseMobs[index];
|
||||||
let enemyInfo = `<img src="${mob.imageUrl}" class='g-height-70vh'><br>`;
|
let enemyInfo = `<img src="${mob.imageUrl}" class='g-height-70vh'><br>`;
|
||||||
let extraRule = '';
|
let extraRule = '';
|
||||||
|
|
||||||
@ -85,7 +88,13 @@ export class MassiveDarkness2Component extends MD2Base implements OnInit {
|
|||||||
// break;
|
// break;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
this.msgBoxService.dlgService.open(SpawnMobDlgComponent, { context: { title: `Enemy Phase(${(index + 1)}/${this.md2Service.enemyPhaseMobs.length})`, mode: MobDlgType.Activating, mob: mob } })
|
this.msgBoxService.dlgService.open(SpawnMobDlgComponent, {
|
||||||
|
context: {
|
||||||
|
title: `Enemy Phase(${(index + 1)}/${this.md2Service.enemyPhaseMobs.length})`,
|
||||||
|
mode: MobDlgType.Activating,
|
||||||
|
mob: mob
|
||||||
|
}
|
||||||
|
})
|
||||||
.onClose.pipe(first()).subscribe(result => {
|
.onClose.pipe(first()).subscribe(result => {
|
||||||
index++;
|
index++;
|
||||||
if (index < this.md2Service.enemyPhaseMobs.length) {
|
if (index < this.md2Service.enemyPhaseMobs.length) {
|
||||||
@ -125,10 +134,7 @@ export class MassiveDarkness2Component extends MD2Base implements OnInit {
|
|||||||
|
|
||||||
}
|
}
|
||||||
enterBossFight() {
|
enterBossFight() {
|
||||||
this.msgBoxService.showInputbox('Boss Fight', 'Choose the boss').pipe(first()).subscribe(result => {
|
this.md2Service.enterBossFight();
|
||||||
this.md2Service.info.isBossFight = true;
|
|
||||||
this.md2Service.info.boss = new BossMicheal(this.md2Service);
|
|
||||||
this.detectChanges();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
69
src/app/games/massive-darkness2/massive-darkness2.logic.ts
Normal file
69
src/app/games/massive-darkness2/massive-darkness2.logic.ts
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import { Observable, Subject } from "rxjs";
|
||||||
|
import { environment } from "../../../environments/environment";
|
||||||
|
import { MsgBoxService } from "../../services/msg-box.service";
|
||||||
|
import { ObjectUtils } from "../../utilities/object-utils";
|
||||||
|
import { StringUtils } from "../../utilities/string-utils";
|
||||||
|
import { GamePlayer } from "../games.model";
|
||||||
|
import { MD2HeroInfo, AttackTarget, HeroClass } from "./massive-darkness2.model";
|
||||||
|
import { MobSkill } from "./massive-darkness2.model.boss";
|
||||||
|
export class MD2Logic {
|
||||||
|
|
||||||
|
public static getTargetHerosByFilter(heros: MD2HeroInfo[], targetType: AttackTarget, onlyOne: boolean = false) {
|
||||||
|
let beenAttackedHero = [] as MD2HeroInfo[];
|
||||||
|
switch (targetType) {
|
||||||
|
case AttackTarget.LeastHp:
|
||||||
|
let lowestHp = Math.min(...heros.map(h => h.hp));
|
||||||
|
beenAttackedHero = heros.filter(h => h.hp == lowestHp);
|
||||||
|
//this.otherAttackTarget = 'attacking the other <b>Lowest HP</b> hero.';
|
||||||
|
break;
|
||||||
|
case AttackTarget.LeastMp:
|
||||||
|
let lowestMp = Math.min(...heros.map(h => h.mp));
|
||||||
|
beenAttackedHero = heros.filter(h => h.hp == lowestMp);
|
||||||
|
//this.otherAttackTarget = 'attacking the other <b>Lowest HP</b> hero.';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AttackTarget.HighestHp:
|
||||||
|
let highestHp = Math.max(...heros.map(h => h.hp));
|
||||||
|
beenAttackedHero = heros.filter(h => h.hp == highestHp);
|
||||||
|
//this.otherAttackTarget = 'attacking the other <b>Highest HP</b> hero.';
|
||||||
|
break;
|
||||||
|
case AttackTarget.HighestMp:
|
||||||
|
let highestMp = Math.max(...heros.map(h => h.mp));
|
||||||
|
beenAttackedHero = heros.filter(h => h.mp == highestMp);
|
||||||
|
//this.otherAttackTarget = 'attacking the other <b>Highest Mp</b> hero.';
|
||||||
|
break;
|
||||||
|
case AttackTarget.LowestLevel:
|
||||||
|
let lowestLevel = Math.max(...heros.map(h => h.level));
|
||||||
|
beenAttackedHero = heros.filter(h => h.level == lowestLevel);
|
||||||
|
//this.otherAttackTarget = 'attacking the other <b>Lowest Level</b> hero.';
|
||||||
|
break;
|
||||||
|
case AttackTarget.LeastCorruption:
|
||||||
|
|
||||||
|
let leastCor = Math.min(...heros.map(h => h.corruptionToken));
|
||||||
|
beenAttackedHero = heros.filter(h => h.corruptionToken == leastCor);
|
||||||
|
break;
|
||||||
|
case AttackTarget.MostCorruption:
|
||||||
|
let mostCor = Math.max(...heros.map(h => h.corruptionToken));
|
||||||
|
beenAttackedHero = heros.filter(h => h.corruptionToken == mostCor);
|
||||||
|
break;
|
||||||
|
case AttackTarget.Random:
|
||||||
|
default:
|
||||||
|
beenAttackedHero = [heros[Math.round(Math.random() * (heros.length - 1))]];
|
||||||
|
//this.otherAttackTarget = 'Just act like normal.';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (onlyOne && beenAttackedHero.length > 1) {
|
||||||
|
beenAttackedHero = [beenAttackedHero[Math.round(Math.random() * (beenAttackedHero.length - 1))]];
|
||||||
|
}
|
||||||
|
return beenAttackedHero;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getTargetHerosHtml(beenAttackedHero: MD2HeroInfo[]) {
|
||||||
|
return `<b>${StringUtils.makeCommaSeparatedString(beenAttackedHero.map(h => this.heroFullName(h)), false, true)}</b>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static heroFullName(hero: MD2HeroInfo) {
|
||||||
|
if (!hero) return '';
|
||||||
|
return `${hero.playerInfo.name} (${HeroClass[hero.class]} - ${hero.name})`
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import { stringify } from "querystring"
|
import { stringify } from "querystring"
|
||||||
import { Subject } from "rxjs"
|
import { Observable, Subject, Subscription } from "rxjs"
|
||||||
import { first } from "rxjs/operators"
|
import { first } from "rxjs/operators"
|
||||||
import { MD2Service } from "../../services/MD2/md2.service"
|
import { MD2Service } from "../../services/MD2/md2.service"
|
||||||
import { StringUtils } from "../../utilities/string-utils"
|
import { StringUtils } from "../../utilities/string-utils"
|
||||||
@ -8,121 +8,6 @@ import { TreasureType, AttackInfo, DefenseInfo, AttackType, MD2Icon, MD2HeroInfo
|
|||||||
import { RollingBlackDice } from "./massive-darkness2.model.dice"
|
import { RollingBlackDice } from "./massive-darkness2.model.dice"
|
||||||
|
|
||||||
|
|
||||||
export interface IBossFight {
|
|
||||||
name: string
|
|
||||||
addTreasureToken: Subject<TreasureType>
|
|
||||||
spawnMob: Subject<void>
|
|
||||||
spawnRoamingMonster: Subject<void>
|
|
||||||
rounds: number
|
|
||||||
actions: number
|
|
||||||
hpPerHero: number
|
|
||||||
info: MobInfo
|
|
||||||
actionBlackDice: number
|
|
||||||
imgUrl: string
|
|
||||||
standUrl: string
|
|
||||||
activating(): boolean
|
|
||||||
prepareForBossFight(): void
|
|
||||||
nextRound(): void
|
|
||||||
}
|
|
||||||
export class BossMicheal implements IBossFight {
|
|
||||||
|
|
||||||
constructor(private md2Service: MD2Service) {
|
|
||||||
this.corruptionTokenHtml = this.md2Service.stateService.imgHtml('Tokens/CorruptToken.png');
|
|
||||||
|
|
||||||
this.name = 'Michael - The Corrupted Archangel';
|
|
||||||
this.imgUrl = md2Service.stateService.imgUrl('/Boss/Michael - The Corrupted Archangel.jpg');
|
|
||||||
this.standUrl = md2Service.stateService.imgUrl('/Boss/Michael.png');
|
|
||||||
this.hpPerHero = 15;
|
|
||||||
this.info = new MobInfo({
|
|
||||||
description: this.name,
|
|
||||||
type: MobType.Boss,
|
|
||||||
hp: this.md2Service.heros.length * this.hpPerHero,
|
|
||||||
unitRemainHp: this.md2Service.heros.length * this.hpPerHero,
|
|
||||||
level: 10,
|
|
||||||
combatSkill: new MobSkill(`Combat 1 ${this.md2Service.stateService.iconHtml(MD2Icon.EnemySkill)}`,
|
|
||||||
`Deal 1 Wound for each ${this.corruptionTokenHtml} on the attacking or defending Hero. Discard the tokens afterwards(once per combat).`),
|
|
||||||
imageUrl: md2Service.stateService.imgUrl('/Boss/Michael.png')
|
|
||||||
});
|
|
||||||
this.info.defenseInfo = new DefenseInfo(5, 1);
|
|
||||||
this.info.attackInfos = [new AttackInfo(MD2Icon.Melee, 2, 2, 0, 1)];
|
|
||||||
this.actions = 1;
|
|
||||||
this.rounds = 0;
|
|
||||||
this.actionBlackDice = 2;
|
|
||||||
}
|
|
||||||
name: string
|
|
||||||
addTreasureToken: Subject<TreasureType>
|
|
||||||
spawnMob: Subject<void>
|
|
||||||
spawnRoamingMonster: Subject<void>
|
|
||||||
rounds: number
|
|
||||||
actions: number
|
|
||||||
hpPerHero: number
|
|
||||||
info: MobInfo
|
|
||||||
actionBlackDice: number
|
|
||||||
imgUrl: string
|
|
||||||
standUrl: string
|
|
||||||
corruptionTokenHtml: string
|
|
||||||
activating(): boolean {
|
|
||||||
|
|
||||||
let actionResult = new RollingBlackDice().roll(this.actionBlackDice);
|
|
||||||
let actionHtml = '';
|
|
||||||
let beenAttackedHero = [] as MD2HeroInfo[];
|
|
||||||
let bossAction: MobSkill;
|
|
||||||
switch (actionResult.claws) {
|
|
||||||
case 0:
|
|
||||||
//Justice From Above
|
|
||||||
beenAttackedHero = this.md2Service.getTargetHerosByFilter(AttackTarget.MostCorruption, true);
|
|
||||||
bossAction = new MobSkill('Justice From Above',
|
|
||||||
`Place Michael in the Zone at ${this.md2Service.getTargetHerosHtml(beenAttackedHero)} and attack Him/Her.`);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
//Lance Dash
|
|
||||||
beenAttackedHero = this.md2Service.getTargetHerosByFilter(AttackTarget.LeastCorruption, true);
|
|
||||||
bossAction = new MobSkill('Lance Dash',
|
|
||||||
`Move Michael and Place 1 ${this.corruptionTokenHtml} in the Zone at ${this.md2Service.getTargetHerosHtml(beenAttackedHero)} and attack Him/Her.`);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
//Dark Blessing
|
|
||||||
bossAction = new MobSkill('Dark Blessing',
|
|
||||||
`Place Michael on the central Zone and add 1 ${this.corruptionTokenHtml} to the Corruption Stone Zone with the least amount of ${this.corruptionTokenHtml}.<br>` +
|
|
||||||
`Deal <b>${this.darkBlessingCorruptionAmt}</b> Wounds per ${this.corruptionTokenHtml} to all Heros in each Tiles <b>distributed as they wish</b>.`);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
this.md2Service.dlgService.open(BossActivationComponent, { context: { boss: this, bossAction: bossAction } }).onClose
|
|
||||||
.pipe(first()).subscribe(result => {
|
|
||||||
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
prepareForBossFight(): void {
|
|
||||||
|
|
||||||
}
|
|
||||||
darkBlessingCorruptionAmt: number = 1;
|
|
||||||
nextRound(): void {
|
|
||||||
this.rounds++;
|
|
||||||
switch (this.rounds) {
|
|
||||||
case 3:
|
|
||||||
case 5:
|
|
||||||
this.darkBlessingCorruptionAmt++;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
case 4:
|
|
||||||
this.info.defenseInfo[0].black += 1;
|
|
||||||
this.info.attackInfos[0].black += 1;
|
|
||||||
break;
|
|
||||||
// case 4:
|
|
||||||
// this.defInfo.black += 2;
|
|
||||||
// this.atkInfos[0].black += 2;
|
|
||||||
// break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export enum MobSkillType {
|
export enum MobSkillType {
|
||||||
Attack,
|
Attack,
|
||||||
Defense,
|
Defense,
|
||||||
@ -146,4 +31,287 @@ export class MobSkill {
|
|||||||
name: string
|
name: string
|
||||||
description: string
|
description: string
|
||||||
targetHeros: MD2HeroInfo[]
|
targetHeros: MD2HeroInfo[]
|
||||||
|
}
|
||||||
|
export interface IBossFight {
|
||||||
|
name: string
|
||||||
|
addTreasureToken: Subject<TreasureType>
|
||||||
|
spawnMob: Subject<void>
|
||||||
|
spawnRoamingMonster: Subject<void>
|
||||||
|
rounds: number
|
||||||
|
actions: number
|
||||||
|
activatedTimes: number
|
||||||
|
info: MobInfo
|
||||||
|
actionBlackDice: number
|
||||||
|
imgUrl: string
|
||||||
|
standUrl: string
|
||||||
|
extraRules: string
|
||||||
|
activating(): boolean
|
||||||
|
prepareForBossFight(): void
|
||||||
|
darknessPhase(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class BossFight implements IBossFight {
|
||||||
|
name: string
|
||||||
|
addTreasureToken: Subject<TreasureType>
|
||||||
|
spawnMob: Subject<void>
|
||||||
|
spawnRoamingMonster: Subject<void>
|
||||||
|
rounds: number
|
||||||
|
actions: number
|
||||||
|
activatedTimes: number
|
||||||
|
info: MobInfo
|
||||||
|
actionBlackDice: number
|
||||||
|
imgUrl: string
|
||||||
|
standUrl: string
|
||||||
|
extraRules: string
|
||||||
|
protected subscription: Subscription
|
||||||
|
|
||||||
|
constructor(protected md2Service: MD2Service) {
|
||||||
|
this.rounds = 1;
|
||||||
|
}
|
||||||
|
activating(): boolean {
|
||||||
|
this.activatedTimes = this.actions;
|
||||||
|
this.runAction();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
runAction() {
|
||||||
|
this.bossAction().pipe(first()).subscribe(result => {
|
||||||
|
this.activatedTimes--;
|
||||||
|
if (this.activatedTimes) {
|
||||||
|
this.runAction();
|
||||||
|
} else {
|
||||||
|
if (false == this.md2Service.heros.some(h => h.remainActions > 0)) {
|
||||||
|
this.md2Service.darknessPhase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
abstract bossAction(): Observable<boolean>;
|
||||||
|
protected actionEnd
|
||||||
|
prepareForBossFight(): void {
|
||||||
|
throw new Error("Method not implemented.")
|
||||||
|
}
|
||||||
|
darknessPhase(): void {
|
||||||
|
throw new Error("Method not implemented.")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
export class BossMicheal extends BossFight {
|
||||||
|
constructor(protected md2Service: MD2Service) {
|
||||||
|
super(md2Service);
|
||||||
|
this.corruptionTokenHtml = this.md2Service.stateService.imgHtml('Tokens/CorruptToken.png');
|
||||||
|
|
||||||
|
this.name = 'Michael - The Corrupted Archangel';
|
||||||
|
this.imgUrl = md2Service.stateService.imgUrl('/Boss/Michael - The Corrupted Archangel.jpg');
|
||||||
|
this.standUrl = md2Service.stateService.imgUrl('/Boss/Michael.png');
|
||||||
|
|
||||||
|
this.info = new MobInfo({
|
||||||
|
description: this.name,
|
||||||
|
type: MobType.Boss,
|
||||||
|
hpPerHero: 15,
|
||||||
|
level: 10,
|
||||||
|
combatSkill: new MobSkill(
|
||||||
|
{
|
||||||
|
name: `Combat 1 ${this.md2Service.stateService.iconHtml(MD2Icon.EnemySkill)}`,
|
||||||
|
description: `Deal 1 Wound for each ${this.corruptionTokenHtml} on the attacking or defending Hero. Discard the tokens afterwards(once per combat).`
|
||||||
|
}),
|
||||||
|
imageUrl: md2Service.stateService.imgUrl('/Boss/Michael.png')
|
||||||
|
});
|
||||||
|
this.info.defenseInfo = new DefenseInfo(5, 1);
|
||||||
|
this.info.attackInfos = [new AttackInfo(MD2Icon.Melee, 2, 2, 0, 1)];
|
||||||
|
this.actions = 1;
|
||||||
|
this.actionBlackDice = 2;
|
||||||
|
|
||||||
|
this.extraRules = `Archangel Michael can’t be the target of any attack, skill, ability or take Wounds until there are no Corruption tokens in the whole Tile.<br><br>` +
|
||||||
|
`Any Hero on a Zone with a ${this.corruptionTokenHtml} may spend 1 action to remove it. Each time a Hero removes a ${this.corruptionTokenHtml} from a Zone they must roll 1 ${this.md2Service.stateService.iconHtml(MD2Icon.BlackDice)}.` +
|
||||||
|
`If ${this.md2Service.stateService.iconHtml(MD2Icon.EnemyClaw)} the Hero takes 1 Wound.<br>If ${this.md2Service.stateService.iconHtml(MD2Icon.EnemySkill)} place 1 ${this.corruptionTokenHtml} on their Dashboard.<br>` +
|
||||||
|
`If ${this.md2Service.stateService.iconHtml(MD2Icon.EnemyClaw)}/${this.md2Service.stateService.iconHtml(MD2Icon.EnemySkill)} the Hero takes 1 Wound and places 1 ${this.corruptionTokenHtml} on their Dashboard.`
|
||||||
|
}
|
||||||
|
activatedTimes: number
|
||||||
|
acted: number
|
||||||
|
name: string
|
||||||
|
addTreasureToken: Subject<TreasureType>
|
||||||
|
spawnMob: Subject<void>
|
||||||
|
spawnRoamingMonster: Subject<void>
|
||||||
|
rounds: number
|
||||||
|
actions: number
|
||||||
|
info: MobInfo
|
||||||
|
actionBlackDice: number
|
||||||
|
imgUrl: string
|
||||||
|
standUrl: string
|
||||||
|
corruptionTokenHtml: string
|
||||||
|
|
||||||
|
bossAction(): Observable<boolean> {
|
||||||
|
|
||||||
|
let actionResult = new RollingBlackDice().roll(this.actionBlackDice);
|
||||||
|
let actionHtml = '';
|
||||||
|
let beenAttackedHero = [] as MD2HeroInfo[];
|
||||||
|
let bossAction: MobSkill;
|
||||||
|
switch (actionResult.claws) {
|
||||||
|
case 0:
|
||||||
|
//Justice From Above
|
||||||
|
beenAttackedHero = this.md2Service.getTargetHerosByFilter(AttackTarget.MostCorruption, true);
|
||||||
|
bossAction = new MobSkill(
|
||||||
|
{
|
||||||
|
name: 'Justice From Above',
|
||||||
|
description: `Place Michael in the Zone at ${this.md2Service.getTargetHerosHtml(beenAttackedHero)} and attack Him/Her.`
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
//Lance Dash
|
||||||
|
beenAttackedHero = this.md2Service.getTargetHerosByFilter(AttackTarget.LeastCorruption, true);
|
||||||
|
bossAction = new MobSkill({
|
||||||
|
name: 'Lance Dash',
|
||||||
|
description:
|
||||||
|
`Move Michael and Place 1 ${this.corruptionTokenHtml} in the Zone at ${this.md2Service.getTargetHerosHtml(beenAttackedHero)} and attack Him/Her.`
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
//Dark Blessing
|
||||||
|
bossAction = new MobSkill({
|
||||||
|
name: 'Dark Blessing',
|
||||||
|
description:
|
||||||
|
`Place Michael on the central Zone and add 1 ${this.corruptionTokenHtml} to the Corruption Stone Zone with the least amount of ${this.corruptionTokenHtml}.<br>` +
|
||||||
|
`Deal <b>${this.darkBlessingCorruptionAmt}</b> Wounds per ${this.corruptionTokenHtml} to all Heros in each Tiles <b>distributed as they wish</b>.`
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return this.md2Service.dlgService.open(BossActivationComponent, { context: { boss: this, bossAction: bossAction, currentAction: this.activatedTimes, allActions: this.actions } }).onClose;
|
||||||
|
|
||||||
|
}
|
||||||
|
prepareForBossFight(): void {
|
||||||
|
this.md2Service.heros.forEach(hero => {
|
||||||
|
hero.uiShowCorruptionToken = true;
|
||||||
|
});
|
||||||
|
this.md2Service.msgBoxService.show('Prepare Boss Fight', {
|
||||||
|
text: `<h6>Place ${this.md2Service.heros.length * 2} ${this.corruptionTokenHtml} on the Corruption Stone Zones (Shadow
|
||||||
|
Zones).<br>Players choose the Zones, but must distribute
|
||||||
|
the tokens as equally as possible among them.</h6>`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
darkBlessingCorruptionAmt: number = 1;
|
||||||
|
darknessPhase(): void {
|
||||||
|
this.rounds++;
|
||||||
|
switch (this.rounds) {
|
||||||
|
case 3:
|
||||||
|
case 5:
|
||||||
|
this.darkBlessingCorruptionAmt++;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
case 4:
|
||||||
|
this.info.defenseInfo.black += 1;
|
||||||
|
this.info.attackInfos[0].black += 1;
|
||||||
|
break;
|
||||||
|
// case 4:
|
||||||
|
// this.defInfo.black += 2;
|
||||||
|
// this.atkInfos[0].black += 2;
|
||||||
|
// break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export class BossReaper extends BossFight {
|
||||||
|
|
||||||
|
constructor(protected md2Service: MD2Service) {
|
||||||
|
super(md2Service);
|
||||||
|
this.timeTokenHtml = this.md2Service.stateService.imgHtml('Tokens/TimeToken.png');
|
||||||
|
|
||||||
|
this.name = 'The Reaper';
|
||||||
|
this.imgUrl = md2Service.stateService.imgUrl('/Boss/The Reaper.jpg');
|
||||||
|
this.standUrl = md2Service.stateService.imgUrl('/Boss/The Reaper-Stand.png');
|
||||||
|
|
||||||
|
this.info = new MobInfo({
|
||||||
|
description: this.name,
|
||||||
|
type: MobType.Boss,
|
||||||
|
hpPerHero: 25,
|
||||||
|
level: 10,
|
||||||
|
combatSkill: new MobSkill(
|
||||||
|
{
|
||||||
|
description: `If the Hero has no ${this.md2Service.stateService.iconHtml(MD2Icon.Mana)}, they take 1 ${this.md2Service.stateService.iconHtml(MD2Icon.Frost)}`,
|
||||||
|
type: MobSkillType.Attack,
|
||||||
|
|
||||||
|
}),
|
||||||
|
imageUrl: md2Service.stateService.imgUrl('/Boss/The Reaper-Stand.png')
|
||||||
|
});
|
||||||
|
this.info.defenseInfo = new DefenseInfo(4, 3);
|
||||||
|
this.info.attackInfos = [new AttackInfo(MD2Icon.Melee, 1, 2, 0, 3)];
|
||||||
|
this.actions = 1;
|
||||||
|
this.actionBlackDice = 2;
|
||||||
|
this.extraRules = `A Hero standing in the Hourglass Zone may spend 1 action to add 1 ${this.timeTokenHtml} in each Hourglass Zone.`;
|
||||||
|
}
|
||||||
|
name: string
|
||||||
|
addTreasureToken: Subject<TreasureType>
|
||||||
|
spawnMob: Subject<void>
|
||||||
|
spawnRoamingMonster: Subject<void>
|
||||||
|
rounds: number
|
||||||
|
actions: number
|
||||||
|
info: MobInfo
|
||||||
|
actionBlackDice: number
|
||||||
|
imgUrl: string
|
||||||
|
standUrl: string
|
||||||
|
timeTokenHtml: string
|
||||||
|
bossAction() {
|
||||||
|
|
||||||
|
let actionResult = new RollingBlackDice().roll(this.actionBlackDice);
|
||||||
|
let actionHtml = '';
|
||||||
|
let beenAttackedHero = [] as MD2HeroInfo[];
|
||||||
|
let bossAction: MobSkill;
|
||||||
|
switch (actionResult.claws) {
|
||||||
|
case 0:
|
||||||
|
//Justice From Above
|
||||||
|
beenAttackedHero = this.md2Service.getTargetHerosByFilter(AttackTarget.LeastMp, true);
|
||||||
|
bossAction = new MobSkill(
|
||||||
|
{
|
||||||
|
name: 'Soul Drain',
|
||||||
|
description: `Place The Reaper in the Zone at ${this.md2Service.getTargetHerosHtml(beenAttackedHero)} and attack Him/Her.`
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
//Lance Dash
|
||||||
|
beenAttackedHero = this.md2Service.getTargetHerosByFilter(AttackTarget.LeastCorruption, true);
|
||||||
|
bossAction = new MobSkill({
|
||||||
|
name: 'Time Ticking',
|
||||||
|
description:
|
||||||
|
`Place The Reaper in the <b>Hourglass Zone</b> withe the least ${this.timeTokenHtml} and remove 1 ${this.timeTokenHtml} from <b>The OtherHourglass Zone</b>.`
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
//Dark Blessing
|
||||||
|
bossAction = new MobSkill({
|
||||||
|
name: 'Death Is Coming',
|
||||||
|
description:
|
||||||
|
`Place The Reaper in the central Zone.<br>` +
|
||||||
|
`Roll 1 ${this.md2Service.stateService.iconHtml(MD2Icon.YellowDice)}. Remove ${this.timeTokenHtml} equal to ${this.md2Service.stateService.iconHtml(MD2Icon.Melee)} rolled from both <b>Hourglass Zone</b>.<br>` +
|
||||||
|
`Each Hero discards ${this.md2Service.stateService.iconHtml(MD2Icon.MP)} equal to ${this.md2Service.stateService.iconHtml(MD2Icon.Melee)} rolled.`
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return this.md2Service.dlgService.open(BossActivationComponent, { context: { boss: this, bossAction: bossAction, currentAction: this.activatedTimes, allActions: this.actions } }).onClose;
|
||||||
|
}
|
||||||
|
prepareForBossFight(): void {
|
||||||
|
this.md2Service.msgBoxService.show('Prepare Boss Fight', {
|
||||||
|
text: `<h6>Place 2 ${this.timeTokenHtml} in each Hourglass Zone.</h6>`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
darkBlessingCorruptionAmt: number = 1;
|
||||||
|
darknessPhase(): void {
|
||||||
|
this.rounds++;
|
||||||
|
if (this.rounds > 4) {
|
||||||
|
this.actions = 3;
|
||||||
|
} else if (this.rounds > 1) {
|
||||||
|
this.actions = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,7 +1,9 @@
|
|||||||
import { Subject } from "rxjs";
|
import { Observable, Subject } from "rxjs";
|
||||||
import { environment } from "../../../environments/environment";
|
import { environment } from "../../../environments/environment";
|
||||||
|
import { MsgBoxService } from "../../services/msg-box.service";
|
||||||
import { ObjectUtils } from "../../utilities/object-utils";
|
import { ObjectUtils } from "../../utilities/object-utils";
|
||||||
import { GamePlayer } from "../games.model";
|
import { GamePlayer } from "../games.model";
|
||||||
|
import { MD2Clone } from "./factorys/md2-clone";
|
||||||
import { MobSkill } from "./massive-darkness2.model.boss";
|
import { MobSkill } from "./massive-darkness2.model.boss";
|
||||||
|
|
||||||
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)}` : '')}` }
|
||||||
@ -9,7 +11,8 @@ export enum MobDlgType {
|
|||||||
Spawn,
|
Spawn,
|
||||||
Activating,
|
Activating,
|
||||||
BeenAttacked,
|
BeenAttacked,
|
||||||
PreView
|
PreView,
|
||||||
|
Dashboard
|
||||||
}
|
}
|
||||||
export enum RoundPhase {
|
export enum RoundPhase {
|
||||||
HeroPhase,
|
HeroPhase,
|
||||||
@ -31,6 +34,7 @@ export enum HeroClass {
|
|||||||
Ranger,
|
Ranger,
|
||||||
Shaman,
|
Shaman,
|
||||||
Paladin,
|
Paladin,
|
||||||
|
Druid,
|
||||||
}
|
}
|
||||||
export enum MobType {
|
export enum MobType {
|
||||||
Mob,
|
Mob,
|
||||||
@ -68,14 +72,16 @@ export enum MD2Icon {
|
|||||||
RedDice,
|
RedDice,
|
||||||
BlueDice,
|
BlueDice,
|
||||||
YellowDice,
|
YellowDice,
|
||||||
OrangeDice
|
OrangeDice,
|
||||||
|
BlackDice
|
||||||
}
|
}
|
||||||
export enum AttackTarget {
|
export enum AttackTarget {
|
||||||
Random = 40,
|
Random = 40,
|
||||||
LowestHp = 50,
|
LeastHp = 50,
|
||||||
HighestHp = 60,
|
LeastMp = 60,
|
||||||
HighestMp = 70,
|
HighestHp = 70,
|
||||||
LowestLevel = 80,
|
HighestMp = 80,
|
||||||
|
LowestLevel = 90,
|
||||||
MostCorruption = 200,
|
MostCorruption = 200,
|
||||||
LeastCorruption = 201
|
LeastCorruption = 201
|
||||||
}
|
}
|
||||||
@ -132,8 +138,12 @@ export class DrawingBag<T extends IDrawingItem> {
|
|||||||
}
|
}
|
||||||
drawingItems: IDrawingItem[]
|
drawingItems: IDrawingItem[]
|
||||||
removedItems: IDrawingItem[]
|
removedItems: IDrawingItem[]
|
||||||
public bagIsEmpty() {
|
public bagIsEmpty(predicate: (value: T) => boolean = undefined) {
|
||||||
return this.drawingItems.reduce((sum, current) => sum + current.drawingWeight, 0) == 0;
|
if (predicate) {
|
||||||
|
return this.drawingItems.filter(predicate).reduce((sum, current) => sum + current.drawingWeight, 0) == 0;
|
||||||
|
} else {
|
||||||
|
return this.drawingItems.reduce((sum, current) => sum + current.drawingWeight, 0) == 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Draw(amount: number): T[] {
|
public Draw(amount: number): T[] {
|
||||||
@ -144,7 +154,7 @@ export class DrawingBag<T extends IDrawingItem> {
|
|||||||
public DrawAndRemove(amount: number = 1, predicate: (value: T) => boolean = undefined): T[] {
|
public DrawAndRemove(amount: number = 1, predicate: (value: T) => boolean = undefined): T[] {
|
||||||
let drawItems: T[] = [];
|
let drawItems: T[] = [];
|
||||||
for (let i = 0; i < amount; i++) {
|
for (let i = 0; i < amount; i++) {
|
||||||
if (!this.bagIsEmpty()) {
|
if (!this.bagIsEmpty(predicate)) {
|
||||||
let drawItem = null as T;
|
let drawItem = null as T;
|
||||||
let drawingPool = [] as T[];
|
let drawingPool = [] as T[];
|
||||||
if (predicate) {
|
if (predicate) {
|
||||||
@ -159,7 +169,7 @@ export class DrawingBag<T extends IDrawingItem> {
|
|||||||
const item = drawingPool[i];
|
const item = drawingPool[i];
|
||||||
drawCalc += item.drawingWeight;
|
drawCalc += item.drawingWeight;
|
||||||
if (drawCalc >= drawIndex) {
|
if (drawCalc >= drawIndex) {
|
||||||
drawItem = ObjectUtils.CloneValue(item);
|
drawItem = MD2Clone.CloneDrawingItem(item);
|
||||||
drawItem.drawingWeight = 1;
|
drawItem.drawingWeight = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -183,7 +193,7 @@ export class DrawingBag<T extends IDrawingItem> {
|
|||||||
this.removedItems = [];
|
this.removedItems = [];
|
||||||
}
|
}
|
||||||
public AddItem(item: IDrawingItem) {
|
public AddItem(item: IDrawingItem) {
|
||||||
let existingItem = this.drawingItems.find(i => i.name == item.name);
|
let existingItem = this.drawingItems.find(i => i.identifyName == item.identifyName);
|
||||||
if (existingItem) {
|
if (existingItem) {
|
||||||
existingItem.drawingWeight += item.drawingWeight;
|
existingItem.drawingWeight += item.drawingWeight;
|
||||||
} else {
|
} else {
|
||||||
@ -193,17 +203,34 @@ export class DrawingBag<T extends IDrawingItem> {
|
|||||||
|
|
||||||
public RemoveItem(item: IDrawingItem) {
|
public RemoveItem(item: IDrawingItem) {
|
||||||
if (item) {
|
if (item) {
|
||||||
let existingItem = this.drawingItems.find(i => i.name == item.name);
|
|
||||||
if (existingItem) {
|
|
||||||
existingItem.drawingWeight -= item.drawingWeight;
|
|
||||||
|
|
||||||
let removedItem = this.removedItems.find(i => i.name == item.name);
|
if (item.identifyName) {
|
||||||
if (removedItem) {
|
let existingItem = this.drawingItems.find(i => i.identifyName == item.identifyName);
|
||||||
removedItem.drawingWeight += item.drawingWeight;
|
if (existingItem) {
|
||||||
} else {
|
existingItem.drawingWeight -= item.drawingWeight;
|
||||||
this.removedItems.push(item);
|
|
||||||
|
let removedItem = this.removedItems.find(i => i.identifyName == item.identifyName);
|
||||||
|
if (removedItem) {
|
||||||
|
removedItem.drawingWeight += item.drawingWeight;
|
||||||
|
} else {
|
||||||
|
this.removedItems.push(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
let existingItem = this.drawingItems.find(i => i.name == item.name);
|
||||||
|
if (existingItem) {
|
||||||
|
existingItem.drawingWeight -= item.drawingWeight;
|
||||||
|
|
||||||
|
let removedItem = this.removedItems.find(i => i.name == item.name);
|
||||||
|
if (removedItem) {
|
||||||
|
removedItem.drawingWeight += item.drawingWeight;
|
||||||
|
} else {
|
||||||
|
this.removedItems.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -214,11 +241,13 @@ export class DrawingBag<T extends IDrawingItem> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
export interface IMobFactory {
|
export interface IMobFactory {
|
||||||
|
mobName: string;
|
||||||
generate(level: number): MobInfo;
|
generate(level: number): MobInfo;
|
||||||
}
|
}
|
||||||
export interface IDrawingItem {
|
export interface IDrawingItem {
|
||||||
imageUrl: string
|
imageUrl: string
|
||||||
name: string
|
name: string
|
||||||
|
get identifyName(): string
|
||||||
description: string
|
description: string
|
||||||
drawingWeight: number
|
drawingWeight: number
|
||||||
}
|
}
|
||||||
@ -234,6 +263,9 @@ export class DrawingItem implements IDrawingItem {
|
|||||||
this.description = description
|
this.description = description
|
||||||
this.drawingWeight = drawingWeight
|
this.drawingWeight = drawingWeight
|
||||||
}
|
}
|
||||||
|
get identifyName(): string {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
imageUrl: string
|
imageUrl: string
|
||||||
name: string
|
name: string
|
||||||
description: string
|
description: string
|
||||||
@ -249,6 +281,9 @@ export class TreasureItem extends DrawingItem {
|
|||||||
}
|
}
|
||||||
type: TreasureType;
|
type: TreasureType;
|
||||||
itemAmount: number;
|
itemAmount: number;
|
||||||
|
get identifyName(): string {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
export class MobInfo implements IDrawingItem {
|
export class MobInfo implements IDrawingItem {
|
||||||
constructor(
|
constructor(
|
||||||
@ -270,13 +305,15 @@ export class MobInfo implements IDrawingItem {
|
|||||||
level: number;
|
level: number;
|
||||||
rewardTokens: number;
|
rewardTokens: number;
|
||||||
hp: number;
|
hp: number;
|
||||||
|
hpPerHero: number;
|
||||||
mobAmount: number;
|
mobAmount: number;
|
||||||
carriedTreasure: TreasureItem[];
|
carriedTreasure: TreasureItem[];
|
||||||
fixedCarriedTreasure: TreasureItem[];
|
fixedCarriedTreasure: TreasureItem[];
|
||||||
unitRemainHp: number;
|
unitRemainHp: number;
|
||||||
attackInfos: AttackInfo[];
|
attackInfos: AttackInfo[];
|
||||||
defenseInfo: DefenseInfo;
|
defenseInfo: DefenseInfo;
|
||||||
|
actions: number = 0;
|
||||||
|
activateDescription: string;
|
||||||
combatSkill: MobSkill
|
combatSkill: MobSkill
|
||||||
|
|
||||||
fireToken: number = 0;
|
fireToken: number = 0;
|
||||||
@ -288,6 +325,9 @@ export class MobInfo implements IDrawingItem {
|
|||||||
uiCorruptionTokens: number;
|
uiCorruptionTokens: number;
|
||||||
uiAttackedBy: string;
|
uiAttackedBy: string;
|
||||||
|
|
||||||
|
get identifyName(): string {
|
||||||
|
return `${this.name}_${this.level}`;
|
||||||
|
}
|
||||||
public get carriedTreasureHtml(): string {
|
public get carriedTreasureHtml(): string {
|
||||||
if (!this.carriedTreasure) return '';
|
if (!this.carriedTreasure) return '';
|
||||||
return this.carriedTreasure.map(i => `<img src="${i.imageUrl}" class='mr-1' width="40px">`)
|
return this.carriedTreasure.map(i => `<img src="${i.imageUrl}" class='mr-1' width="40px">`)
|
||||||
@ -327,7 +367,8 @@ export class MobInfo implements IDrawingItem {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public actionSubject: Subject<string>;
|
||||||
|
public activateFunction?: (mob: MobInfo, msgBoxService: MsgBoxService, heros: MD2HeroInfo[]) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MD2HeroInfo {
|
export class MD2HeroInfo {
|
||||||
@ -354,10 +395,12 @@ export class MD2HeroInfo {
|
|||||||
shadowSkillHtml: string;
|
shadowSkillHtml: string;
|
||||||
remainActions: number = 3;
|
remainActions: number = 3;
|
||||||
rage: number = 0;
|
rage: number = 0;
|
||||||
|
uiActivating = false;
|
||||||
|
uiShowCorruptionToken = false;
|
||||||
|
uiBossFight = 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})`
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -403,6 +446,9 @@ export class MD2EnemyPhaseSpecialRule implements IDrawingItem {
|
|||||||
this.title = title
|
this.title = title
|
||||||
this.description = description
|
this.description = description
|
||||||
}
|
}
|
||||||
|
get identifyName(): string {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
imageUrl: string;
|
imageUrl: string;
|
||||||
name: string;
|
name: string;
|
||||||
drawingWeight: number;
|
drawingWeight: number;
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
<span class="MD2Icon {{icon}} {{iconClass}} {{sizeClass}}"></span>
|
<span class="MD2Icon {{iconName}} {{iconClass}} {{sizeClass}}"></span>
|
||||||
@ -10,10 +10,26 @@ export class MD2IconComponent implements OnInit {
|
|||||||
|
|
||||||
@Input() iconClass: string = 'mr-1';
|
@Input() iconClass: string = 'mr-1';
|
||||||
|
|
||||||
@Input("icon") icon: string;
|
|
||||||
|
|
||||||
|
private _icon: string | MD2Icon;
|
||||||
|
|
||||||
|
@Input() public set icon(v: string | MD2Icon) {
|
||||||
|
if (this._icon != v) {
|
||||||
|
this._icon = v;
|
||||||
|
|
||||||
|
}
|
||||||
|
if (this.isMD2Icon(v)) {
|
||||||
|
this.iconName = MD2Icon[v].toLowerCase();
|
||||||
|
} else {
|
||||||
|
this.iconName = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isMD2Icon(icon: MD2Icon | string): icon is MD2Icon {
|
||||||
|
return Number.isInteger(icon);
|
||||||
|
}
|
||||||
@Input() size: string = 'sm';
|
@Input() size: string = 'sm';
|
||||||
|
iconName: string;
|
||||||
constructor() { }
|
constructor() { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
|||||||
@ -1,28 +1,30 @@
|
|||||||
<label class='label'>Weapon Info</label>
|
<!-- <label class='label'>Weapon Info</label> -->
|
||||||
<div class="g-brd-3 g-brd-bottom--dashed g-brd-gray-light-v2 mb-3 mt-2 row" *ngFor="let info of mob.attackInfos">
|
<ng-container *ngIf="display">
|
||||||
<div class="col-md-4">
|
<div class="g-brd-3 g-brd-bottom--dashed g-brd-gray-light-v2 mb-3 mt-4 row" *ngFor="let info of mob.attackInfos">
|
||||||
<md2-icon icon="attack" size="lg"></md2-icon>
|
<div class="col-md-4">
|
||||||
</div>
|
<md2-icon [icon]="info.type" size="lg"></md2-icon>
|
||||||
<div class="col-md-8">
|
|
||||||
<div *ngIf="info.yellow" class="g-height-45">
|
|
||||||
<span class="MD2Icon Yellow dice g-font-size-50">
|
|
||||||
<span class="MD2text diceAmount">x{{info.yellow}}</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="info.orange" class="g-height-45 mt-1">
|
<div class="col-md-8">
|
||||||
<span class="MD2Icon Orange dice g-font-size-50">
|
<div *ngIf="info.yellow" class="g-height-45">
|
||||||
<span class="MD2text diceAmount">x{{info.orange}}</span>
|
<span class="MD2Icon Yellow dice g-font-size-50">
|
||||||
</span>
|
<span class="MD2text diceAmount">x{{info.yellow}}</span>
|
||||||
</div>
|
</span>
|
||||||
<div *ngIf="info.red" class="g-height-45 mt-1">
|
</div>
|
||||||
<span class="MD2Icon Red dice g-font-size-50">
|
<div *ngIf="info.orange" class="g-height-45 mt-1">
|
||||||
<span class="MD2text diceAmount">x{{info.red}}</span>
|
<span class="MD2Icon Orange dice g-font-size-50">
|
||||||
</span>
|
<span class="MD2text diceAmount">x{{info.orange}}</span>
|
||||||
</div>
|
</span>
|
||||||
<div *ngIf="mob.defenseInfo.black" class="g-height-45 mt-1">
|
</div>
|
||||||
<span class="MD2Icon Black dice g-font-size-50">
|
<div *ngIf="info.red" class="g-height-45 mt-1">
|
||||||
<span class="MD2text diceAmount">x{{mob.defenseInfo.black}}</span>
|
<span class="MD2Icon Red dice g-font-size-50">
|
||||||
</span>
|
<span class="MD2text diceAmount">x{{info.red}}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="mob.defenseInfo.black" class="g-height-45 mt-1">
|
||||||
|
<span class="MD2Icon Black dice g-font-size-50">
|
||||||
|
<span class="MD2text diceAmount">x{{mob.defenseInfo.black}}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ng-container>
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import { MD2Icon, MobDlgType, MobInfo } from '../../../massive-darkness2.model';
|
import { MD2Icon, MobDlgType, MobInfo, MobType } from '../../../massive-darkness2.model';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'md2-mob-attack-info',
|
selector: 'md2-mob-attack-info',
|
||||||
@ -22,9 +22,23 @@ export class MobAttackInfoComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
@Input() mode: MobDlgType = MobDlgType.PreView;
|
@Input() mode: MobDlgType = MobDlgType.PreView;
|
||||||
|
|
||||||
constructor() { }
|
display: boolean = false;
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
switch (this.mode) {
|
||||||
|
case MobDlgType.Spawn:
|
||||||
|
this.display = this.mob.type != MobType.Mob;
|
||||||
|
break;
|
||||||
|
case MobDlgType.Activating:
|
||||||
|
case MobDlgType.PreView:
|
||||||
|
case MobDlgType.Dashboard:
|
||||||
|
this.display = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.display = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,24 @@
|
|||||||
<div class='form-group row' *ngIf="showSkill">
|
<!-- <div class='form-group row' *ngIf="showSkill">
|
||||||
<label class='label col-sm-3 form-control-label MD2text g-font-size-30'
|
<label class='label col-sm-3 form-control-label MD2text g-font-size-30'>
|
||||||
[innerHtml]="mob.combatSkill.skillName"></label>
|
{{mob.combatSkill.skillRoll}} <md2-icon icon="enemySkill" size="md"></md2-icon>
|
||||||
<div class='col-sm' [innerHtml]="mob.combatSkill.skillDescription"></div>
|
</label>
|
||||||
|
<div class='col-sm' [innerHtml]="mob.combatSkill.description"></div>
|
||||||
|
</div> -->
|
||||||
|
<div *ngIf="showBlackDice" class="row">
|
||||||
|
<!-- <md2-icon></md2-icon> -->
|
||||||
|
<div class="col-md-4">
|
||||||
|
<md2-icon icon="enemySkill" size="lg"></md2-icon>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<span class="MD2Icon Black dice g-font-size-50">
|
||||||
|
<span class="MD2text blackDiceAmount">x{{mob.minionAmount}}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class='form-group' *ngIf="showSkill">
|
||||||
|
<label for='' class='MD2text g-font-size-22 label mb-2'>
|
||||||
|
<md2-icon icon="blackDice" size="lg"></md2-icon> {{skillTriggerHtml}} <md2-icon icon="enemySkill" size="md">
|
||||||
|
</md2-icon>
|
||||||
|
</label>
|
||||||
|
<div class='g-font-size-20 skillDesc MD2text' [innerHtml]="mob.combatSkill.description"></div>
|
||||||
</div>
|
</div>
|
||||||
@ -17,3 +17,12 @@
|
|||||||
left: 26px;
|
left: 26px;
|
||||||
font-size: 30px;
|
font-size: 30px;
|
||||||
}
|
}
|
||||||
|
.skillDesc {
|
||||||
|
padding-left: 8px;
|
||||||
|
.MD2Icon {
|
||||||
|
font-size: 45px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.skillDesc .MD2Icon {
|
||||||
|
font-size: 45px;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import { MD2Icon, MobDlgType, MobInfo } from '../../../massive-darkness2.model';
|
import { MD2Icon, MobDlgType, MobInfo, MobType } from '../../../massive-darkness2.model';
|
||||||
import { MobSkillType } from '../../../massive-darkness2.model.boss';
|
import { MobSkillType } from '../../../massive-darkness2.model.boss';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -22,6 +22,9 @@ export class MobCombatInfoComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Input() mode: MobDlgType = MobDlgType.PreView;
|
@Input() mode: MobDlgType = MobDlgType.PreView;
|
||||||
|
showSkill: boolean = false;
|
||||||
|
showBlackDice: boolean
|
||||||
|
skillTriggerHtml: string = '';
|
||||||
constructor() { }
|
constructor() { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
@ -34,14 +37,17 @@ export class MobCombatInfoComponent implements OnInit {
|
|||||||
this.showSkill = [MobSkillType.Combat, MobSkillType.Defense].includes(this.mob.combatSkill.type);
|
this.showSkill = [MobSkillType.Combat, MobSkillType.Defense].includes(this.mob.combatSkill.type);
|
||||||
break;
|
break;
|
||||||
case MobDlgType.PreView:
|
case MobDlgType.PreView:
|
||||||
case MobDlgType.Spawn:
|
|
||||||
default:
|
|
||||||
this.showSkill = true;
|
this.showSkill = true;
|
||||||
break;
|
break;
|
||||||
|
case MobDlgType.Spawn:
|
||||||
|
default:
|
||||||
|
this.showSkill = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
this.skillTriggerHtml = `${MobSkillType[this.mob.combatSkill.type]} ${this.mob.combatSkill.skillRoll} `
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.showBlackDice = this.mob.type == MobType.Mob && (this.mode == MobDlgType.Activating || this.mode == MobDlgType.BeenAttacked) && this.mob.minionAmount > 0;;
|
||||||
}
|
}
|
||||||
showSkill: boolean = false;;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +1,20 @@
|
|||||||
<label class='label'>Defense Info</label>
|
<!-- <label class='label'>Defense Info</label> -->
|
||||||
<div class="g-brd-3 g-brd-bottom--dashed g-brd-gray-light-v2 mb-3 mt-2 row">
|
<ng-container *ngIf="display">
|
||||||
<div class="col-md-4">
|
<div class="g-brd-3 g-brd-bottom--dashed g-brd-gray-light-v2 mb-3 mt-2 row">
|
||||||
<md2-icon icon="defense" size="lg"></md2-icon>
|
<div class="col-md-4">
|
||||||
</div>
|
<md2-icon icon="defense" size="lg"></md2-icon>
|
||||||
<div class="col-md-8">
|
|
||||||
<div *ngIf="mob.defenseInfo.blue" class="g-height-45">
|
|
||||||
<span class="MD2Icon Blue dice g-font-size-50">
|
|
||||||
<span class="MD2text diceAmount">x{{mob.defenseInfo.blue}}</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="mob.defenseInfo.black" class="g-height-45 mt-1">
|
<div class="col-md-8">
|
||||||
<span class="MD2Icon Black dice g-font-size-50">
|
<div *ngIf="mob.defenseInfo.blue" class="g-height-45">
|
||||||
<span class="MD2text diceAmount">x{{mob.defenseInfo.black}}</span>
|
<span class="MD2Icon Blue dice g-font-size-50">
|
||||||
</span>
|
<span class="MD2text diceAmount">x{{mob.defenseInfo.blue}}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="mob.defenseInfo.black" class="g-height-45 mt-1">
|
||||||
|
<span class="MD2Icon Black dice g-font-size-50">
|
||||||
|
<span class="MD2text diceAmount">x{{mob.defenseInfo.black}}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ng-container>
|
||||||
@ -1,5 +1,6 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import { MD2Icon, MobInfo, MobDlgType } from '../../../massive-darkness2.model';
|
import { MD2Icon, MobInfo, MobDlgType } from '../../../massive-darkness2.model';
|
||||||
|
import { MobSkillType } from '../../../massive-darkness2.model.boss';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'md2-mob-def-info',
|
selector: 'md2-mob-def-info',
|
||||||
@ -21,8 +22,22 @@ export class MobDefInfoComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Input() mode: MobDlgType = MobDlgType.PreView;
|
@Input() mode: MobDlgType = MobDlgType.PreView;
|
||||||
|
|
||||||
|
display: boolean = false;
|
||||||
|
|
||||||
constructor() { }
|
constructor() { }
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
switch (this.mode) {
|
||||||
|
case MobDlgType.BeenAttacked:
|
||||||
|
case MobDlgType.PreView:
|
||||||
|
case MobDlgType.Spawn:
|
||||||
|
case MobDlgType.Dashboard:
|
||||||
|
this.display = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.display = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,27 +1,53 @@
|
|||||||
<label class='label'>Level <b class="MD2text g-font-size-18">{{mob.level}}</b></label><br>
|
<div class="row no-gutters">
|
||||||
|
<div class="col-md-6">
|
||||||
|
|
||||||
<ng-container *ngIf="mob.mobAmount">
|
<label class='label g-text-nowrap'>Level <b class="MD2text g-font-size-18">{{mob.level}}</b></label><br>
|
||||||
<label class='label'>Alive Units <b class="MD2text g-font-size-18">{{mob.mobAmount}}</b></label><br>
|
|
||||||
|
<label class='label g-text-nowrap'>Total HP <b class="MD2text g-font-size-18">{{mob.totalHp}}</b></label>
|
||||||
|
</div>
|
||||||
|
<div class="pl-2 col-md-6" *ngIf="mob.mobAmount">
|
||||||
|
|
||||||
|
<ng-container>
|
||||||
|
<label class='label g-text-nowrap'>Alive Units <b
|
||||||
|
class="MD2text g-font-size-18">{{mob.mobAmount}}</b></label><br>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6" *ngIf="showTokenAdjustment||mob.fireToken>0">
|
||||||
|
|
||||||
|
<adj-number-input name="mobFire" [(ngModel)]="mob.fireToken" minimum="0"
|
||||||
|
title="{{iconHtml(MD2Icon.Fire,'g-color-google-plus mr-1 g-font-size-18')}}Fire Token">
|
||||||
|
</adj-number-input>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6" *ngIf="showTokenAdjustment||mob.frozenToken>0">
|
||||||
|
|
||||||
|
<adj-number-input name="mobFrost" [(ngModel)]="mob.frozenToken" minimum="0"
|
||||||
|
title="{{iconHtml(MD2Icon.Frost,'g-color-aqua mr-1 g-font-size-18')}}Frozen Token">
|
||||||
|
</adj-number-input>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<ng-container *ngIf="showAdjustment">
|
||||||
|
|
||||||
|
<adj-number-input name="mob{{mob.name}}" [ngModel]="mob.unitRemainHp" [maximum]="mob.hp" minimum="1"
|
||||||
|
title="Target Unit HP" (hitChange)="adjustMobHp($event)" (hitMinimum)="adjustMobHp(-1)"
|
||||||
|
(hitMaximum)="adjustMobHp(1)">
|
||||||
|
</adj-number-input>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<label class='label'>Total HP <b class="MD2text g-font-size-18">{{mob.totalHp}}</b></label><br>
|
|
||||||
|
|
||||||
<ng-container *ngIf="mob.carriedTreasureHtml">
|
<ng-container *ngIf="mob.carriedTreasureHtml">
|
||||||
<label class='label'>Carried Treasure</label><br>
|
<label class='label'>Carried Treasure</label><br>
|
||||||
<div [innerHtml]="mob.carriedTreasureHtml"></div>
|
<div [innerHtml]="mob.carriedTreasureHtml"></div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<md2-mob-attack-info [mob]="mob" [mode]="mode" *ngIf="mob.attackInfos&&mob.attackInfos.length>0&& !hideWeaponInfo">
|
<div class="g-height-20 mb-1"></div>
|
||||||
|
<md2-mob-attack-info [mob]="mob" [mode]="mode">
|
||||||
</md2-mob-attack-info>
|
</md2-mob-attack-info>
|
||||||
<md2-mob-def-info [mob]="mob" [mode]="mode" *ngIf="mob.defenseInfo&& !hideWeaponInfo"></md2-mob-def-info>
|
<md2-mob-def-info [mob]="mob" [mode]="mode"></md2-mob-def-info>
|
||||||
<md2-mob-combat-info [mob]="mob" [mode]="mode"></md2-mob-combat-info>
|
<md2-mob-combat-info [mob]="mob" [mode]="mode"></md2-mob-combat-info>
|
||||||
<div *ngIf="showBlackDice" class="row">
|
|
||||||
<!-- <md2-icon></md2-icon> -->
|
|
||||||
<div class="col-md-4">
|
|
||||||
<md2-icon icon="enemySkill" size="lg"></md2-icon>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-8">
|
|
||||||
<span class="MD2Icon Black dice g-font-size-50">
|
|
||||||
<span class="MD2text blackDiceAmount">x{{mob.minionAmount}}</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
import { ChangeDetectorRef, Component, Input, OnInit } from '@angular/core';
|
import { ChangeDetectorRef, Component, Input, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { MD2MobService } from '../../../../services/MD2/md2-mob.service';
|
||||||
import { MD2Service } from '../../../../services/MD2/md2.service';
|
import { MD2Service } from '../../../../services/MD2/md2.service';
|
||||||
import { StateService } from '../../../../services/state.service';
|
import { StateService } from '../../../../services/state.service';
|
||||||
import { MD2Icon, MobDlgType, MobInfo } from '../../massive-darkness2.model';
|
import { MD2Icon, MobDlgType, MobInfo } from '../../massive-darkness2.model';
|
||||||
@ -39,11 +40,9 @@ export class MobDetailInfoComponent extends MD2ComponentBase implements OnInit {
|
|||||||
this.showAttackingInfo = typeof value !== "undefined" && value !== false;
|
this.showAttackingInfo = typeof value !== "undefined" && value !== false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get showBlackDice(): boolean {
|
|
||||||
return (this.mode == MobDlgType.Activating || this.mode == MobDlgType.BeenAttacked) && this.mob.minionAmount > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
private mobService: MD2MobService,
|
||||||
public md2Service: MD2Service,
|
public md2Service: MD2Service,
|
||||||
protected stateService: StateService,
|
protected stateService: StateService,
|
||||||
protected route: ActivatedRoute,
|
protected route: ActivatedRoute,
|
||||||
@ -64,4 +63,21 @@ export class MobDetailInfoComponent extends MD2ComponentBase implements OnInit {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get showAdjustment(): boolean {
|
||||||
|
return [MobDlgType.Activating, MobDlgType.BeenAttacked, MobDlgType.Dashboard].includes(this.mode);
|
||||||
|
}
|
||||||
|
public get showTokenAdjustment(): boolean {
|
||||||
|
return [MobDlgType.Activating, MobDlgType.BeenAttacked].includes(this.mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
adjustMobHp(adjustAmount: number) {
|
||||||
|
if (adjustAmount < 0) {
|
||||||
|
this.mobService.attackMob(this.mob, 1);
|
||||||
|
} else {
|
||||||
|
this.mobService.healMob(this.mob, 1);
|
||||||
|
}
|
||||||
|
this.md2Service.refreshUI$.next();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
<img class="g-width-95x img-thumbnail mobBg" src="{{imgUrl('/Mobs/BG.png')}}" />
|
||||||
|
<img class="mobImg roamingMonster" src="{{getMobImageUrl(mob)}}" (click)="showMobImage(mob)" *ngIf="!isMob" />
|
||||||
|
<div *ngIf="isMob">
|
||||||
|
<img class="mobImg mobLeader" src="{{mob.leaderImgUrl}}" (click)="showMobImage(mob)" />
|
||||||
|
<img class="mobImg mobMinion" src="{{mob.minionImgUrl}}" (click)="showMobImage(mob)" />
|
||||||
|
|
||||||
|
</div>
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
.mobImg {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
|
&.roamingMonster {
|
||||||
|
width: 95%;
|
||||||
|
max-height: 80%;
|
||||||
|
}
|
||||||
|
&.mobLeader {
|
||||||
|
z-index: 3;
|
||||||
|
width: 70%;
|
||||||
|
max-height: 80%;
|
||||||
|
top: 40px;
|
||||||
|
}
|
||||||
|
&.mobMinion {
|
||||||
|
width: 60%;
|
||||||
|
max-height: 80%;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.mobBg {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { MobStandInfoComponent } from './mob-stand-info.component';
|
||||||
|
|
||||||
|
describe('MobStandInfoComponent', () => {
|
||||||
|
let component: MobStandInfoComponent;
|
||||||
|
let fixture: ComponentFixture<MobStandInfoComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ MobStandInfoComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(MobStandInfoComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,69 @@
|
|||||||
|
import { ChangeDetectorRef, Component, Input, OnInit } from '@angular/core';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { first } from 'rxjs/operators';
|
||||||
|
import { MD2Service } from '../../../../services/MD2/md2.service';
|
||||||
|
import { StateService } from '../../../../services/state.service';
|
||||||
|
import { StringUtils } from '../../../../utilities/string-utils';
|
||||||
|
import { MD2Icon, MobInfo, MobDlgType, MobType } from '../../massive-darkness2.model';
|
||||||
|
import { MD2ComponentBase } from '../../MD2Base';
|
||||||
|
import { SpawnMobDlgComponent } from '../spawn-mob-dlg/spawn-mob-dlg.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'md2-mob-stand-info',
|
||||||
|
templateUrl: './mob-stand-info.component.html',
|
||||||
|
styleUrls: ['./mob-stand-info.component.scss']
|
||||||
|
})
|
||||||
|
export class MobStandInfoComponent extends MD2ComponentBase implements OnInit {
|
||||||
|
|
||||||
|
MD2Icon = MD2Icon;
|
||||||
|
private _mob: MobInfo;
|
||||||
|
public get mob(): MobInfo {
|
||||||
|
return this._mob;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Input() public set mob(v: MobInfo) {
|
||||||
|
if (this._mob != v) {
|
||||||
|
this._mob = v;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Input() mode: MobDlgType = MobDlgType.PreView;
|
||||||
|
public get hideWeaponInfo(): boolean {
|
||||||
|
return this.mode == MobDlgType.Spawn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public md2Service: MD2Service,
|
||||||
|
protected stateService: StateService,
|
||||||
|
protected route: ActivatedRoute,
|
||||||
|
protected cdRef: ChangeDetectorRef,
|
||||||
|
) {
|
||||||
|
super(md2Service, stateService, route, cdRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMobImageUrl(mob: MobInfo): string {
|
||||||
|
if (StringUtils.isNullOrWhitespace(mob.leaderImgUrl)) {
|
||||||
|
return mob.imageUrl;
|
||||||
|
} else {
|
||||||
|
return mob.leaderImgUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
showMobImage(mob: MobInfo) {
|
||||||
|
this.md2Service.dlgService.open(SpawnMobDlgComponent, { context: { title: `${mob.description}`, mode: MobDlgType.PreView, mob: mob } })
|
||||||
|
.onClose.pipe(first()).subscribe(result => {
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public get isMob(): boolean {
|
||||||
|
return this.mob.type == MobType.Mob;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -28,21 +28,16 @@
|
|||||||
<div class="col col-sm-6 col-md-6 col-lg-4 mb-4" *ngFor="let mob of this.mobs">
|
<div class="col col-sm-6 col-md-6 col-lg-4 mb-4" *ngFor="let mob of this.mobs">
|
||||||
<div class="row no-gutters">
|
<div class="row no-gutters">
|
||||||
<div class="col-12 col-md-8">
|
<div class="col-12 col-md-8">
|
||||||
|
<md2-mob-stand-info [mob]="mob"></md2-mob-stand-info>
|
||||||
<img class="mobImg g-width-95x" src="{{mob.imageUrl}}" (click)="showMobImage(mob)" />
|
|
||||||
</div>
|
</div>
|
||||||
<div class=" col-12 col-md-4">
|
<div class=" col-12 col-md-4">
|
||||||
|
|
||||||
|
|
||||||
<md2-mob-detail-info name="mobDetail{{mob.name}}" [mob]="mob" [mode]="MobDlgType.PreView">
|
<md2-mob-detail-info name="mobDetail{{mob.name}}" [mob]="mob" [mode]="MobDlgType.Dashboard">
|
||||||
</md2-mob-detail-info>
|
</md2-mob-detail-info>
|
||||||
|
|
||||||
<adj-number-input name="mob{{mob.name}}" [(ngModel)]="mob.unitRemainHp"
|
|
||||||
[maximum]="isRoamingMonster?null: mob.hp" minimum="1" title="Target Unit HP"
|
|
||||||
(hitMinimum)="killOneUnit(mob)" (hitMaximum)="addOneUnit(mob)">
|
|
||||||
</adj-number-input>
|
|
||||||
<button nbButton hero status="danger" size="small" (click)="attackMob(mob)"
|
<button nbButton hero status="danger" size="small" (click)="attackMob(mob)"
|
||||||
*ngIf="md2Service.showAttackBtn">Attack It</button>
|
*ngIf="md2Service.info.showAttackBtn">Attack It</button>
|
||||||
<!-- <div class='form-group'>
|
<!-- <div class='form-group'>
|
||||||
<label for='playerAmount' class='label'>Current Unit HP</label>
|
<label for='playerAmount' class='label'>Current Unit HP</label>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@ -18,83 +18,6 @@ $mob-card-height: 556px;
|
|||||||
/* right: auto; */
|
/* right: auto; */
|
||||||
z-index: 99;
|
z-index: 99;
|
||||||
}
|
}
|
||||||
.mobImg {
|
|
||||||
object-fit: cover;
|
|
||||||
&.Gargoyles-lv1-2 {
|
|
||||||
object-position: 0 0;
|
|
||||||
}
|
|
||||||
&.Demons-lv1-2 {
|
|
||||||
object-position: calc(#{$mob-card-width} * -1) 0;
|
|
||||||
}
|
|
||||||
&.Undead-lv1-2 {
|
|
||||||
object-position: calc(#{$mob-card-width} * -2) 0;
|
|
||||||
}
|
|
||||||
&.FireEntities-lv1-2 {
|
|
||||||
object-position: calc(#{$mob-card-width} * -3) 0;
|
|
||||||
}
|
|
||||||
&.FallenAngels-lv1-2 {
|
|
||||||
object-position: calc(#{$mob-card-width} * -4) 0;
|
|
||||||
}
|
|
||||||
&.InfernalImps-lv1-2 {
|
|
||||||
object-position: calc(#{$mob-card-width} * -5) 0;
|
|
||||||
}
|
|
||||||
&.Skeletons-lv1-2 {
|
|
||||||
object-position: calc(#{$mob-card-width} * -6) 0;
|
|
||||||
}
|
|
||||||
&.Satyrs-lv1-2 {
|
|
||||||
object-position: calc(#{$mob-card-width} * -7) 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.Gargoyles-lv3-4 {
|
|
||||||
object-position: 0 calc(#{$mob-card-height} * -1);
|
|
||||||
}
|
|
||||||
&.FireEntities-lv3-4 {
|
|
||||||
object-position: calc(#{$mob-card-width} * -1) calc(#{$mob-card-height} * -1);
|
|
||||||
}
|
|
||||||
&.Skeletons-lv3-4 {
|
|
||||||
object-position: calc(#{$mob-card-width} * -2) calc(#{$mob-card-height} * -1);
|
|
||||||
}
|
|
||||||
&.InfernalImps-lv3-4 {
|
|
||||||
object-position: calc(#{$mob-card-width} * -3) calc(#{$mob-card-height} * -1);
|
|
||||||
}
|
|
||||||
&.Undead-lv3-4 {
|
|
||||||
object-position: calc(#{$mob-card-width} * -4) calc(#{$mob-card-height} * -1);
|
|
||||||
}
|
|
||||||
&.Demons-lv3-4 {
|
|
||||||
object-position: calc(#{$mob-card-width} * -5) calc(#{$mob-card-height} * -1);
|
|
||||||
}
|
|
||||||
&.Satyrs-lv3-4 {
|
|
||||||
object-position: calc(#{$mob-card-width} * -6) calc(#{$mob-card-height} * -1);
|
|
||||||
}
|
|
||||||
&.FallenAngels-lv3-4 {
|
|
||||||
object-position: calc(#{$mob-card-width} * -7) calc(#{$mob-card-height} * -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.Satyrs-lv5 {
|
|
||||||
object-position: 0 calc(#{$mob-card-height} * -2);
|
|
||||||
}
|
|
||||||
&.FallenAngels-lv5 {
|
|
||||||
object-position: calc(#{$mob-card-width} * -1) calc(#{$mob-card-height} * -2);
|
|
||||||
}
|
|
||||||
&.Gargoyles-lv5 {
|
|
||||||
object-position: calc(#{$mob-card-width} * -2) calc(#{$mob-card-height} * -2);
|
|
||||||
}
|
|
||||||
&.FireEntities-lv5 {
|
|
||||||
object-position: calc(#{$mob-card-width} * -3) calc(#{$mob-card-height} * -2);
|
|
||||||
}
|
|
||||||
&.InfernalImps-lv5 {
|
|
||||||
object-position: calc(#{$mob-card-width} * -4) calc(#{$mob-card-height} * -2);
|
|
||||||
}
|
|
||||||
&.Undead-lv5 {
|
|
||||||
object-position: calc(#{$mob-card-width} * -5) calc(#{$mob-card-height} * -2);
|
|
||||||
}
|
|
||||||
&.Skeletons-lv5 {
|
|
||||||
object-position: calc(#{$mob-card-width} * -6) calc(#{$mob-card-height} * -2);
|
|
||||||
}
|
|
||||||
&.Demons-lv5 {
|
|
||||||
object-position: calc(#{$mob-card-width} * -7) calc(#{$mob-card-height} * -2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#clip {
|
#clip {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
@ -1,13 +1,16 @@
|
|||||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit } from '@angular/core';
|
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { NbDialogService } from '@nebular/theme';
|
import { NbDialogService } from '@nebular/theme';
|
||||||
|
import { stringify } from 'querystring';
|
||||||
import { first } from 'rxjs/operators';
|
import { first } from 'rxjs/operators';
|
||||||
import { FileService } from '../../../services/file.service';
|
import { FileService } from '../../../services/file.service';
|
||||||
|
import { MD2MobService } from '../../../services/MD2/md2-mob.service';
|
||||||
import { MD2Service } from '../../../services/MD2/md2.service';
|
import { MD2Service } from '../../../services/MD2/md2.service';
|
||||||
import { MsgBoxService } from '../../../services/msg-box.service';
|
import { MsgBoxService } from '../../../services/msg-box.service';
|
||||||
import { StateService } from '../../../services/state.service';
|
import { StateService } from '../../../services/state.service';
|
||||||
import { ADIcon } from '../../../ui/alert-dlg/alert-dlg.model';
|
import { ADIcon } from '../../../ui/alert-dlg/alert-dlg.model';
|
||||||
import { NumberUtils } from '../../../utilities/number-utils';
|
import { NumberUtils } from '../../../utilities/number-utils';
|
||||||
|
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';
|
||||||
@ -34,6 +37,7 @@ export class MobsComponent extends MD2ComponentBase implements OnInit {
|
|||||||
private fileService: FileService,
|
private fileService: FileService,
|
||||||
private msgBoxService: MsgBoxService,
|
private msgBoxService: MsgBoxService,
|
||||||
private dlgService: NbDialogService,
|
private dlgService: NbDialogService,
|
||||||
|
private mobService: MD2MobService,
|
||||||
public md2Service: MD2Service,
|
public md2Service: MD2Service,
|
||||||
protected stateService: StateService,
|
protected stateService: StateService,
|
||||||
protected route: ActivatedRoute,
|
protected route: ActivatedRoute,
|
||||||
@ -44,6 +48,7 @@ export class MobsComponent extends MD2ComponentBase implements OnInit {
|
|||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.initMobDecks();
|
this.initMobDecks();
|
||||||
|
super.ngOnInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -61,7 +66,6 @@ export class MobsComponent extends MD2ComponentBase implements OnInit {
|
|||||||
|
|
||||||
|
|
||||||
initMobDecks() {
|
initMobDecks() {
|
||||||
this.md2Service.initMobDecks();
|
|
||||||
this.mobs = [];
|
this.mobs = [];
|
||||||
this.cdRef.detectChanges();
|
this.cdRef.detectChanges();
|
||||||
let spawn$ = this.isRoamingMonster ? this.md2Service.darknessPhaseRule.spawnRoamingMonster : this.md2Service.darknessPhaseRule.spawnMob;
|
let spawn$ = this.isRoamingMonster ? this.md2Service.darknessPhaseRule.spawnRoamingMonster : this.md2Service.darknessPhaseRule.spawnMob;
|
||||||
@ -74,8 +78,9 @@ export class MobsComponent extends MD2ComponentBase implements OnInit {
|
|||||||
let result = this.md2Service.spawnMob(this.isRoamingMonster);
|
let result = this.md2Service.spawnMob(this.isRoamingMonster);
|
||||||
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;
|
||||||
|
|
||||||
this.dlgService.open(SpawnMobDlgComponent, { context: { title: titleText, mode: actType, mob: result.mob } })
|
this.dlgService.open(SpawnMobDlgComponent, { context: { title: titleText, mode: actType, mob: mob } })
|
||||||
.onClose.pipe(first()).subscribe(result => {
|
.onClose.pipe(first()).subscribe(result => {
|
||||||
this.afterSpawn();
|
this.afterSpawn();
|
||||||
});
|
});
|
||||||
@ -83,7 +88,7 @@ export class MobsComponent extends MD2ComponentBase implements OnInit {
|
|||||||
}
|
}
|
||||||
afterSpawn() {
|
afterSpawn() {
|
||||||
this.cdRef.detectChanges();
|
this.cdRef.detectChanges();
|
||||||
this.md2Service.broadcastMobsInfo();
|
this.md2Service.broadcastService.broadcastMobsInfo();
|
||||||
if (this.showRoundMessage) {
|
if (this.showRoundMessage) {
|
||||||
this.msgBoxService.show(`${NumberUtils.Ordinal(this.md2Service.info.round)} Hero Phase`, { icon: ADIcon.INFO });
|
this.msgBoxService.show(`${NumberUtils.Ordinal(this.md2Service.info.round)} Hero Phase`, { icon: ADIcon.INFO });
|
||||||
}
|
}
|
||||||
@ -103,14 +108,21 @@ export class MobsComponent extends MD2ComponentBase implements OnInit {
|
|||||||
this.cdRef.detectChanges();
|
this.cdRef.detectChanges();
|
||||||
}
|
}
|
||||||
killOneUnit(mob: MobInfo) {
|
killOneUnit(mob: MobInfo) {
|
||||||
|
let attacker = this.md2Service.currentActivateHero;
|
||||||
if (mob.mobAmount > 1) {
|
if (mob.mobAmount > 1) {
|
||||||
mob.mobAmount--;
|
mob.mobAmount--;
|
||||||
mob.unitRemainHp = mob.hp;
|
mob.unitRemainHp = mob.hp;
|
||||||
if (this.attacking) {
|
if (this.attacking) {
|
||||||
this.attackingAttackerExp += 1;
|
this.attackingAttackerExp += 1;
|
||||||
} else {
|
} else {
|
||||||
this.msgBoxService.show('The Attacker Gain 1 Exp', { icon: ADIcon.INFO }).pipe(first()).subscribe(result => {
|
|
||||||
});
|
if (attacker) {
|
||||||
|
attacker.exp += 1;
|
||||||
|
this.msgBoxService.show(`${attacker.heroFullName} Gain 1 Exp`, { icon: ADIcon.INFO }).pipe(first()).subscribe(result => {
|
||||||
|
this.md2Service.broadcastService.broadcastHeroInfoToOwner(attacker);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -122,7 +134,11 @@ export class MobsComponent extends MD2ComponentBase implements OnInit {
|
|||||||
this.attackingAttackerExp += 1;
|
this.attackingAttackerExp += 1;
|
||||||
this.attackingAttackerReward = `<br> and gains ${mob.carriedTreasureHtml}`;
|
this.attackingAttackerReward = `<br> and gains ${mob.carriedTreasureHtml}`;
|
||||||
} else {
|
} else {
|
||||||
this.msgBoxService.show(`All Hero Gain ${mob.leaderExp} Exp`, { text: `The Attacker Gain 1 Extra Exp.<br> and gains ${mob.carriedTreasureHtml}`, icon: ADIcon.INFO }).pipe(first()).subscribe(result => {
|
let messageText = '';
|
||||||
|
if (attacker) {
|
||||||
|
messageText = `<b>${attacker.heroFullName}</b> Gain 1 Extra Exp.<br> and gains ${mob.carriedTreasureHtml}`;
|
||||||
|
}
|
||||||
|
this.msgBoxService.show(`All Hero Gain ${mob.leaderExp} Exp`, { text: messageText, icon: ADIcon.INFO }).pipe(first()).subscribe(result => {
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -148,49 +164,7 @@ export class MobsComponent extends MD2ComponentBase implements OnInit {
|
|||||||
.onClose.pipe(first()).subscribe(mobResult => {
|
.onClose.pipe(first()).subscribe(mobResult => {
|
||||||
if (mobResult) {
|
if (mobResult) {
|
||||||
let attackDamage = mobResult.uiWounds;
|
let attackDamage = mobResult.uiWounds;
|
||||||
if (attackDamage) {
|
this.mobService.attackMob(mobResult, attackDamage);
|
||||||
do {
|
|
||||||
if (attackDamage >= mob.unitRemainHp) {
|
|
||||||
attackDamage -= mob.unitRemainHp;
|
|
||||||
this.killOneUnit(mob);
|
|
||||||
} else {
|
|
||||||
let originAttackDamage = attackDamage;
|
|
||||||
attackDamage -= mob.unitRemainHp;
|
|
||||||
mob.unitRemainHp -= originAttackDamage;
|
|
||||||
}
|
|
||||||
} while (attackDamage > 0 && mob.mobAmount > 0);
|
|
||||||
|
|
||||||
this.attacking = false;
|
|
||||||
|
|
||||||
let attacker = this.md2Service.info.currentActivateHero;
|
|
||||||
let attackerTitle = 'The Attacker';
|
|
||||||
if (attacker) {
|
|
||||||
attackerTitle = this.md2Service.heroFullName(attacker);
|
|
||||||
}
|
|
||||||
if (this.attackingAllExp > 0) {
|
|
||||||
this.msgBoxService.show(`All Hero Gains ${this.attackingAllExp} Exp`,
|
|
||||||
{ text: `${attackerTitle} Gains ${this.attackingAttackerExp} Extra Exp.<br> and gains ${mob.carriedTreasureHtml}`, icon: ADIcon.INFO })
|
|
||||||
.pipe(first()).subscribe(result => {
|
|
||||||
for (let i = 0; i < this.md2Service.heros.length; i++) {
|
|
||||||
const hero = this.md2Service.heros[i];
|
|
||||||
hero.exp += this.attackingAllExp;
|
|
||||||
}
|
|
||||||
attacker.exp += this.attackingAttackerExp;
|
|
||||||
this.md2Service.broadcastAllHeroInfoToAll();
|
|
||||||
});
|
|
||||||
} else if (this.attackingAttackerExp > 0) {
|
|
||||||
|
|
||||||
this.msgBoxService.show(`${attackerTitle} Gains ${this.attackingAttackerExp} Exp`, { icon: ADIcon.INFO }).pipe(first()).subscribe(result => {
|
|
||||||
attacker.exp += this.attackingAttackerExp;
|
|
||||||
this.md2Service.broadcastAllHeroInfoToAll();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
this.cdRef.detectChanges();
|
|
||||||
}
|
|
||||||
this.cdRef.detectChanges();
|
|
||||||
this.md2Service.broadcastMobsInfo();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
@ -203,6 +177,16 @@ export class MobsComponent extends MD2ComponentBase implements OnInit {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public getMobImageUrl(mob: MobInfo): string {
|
||||||
|
if (StringUtils.isNullOrWhitespace(mob.leaderImgUrl)) {
|
||||||
|
return mob.imageUrl;
|
||||||
|
} else {
|
||||||
|
return mob.leaderImgUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
showMobImage(mob: MobInfo) {
|
showMobImage(mob: MobInfo) {
|
||||||
this.dlgService.open(SpawnMobDlgComponent, { context: { title: `${mob.description}`, mode: MobDlgType.PreView, mob: mob } })
|
this.dlgService.open(SpawnMobDlgComponent, { context: { title: `${mob.description}`, mode: MobDlgType.PreView, mob: mob } })
|
||||||
.onClose.pipe(first()).subscribe(result => {
|
.onClose.pipe(first()).subscribe(result => {
|
||||||
|
|||||||
@ -5,13 +5,21 @@
|
|||||||
</nb-card-header>
|
</nb-card-header>
|
||||||
<nb-card-body>
|
<nb-card-body>
|
||||||
<div class="row no-gutters">
|
<div class="row no-gutters">
|
||||||
<div class="col-md-7">
|
<div class="col-md-7 g-height-90vh">
|
||||||
<img src="{{mob.imageUrl}}" class="g-width-90x">
|
<!-- <img src="{{mob.imageUrl}}" class="g-width-90x"> -->
|
||||||
|
<md2-mob-stand-info [mob]="mob" [mode]="mode"></md2-mob-stand-info>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-5">
|
<div class="col-md-5">
|
||||||
|
|
||||||
<md2-mob-detail-info [mob]="mob" [mode]="mode">
|
<md2-mob-detail-info [mob]="mob" [mode]="mode">
|
||||||
</md2-mob-detail-info>
|
</md2-mob-detail-info>
|
||||||
|
<div *ngIf="actionInfoHtml">
|
||||||
|
|
||||||
|
<div class="alert alert-warning" role="alert" [innerHtml]="actionInfoHtml">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<ng-container *ngIf="mode==MobDlgType.Spawn&&mob.type==MobType.Mob">
|
<ng-container *ngIf="mode==MobDlgType.Spawn&&mob.type==MobType.Mob">
|
||||||
<div class="row form-group mt-2">
|
<div class="row form-group mt-2">
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
@ -71,7 +79,7 @@
|
|||||||
<label for='damages' class='label'>Cause How Many Damages?</label>
|
<label for='damages' class='label'>Cause How Many Damages?</label>
|
||||||
<input type='number' nbInput fullWidth id='damages' name='damages' [(ngModel)]='mob.uiWounds'>
|
<input type='number' nbInput fullWidth id='damages' name='damages' [(ngModel)]='mob.uiWounds'>
|
||||||
</div>
|
</div>
|
||||||
<div class='form-group'>
|
<!-- <div class='form-group'>
|
||||||
<label for='damages' class='label'>Cause How Many <span
|
<label for='damages' class='label'>Cause How Many <span
|
||||||
[innerHtml]="iconHtml(MD2Icon.Fire,'g-color-google-plus mr-1 g-font-size-18')"></span>?</label>
|
[innerHtml]="iconHtml(MD2Icon.Fire,'g-color-google-plus mr-1 g-font-size-18')"></span>?</label>
|
||||||
<input type='number' nbInput fullWidth id='uiFireTokens' name='uiFireTokens'
|
<input type='number' nbInput fullWidth id='uiFireTokens' name='uiFireTokens'
|
||||||
@ -82,7 +90,7 @@
|
|||||||
[innerHtml]="iconHtml(MD2Icon.Frost,'g-color-aqua mr-1 g-font-size-18')"></span>?</label>
|
[innerHtml]="iconHtml(MD2Icon.Frost,'g-color-aqua mr-1 g-font-size-18')"></span>?</label>
|
||||||
<input type='number' nbInput fullWidth id='uiFrozenTokens' name='uiFrozenTokens'
|
<input type='number' nbInput fullWidth id='uiFrozenTokens' name='uiFrozenTokens'
|
||||||
[(ngModel)]='mob.uiFrozenTokens'>
|
[(ngModel)]='mob.uiFrozenTokens'>
|
||||||
</div>
|
</div> -->
|
||||||
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
|
import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { NbDialogRef } from '@nebular/theme';
|
import { NbDialogRef } from '@nebular/theme';
|
||||||
|
import { first } from 'rxjs/operators';
|
||||||
import { FileService } from '../../../../services/file.service';
|
import { FileService } from '../../../../services/file.service';
|
||||||
import { MD2Service } from '../../../../services/MD2/md2.service';
|
import { MD2Service } from '../../../../services/MD2/md2.service';
|
||||||
import { MsgBoxService } from '../../../../services/msg-box.service';
|
import { MsgBoxService } from '../../../../services/msg-box.service';
|
||||||
@ -23,7 +24,7 @@ export class SpawnMobDlgComponent extends MD2ComponentBase implements OnInit {
|
|||||||
titleHtml: string;
|
titleHtml: string;
|
||||||
MD2Icon = MD2Icon;
|
MD2Icon = MD2Icon;
|
||||||
mob: MobInfo;
|
mob: MobInfo;
|
||||||
|
actionInfoHtml: string;
|
||||||
beenAttackedHero = [] as MD2HeroInfo[];
|
beenAttackedHero = [] as MD2HeroInfo[];
|
||||||
attackTarget: string;
|
attackTarget: string;
|
||||||
otherAttackTarget: string;
|
otherAttackTarget: string;
|
||||||
@ -41,6 +42,13 @@ export class SpawnMobDlgComponent extends MD2ComponentBase implements OnInit {
|
|||||||
//this.mob = new MobInfo(this.mob);
|
//this.mob = new MobInfo(this.mob);
|
||||||
if (this.mode == MobDlgType.Spawn && this.mob.type == MobType.Mob) {
|
if (this.mode == MobDlgType.Spawn && this.mob.type == MobType.Mob) {
|
||||||
this.mob.attackInfos = [new AttackInfo(MD2Icon.Melee), new AttackInfo(MD2Icon.Range), new AttackInfo(MD2Icon.Magic)];
|
this.mob.attackInfos = [new AttackInfo(MD2Icon.Melee), new AttackInfo(MD2Icon.Range), new AttackInfo(MD2Icon.Magic)];
|
||||||
|
} else if (this.mode == MobDlgType.Activating) {
|
||||||
|
if (this.mob.actionSubject) {
|
||||||
|
this.mob.actionSubject.pipe(first()).subscribe(result => {
|
||||||
|
this.actionInfoHtml = result;
|
||||||
|
});
|
||||||
|
this.mob.activateFunction(this.mob, this.md2Service.msgBoxService, this.md2Service.info.heros);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.mob.uiWounds = 0;
|
this.mob.uiWounds = 0;
|
||||||
this.mob.uiFrozenTokens = 0;
|
this.mob.uiFrozenTokens = 0;
|
||||||
@ -52,22 +60,20 @@ export class SpawnMobDlgComponent extends MD2ComponentBase implements OnInit {
|
|||||||
|
|
||||||
this.mob.attackInfos = this.mob.attackInfos.filter(a => a.yellow > 0 || a.orange > 0 || a.red > 0);
|
this.mob.attackInfos = this.mob.attackInfos.filter(a => a.yellow > 0 || a.orange > 0 || a.red > 0);
|
||||||
}
|
}
|
||||||
// switch (this.mode) {
|
switch (this.mode) {
|
||||||
// case MobDlgType.Spawn:
|
case MobDlgType.Spawn:
|
||||||
// return 'warning';
|
this.mob.attackInfos = this.mob.attackInfos.filter(a => a.yellow > 0 || a.orange > 0 || a.red > 0);
|
||||||
// break;
|
break;
|
||||||
// case MobDlgType.Activating:
|
case MobDlgType.Activating:
|
||||||
// return 'danger';
|
break;
|
||||||
// break;
|
case MobDlgType.BeenAttacked:
|
||||||
// case MobDlgType.BeenAttacked:
|
break;
|
||||||
// return 'info';
|
case MobDlgType.PreView:
|
||||||
// break;
|
default:
|
||||||
// case MobDlgType.PreView:
|
break;
|
||||||
// default:
|
}
|
||||||
// return '';
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
this.md2Service.info.showAttackBtn = false;
|
this.md2Service.info.showAttackBtn = false;
|
||||||
|
this.md2Service.refreshUI$.next();
|
||||||
this.dlgRef.close(this.mob);
|
this.dlgRef.close(this.mob);
|
||||||
}
|
}
|
||||||
cancel() {
|
cancel() {
|
||||||
@ -97,7 +103,7 @@ export class SpawnMobDlgComponent extends MD2ComponentBase implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (targetType) {
|
switch (targetType) {
|
||||||
case AttackTarget.LowestHp:
|
case AttackTarget.LeastHp:
|
||||||
let lowestHp = Math.min(...this.md2Service.heros.map(h => h.hp));
|
let lowestHp = Math.min(...this.md2Service.heros.map(h => h.hp));
|
||||||
this.beenAttackedHero = this.md2Service.heros.filter(h => h.hp == lowestHp);
|
this.beenAttackedHero = this.md2Service.heros.filter(h => h.hp == lowestHp);
|
||||||
//this.otherAttackTarget = 'attacking the other <b>Lowest HP</b> hero.';
|
//this.otherAttackTarget = 'attacking the other <b>Lowest HP</b> hero.';
|
||||||
|
|||||||
@ -47,7 +47,7 @@ export class TreasureBagComponent extends MD2ComponentBase implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.md2Service.initTreasureBag();
|
//this.md2Service.initTreasureBag();
|
||||||
this.detectChanges();
|
this.detectChanges();
|
||||||
}
|
}
|
||||||
detectChanges() {
|
detectChanges() {
|
||||||
@ -59,7 +59,7 @@ export class TreasureBagComponent extends MD2ComponentBase implements OnInit {
|
|||||||
resetTreasureBag(showConfirmMsg = true) {
|
resetTreasureBag(showConfirmMsg = true) {
|
||||||
this.msgBoxService.show("Restore Treasure Bag", { text: 'Are you sure?', icon: ADIcon.QUESTION, buttons: ADButtons.YesNo }).pipe(first()).subscribe(result => {
|
this.msgBoxService.show("Restore Treasure Bag", { text: 'Are you sure?', icon: ADIcon.QUESTION, buttons: ADButtons.YesNo }).pipe(first()).subscribe(result => {
|
||||||
if (result) {
|
if (result) {
|
||||||
this.md2Service.initTreasureBag();
|
//this.md2Service.initTreasureBag();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -23,11 +23,11 @@ export class MD2BroadcastService {
|
|||||||
) { }
|
) { }
|
||||||
|
|
||||||
public get playerHero(): MD2HeroInfo {
|
public get playerHero(): MD2HeroInfo {
|
||||||
return this.stateService.info.heros.find(h => h.playerInfo.signalRClientId == this.loginUserService.userAccess.signalRSessionId);
|
return this.stateService.playerHero;
|
||||||
}
|
}
|
||||||
public broadcastAllHeroInfoToAll() {
|
public broadcastAllHeroInfoToAll() {
|
||||||
this.stateService.info.heros.forEach(element => {
|
this.stateService.info.heros.forEach(element => {
|
||||||
this.broadcastHeroInfoToAll(element);
|
this.broadcastHeroInfoToOwner(element);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ export class MD2BroadcastService {
|
|||||||
receiver: { isGroup: false, sessionId: hero.playerInfo.signalRClientId } as SignalRSession,
|
receiver: { isGroup: false, sessionId: hero.playerInfo.signalRClientId } as SignalRSession,
|
||||||
from: { isGroup: true, sessionId: this.gameRoomService.gameRoomId },
|
from: { isGroup: true, sessionId: this.gameRoomService.gameRoomId },
|
||||||
actionType: 'hero',
|
actionType: 'hero',
|
||||||
actionName: 'update',
|
actionName: 'updateMyHero',
|
||||||
} as SignalRMessage;
|
} as SignalRMessage;
|
||||||
message.parameters = { hero: JSON.stringify(hero) };
|
message.parameters = { hero: JSON.stringify(hero) };
|
||||||
this.gameRoomService.sendMessage(message).pipe(first()).subscribe(result => {
|
this.gameRoomService.sendMessage(message).pipe(first()).subscribe(result => {
|
||||||
@ -90,6 +90,12 @@ export class MD2BroadcastService {
|
|||||||
parameters['gameInfo'] = JSON.stringify(this.stateService.info);
|
parameters['gameInfo'] = JSON.stringify(this.stateService.info);
|
||||||
this.broadcastMessage('GameRoom', 'update', parameters);
|
this.broadcastMessage('GameRoom', 'update', parameters);
|
||||||
}
|
}
|
||||||
|
public broadcastRoundPhase() {
|
||||||
|
let parameters = {};
|
||||||
|
parameters['phase'] = JSON.stringify(this.stateService.info.roundPhase);
|
||||||
|
this.broadcastMessage('GameRoom', 'phase', parameters);
|
||||||
|
}
|
||||||
|
|
||||||
public broadcastMobsInfo() {
|
public broadcastMobsInfo() {
|
||||||
let parameters = {};
|
let parameters = {};
|
||||||
parameters['roamingMonsters'] = JSON.stringify(this.stateService.info.roamingMonsters);
|
parameters['roamingMonsters'] = JSON.stringify(this.stateService.info.roamingMonsters);
|
||||||
|
|||||||
51
src/app/services/MD2/md2-init.service.ts
Normal file
51
src/app/services/MD2/md2-init.service.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { CoreGameMobFactories } from '../../games/massive-darkness2/factorys/mobs/CoreGame';
|
||||||
|
import { CoreGameRMFactories } from '../../games/massive-darkness2/factorys/roamingMonsters/CoreGame';
|
||||||
|
import { DrawingBag, MobInfo, TreasureItem, TreasureType } from '../../games/massive-darkness2/massive-darkness2.model';
|
||||||
|
import { MD2StateService } from './md2-state.service';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class MD2InitService {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private stateService: MD2StateService
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public initMobDecks() {
|
||||||
|
this.stateService.mobDeck = new DrawingBag();
|
||||||
|
this.stateService.roamingMobDeck = new DrawingBag();
|
||||||
|
|
||||||
|
this.initCoreGameMobs();
|
||||||
|
this.initCoreGameRoamingMonsters();
|
||||||
|
}
|
||||||
|
|
||||||
|
private initCoreGameRoamingMonsters() {
|
||||||
|
CoreGameRMFactories.forEach(factory => {
|
||||||
|
for (let i = 1; i <= 5; i++) {
|
||||||
|
this.stateService.roamingMobDeck.AddItem(new MobInfo({ name: factory.mobName, level: i, drawingWeight: 1 }));
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
private initCoreGameMobs() {
|
||||||
|
CoreGameMobFactories.forEach(factory => {
|
||||||
|
for (let i = 1; i <= 5; i++) {
|
||||||
|
this.stateService.mobDeck.AddItem(new MobInfo({ name: factory.mobName, level: i, drawingWeight: 1 }));
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public initTreasureBag() {
|
||||||
|
this.stateService.treasureBag.ClearAllItems();
|
||||||
|
this.addTreasure(TreasureType.Common, 15);
|
||||||
|
this.addTreasure(TreasureType.Rare, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
public addTreasure(type: TreasureType, amount: number = 1) {
|
||||||
|
this.stateService.treasureBag.AddItem(new TreasureItem(type, amount));
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/app/services/MD2/md2-mob.service.spec.ts
Normal file
16
src/app/services/MD2/md2-mob.service.spec.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { MD2MobService } from './md2-mob.service';
|
||||||
|
|
||||||
|
describe('MD2MobService', () => {
|
||||||
|
let service: MD2MobService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(MD2MobService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
140
src/app/services/MD2/md2-mob.service.ts
Normal file
140
src/app/services/MD2/md2-mob.service.ts
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { first } from 'rxjs/operators';
|
||||||
|
import { MobInfo, MobType } from '../../games/massive-darkness2/massive-darkness2.model';
|
||||||
|
import { ADIcon } from '../../ui/alert-dlg/alert-dlg.model';
|
||||||
|
import { MsgBoxService } from '../msg-box.service';
|
||||||
|
import { MD2StateService } from './md2-state.service';
|
||||||
|
import { MD2Service } from './md2.service';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class MD2MobService {
|
||||||
|
|
||||||
|
attackingAllExp: number = 0;
|
||||||
|
attackingAttackerExp: number = 0;
|
||||||
|
attackingAttackerReward: string = '';
|
||||||
|
constructor(
|
||||||
|
private md2Service: MD2Service,
|
||||||
|
private stateService: MD2StateService,
|
||||||
|
private msgBoxService: MsgBoxService
|
||||||
|
) { }
|
||||||
|
public get roamingMonsters() {
|
||||||
|
return this.stateService.info.roamingMonsters;
|
||||||
|
}
|
||||||
|
public get mobs() {
|
||||||
|
return this.stateService.info.mobs;
|
||||||
|
}
|
||||||
|
|
||||||
|
addOneUnit(mob: MobInfo) {
|
||||||
|
if (mob.type == MobType.Mob) {
|
||||||
|
mob.mobAmount++;
|
||||||
|
mob.unitRemainHp = 1;
|
||||||
|
this.md2Service.refreshUI$.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private killOneUnit(mob: MobInfo) {
|
||||||
|
let attacker = this.md2Service.currentActivateHero;
|
||||||
|
if (mob.mobAmount > 1) {
|
||||||
|
mob.mobAmount--;
|
||||||
|
mob.unitRemainHp = mob.hp;
|
||||||
|
this.attackingAttackerExp += 1;
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (mob.type == MobType.Mob) {
|
||||||
|
this.mobs.splice(this.mobs.indexOf(mob), 1);
|
||||||
|
} else {
|
||||||
|
this.roamingMonsters.splice(this.roamingMonsters.indexOf(mob), 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
mob.mobAmount = 0;
|
||||||
|
|
||||||
|
this.attackingAllExp += mob.leaderExp;
|
||||||
|
this.attackingAttackerExp += 1;
|
||||||
|
this.attackingAttackerReward = `<br> and gains ${mob.carriedTreasureHtml}`;
|
||||||
|
|
||||||
|
this.md2Service.mobBeenKilledSubject.next(mob);
|
||||||
|
|
||||||
|
}
|
||||||
|
this.md2Service.refreshUI$.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
healMob(mob: MobInfo, healAmount: number) {
|
||||||
|
switch (mob.type) {
|
||||||
|
case MobType.Mob:
|
||||||
|
mob.unitRemainHp += healAmount;
|
||||||
|
if (mob.unitRemainHp > mob.hp) {
|
||||||
|
mob.unitRemainHp -= mob.hp;
|
||||||
|
mob.mobAmount += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case MobType.RoamingMonster:
|
||||||
|
case MobType.Boss:
|
||||||
|
mob.unitRemainHp += healAmount;
|
||||||
|
if (mob.unitRemainHp > mob.hp) {
|
||||||
|
mob.unitRemainHp = mob.hp;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.md2Service.refreshUI$.next();
|
||||||
|
}
|
||||||
|
attackMob(mob: MobInfo, attackDamage: number) {
|
||||||
|
|
||||||
|
this.attackingAttackerReward = '';
|
||||||
|
if (attackDamage) {
|
||||||
|
do {
|
||||||
|
if (attackDamage >= mob.unitRemainHp) {
|
||||||
|
attackDamage -= mob.unitRemainHp;
|
||||||
|
this.killOneUnit(mob);
|
||||||
|
} else {
|
||||||
|
let originAttackDamage = attackDamage;
|
||||||
|
attackDamage -= mob.unitRemainHp;
|
||||||
|
mob.unitRemainHp -= originAttackDamage;
|
||||||
|
}
|
||||||
|
} while (attackDamage > 0 && mob.mobAmount > 0);
|
||||||
|
|
||||||
|
let attacker = this.md2Service.currentActivateHero;
|
||||||
|
let attackerTitle = '';
|
||||||
|
if (attacker) {
|
||||||
|
attackerTitle = attacker.heroFullName;
|
||||||
|
}
|
||||||
|
if (this.attackingAllExp > 0) {
|
||||||
|
let attackerRewardText = '';
|
||||||
|
if (attacker) {
|
||||||
|
attackerRewardText = `<b>${attackerTitle}</b> Gains ${this.attackingAttackerExp} Extra Exp.<br> and gains ${mob.carriedTreasureHtml}`;
|
||||||
|
}
|
||||||
|
this.msgBoxService.show(`All Hero Gains ${this.attackingAllExp} Exp`,
|
||||||
|
{ text: attackerRewardText, icon: ADIcon.INFO })
|
||||||
|
.pipe(first()).subscribe(result => {
|
||||||
|
for (let i = 0; i < this.md2Service.heros.length; i++) {
|
||||||
|
const hero = this.md2Service.heros[i];
|
||||||
|
hero.exp += this.attackingAllExp;
|
||||||
|
}
|
||||||
|
if (attacker) {
|
||||||
|
attacker.exp += this.attackingAttackerExp;
|
||||||
|
}
|
||||||
|
this.attackingAllExp = 0;
|
||||||
|
this.attackingAttackerExp = 0;
|
||||||
|
this.md2Service.broadcastService.broadcastAllHeroInfoToAll();
|
||||||
|
});
|
||||||
|
} else if (this.attackingAttackerExp > 0 && attacker) {
|
||||||
|
this.msgBoxService.show(`<b>${attackerTitle}</b> Gains ${this.attackingAttackerExp} Exp`, { icon: ADIcon.INFO }).pipe(first()).subscribe(result => {
|
||||||
|
attacker.exp += this.attackingAttackerExp;
|
||||||
|
this.attackingAttackerExp = 0;
|
||||||
|
this.md2Service.broadcastService.broadcastHeroInfoToOwner(attacker);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
this.md2Service.refreshUI$.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { MD2Icon, TreasureType } from '../../games/massive-darkness2/massive-darkness2.model';
|
import { DrawingBag, MD2HeroInfo, MD2Icon, MobInfo, TreasureItem, TreasureType } from '../../games/massive-darkness2/massive-darkness2.model';
|
||||||
import { FileService } from '../file.service';
|
import { FileService } from '../file.service';
|
||||||
import { MD2GameInfo } from './md2.service';
|
import { MD2GameInfo } from './md2.service';
|
||||||
|
|
||||||
@ -12,6 +12,10 @@ export class MD2StateService {
|
|||||||
private _playerAmount: number = 2;
|
private _playerAmount: number = 2;
|
||||||
|
|
||||||
public info: MD2GameInfo;
|
public info: MD2GameInfo;
|
||||||
|
public playerHero: MD2HeroInfo;
|
||||||
|
public mobDeck: DrawingBag<MobInfo>;
|
||||||
|
public roamingMobDeck: DrawingBag<MobInfo>;
|
||||||
|
public treasureBag: DrawingBag<TreasureItem> = new DrawingBag<TreasureItem>();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public fileService: FileService,
|
public fileService: FileService,
|
||||||
@ -21,7 +25,7 @@ export class MD2StateService {
|
|||||||
if (icon < MD2Icon.RedDice) {
|
if (icon < MD2Icon.RedDice) {
|
||||||
return `<span class='MD2Icon ${cssClass}'>${String.fromCharCode(65 + icon)}</span>`
|
return `<span class='MD2Icon ${cssClass}'>${String.fromCharCode(65 + icon)}</span>`
|
||||||
} else {
|
} else {
|
||||||
return `<span class='MD2Icon dice ${MD2Icon[icon].replace('Dice', '')} ${cssClass}'></span>`;
|
return `<span class='MD2Icon dice ${MD2Icon[icon].replace('Dice', '')} ${cssClass}'></span>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { AttackInfo, AttackTarget, CoreGameDarknessPhaseRule, DefenseInfo, Drawi
|
|||||||
import { first, map, reduce } from "rxjs/operators";
|
import { first, map, reduce } from "rxjs/operators";
|
||||||
import { NbDialogService } from '@nebular/theme';
|
import { NbDialogService } from '@nebular/theme';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { IBossFight } from '../../games/massive-darkness2/massive-darkness2.model.boss';
|
import { BossMicheal, BossReaper, IBossFight } from '../../games/massive-darkness2/massive-darkness2.model.boss';
|
||||||
import { ADIcon, MessageBoxConfig } from '../../ui/alert-dlg/alert-dlg.model';
|
import { ADIcon, MessageBoxConfig } from '../../ui/alert-dlg/alert-dlg.model';
|
||||||
import { NumberUtils } from '../../utilities/number-utils';
|
import { NumberUtils } from '../../utilities/number-utils';
|
||||||
import { StringUtils } from '../../utilities/string-utils';
|
import { StringUtils } from '../../utilities/string-utils';
|
||||||
@ -15,6 +15,11 @@ import { SignalRService, SignalRSession, SignalRMessage } from '../signal-r.serv
|
|||||||
import { MD2StateService } from './md2-state.service';
|
import { MD2StateService } from './md2-state.service';
|
||||||
import { MD2BroadcastService } from './md2-broadcast.service';
|
import { MD2BroadcastService } from './md2-broadcast.service';
|
||||||
import { CoreGameMobFactories } from '../../games/massive-darkness2/factorys/mobs/CoreGame';
|
import { CoreGameMobFactories } from '../../games/massive-darkness2/factorys/mobs/CoreGame';
|
||||||
|
import { MD2Logic } from '../../games/massive-darkness2/massive-darkness2.logic';
|
||||||
|
import { CoreGameRMFactories } from '../../games/massive-darkness2/factorys/roamingMonsters/CoreGame';
|
||||||
|
import { MD2InitService } from './md2-init.service';
|
||||||
|
import { ArrayUtils } from '../../utilities/array-utils';
|
||||||
|
import { DropDownOption } from '../../entity/dropDownOption';
|
||||||
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
@ -28,13 +33,12 @@ export class MD2Service {
|
|||||||
public enemyPhaseSubject = new Subject<MobInfo>();
|
public enemyPhaseSubject = new Subject<MobInfo>();
|
||||||
public initialized = false;
|
public initialized = false;
|
||||||
public mobBeenKilledSubject = new Subject<MobInfo>();
|
public mobBeenKilledSubject = new Subject<MobInfo>();
|
||||||
public mobDeck: DrawingBag<MobInfo>;
|
|
||||||
public roamingMobDeck: DrawingBag<MobInfo>;
|
|
||||||
public treasureBag: DrawingBag<TreasureItem> = new DrawingBag<TreasureItem>();
|
|
||||||
|
|
||||||
public refreshUI$: Subject<void> = new Subject<void>();
|
public refreshUI$: Subject<void> = new Subject<void>();
|
||||||
public refreshTreasureBagSubject = new Subject<DrawingBag<TreasureItem>>();
|
public refreshTreasureBagSubject = new Subject<DrawingBag<TreasureItem>>();
|
||||||
|
|
||||||
|
public heroAttackingSubject = new Subject<MD2HeroInfo>();
|
||||||
|
|
||||||
|
|
||||||
public get heros() {
|
public get heros() {
|
||||||
return this.stateService.info.heros;
|
return this.stateService.info.heros;
|
||||||
@ -76,67 +80,6 @@ export class MD2Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// #endregion Constructors (1)
|
// #endregion Constructors (1)
|
||||||
private initCoreGameRoamingMonsters() {
|
|
||||||
let mobs = [];
|
|
||||||
this.roamingMobDeck.AddItem(new MobInfo({ name: 'Andra', hp: 5, level: 1, rewardTokens: 2, type: MobType.RoamingMonster, fixedCarriedTreasure: [new TreasureItem(TreasureType.Rare)] }));
|
|
||||||
this.roamingMobDeck.AddItem(new MobInfo({ name: 'Andra', hp: 7, level: 3, rewardTokens: 2, type: MobType.RoamingMonster, fixedCarriedTreasure: [new TreasureItem(TreasureType.Epic)] }));
|
|
||||||
this.roamingMobDeck.AddItem(new MobInfo({ name: 'Andra', hp: 5, level: 5, rewardTokens: 0, type: MobType.RoamingMonster, fixedCarriedTreasure: [new TreasureItem(TreasureType.Epic, 3)] }));
|
|
||||||
|
|
||||||
this.roamingMobDeck.AddItem(new MobInfo({
|
|
||||||
name: 'Ytheria, Undead Queen', hp: 4, level: 1, rewardTokens: 2,
|
|
||||||
attackInfos: [new AttackInfo(MD2Icon.Melee, 1), new AttackInfo(MD2Icon.Rage, 2, 0, 0, 1)],
|
|
||||||
defenseInfo: new DefenseInfo(1, 1),
|
|
||||||
type: MobType.RoamingMonster, fixedCarriedTreasure: [new TreasureItem(TreasureType.Rare)]
|
|
||||||
}));
|
|
||||||
this.roamingMobDeck.AddItem(new MobInfo({
|
|
||||||
name: 'Ytheria, Undead Queen', hp: 6, level: 3, rewardTokens: 2,
|
|
||||||
attackInfos: [new AttackInfo(MD2Icon.Melee, 0, 1), new AttackInfo(MD2Icon.Rage, 1, 1, 0, 1)],
|
|
||||||
defenseInfo: new DefenseInfo(2, 1),
|
|
||||||
type: MobType.RoamingMonster, fixedCarriedTreasure: [new TreasureItem(TreasureType.Epic)]
|
|
||||||
}));
|
|
||||||
this.roamingMobDeck.AddItem(new MobInfo({
|
|
||||||
name: 'Ytheria, Undead Queen', hp: 8, level: 5, rewardTokens: 0,
|
|
||||||
attackInfos: [new AttackInfo(MD2Icon.Melee, 2, 1), new AttackInfo(MD2Icon.Rage, 2, 1, 1, 1)],
|
|
||||||
defenseInfo: new DefenseInfo(4, 1),
|
|
||||||
type: MobType.RoamingMonster, fixedCarriedTreasure: [new TreasureItem(TreasureType.Epic, 3)]
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.roamingMobDeck.AddItem(new MobInfo({
|
|
||||||
name: 'Lyidan, Incubus Lord', hp: 7, level: 1, rewardTokens: 2,
|
|
||||||
type: MobType.RoamingMonster, fixedCarriedTreasure: [new TreasureItem(TreasureType.Rare)]
|
|
||||||
}));
|
|
||||||
this.roamingMobDeck.AddItem(new MobInfo({
|
|
||||||
name: 'Lyidan, Incubus Lord', hp: 10, level: 3, rewardTokens: 2,
|
|
||||||
type: MobType.RoamingMonster, fixedCarriedTreasure: [new TreasureItem(TreasureType.Epic)]
|
|
||||||
}));
|
|
||||||
this.roamingMobDeck.AddItem(new MobInfo({
|
|
||||||
name: 'Lyidan, Incubus Lord', hp: 7, level: 5, rewardTokens: 0,
|
|
||||||
type: MobType.RoamingMonster, fixedCarriedTreasure: [new TreasureItem(TreasureType.Epic, 3)]
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.roamingMobDeck.AddItem(new MobInfo({
|
|
||||||
name: 'The Ghoul', hp: 5, level: 1, rewardTokens: 2,
|
|
||||||
type: MobType.RoamingMonster, fixedCarriedTreasure: [new TreasureItem(TreasureType.Rare)]
|
|
||||||
}));
|
|
||||||
this.roamingMobDeck.AddItem(new MobInfo({
|
|
||||||
name: 'The Ghoul', hp: 8, level: 3, rewardTokens: 2,
|
|
||||||
type: MobType.RoamingMonster, fixedCarriedTreasure: [new TreasureItem(TreasureType.Epic)]
|
|
||||||
}));
|
|
||||||
this.roamingMobDeck.AddItem(new MobInfo({
|
|
||||||
name: 'The Ghoul', hp: 5, level: 5, rewardTokens: 0,
|
|
||||||
type: MobType.RoamingMonster, fixedCarriedTreasure: [new TreasureItem(TreasureType.Epic, 3)]
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
private initCoreGameMobs() {
|
|
||||||
CoreGameMobFactories.forEach(factory => {
|
|
||||||
for (let i = 1; i <= 5; i++) {
|
|
||||||
this.mobDeck.AddItem(factory.generate(i));
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// #region Public Getters And Setters (5)
|
// #region Public Getters And Setters (5)
|
||||||
|
|
||||||
public get highestPlayerLevel(): number {
|
public get highestPlayerLevel(): number {
|
||||||
@ -156,13 +99,23 @@ export class MD2Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public get playerHero(): MD2HeroInfo {
|
public get playerHero(): MD2HeroInfo {
|
||||||
return this.heros.find(h => h.playerInfo.signalRClientId == this.loginUserService.userAccess.signalRSessionId);
|
return this.stateService.playerHero;
|
||||||
}
|
}
|
||||||
|
public get currentActivateHero(): MD2HeroInfo {
|
||||||
|
return this.stateService.info.heros.find(h => h.uiActivating);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// #endregion Public Getters And Setters (5)
|
// #endregion Public Getters And Setters (5)
|
||||||
|
|
||||||
// #region Public Methods (27)
|
// #region Public Methods (27)
|
||||||
|
|
||||||
|
public get treasureBag() {
|
||||||
|
return this.stateService.treasureBag
|
||||||
|
}
|
||||||
|
|
||||||
public addTreasure(type: TreasureType, amount: number = 1) {
|
public addTreasure(type: TreasureType, amount: number = 1) {
|
||||||
this.treasureBag.AddItem(new TreasureItem(type, amount));
|
this.treasureBag.AddItem(new TreasureItem(type, amount));
|
||||||
this.refreshTreasureBagSubject.next(this.treasureBag);
|
this.refreshTreasureBagSubject.next(this.treasureBag);
|
||||||
@ -174,13 +127,19 @@ export class MD2Service {
|
|||||||
let remainFrozenToken = Math.max(0, hero.frozenToken - hero.remainActions);
|
let remainFrozenToken = Math.max(0, hero.frozenToken - hero.remainActions);
|
||||||
hero.remainActions = Math.max(0, hero.remainActions - hero.frozenToken);
|
hero.remainActions = Math.max(0, hero.remainActions - hero.frozenToken);
|
||||||
hero.frozenToken = remainFrozenToken;
|
hero.frozenToken = remainFrozenToken;
|
||||||
this.broadcastHeroInfoToOwner(hero);
|
this.broadcastService.broadcastHeroInfoToOwner(hero);
|
||||||
});
|
});
|
||||||
this.stateService.info.roundPhase = RoundPhase.HeroPhase;
|
this.stateService.info.roundPhase = RoundPhase.HeroPhase;
|
||||||
this.stateService.info.round++;
|
if (!this.stateService.info.isBossFight) {
|
||||||
if (this.darknessPhaseRule.runDarknessPhase()) {
|
this.stateService.info.round++;
|
||||||
this.msgBoxService.show(`${NumberUtils.Ordinal(this.stateService.info.round)} Hero Phase`, { icon: ADIcon.INFO });
|
if (this.darknessPhaseRule.runDarknessPhase()) {
|
||||||
|
this.msgBoxService.show(`${NumberUtils.Ordinal(this.stateService.info.round)} Hero Phase`, { icon: ADIcon.INFO });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.stateService.info.boss.darknessPhase();
|
||||||
|
this.msgBoxService.show(`Boss Fight - ${NumberUtils.Ordinal(this.stateService.info.boss.rounds)} Hero Phase`, { icon: ADIcon.INFO });
|
||||||
}
|
}
|
||||||
|
|
||||||
//this.runNextPhase();
|
//this.runNextPhase();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,9 +153,9 @@ export class MD2Service {
|
|||||||
level = 5;
|
level = 5;
|
||||||
}
|
}
|
||||||
if (isRoamingMonster) {
|
if (isRoamingMonster) {
|
||||||
mobDeck = this.roamingMobDeck;
|
mobDeck = this.stateService.roamingMobDeck;
|
||||||
} else {
|
} else {
|
||||||
mobDeck = this.mobDeck;
|
mobDeck = this.stateService.mobDeck;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mobDeck.drawingItems.filter(m => (m as MobInfo).level == level)
|
if (mobDeck.drawingItems.filter(m => (m as MobInfo).level == level)
|
||||||
@ -205,40 +164,44 @@ export class MD2Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let newSpawnMob = new MobInfo(mobDeck.DrawAndRemove(1, m => m.level == level)[0]);
|
let newSpawnMob = new MobInfo(mobDeck.DrawAndRemove(1, m => m.level == level)[0]);
|
||||||
if (isRoamingMonster) {
|
|
||||||
newSpawnMob.unitRemainHp = newSpawnMob.hp * this.playerAmount;
|
|
||||||
newSpawnMob.mobAmount = 0;
|
|
||||||
} else {
|
|
||||||
newSpawnMob.mobAmount = this.playerAmount + 1;
|
|
||||||
}
|
|
||||||
newSpawnMob.imageUrl = this.mobImage(newSpawnMob.name, newSpawnMob.level, isRoamingMonster);
|
|
||||||
|
|
||||||
let exitingMob = 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);
|
||||||
|
|
||||||
if (exitingMob) {
|
if (exitingMob) {
|
||||||
exitingMob.level = newSpawnMob.level;
|
exitingMob.level = newSpawnMob.level;
|
||||||
exitingMob.hp = newSpawnMob.hp;
|
exitingMob.hp = newSpawnMob.hp;
|
||||||
exitingMob.imageUrl = newSpawnMob.imageUrl;
|
exitingMob.imageUrl = newSpawnMob.imageUrl;
|
||||||
|
exitingMob.attackInfos = newSpawnMob.attackInfos;
|
||||||
|
exitingMob.defenseInfo = newSpawnMob.defenseInfo;
|
||||||
|
exitingMob.combatSkill = newSpawnMob.combatSkill;
|
||||||
} else {
|
} else {
|
||||||
this.mobs.push(newSpawnMob);
|
if (isRoamingMonster) {
|
||||||
|
newSpawnMob = CoreGameRMFactories.find(f => f.mobName == newSpawnMob.name).generate(level);
|
||||||
|
newSpawnMob.hp = newSpawnMob.hpPerHero * this.playerAmount;
|
||||||
|
newSpawnMob.unitRemainHp = newSpawnMob.hp;
|
||||||
|
newSpawnMob.mobAmount = 0;
|
||||||
|
this.roamingMonsters.push(newSpawnMob);
|
||||||
|
} else {
|
||||||
|
newSpawnMob = CoreGameMobFactories.find(f => f.mobName == newSpawnMob.name).generate(level);
|
||||||
|
newSpawnMob.mobAmount = this.playerAmount + 1;
|
||||||
|
this.mobs.push(newSpawnMob);
|
||||||
|
}
|
||||||
|
|
||||||
newSpawnMob.carriedTreasure = this.treasureBag.DrawAndRemove(newSpawnMob.rewardTokens);
|
newSpawnMob.carriedTreasure = this.treasureBag.DrawAndRemove(newSpawnMob.rewardTokens);
|
||||||
this.refreshTreasureBagSubject.next(this.treasureBag);
|
this.refreshTreasureBagSubject.next(this.treasureBag);
|
||||||
}
|
}
|
||||||
|
newSpawnMob.imageUrl = this.mobImage(newSpawnMob.name, newSpawnMob.level, isRoamingMonster);
|
||||||
|
|
||||||
return { exitingMob, mob: newSpawnMob };
|
return { exitingMob, mob: newSpawnMob };
|
||||||
}
|
}
|
||||||
|
|
||||||
public enemyPhase() {
|
public enemyPhase() {
|
||||||
//this.msgBoxService
|
//this.msgBoxService
|
||||||
let monsterBag = new DrawingBag<MobInfo>();
|
this.enemyPhaseMobs = this.roamingMonsters.concat(this.mobs);
|
||||||
monsterBag.drawingItems = this.roamingMonsters.concat(this.mobs);
|
|
||||||
for (let i = 0; i < monsterBag.drawingItems.length; i++) {
|
if (this.enemyPhaseMobs.length > 0) {
|
||||||
const element = monsterBag.drawingItems[i];
|
this.enemyPhaseMobs = ArrayUtils.Shuffle(this.enemyPhaseMobs);
|
||||||
element.drawingWeight = 1;
|
|
||||||
}
|
|
||||||
if (monsterBag.drawingItems.length > 0) {
|
|
||||||
this.enemyPhaseMobs = monsterBag.DrawAndRemove(monsterBag.drawingItems.length);
|
|
||||||
//this.showEnemyPhaseAction();
|
//this.showEnemyPhaseAction();
|
||||||
this.enemyPhaseSubject.next(this.enemyPhaseMobs[0]);
|
this.enemyPhaseSubject.next(this.enemyPhaseMobs[0]);
|
||||||
} else {
|
} else {
|
||||||
@ -247,33 +210,53 @@ export class MD2Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public enterBossFight() {
|
public enterBossFight() {
|
||||||
|
this.msgBoxService.showInputbox('Boss Fight', 'Choose the boss', {
|
||||||
|
inputType: 'dropdown',
|
||||||
|
dropDownOptions: [new DropDownOption('The Reaper', 'The Reaper'), new DropDownOption('Michael - The Corrupted Archangel', 'Michael - The Corrupted Archangel')]
|
||||||
|
}).pipe(first()).subscribe(result => {
|
||||||
|
if (result) {
|
||||||
|
this.info.mobs = [];
|
||||||
|
this.info.roamingMonsters = [];
|
||||||
|
|
||||||
|
if (result == 'The Reaper') {
|
||||||
|
this.info.boss = new BossReaper(this);
|
||||||
|
} else {
|
||||||
|
this.info.boss = new BossMicheal(this);
|
||||||
|
}
|
||||||
|
this.stateService.info.roamingMonsters = [];
|
||||||
|
this.stateService.info.mobs = [];
|
||||||
|
this.stateService.info.isBossFight = true;
|
||||||
|
this.info.isBossFight = true;
|
||||||
|
this.info.boss.info.hp = this.info.boss.info.hpPerHero * this.info.heros.length;
|
||||||
|
this.info.boss.info.unitRemainHp = this.info.boss.info.hp;
|
||||||
|
this.refreshUI$.next();
|
||||||
|
this.info.boss.prepareForBossFight();
|
||||||
|
this.levelUpPhase(false);
|
||||||
|
this.heros.forEach(hero => {
|
||||||
|
hero.hp = hero.hpMaximum;
|
||||||
|
hero.mp = hero.mpMaximum;
|
||||||
|
hero.remainActions = 3;
|
||||||
|
hero.uiActivating = false;
|
||||||
|
hero.uiBossFight = true;
|
||||||
|
});
|
||||||
|
this.broadcastService.broadcastAllHeroInfoToAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
//this.sendMsgboxMsg
|
//this.sendMsgboxMsg
|
||||||
}
|
}
|
||||||
|
public activateBoss() {
|
||||||
|
this.stateService.info.boss.activating();
|
||||||
|
}
|
||||||
public fileList(folderPath: string) {
|
public fileList(folderPath: string) {
|
||||||
return this.fileService.FileList('Images/MD2/' + folderPath);
|
return this.fileService.FileList('Images/MD2/' + folderPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public heroFullName(hero: MD2HeroInfo) {
|
public heroFullName(hero: MD2HeroInfo) {
|
||||||
if (!hero) return '';
|
return MD2Logic.heroFullName(hero);
|
||||||
return `${hero.playerInfo.name} (${HeroClass[hero.class]} - ${hero.name})`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public initMobDecks() {
|
public levelUpPhase(runNextPhase: boolean = true) {
|
||||||
this.mobDeck = new DrawingBag();
|
|
||||||
this.roamingMobDeck = new DrawingBag();
|
|
||||||
|
|
||||||
this.initCoreGameMobs();
|
|
||||||
this.initCoreGameRoamingMonsters();
|
|
||||||
}
|
|
||||||
|
|
||||||
public initTreasureBag() {
|
|
||||||
this.treasureBag.ClearAllItems();
|
|
||||||
this.addTreasure(TreasureType.Common, 15);
|
|
||||||
this.addTreasure(TreasureType.Rare, 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
public levelUpPhase() {
|
|
||||||
for (let i = 0; i < this.heros.length; i++) {
|
for (let i = 0; i < this.heros.length; i++) {
|
||||||
const hero = this.heros[i];
|
const hero = this.heros[i];
|
||||||
let levelUpInfo = MD2Rules.checkCoreGameLevelup(hero.level, hero.exp);
|
let levelUpInfo = MD2Rules.checkCoreGameLevelup(hero.level, hero.exp);
|
||||||
@ -289,11 +272,12 @@ export class MD2Service {
|
|||||||
levelUpInfo = MD2Rules.checkCoreGameLevelup(hero.level, hero.exp);
|
levelUpInfo = MD2Rules.checkCoreGameLevelup(hero.level, hero.exp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.runNextPhase();
|
if (runNextPhase) {
|
||||||
|
this.runNextPhase();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public mobImage(name: string, level: number, isRoamingMonsters: boolean) {
|
public mobImage(name: string, level: number, isRoamingMonsters: boolean) {
|
||||||
name = StringUtils.replaceAll(name, ' ', '').replace(',', '');
|
|
||||||
if (level < 3) {
|
if (level < 3) {
|
||||||
level = 1;
|
level = 1;
|
||||||
} else if (level < 5) {
|
} else if (level < 5) {
|
||||||
@ -314,6 +298,7 @@ export class MD2Service {
|
|||||||
hero.hp = hero.hpMaximum;
|
hero.hp = hero.hpMaximum;
|
||||||
hero.mp = hero.mpMaximum;
|
hero.mp = hero.mpMaximum;
|
||||||
hero.exp = 0;
|
hero.exp = 0;
|
||||||
|
this.stateService.playerHero = hero;
|
||||||
let message = {
|
let message = {
|
||||||
receiver: { isGroup: true, sessionId: this.gameRoomService.gameRoomId } as SignalRSession,
|
receiver: { isGroup: true, sessionId: this.gameRoomService.gameRoomId } as SignalRSession,
|
||||||
from: { isGroup: false, sessionId: this.loginUserService.userAccess.signalRSessionId },
|
from: { isGroup: false, sessionId: this.loginUserService.userAccess.signalRSessionId },
|
||||||
@ -368,51 +353,11 @@ export class MD2Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getTargetHerosByFilter(targetType: AttackTarget, onlyOne: boolean = false) {
|
public getTargetHerosByFilter(targetType: AttackTarget, onlyOne: boolean = false) {
|
||||||
let beenAttackedHero = [] as MD2HeroInfo[];
|
return MD2Logic.getTargetHerosByFilter(this.stateService.info.heros, targetType, onlyOne);
|
||||||
switch (targetType) {
|
|
||||||
case AttackTarget.LowestHp:
|
|
||||||
let lowestHp = Math.min(...this.heros.map(h => h.hp));
|
|
||||||
beenAttackedHero = this.heros.filter(h => h.hp == lowestHp);
|
|
||||||
//this.otherAttackTarget = 'attacking the other <b>Lowest HP</b> hero.';
|
|
||||||
break;
|
|
||||||
case AttackTarget.HighestHp:
|
|
||||||
let highestHp = Math.max(...this.heros.map(h => h.hp));
|
|
||||||
beenAttackedHero = this.heros.filter(h => h.hp == highestHp);
|
|
||||||
//this.otherAttackTarget = 'attacking the other <b>Highest HP</b> hero.';
|
|
||||||
break;
|
|
||||||
case AttackTarget.HighestMp:
|
|
||||||
let highestMp = Math.max(...this.heros.map(h => h.mp));
|
|
||||||
beenAttackedHero = this.heros.filter(h => h.mp == highestMp);
|
|
||||||
//this.otherAttackTarget = 'attacking the other <b>Highest Mp</b> hero.';
|
|
||||||
break;
|
|
||||||
case AttackTarget.LowestLevel:
|
|
||||||
let lowestLevel = Math.max(...this.heros.map(h => h.level));
|
|
||||||
beenAttackedHero = this.heros.filter(h => h.level == lowestLevel);
|
|
||||||
//this.otherAttackTarget = 'attacking the other <b>Lowest Level</b> hero.';
|
|
||||||
break;
|
|
||||||
case AttackTarget.LeastCorruption:
|
|
||||||
|
|
||||||
let leastCor = Math.min(...this.heros.map(h => h.corruptionToken));
|
|
||||||
beenAttackedHero = this.heros.filter(h => h.corruptionToken == leastCor);
|
|
||||||
break;
|
|
||||||
case AttackTarget.MostCorruption:
|
|
||||||
let mostCor = Math.max(...this.heros.map(h => h.corruptionToken));
|
|
||||||
beenAttackedHero = this.heros.filter(h => h.corruptionToken == mostCor);
|
|
||||||
break;
|
|
||||||
case AttackTarget.Random:
|
|
||||||
default:
|
|
||||||
beenAttackedHero = [this.heros[Math.round(Math.random() * (this.heros.length - 1))]];
|
|
||||||
//this.otherAttackTarget = 'Just act like normal.';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (onlyOne && beenAttackedHero.length > 1) {
|
|
||||||
beenAttackedHero = [beenAttackedHero[Math.round(Math.random() * (beenAttackedHero.length - 1))]];
|
|
||||||
}
|
|
||||||
return beenAttackedHero;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getTargetHerosHtml(beenAttackedHero: MD2HeroInfo[]) {
|
public getTargetHerosHtml(beenAttackedHero: MD2HeroInfo[]) {
|
||||||
return `<b>${StringUtils.makeCommaSeparatedString(beenAttackedHero.map(h => this.heroFullName(h)), false, true)}</b>`;
|
return MD2Logic.getTargetHerosHtml(beenAttackedHero);
|
||||||
}
|
}
|
||||||
// #endregion Public Methods (27)
|
// #endregion Public Methods (27)
|
||||||
|
|
||||||
@ -433,12 +378,10 @@ export class MD2GameInfo {
|
|||||||
if (this.boss.info) {
|
if (this.boss.info) {
|
||||||
this.boss.info = new MobInfo(this.boss.info);
|
this.boss.info = new MobInfo(this.boss.info);
|
||||||
}
|
}
|
||||||
this.currentActivateHero = new MD2HeroInfo(this.currentActivateHero);
|
|
||||||
this.heros = this.heros.map(h => new MD2HeroInfo(h));
|
this.heros = this.heros.map(h => new MD2HeroInfo(h));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
public currentActivateHero: MD2HeroInfo;
|
|
||||||
public isBossFight: boolean = false;
|
public isBossFight: boolean = false;
|
||||||
public mobs: MobInfo[] = [];
|
public mobs: MobInfo[] = [];
|
||||||
public roamingMonsters: MobInfo[] = [];
|
public roamingMonsters: MobInfo[] = [];
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<div class='form-group'>
|
<div class='form-group adjustContainer'>
|
||||||
<label for='playerAmount' class='label' *ngIf="title" [innerHtml]="titleHtml"></label>
|
<label for='playerAmount' class='label' *ngIf="title" [innerHtml]="titleHtml"></label>
|
||||||
<div>
|
<div>
|
||||||
<button nbButton outline type="button" status="primary" size="{{size}}" (click)="adjustNumber(false)">
|
<button nbButton outline type="button" status="primary" size="{{size}}" (click)="adjustNumber(false)">
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
.adjustContainer {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
@ -57,17 +57,21 @@ export class AdjacentNumberInputComponent implements ControlValueAccessor, OnIni
|
|||||||
@Output() hitMaximum = new EventEmitter<number>();
|
@Output() hitMaximum = new EventEmitter<number>();
|
||||||
@Output() hitIncreasing = new EventEmitter<number>();
|
@Output() hitIncreasing = new EventEmitter<number>();
|
||||||
@Output() hitDecreasing = new EventEmitter<number>();
|
@Output() hitDecreasing = new EventEmitter<number>();
|
||||||
|
@Output() hitChange = new EventEmitter<number>();
|
||||||
|
|
||||||
onChange = (value: number) => {
|
onChange = (value: number) => {
|
||||||
|
|
||||||
};
|
};
|
||||||
onTouched = () => { };
|
onTouched = () => { };
|
||||||
constructor(
|
constructor(
|
||||||
private cdRef: ChangeDetectorRef
|
private cdRef: ChangeDetectorRef
|
||||||
) { }
|
) { }
|
||||||
writeValue(obj: number): void {
|
writeValue(obj: number): void {
|
||||||
this.currentNumber = obj;
|
if (this.currentNumber != obj) {
|
||||||
this.onChange(obj);
|
|
||||||
|
this.currentNumber = obj;
|
||||||
|
this.onChange(obj);
|
||||||
|
this.cdRef.detectChanges();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
registerOnChange(fn: (value: number) => void): void {
|
registerOnChange(fn: (value: number) => void): void {
|
||||||
@ -99,6 +103,8 @@ export class AdjacentNumberInputComponent implements ControlValueAccessor, OnIni
|
|||||||
if (null == this.maximum || this.currentNumber < this.maximum) {
|
if (null == this.maximum || this.currentNumber < this.maximum) {
|
||||||
this.currentNumber++;
|
this.currentNumber++;
|
||||||
this.hitIncreasing.next(1);
|
this.hitIncreasing.next(1);
|
||||||
|
this.hitChange.next(1);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
this.hitMaximum.next(this.currentNumber);
|
this.hitMaximum.next(this.currentNumber);
|
||||||
}
|
}
|
||||||
@ -106,6 +112,7 @@ export class AdjacentNumberInputComponent implements ControlValueAccessor, OnIni
|
|||||||
if (null == this.minimum || this.currentNumber > this.minimum) {
|
if (null == this.minimum || this.currentNumber > this.minimum) {
|
||||||
this.currentNumber--;
|
this.currentNumber--;
|
||||||
this.hitDecreasing.next(1);
|
this.hitDecreasing.next(1);
|
||||||
|
this.hitChange.next(-1);
|
||||||
} else {
|
} else {
|
||||||
this.hitMinimum.next(this.currentNumber);
|
this.hitMinimum.next(this.currentNumber);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,4 +40,22 @@ export class ArrayUtils {
|
|||||||
}
|
}
|
||||||
arr.splice(new_index, 0, arr.splice(old_index, 1)[0]);
|
arr.splice(new_index, 0, arr.splice(old_index, 1)[0]);
|
||||||
};
|
};
|
||||||
|
public static Shuffle(array) {
|
||||||
|
let currentIndex = array.length, randomIndex;
|
||||||
|
|
||||||
|
// While there remain elements to shuffle.
|
||||||
|
while (currentIndex > 0) {
|
||||||
|
|
||||||
|
// Pick a remaining element.
|
||||||
|
randomIndex = Math.floor(Math.random() * currentIndex);
|
||||||
|
currentIndex--;
|
||||||
|
|
||||||
|
// And swap it with the current element.
|
||||||
|
[array[currentIndex], array[randomIndex]] = [
|
||||||
|
array[randomIndex], array[currentIndex]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,26 +1,26 @@
|
|||||||
// Typography
|
// Typography
|
||||||
// @import "globals/typo-font-sizes";
|
@import "globals/typo-font-sizes";
|
||||||
// @import "globals/typo-font-weights";
|
@import "globals/typo-font-weights";
|
||||||
// @import "globals/typo-text-transforms";
|
@import "globals/typo-text-transforms";
|
||||||
// @import "globals/typo-text-decorations";
|
@import "globals/typo-text-decorations";
|
||||||
// @import "globals/typo-letter-spacings";
|
@import "globals/typo-letter-spacings";
|
||||||
// @import "globals/typo-line-heights";
|
@import "globals/typo-line-heights";
|
||||||
// @import "globals/typo-font-styles";
|
@import "globals/typo-font-styles";
|
||||||
// @import "globals/typo-list-styles";
|
@import "globals/typo-list-styles";
|
||||||
// @import "globals/typo-text-styles";
|
@import "globals/typo-text-styles";
|
||||||
|
|
||||||
// Border styles
|
// Border styles
|
||||||
// @import "globals/borders";
|
@import "globals/borders";
|
||||||
// @import "globals/border-none";
|
@import "globals/border-none";
|
||||||
// @import "globals/border-styles";
|
@import "globals/border-styles";
|
||||||
// @import "globals/border-radiuses";
|
@import "globals/border-radiuses";
|
||||||
// @import "globals/border-dashed";
|
@import "globals/border-dashed";
|
||||||
// @import "globals/border-dotted";
|
@import "globals/border-dotted";
|
||||||
// @import "globals/border-widths";
|
@import "globals/border-widths";
|
||||||
|
|
||||||
//Common
|
//Common
|
||||||
|
|
||||||
@import "globals/heights";
|
@import "globals/heights";
|
||||||
@import "globals/widths";
|
@import "globals/widths";
|
||||||
// @import "globals/z-index";
|
@import "globals/z-index";
|
||||||
// @import "globals/cursor";
|
@import "globals/cursor";
|
||||||
|
|||||||
@ -2,6 +2,30 @@
|
|||||||
Heights
|
Heights
|
||||||
------------------------------------*/
|
------------------------------------*/
|
||||||
|
|
||||||
|
$i: 5;
|
||||||
|
@while $i < 100 {
|
||||||
|
.g-height-#{$i}vh {
|
||||||
|
height: #{$i}vh;
|
||||||
|
}
|
||||||
|
$i: $i + 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
$i: 10;
|
||||||
|
@while $i < 200 {
|
||||||
|
.g-height-#{$i}px {
|
||||||
|
height: #{$i}px;
|
||||||
|
}
|
||||||
|
$i: $i + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
$i: 200;
|
||||||
|
@while $i < 800 {
|
||||||
|
.g-height-#{$i}px {
|
||||||
|
height: #{$i}px;
|
||||||
|
}
|
||||||
|
$i: $i + 20;
|
||||||
|
}
|
||||||
|
|
||||||
@each $breakpoint in map-keys($grid-breakpoints) {
|
@each $breakpoint in map-keys($grid-breakpoints) {
|
||||||
@include media-breakpoint-up($breakpoint) {
|
@include media-breakpoint-up($breakpoint) {
|
||||||
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
|
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
|
||||||
@ -37,6 +61,39 @@
|
|||||||
}
|
}
|
||||||
$i: $i + 5;
|
$i: $i + 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$i: 5;
|
||||||
|
@while $i < 100 {
|
||||||
|
.g-height-#{$i}vh {
|
||||||
|
height: #{$i}vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.g-max-height-#{$i}vh#{$infix} {
|
||||||
|
max-height: #{$i}vh !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.g-min-height-#{$i}vh#{$infix} {
|
||||||
|
min-height: #{$i}vh !important;
|
||||||
|
}
|
||||||
|
$i: $i + 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
$i: 10;
|
||||||
|
@while $i < 200 {
|
||||||
|
.g-height-#{$i}px#{$infix} {
|
||||||
|
height: #{$i}px;
|
||||||
|
}
|
||||||
|
$i: $i + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
$i: 200;
|
||||||
|
@while $i < 800 {
|
||||||
|
.g-height-#{$i}px#{$infix} {
|
||||||
|
height: #{$i}px;
|
||||||
|
}
|
||||||
|
$i: $i + 20;
|
||||||
|
}
|
||||||
|
|
||||||
/* Auto Height */
|
/* Auto Height */
|
||||||
.g-height-auto#{$infix} {
|
.g-height-auto#{$infix} {
|
||||||
height: auto;
|
height: auto;
|
||||||
|
|||||||
@ -4,3 +4,7 @@
|
|||||||
.g-text-break-word {
|
.g-text-break-word {
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.g-text-nowrap {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|||||||
@ -15,6 +15,30 @@
|
|||||||
.MD2text {
|
.MD2text {
|
||||||
font-family: "DwarvenAxeBBW00-Regular", sans-serif !important;
|
font-family: "DwarvenAxeBBW00-Regular", sans-serif !important;
|
||||||
}
|
}
|
||||||
|
.MD2IconContainer-sm {
|
||||||
|
.MD2Icon {
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.MD2IconContainer-md {
|
||||||
|
.MD2Icon {
|
||||||
|
font-size: 30px;
|
||||||
|
line-height: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.MD2IconContainer-lg {
|
||||||
|
.MD2Icon {
|
||||||
|
font-size: 40px;
|
||||||
|
line-height: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.MD2IconContainer-xl {
|
||||||
|
.MD2Icon {
|
||||||
|
font-size: 50px;
|
||||||
|
line-height: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
.MD2Icon {
|
.MD2Icon {
|
||||||
font-family: "Massive Darkness 2", sans-serif !important;
|
font-family: "Massive Darkness 2", sans-serif !important;
|
||||||
//font-size: 50px;
|
//font-size: 50px;
|
||||||
@ -107,13 +131,13 @@
|
|||||||
&::before {
|
&::before {
|
||||||
content: "U";
|
content: "U";
|
||||||
}
|
}
|
||||||
color: orangered !important;
|
color: #ffab6a !important;
|
||||||
}
|
}
|
||||||
&.diceBlack {
|
&.diceBlack {
|
||||||
&::before {
|
&::before {
|
||||||
content: "U";
|
content: "U";
|
||||||
}
|
}
|
||||||
color: black !important;
|
color: #5b5d64 !important;
|
||||||
}
|
}
|
||||||
&.diceRed {
|
&.diceRed {
|
||||||
&::before {
|
&::before {
|
||||||
@ -124,16 +148,16 @@
|
|||||||
&.dice {
|
&.dice {
|
||||||
font-family: "Massive Darkness 2", sans-serif !important;
|
font-family: "Massive Darkness 2", sans-serif !important;
|
||||||
&.Blue {
|
&.Blue {
|
||||||
color: aqua !important;
|
color: #58a1ff !important;
|
||||||
}
|
}
|
||||||
&.Yellow {
|
&.Yellow {
|
||||||
color: #ffc107 !important;
|
color: #ffc107 !important;
|
||||||
}
|
}
|
||||||
&.Orange {
|
&.Orange {
|
||||||
color: orangered !important;
|
color: #ffab6a !important;
|
||||||
}
|
}
|
||||||
&.Black {
|
&.Black {
|
||||||
color: black !important;
|
color: #5b5d64 !important;
|
||||||
}
|
}
|
||||||
&.Red {
|
&.Red {
|
||||||
color: crimson !important;
|
color: crimson !important;
|
||||||
|
|||||||
@ -17,6 +17,6 @@
|
|||||||
@import "form-controls";
|
@import "form-controls";
|
||||||
@import "md2";
|
@import "md2";
|
||||||
nb-card {
|
nb-card {
|
||||||
max-width: 90vw;
|
max-width: 96vw;
|
||||||
max-height: 96vh;
|
max-height: 96vh;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ const urls = [
|
|||||||
'https://api.happiness.tours'
|
'https://api.happiness.tours'
|
||||||
];
|
];
|
||||||
const LINE_CLIENT_ID = '1657422139';
|
const LINE_CLIENT_ID = '1657422139';
|
||||||
const dockerDebug = urls[0];
|
const dockerDebug = urls[2];
|
||||||
export const environment = {
|
export const environment = {
|
||||||
production: false,
|
production: false,
|
||||||
apiUrl: dockerDebug,
|
apiUrl: dockerDebug,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user