Compare commits
No commits in common. "f30c41afbaef82d54eb841746d131d8e995f160d" and "b41c01e6f795f6afdaf4435d4fca4ab717402261" have entirely different histories.
f30c41afba
...
b41c01e6f7
@ -20,7 +20,7 @@ export interface LoginTokenViewModel {
|
|||||||
avatarImage: string;
|
avatarImage: string;
|
||||||
role: Role;
|
role: Role;
|
||||||
cellGroup: PastoralDomain;
|
cellGroup: PastoralDomain;
|
||||||
signalRConnectionId;
|
signalRSessionId;
|
||||||
sessionTabId: string;
|
sessionTabId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,6 @@ export interface IGamePlayer {
|
|||||||
isPlayer: boolean;
|
isPlayer: boolean;
|
||||||
signalRClientId: string;
|
signalRClientId: string;
|
||||||
tabId: string;
|
tabId: string;
|
||||||
isDisconnected: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GamePlayer implements IGamePlayer {
|
export class GamePlayer implements IGamePlayer {
|
||||||
@ -15,5 +14,4 @@ export class GamePlayer implements IGamePlayer {
|
|||||||
isPlayer: boolean;
|
isPlayer: boolean;
|
||||||
signalRClientId: string;
|
signalRClientId: string;
|
||||||
tabId: string;
|
tabId: string;
|
||||||
isDisconnected: boolean;
|
|
||||||
}
|
}
|
||||||
@ -7,8 +7,6 @@ import { SignalRMessage } from "../../services/signal-r.service";
|
|||||||
import { StateService } from "../../services/state.service";
|
import { StateService } from "../../services/state.service";
|
||||||
import { ADIcon, MessageBoxConfig } from "../../ui/alert-dlg/alert-dlg.model";
|
import { ADIcon, MessageBoxConfig } from "../../ui/alert-dlg/alert-dlg.model";
|
||||||
import { MD2HeroInfo, MD2Icon, MobInfo, RoundPhase } from "./massive-darkness2.model";
|
import { MD2HeroInfo, MD2Icon, MobInfo, RoundPhase } from "./massive-darkness2.model";
|
||||||
import { LoginUserService } from "../../services/login-user.service";
|
|
||||||
import { GamePlayer } from "../games.model";
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export abstract class MD2Base {
|
export abstract class MD2Base {
|
||||||
@ -60,14 +58,14 @@ export abstract class MD2Base {
|
|||||||
}
|
}
|
||||||
|
|
||||||
imgUrl(imgPath: string) {
|
imgUrl(imgPath: string) {
|
||||||
return this.md2Service.imgUrl(imgPath);
|
return this.md2Service.stateService.imgUrl(imgPath);
|
||||||
}
|
}
|
||||||
fileList(folderPath: string) {
|
fileList(folderPath: string) {
|
||||||
return this.md2Service.fileList(folderPath);
|
return this.md2Service.fileList(folderPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
iconHtml(icon: MD2Icon, cssClass = '') {
|
iconHtml(icon: MD2Icon, cssClass = '') {
|
||||||
return this.md2Service.iconHtml(icon, cssClass);
|
return this.md2Service.stateService.iconHtml(icon, cssClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
imgHtml(imgFile: string, cssClass = '') {
|
imgHtml(imgFile: string, cssClass = '') {
|
||||||
@ -83,17 +81,12 @@ export abstract class MD2Base {
|
|||||||
}
|
}
|
||||||
abstract refreshUI();
|
abstract refreshUI();
|
||||||
handleSignalRCallback(message: SignalRMessage): void {
|
handleSignalRCallback(message: SignalRMessage): void {
|
||||||
if (message.from) {
|
// if (message.from.isGroup) {
|
||||||
if (message.from.isGroup) {
|
// if (!this.isHeroDashboard) return;
|
||||||
if (!this.isHeroDashboard) return;
|
// } else {
|
||||||
} else {
|
// if (this.isHeroDashboard && this.md2Service.playerHero.playerInfo.signalRClientId == message.from.sessionId) return;
|
||||||
if (this.isHeroDashboard && this.md2Service.playerHero?.playerInfo?.signalRClientId == message.from.connectionId) return;
|
// }
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.isHeroDashboard) {
|
|
||||||
|
|
||||||
}
|
|
||||||
switch (message.actionType) {
|
switch (message.actionType) {
|
||||||
case 'hero':
|
case 'hero':
|
||||||
let heroInfo = new MD2HeroInfo(JSON.parse(message.parameters['hero']));
|
let heroInfo = new MD2HeroInfo(JSON.parse(message.parameters['hero']));
|
||||||
@ -102,12 +95,43 @@ export abstract class MD2Base {
|
|||||||
this.md2Service.heros.push(heroInfo);
|
this.md2Service.heros.push(heroInfo);
|
||||||
break;
|
break;
|
||||||
case 'update':
|
case 'update':
|
||||||
this.updateHeroInfo(heroInfo);
|
let exitingHero = this.md2Service.heros.find(h => h.playerInfo.signalRClientId == heroInfo.playerInfo.signalRClientId);
|
||||||
|
if (exitingHero) {
|
||||||
|
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 {
|
||||||
|
this.md2Service.heros.push(heroInfo);
|
||||||
|
}
|
||||||
|
if (!this.isHeroDashboard) {
|
||||||
|
if (this.gameInfo.roundPhase == RoundPhase.HeroPhase) {
|
||||||
|
if (!this.md2Service.heros.some(h => h.remainActions > 0) && !this.md2Service.heros.some(h => h.uiActivating)) {
|
||||||
|
if (!this.md2Service.info.isBossFight) {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Object.assign(heroInfo, exitingHero);
|
//Object.assign(heroInfo, exitingHero);
|
||||||
break;
|
break;
|
||||||
case 'updateMyHero':
|
case 'updateMyHero':
|
||||||
if (this.isHeroDashboard) {
|
if (this.isHeroDashboard) {
|
||||||
this.md2Service.playerHero = heroInfo;
|
this.md2Service.stateService.playerHero = heroInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -116,45 +140,15 @@ export abstract class MD2Base {
|
|||||||
}
|
}
|
||||||
this.detectChanges();
|
this.detectChanges();
|
||||||
break;
|
break;
|
||||||
case 'heroes':
|
|
||||||
switch (message.actionName) {
|
|
||||||
case 'updateAll':
|
|
||||||
if (this.isHeroDashboard) {
|
|
||||||
let allHeroes = (JSON.parse(message.parameters['heros']) as MD2HeroInfo[]).map(h => new MD2HeroInfo(h));
|
|
||||||
//Remove heroes that are not in the list
|
|
||||||
this.md2Service.info.heros = this.md2Service.heros.filter(h => allHeroes.some(h2 => h2.playerInfo.tabId == h.playerInfo.tabId));
|
|
||||||
allHeroes.forEach(heroInfo => {
|
|
||||||
this.updateHeroInfo(heroInfo);
|
|
||||||
});
|
|
||||||
this.detectChanges();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'GameRoom':
|
case 'GameRoom':
|
||||||
switch (message.actionName) {
|
switch (message.actionName) {
|
||||||
case 'Leaving':
|
case 'Leaving':
|
||||||
let leavingPlayerInfo = message.value as GamePlayer;
|
this.md2Service.heros.splice(this.md2Service.heros.findIndex(h => h.playerInfo.tabId == message.from.sessionId));
|
||||||
let leavingHero = this.md2Service.heros.find(h => h.playerInfo.tabId == leavingPlayerInfo.tabId);
|
|
||||||
if (leavingHero) {
|
|
||||||
leavingHero.playerInfo.isDisconnected = true;
|
|
||||||
}
|
|
||||||
//var disconnectHero = this.md2Service.heros.splice(this.md2Service.heros.findIndex(h => h.playerInfo.signalRClientId == leavingPlayerInfo.signalRClientId));
|
|
||||||
//this.md2Service.info.disconnectedHeroes.push(...disconnectHero);
|
|
||||||
this.detectChanges();
|
this.detectChanges();
|
||||||
break;
|
break;
|
||||||
case 'update':
|
case 'update':
|
||||||
if (this.isHeroDashboard) {
|
if (this.isHeroDashboard) {
|
||||||
this.md2Service.info = new MD2GameInfo(JSON.parse(message.parameters['gameInfo']) as MD2GameInfo);
|
this.md2Service.info = new MD2GameInfo(JSON.parse(message.parameters['gameInfo']) as MD2GameInfo);
|
||||||
let playerHero = this.md2Service.heros.find(h => h.playerInfo.tabId == this.stateService.loginUserService.sessionTabId);
|
|
||||||
if (playerHero) {
|
|
||||||
|
|
||||||
playerHero.playerInfo = this.md2Service.gameRoomService.currentPlayer();
|
|
||||||
playerHero.playerInfo.isDisconnected = false;
|
|
||||||
this.md2Service.playerHero = playerHero;
|
|
||||||
this.md2Service.broadcastMyHeroInfo();
|
|
||||||
}
|
|
||||||
this.detectChanges();
|
this.detectChanges();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -164,17 +158,10 @@ export abstract class MD2Base {
|
|||||||
this.detectChanges();
|
this.detectChanges();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'getGameInfo':
|
|
||||||
|
|
||||||
if (!this.isHeroDashboard) {
|
|
||||||
|
|
||||||
this.md2Service.broadcastGameInfo();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'sendJoinInfo':
|
case 'sendJoinInfo':
|
||||||
if (this.isHeroDashboard && this.md2Service.playerHero) {
|
if (this.isHeroDashboard && this.md2Service.playerHero) {
|
||||||
this.md2Service.playerHero.playerInfo.signalRClientId = message.parameters['signalrconnid'];
|
this.md2Service.playerHero.playerInfo.signalRClientId = message.parameters['signalrconnid'];
|
||||||
this.md2Service.broadcastMyHeroInfo();
|
this.md2Service.broadcastService.broadcastMyHeroInfo();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -242,41 +229,6 @@ export abstract class MD2Base {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateHeroInfo(heroInfo: MD2HeroInfo) {
|
|
||||||
let exitingHero = this.md2Service.heros.find(h => h.playerInfo.tabId == heroInfo.playerInfo.tabId);
|
|
||||||
if (exitingHero) {
|
|
||||||
//For boss fight, if the hero finished activating, activate the boss
|
|
||||||
let activateBoss = exitingHero.uiActivating && !heroInfo.uiActivating;
|
|
||||||
|
|
||||||
this.md2Service.heros[this.md2Service.heros.indexOf(exitingHero)] = heroInfo;
|
|
||||||
//My hero update
|
|
||||||
if (this.isHeroDashboard && this.md2Service.loginUserService.sessionTabId == heroInfo.playerInfo.tabId) {
|
|
||||||
this.md2Service.playerHero = heroInfo;
|
|
||||||
}
|
|
||||||
if (!this.isHeroDashboard && this.md2Service.info.isBossFight && activateBoss) {
|
|
||||||
this.md2Service.activateBoss();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.md2Service.heros.push(heroInfo);
|
|
||||||
}
|
|
||||||
if (!this.isHeroDashboard) {
|
|
||||||
if (this.gameInfo.roundPhase == RoundPhase.HeroPhase) {
|
|
||||||
if (!this.md2Service.heros.some(h => h.remainActions > 0) && !this.md2Service.heros.some(h => h.uiActivating)) {
|
|
||||||
if (!this.md2Service.info.isBossFight) {
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract heroAction(hero: MD2HeroInfo, action: string);
|
abstract heroAction(hero: MD2HeroInfo, action: string);
|
||||||
}
|
}
|
||||||
@ -308,14 +260,14 @@ export abstract class MD2ComponentBase {
|
|||||||
this.destroy$.complete();
|
this.destroy$.complete();
|
||||||
}
|
}
|
||||||
imgUrl(imgPath: string) {
|
imgUrl(imgPath: string) {
|
||||||
return this.md2Service.imgUrl(imgPath);
|
return this.md2Service.stateService.imgUrl(imgPath);
|
||||||
}
|
}
|
||||||
fileList(folderPath: string) {
|
fileList(folderPath: string) {
|
||||||
return this.md2Service.fileList(folderPath);
|
return this.md2Service.fileList(folderPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
iconHtml(icon: MD2Icon, cssClass = '') {
|
iconHtml(icon: MD2Icon, cssClass = '') {
|
||||||
return this.md2Service.iconHtml(icon, cssClass);
|
return this.md2Service.stateService.iconHtml(icon, cssClass);
|
||||||
}
|
}
|
||||||
detectChanges() {
|
detectChanges() {
|
||||||
if (!this.cdRef['destroyed']) {
|
if (!this.cdRef['destroyed']) {
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
<div class="col-md-7">
|
<div class="col-md-7">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md">
|
<div class="col-md">
|
||||||
<adj-number-input name="mob{{boss.info.name}}" [(ngModel)]="boss.info.hp" minimum="0"
|
<adj-number-input name="mob{{boss.info.name}}" [(ngModel)]="boss.info.unitRemainHp" minimum="0"
|
||||||
class="mb-3" title="Boss HP" (hitMinimum)="WIN()">
|
class="mb-3" title="Boss HP" (hitMinimum)="WIN()">
|
||||||
</adj-number-input>
|
</adj-number-input>
|
||||||
<md2-mob-attack-info [mob]="boss.info">
|
<md2-mob-attack-info [mob]="boss.info">
|
||||||
|
|||||||
@ -52,11 +52,7 @@ export class BossFightComponent extends MD2ComponentBase {
|
|||||||
this.boss.activating();
|
this.boss.activating();
|
||||||
}
|
}
|
||||||
WIN() {
|
WIN() {
|
||||||
this.msgBoxService.show('Win', { text: 'You Win the Boss Fight', icon: ADIcon.INFO });
|
|
||||||
this.md2Service.info.isBossFight = false;
|
|
||||||
this.md2Service.info.boss = undefined;
|
|
||||||
this.md2Service.heros.forEach(h => h.uiBossFight = false);
|
|
||||||
this.md2Service.broadcastGameInfo();
|
|
||||||
}
|
}
|
||||||
attack(mob: MobInfo) {
|
attack(mob: MobInfo) {
|
||||||
|
|
||||||
@ -66,9 +62,6 @@ export class BossFightComponent extends MD2ComponentBase {
|
|||||||
let attackDamage = mobResult.uiWounds;
|
let attackDamage = mobResult.uiWounds;
|
||||||
if (attackDamage) {
|
if (attackDamage) {
|
||||||
this.boss.info.hp -= attackDamage;
|
this.boss.info.hp -= attackDamage;
|
||||||
if (this.boss.info.hp <= 0) {
|
|
||||||
this.WIN();
|
|
||||||
}
|
|
||||||
this.cdRef.detectChanges();
|
this.cdRef.detectChanges();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,99 @@ import { MobSkillType } from "../../massive-darkness2.model.boss";
|
|||||||
import { MD2DiceSet, MD2MobSkill } from "../../massive-darkness2.db.model";
|
import { MD2DiceSet, MD2MobSkill } from "../../massive-darkness2.db.model";
|
||||||
|
|
||||||
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 = [
|
||||||
|
|
||||||
|
new MobInfo({
|
||||||
|
name: 'Andra', level: 1, hp: 5,
|
||||||
|
|
||||||
|
attackInfos: [new AttackInfo(MD2Icon.Melee, 1, 0, 0, 1), new AttackInfo(MD2Icon.Range, 1, 0, 0, 1)],
|
||||||
|
defenseInfo: { blue: 2, black: 1 } as MD2DiceSet,
|
||||||
|
}),
|
||||||
|
new MobInfo({
|
||||||
|
name: 'Andra', level: 3, hp: 7,
|
||||||
|
|
||||||
|
attackInfos: [new AttackInfo(MD2Icon.Melee, 1, 1, 0, 1), new AttackInfo(MD2Icon.Range, 1, 1, 0, 1)],
|
||||||
|
defenseInfo: { blue: 3, black: 1 } as MD2DiceSet,
|
||||||
|
}),
|
||||||
|
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: { blue: 5, black: 1 } as MD2DiceSet,
|
||||||
|
}),
|
||||||
|
|
||||||
|
new MobInfo({
|
||||||
|
name: 'Ytheria, Undead Queen', level: 1, hp: 4,
|
||||||
|
attackInfos: [new AttackInfo(MD2Icon.Melee, 1), new AttackInfo(MD2Icon.Range, 2, 0, 0, 1)],
|
||||||
|
defenseInfo: { blue: 1, black: 1 } as MD2DiceSet,
|
||||||
|
|
||||||
|
}),
|
||||||
|
new MobInfo({
|
||||||
|
name: 'Ytheria, Undead Queen', level: 3, hp: 6,
|
||||||
|
attackInfos: [new AttackInfo(MD2Icon.Melee, 0, 1), new AttackInfo(MD2Icon.Range, 1, 1, 0, 1)],
|
||||||
|
defenseInfo: { blue: 2, black: 1 } as MD2DiceSet,
|
||||||
|
|
||||||
|
}),
|
||||||
|
new MobInfo({
|
||||||
|
name: 'Ytheria, Undead Queen', level: 5, hp: 8,
|
||||||
|
attackInfos: [new AttackInfo(MD2Icon.Melee, 2, 1), new AttackInfo(MD2Icon.Range, 2, 1, 0, 1)],
|
||||||
|
defenseInfo: { blue: 4, black: 1 } as MD2DiceSet,
|
||||||
|
}),
|
||||||
|
|
||||||
|
new MobInfo({
|
||||||
|
name: 'Lyidan, Incubus Lord', level: 1, hp: 7,
|
||||||
|
attackInfos: [new AttackInfo(MD2Icon.Melee, 0, 1, 0, 2)],
|
||||||
|
defenseInfo: { blue: 2, black: 1 } as MD2DiceSet,
|
||||||
|
}),
|
||||||
|
new MobInfo({
|
||||||
|
name: 'Lyidan, Incubus Lord', level: 3, hp: 10,
|
||||||
|
attackInfos: [new AttackInfo(MD2Icon.Melee, 0, 2, 0, 1)],
|
||||||
|
defenseInfo: { blue: 2, black: 1 } as MD2DiceSet,
|
||||||
|
}),
|
||||||
|
new MobInfo({
|
||||||
|
name: 'Lyidan, Incubus Lord', level: 5, hp: 12,
|
||||||
|
attackInfos: [new AttackInfo(MD2Icon.Melee, 2, 2, 0, 1)],
|
||||||
|
defenseInfo: { blue: 4, black: 1 } as MD2DiceSet,
|
||||||
|
}),
|
||||||
|
|
||||||
|
new MobInfo({
|
||||||
|
name: 'The Ghoul', level: 1, hp: 5,
|
||||||
|
attackInfos: [new AttackInfo(MD2Icon.Melee, 0, 1, 0, 1)],
|
||||||
|
defenseInfo: { blue: 2, black: 1 } as MD2DiceSet,
|
||||||
|
}),
|
||||||
|
new MobInfo({
|
||||||
|
name: 'The Ghoul', level: 3, hp: 8,
|
||||||
|
attackInfos: [new AttackInfo(MD2Icon.Melee, 0, 2, 0, 2)],
|
||||||
|
defenseInfo: { blue: 3, black: 1 } as MD2DiceSet,
|
||||||
|
}),
|
||||||
|
new MobInfo({
|
||||||
|
name: 'The Ghoul', level: 5, hp: 10,
|
||||||
|
attackInfos: [new AttackInfo(MD2Icon.Melee, 0, 3, 0, 3)],
|
||||||
|
defenseInfo: { blue: 4, black: 1 } as MD2DiceSet,
|
||||||
|
}),
|
||||||
|
|
||||||
|
|
||||||
|
new MobInfo({
|
||||||
|
name: 'Balrog', level: 1, hp: 5,
|
||||||
|
attackInfos: [
|
||||||
|
new AttackInfo(MD2Icon.Magic, 0, 1, 0, 2),
|
||||||
|
],
|
||||||
|
defenseInfo: { blue: 2, black: 1 } as MD2DiceSet,
|
||||||
|
}),
|
||||||
|
new MobInfo({
|
||||||
|
name: 'Balrog', level: 3, hp: 8,
|
||||||
|
attackInfos: [
|
||||||
|
new AttackInfo(MD2Icon.Magic, 0, 2, 0, 2),
|
||||||
|
],
|
||||||
|
defenseInfo: { blue: 3, black: 1 } as MD2DiceSet,
|
||||||
|
}),
|
||||||
|
new MobInfo({
|
||||||
|
name: 'Balrog', level: 5, hp: 10,
|
||||||
|
attackInfos: [
|
||||||
|
new AttackInfo(MD2Icon.Magic, 0, 3, 0, 2),
|
||||||
|
],
|
||||||
|
defenseInfo: { blue: 4, black: 1 } as MD2DiceSet,
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
|
||||||
export abstract class CoreGameRMFactory implements IMobFactory {
|
export abstract class CoreGameRMFactory implements IMobFactory {
|
||||||
abstract mobName: string;
|
abstract mobName: string;
|
||||||
@ -99,7 +192,7 @@ export class RMUndeadQueenFactory extends CoreGameRMFactory {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.mob.skills = [
|
this.mob.skills = [
|
||||||
|
|||||||
@ -126,10 +126,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-6 hero-skills-col">
|
<div class="col-6 hero-skills-col">
|
||||||
<div class="hero-skills">
|
<div class="hero-skills">
|
||||||
<div class="skills-title" (click)="showSkills('abilities')">Abilities</div>
|
<div class="skills-title">Abilities</div>
|
||||||
<div class="skill-content" [innerHTML]="hero.skillHtml"></div>
|
<div class="skill-content" [innerHTML]="hero.skillHtml"></div>
|
||||||
<div class="skills-title shadow-skills-title" (click)="showSkills('shadow')">
|
<div class="skills-title shadow-skills-title">Shadow Abilities</div>
|
||||||
Shadow Abilities</div>
|
|
||||||
<div class="skill-content shadow-skill-content"
|
<div class="skill-content shadow-skill-content"
|
||||||
[innerHTML]="hero.shadowSkillHtml"></div>
|
[innerHTML]="hero.shadowSkillHtml"></div>
|
||||||
</div>
|
</div>
|
||||||
@ -139,7 +138,7 @@
|
|||||||
<!-- <img class="MD2HeroCard " src="{{imgUrl('Heros/'+className+'.jpg')}}" (click)="toggleFlip()"> -->
|
<!-- <img class="MD2HeroCard " src="{{imgUrl('Heros/'+className+'.jpg')}}" (click)="toggleFlip()"> -->
|
||||||
|
|
||||||
<!-- Action Buttons (Desktop/Landscape) -->
|
<!-- Action Buttons (Desktop/Landscape) -->
|
||||||
<div class="hero-actions d-block">
|
<div class="hero-actions d-none d-sm-block">
|
||||||
<div class="action-buttons-group" *ngIf="hero.uiActivating && hero.remainActions > 0">
|
<div class="action-buttons-group" *ngIf="hero.uiActivating && hero.remainActions > 0">
|
||||||
<button nbButton hero class="action-btn" status="info" (click)="moveAction()"
|
<button nbButton hero class="action-btn" status="info" (click)="moveAction()"
|
||||||
*ngIf="!showMoveAction">
|
*ngIf="!showMoveAction">
|
||||||
|
|||||||
@ -810,6 +810,3 @@
|
|||||||
-ms-transform: rotateY(-180deg);
|
-ms-transform: rotateY(-180deg);
|
||||||
transform: rotateY(-180deg);
|
transform: rotateY(-180deg);
|
||||||
}
|
}
|
||||||
::ng-deep .skill-content .MD2Icon {
|
|
||||||
font-size: 30px;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -14,7 +14,6 @@ import { DebounceTimer } from '../../../utilities/timer-utils';
|
|||||||
import { HeroClass, MD2HeroInfo, MD2HeroProfile, MD2Icon } from '../massive-darkness2.model';
|
import { HeroClass, MD2HeroInfo, MD2HeroProfile, MD2Icon } from '../massive-darkness2.model';
|
||||||
import { MD2Base } from '../MD2Base';
|
import { MD2Base } from '../MD2Base';
|
||||||
import { MD2HeroProfileService } from '../service/massive-darkness2.service';
|
import { MD2HeroProfileService } from '../service/massive-darkness2.service';
|
||||||
import { SignalRService } from '../../../services/signal-r.service';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ngx-hero-dashboard',
|
selector: 'ngx-hero-dashboard',
|
||||||
@ -56,10 +55,6 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
|
|||||||
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'),
|
new DropDownOption(HeroClass.Druid, 'Druid'),
|
||||||
new DropDownOption(HeroClass.Necromancer, 'Necromancer'),
|
|
||||||
new DropDownOption(HeroClass.Monk, 'Monk'),
|
|
||||||
new DropDownOption(HeroClass.Thinker, 'Thinker'),
|
|
||||||
new DropDownOption(HeroClass.Bard, 'Bard'),
|
|
||||||
];
|
];
|
||||||
heros = [] as MD2HeroInfo[];
|
heros = [] as MD2HeroInfo[];
|
||||||
heroProfiles: MD2HeroProfile[] = [];
|
heroProfiles: MD2HeroProfile[] = [];
|
||||||
@ -71,15 +66,6 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
|
|||||||
return this.md2Service.playerHero;
|
return this.md2Service.playerHero;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get className() {
|
|
||||||
if (this.md2Service.playerHero) {
|
|
||||||
return HeroClass[this.md2Service.playerHero.class];
|
|
||||||
}
|
|
||||||
if (this.selectedHeroClass) {
|
|
||||||
return HeroClass[this.selectedHeroClass];
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
public get currentSelectingHero(): MD2HeroInfo {
|
public get currentSelectingHero(): MD2HeroInfo {
|
||||||
return this.heros[this.currentHeroIndex];
|
return this.heros[this.currentHeroIndex];
|
||||||
}
|
}
|
||||||
@ -92,7 +78,6 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
|
|||||||
protected route: ActivatedRoute,
|
protected route: ActivatedRoute,
|
||||||
protected cdRef: ChangeDetectorRef,
|
protected cdRef: ChangeDetectorRef,
|
||||||
private msgBoxService: MsgBoxService,
|
private msgBoxService: MsgBoxService,
|
||||||
private signalRService: SignalRService
|
|
||||||
) {
|
) {
|
||||||
super(md2Service, stateService, route, cdRef);
|
super(md2Service, stateService, route, cdRef);
|
||||||
this.isHeroDashboard = true;
|
this.isHeroDashboard = true;
|
||||||
@ -104,15 +89,6 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
|
|||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
super.ngOnInit();
|
super.ngOnInit();
|
||||||
|
|
||||||
this.gameRoomService.gameRoomId = this.roomId;
|
|
||||||
this.gameRoomService.joinGameRoom(this.roomId);
|
|
||||||
//this.fetchGameInfo();
|
|
||||||
this.signalRService.signalRMessageConnSubject.subscribe(state => {
|
|
||||||
if (state.status == 'connected') {
|
|
||||||
this.fetchGameInfo();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override signalRInitialized() {
|
override signalRInitialized() {
|
||||||
@ -123,7 +99,8 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
initHero() {
|
initHero() {
|
||||||
if (!this.md2Service.heros.some(h => h.playerInfo.signalRClientId == this.stateService.loginUserService.userAccess.signalRConnectionId)) {
|
this.gameRoomService.gameRoomId = this.roomId;
|
||||||
|
if (!this.md2Service.heros.some(h => h.playerInfo.signalRClientId == this.stateService.loginUserService.userAccess.signalRSessionId)) {
|
||||||
|
|
||||||
this.msgBoxService.showInputbox('Select Hero Class', '', { dropDownOptions: this.classOptions, inputType: 'dropdown' })
|
this.msgBoxService.showInputbox('Select Hero Class', '', { dropDownOptions: this.classOptions, inputType: 'dropdown' })
|
||||||
.pipe(first()).subscribe(heroClass => {
|
.pipe(first()).subscribe(heroClass => {
|
||||||
@ -145,11 +122,10 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
className: string;
|
||||||
|
|
||||||
|
|
||||||
initClassHeroList(heroClass: HeroClass) {
|
initClassHeroList(heroClass: HeroClass) {
|
||||||
this.heros = [];
|
this.heros = [];
|
||||||
|
this.className = HeroClass[heroClass];
|
||||||
this.selectedHeroClass = heroClass;
|
this.selectedHeroClass = heroClass;
|
||||||
this.heroProfileService.getAll().pipe(first()).subscribe(result => {
|
this.heroProfileService.getAll().pipe(first()).subscribe(result => {
|
||||||
|
|
||||||
@ -163,7 +139,7 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
|
|||||||
hp: heroProfile.hp,
|
hp: heroProfile.hp,
|
||||||
mp: heroProfile.mana,
|
mp: heroProfile.mana,
|
||||||
skillHtml: heroProfile.skillHtml,
|
skillHtml: heroProfile.skillHtml,
|
||||||
shadowSkillHtml: heroProfile.shadowSkillHtml.replace("<p>", '<p>' + this.iconHtml(MD2Icon.Shadow) + ' : '),
|
shadowSkillHtml: heroProfile.shadowSkillHtml,
|
||||||
class: heroClass
|
class: heroClass
|
||||||
});
|
});
|
||||||
heroInfo.imgUrl = this.imgUrl('Heros/' + HeroClass[heroClass] + '.jpg');
|
heroInfo.imgUrl = this.imgUrl('Heros/' + HeroClass[heroClass] + '.jpg');
|
||||||
@ -180,18 +156,12 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
|
|||||||
selectCurrentHero() {
|
selectCurrentHero() {
|
||||||
if (this.currentSelectingHero) {
|
if (this.currentSelectingHero) {
|
||||||
this.md2Service.playerJoin(this.currentSelectingHero);
|
this.md2Service.playerJoin(this.currentSelectingHero);
|
||||||
this.md2Service.broadcastMyHeroInfo();
|
|
||||||
this.isSelectingHero = false;
|
this.isSelectingHero = false;
|
||||||
this.detectChanges();
|
this.detectChanges();
|
||||||
|
this.gameRoomService.joinGameRoom(this.roomId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
showSkills(type: string) {
|
|
||||||
if (type == 'abilities') {
|
|
||||||
this.msgBoxService.show('Abilities', { text: this.currentSelectingHero.skillHtml });
|
|
||||||
} else {
|
|
||||||
this.msgBoxService.show('Shadow Abilities', { text: this.currentSelectingHero.shadowSkillHtml });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nextHero() {
|
nextHero() {
|
||||||
this.currentHeroIndex++;
|
this.currentHeroIndex++;
|
||||||
if (this.currentHeroIndex >= this.heros.length) {
|
if (this.currentHeroIndex >= this.heros.length) {
|
||||||
@ -208,12 +178,8 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
|
|||||||
this.detectChanges();
|
this.detectChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchGameInfo() {
|
|
||||||
this.md2Service.broadcastFetchGameInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
broadcastHeroInfo() {
|
broadcastHeroInfo() {
|
||||||
this.md2Service.broadcastMyHeroInfo();
|
this.md2Service.broadcastService.broadcastMyHeroInfo();
|
||||||
this.heroUpdateDebounceTimer.clearOut();
|
this.heroUpdateDebounceTimer.clearOut();
|
||||||
}
|
}
|
||||||
increaseRage() {
|
increaseRage() {
|
||||||
@ -222,8 +188,8 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
openDoor() {
|
openDoor() {
|
||||||
this.md2Service.broadcastHeroAction('openDoor');
|
this.md2Service.broadcastService.broadcastHeroAction('openDoor');
|
||||||
//this.showMoveAction = false;
|
this.showMoveAction = false;
|
||||||
this.detectChanges();
|
this.detectChanges();
|
||||||
}
|
}
|
||||||
moveAction() {
|
moveAction() {
|
||||||
@ -247,7 +213,7 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this.md2Service.broadcastHeroAction(action);
|
this.md2Service.broadcastService.broadcastHeroAction(action);
|
||||||
this.reduceAction();
|
this.reduceAction();
|
||||||
}
|
}
|
||||||
reduceAction() {
|
reduceAction() {
|
||||||
|
|||||||
@ -59,32 +59,23 @@
|
|||||||
<div class="col-12" *ngFor="let hero of md2Service.heros">
|
<div class="col-12" *ngFor="let hero of md2Service.heros">
|
||||||
<label class='label mr-1'>{{hero.playerInfo.name}} ({{heroClassName(hero)}} -
|
<label class='label mr-1'>{{hero.playerInfo.name}} ({{heroClassName(hero)}} -
|
||||||
{{hero.name}})</label>
|
{{hero.name}})</label>
|
||||||
<span class="badge badge-primary mr-1"
|
<span class="badge badge-primary mr-1">Lv.:{{hero.level}}</span>
|
||||||
(click)="adjustHeroValue(hero,'level')">Lv.:{{hero.level}}</span>
|
<span class="badge badge-primary mr-1">HP: {{hero.hp}}/{{hero.hpMaximum}}</span>
|
||||||
<span class="badge badge-primary mr-1" (click)="adjustHeroValue(hero,'hp')">HP:
|
<span class="badge badge-primary mr-1">Mana: {{hero.mp}}/{{hero.mpMaximum}}</span>
|
||||||
{{hero.hp}}/{{hero.hpMaximum}}</span>
|
<span class="badge badge-success mr-1">Exp: {{hero.exp}}</span>
|
||||||
<span class="badge badge-primary mr-1" (click)="adjustHeroValue(hero,'mp')">Mana:
|
<span class="badge badge-danger mr-1" *ngIf="hero.fireToken">
|
||||||
{{hero.mp}}/{{hero.mpMaximum}}</span>
|
<md2-icon icon="fire" size="sm"></md2-icon> {{hero.fireToken}}
|
||||||
<span class="badge badge-success mr-1" (click)="adjustHeroValue(hero,'exp')">Exp:
|
|
||||||
{{hero.exp}}</span>
|
|
||||||
<span class="badge mr-1" *ngIf="hero.fireToken">
|
|
||||||
<md2-icon [icon]="MD2Icon.FireToken" size="sm"></md2-icon> {{hero.fireToken}}
|
|
||||||
</span>
|
</span>
|
||||||
<span class="badge mr-1" *ngIf="hero.frozenToken">
|
<span class="badge badge-info mr-1" *ngIf="hero.frozenToken">
|
||||||
<md2-icon [icon]="MD2Icon.FrozenToken" size="sm"></md2-icon>{{hero.frozenToken}}
|
<md2-icon icon="frozen" size="sm"></md2-icon>{{hero.frozenToken}}
|
||||||
</span>
|
</span>
|
||||||
<span class="badge badge-success mr-1" *ngIf="hero.remainActions>0"
|
<span class="badge badge-success mr-1" *ngIf="hero.remainActions>0">Actions:
|
||||||
(click)="adjustHeroValue(hero,'remainActions')">Actions:
|
|
||||||
{{hero.remainActions}}</span>
|
{{hero.remainActions}}</span>
|
||||||
<span class="badge badge-light mr-1" *ngIf=" !hero.uiActivating"
|
<span class="badge badge-light mr-1" *ngIf=" !hero.uiActivating">Inactive</span>
|
||||||
(click)="activatingHero(hero)">Inactive</span>
|
|
||||||
<span class="badge badge-primary mr-1" *ngIf="hero.uiActivating">Activating</span>
|
<span class="badge badge-primary mr-1" *ngIf="hero.uiActivating">Activating</span>
|
||||||
<span class="badge badge-warning mr-1"
|
|
||||||
*ngIf="hero.playerInfo.isDisconnected">Disconnected</span>
|
|
||||||
<!-- <span class="badge badge-success mr-1">{{hero.playerInfo.signalRClientId}}</span> -->
|
<!-- <span class="badge badge-success mr-1">{{hero.playerInfo.signalRClientId}}</span> -->
|
||||||
|
<!-- <button nbButton hero status="primary" size="tiny" class="ml-2"
|
||||||
<span class="badge badge-danger mr-1" (click)="removeHero(hero)">X
|
(click)="removeHero(hero)">Remove</button> -->
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,3 +0,0 @@
|
|||||||
.badge {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
@ -5,7 +5,7 @@ import { MsgBoxService } from '../../services/msg-box.service';
|
|||||||
import { ArrayUtils } from '../../utilities/array-utils';
|
import { ArrayUtils } from '../../utilities/array-utils';
|
||||||
import { ObjectUtils } from '../../utilities/object-utils';
|
import { ObjectUtils } from '../../utilities/object-utils';
|
||||||
import { first, map, take, takeUntil } from 'rxjs/operators';
|
import { first, map, take, takeUntil } from 'rxjs/operators';
|
||||||
import { TreasureType, DrawingBag, DrawingItem, HeroClass, MD2HeroInfo, RoundPhase, MobInfo, MobDlgType, MD2Icon } from './massive-darkness2.model';
|
import { TreasureType, DrawingBag, DrawingItem, HeroClass, MD2HeroInfo, RoundPhase, MobInfo, MobDlgType } from './massive-darkness2.model';
|
||||||
import { MD2Service } from '../../services/MD2/md2.service';
|
import { MD2Service } from '../../services/MD2/md2.service';
|
||||||
import { GameRoomService } from '../../services/game-room.service';
|
import { GameRoomService } from '../../services/game-room.service';
|
||||||
import { MD2Base } from './MD2Base';
|
import { MD2Base } from './MD2Base';
|
||||||
@ -25,7 +25,6 @@ import { NumberUtils } from '../../utilities/number-utils';
|
|||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class MassiveDarkness2Component extends MD2Base implements OnInit {
|
export class MassiveDarkness2Component extends MD2Base implements OnInit {
|
||||||
MD2Icon = MD2Icon;
|
|
||||||
HeroClass = HeroClass;
|
HeroClass = HeroClass;
|
||||||
constructor(
|
constructor(
|
||||||
private fileService: FileService,
|
private fileService: FileService,
|
||||||
@ -51,31 +50,6 @@ export class MassiveDarkness2Component extends MD2Base implements OnInit {
|
|||||||
}
|
}
|
||||||
override signalRInitialized() {
|
override signalRInitialized() {
|
||||||
|
|
||||||
}
|
|
||||||
adjustHeroValue(hero: MD2HeroInfo, value: string) {
|
|
||||||
this.msgBoxService.showInputbox(`Adjust ${value} for ${hero.playerInfo.name}`, `Enter the new value for ${value}`, {
|
|
||||||
inputType: 'number',
|
|
||||||
inputValue: hero[value].toString()
|
|
||||||
}).pipe(first()).subscribe(result => {
|
|
||||||
if (result) {
|
|
||||||
hero[value] = Number.parseInt(result);
|
|
||||||
this.md2Service.broadcastHeroInfoToAll(hero, true);
|
|
||||||
this.detectChanges();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
activatingHero(hero: MD2HeroInfo) {
|
|
||||||
if (hero.remainActions > 0) {
|
|
||||||
this.msgBoxService.show('Activating', { text: `Are you sure you want to activate ${hero.playerInfo.name}?` }).pipe(first()).subscribe(result => {
|
|
||||||
if (result) {
|
|
||||||
this.md2Service.heros.forEach(h => h.uiActivating = false);
|
|
||||||
hero.uiActivating = true;
|
|
||||||
this.md2Service.broadcastAllHeroInfoToAll();
|
|
||||||
this.detectChanges();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
showQrCode() {
|
showQrCode() {
|
||||||
if (this.md2Service.initialized == false) {
|
if (this.md2Service.initialized == false) {
|
||||||
@ -171,15 +145,10 @@ export class MassiveDarkness2Component extends MD2Base implements OnInit {
|
|||||||
this.md2Service.heros.forEach(hero => {
|
this.md2Service.heros.forEach(hero => {
|
||||||
hero.uiShowAttackBtn = this.md2Service.mobs.length > 0 || this.md2Service.roamingMonsters.length > 0 || this.md2Service.info.isBossFight;
|
hero.uiShowAttackBtn = this.md2Service.mobs.length > 0 || this.md2Service.roamingMonsters.length > 0 || this.md2Service.info.isBossFight;
|
||||||
});
|
});
|
||||||
this.md2Service.broadcastAllHeroInfoToAll();
|
this.md2Service.broadcastService.broadcastAllHeroInfoToAll();
|
||||||
}
|
}
|
||||||
removeHero(hero) {
|
removeHero(hero) {
|
||||||
this.msgBoxService.showConfirmDeleteBox().pipe(first()).subscribe(result => {
|
|
||||||
if (result) {
|
|
||||||
this.md2Service.info.heros.splice(this.md2Service.info.heros.indexOf(hero));
|
this.md2Service.info.heros.splice(this.md2Service.info.heros.indexOf(hero));
|
||||||
this.cdRef.detectChanges();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -15,7 +15,6 @@ export enum MobSkillType {
|
|||||||
Combat,
|
Combat,
|
||||||
Passive,
|
Passive,
|
||||||
ConditionalSkill,
|
ConditionalSkill,
|
||||||
OtherWiseSkill,
|
|
||||||
ActiveSkill,
|
ActiveSkill,
|
||||||
MeleeAttack = 15,
|
MeleeAttack = 15,
|
||||||
RangeAttack,
|
RangeAttack,
|
||||||
@ -53,7 +52,6 @@ export interface IBossFight {
|
|||||||
imgUrl: string
|
imgUrl: string
|
||||||
standUrl: string
|
standUrl: string
|
||||||
extraRules: string
|
extraRules: string
|
||||||
md2Service: MD2Service
|
|
||||||
activating(): boolean
|
activating(): boolean
|
||||||
prepareForBossFight(): void
|
prepareForBossFight(): void
|
||||||
darknessPhase(): void
|
darknessPhase(): void
|
||||||
@ -74,7 +72,7 @@ export abstract class BossFight implements IBossFight {
|
|||||||
extraRules: string
|
extraRules: string
|
||||||
protected subscription: Subscription
|
protected subscription: Subscription
|
||||||
|
|
||||||
constructor(public md2Service: MD2Service) {
|
constructor(protected md2Service: MD2Service) {
|
||||||
this.rounds = 1;
|
this.rounds = 1;
|
||||||
}
|
}
|
||||||
activating(): boolean {
|
activating(): boolean {
|
||||||
@ -106,26 +104,26 @@ export abstract class BossFight implements IBossFight {
|
|||||||
|
|
||||||
}
|
}
|
||||||
export class BossMicheal extends BossFight {
|
export class BossMicheal extends BossFight {
|
||||||
constructor(public md2Service: MD2Service) {
|
constructor(protected md2Service: MD2Service) {
|
||||||
super(md2Service);
|
super(md2Service);
|
||||||
this.corruptionTokenHtml = this.md2Service.imgHtml('Tokens/CorruptToken.png');
|
this.corruptionTokenHtml = this.md2Service.stateService.imgHtml('Tokens/CorruptToken.png');
|
||||||
|
|
||||||
this.name = 'Michael - The Corrupted Archangel';
|
this.name = 'Michael - The Corrupted Archangel';
|
||||||
this.imgUrl = md2Service.imgUrl('/Boss/Michael - The Corrupted Archangel.jpg');
|
this.imgUrl = md2Service.stateService.imgUrl('/Boss/Michael - The Corrupted Archangel.jpg');
|
||||||
this.standUrl = md2Service.imgUrl('/Boss/Michael.png');
|
this.standUrl = md2Service.stateService.imgUrl('/Boss/Michael.png');
|
||||||
|
|
||||||
this.info = new MobInfo({
|
this.info = new MobInfo({
|
||||||
description: this.name,
|
description: this.name,
|
||||||
type: MobType.Boss,
|
type: MobType.Boss,
|
||||||
hpPerHero: 15,
|
hpPerHero: 15,
|
||||||
level: 10,
|
level: 10,
|
||||||
imageUrl: md2Service.imgUrl('/Boss/Michael.png')
|
imageUrl: md2Service.stateService.imgUrl('/Boss/Michael.png')
|
||||||
});
|
});
|
||||||
if (!this.info.skills) {
|
if (!this.info.skills) {
|
||||||
this.info.skills = [];
|
this.info.skills = [];
|
||||||
}
|
}
|
||||||
this.info.skills.push({
|
this.info.skills.push({
|
||||||
name: `Combat 1 ${this.md2Service.iconHtml(MD2Icon.EnemySkill)}`,
|
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).`,
|
description: `Deal 1 Wound for each ${this.corruptionTokenHtml} on the attacking or defending Hero. Discard the tokens afterwards(once per combat).`,
|
||||||
type: MobSkillType.Combat,
|
type: MobSkillType.Combat,
|
||||||
skillRoll: 1
|
skillRoll: 1
|
||||||
@ -136,9 +134,9 @@ export class BossMicheal extends BossFight {
|
|||||||
this.actionBlackDice = 2;
|
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>` +
|
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.iconHtml(MD2Icon.BlackDice)}.` +
|
`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.iconHtml(MD2Icon.EnemyClaw)} the Hero takes 1 Wound.<br>If ${this.md2Service.iconHtml(MD2Icon.EnemySkill)} place 1 ${this.corruptionTokenHtml} on their Dashboard.<br>` +
|
`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.iconHtml(MD2Icon.EnemyClaw)}/${this.md2Service.iconHtml(MD2Icon.EnemySkill)} the Hero takes 1 Wound and places 1 ${this.corruptionTokenHtml} on their Dashboard.`
|
`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
|
activatedTimes: number
|
||||||
acted: number
|
acted: number
|
||||||
@ -233,26 +231,26 @@ export class BossMicheal extends BossFight {
|
|||||||
|
|
||||||
export class BossReaper extends BossFight {
|
export class BossReaper extends BossFight {
|
||||||
|
|
||||||
constructor(public md2Service: MD2Service) {
|
constructor(protected md2Service: MD2Service) {
|
||||||
super(md2Service);
|
super(md2Service);
|
||||||
this.timeTokenHtml = this.md2Service.imgHtml('Tokens/TimeToken.png');
|
this.timeTokenHtml = this.md2Service.stateService.imgHtml('Tokens/TimeToken.png');
|
||||||
|
|
||||||
this.name = 'The Reaper';
|
this.name = 'The Reaper';
|
||||||
this.imgUrl = md2Service.imgUrl('/Boss/The Reaper.jpg');
|
this.imgUrl = md2Service.stateService.imgUrl('/Boss/The Reaper.jpg');
|
||||||
this.standUrl = md2Service.imgUrl('/Boss/The Reaper-Stand.png');
|
this.standUrl = md2Service.stateService.imgUrl('/Boss/The Reaper-Stand.png');
|
||||||
|
|
||||||
this.info = new MobInfo({
|
this.info = new MobInfo({
|
||||||
description: this.name,
|
description: this.name,
|
||||||
type: MobType.Boss,
|
type: MobType.Boss,
|
||||||
hpPerHero: 25,
|
hpPerHero: 25,
|
||||||
level: 10,
|
level: 10,
|
||||||
imageUrl: md2Service.imgUrl('/Boss/The Reaper-Stand.png')
|
imageUrl: md2Service.stateService.imgUrl('/Boss/The Reaper-Stand.png')
|
||||||
});
|
});
|
||||||
if (!this.info.skills) {
|
if (!this.info.skills) {
|
||||||
this.info.skills = [];
|
this.info.skills = [];
|
||||||
}
|
}
|
||||||
this.info.skills.push({
|
this.info.skills.push({
|
||||||
description: `If the Hero has no ${this.md2Service.iconHtml(MD2Icon.Mana_Color)}, they take 1 ${this.md2Service.iconHtml(MD2Icon.FrozenToken)}`,
|
description: `If the Hero has no ${this.md2Service.stateService.iconHtml(MD2Icon.Mana_Color)}, they take 1 ${this.md2Service.stateService.iconHtml(MD2Icon.FrozenToken)}`,
|
||||||
type: MobSkillType.Attack,
|
type: MobSkillType.Attack,
|
||||||
skillRoll: 1
|
skillRoll: 1
|
||||||
} as MD2MobSkill);
|
} as MD2MobSkill);
|
||||||
@ -305,8 +303,8 @@ export class BossReaper extends BossFight {
|
|||||||
name: 'Death Is Coming',
|
name: 'Death Is Coming',
|
||||||
description:
|
description:
|
||||||
`Place The Reaper in the central Zone.<br>` +
|
`Place The Reaper in the central Zone.<br>` +
|
||||||
`Roll 1 ${this.md2Service.iconHtml(MD2Icon.YellowDice)}. Remove ${this.timeTokenHtml} equal to ${this.md2Service.iconHtml(MD2Icon.Melee)} rolled from both <b>Hourglass Zone</b>.<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.iconHtml(MD2Icon.MP)} equal to ${this.md2Service.iconHtml(MD2Icon.Melee)} rolled.`
|
`Each Hero discards ${this.md2Service.stateService.iconHtml(MD2Icon.MP)} equal to ${this.md2Service.stateService.iconHtml(MD2Icon.Melee)} rolled.`
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@ -37,10 +37,6 @@ export enum HeroClass {
|
|||||||
Shaman,
|
Shaman,
|
||||||
Paladin,
|
Paladin,
|
||||||
Druid,
|
Druid,
|
||||||
Necromancer,
|
|
||||||
Monk,
|
|
||||||
Thinker,
|
|
||||||
Bard
|
|
||||||
}
|
}
|
||||||
export enum MobType {
|
export enum MobType {
|
||||||
Mob,
|
Mob,
|
||||||
@ -381,6 +377,7 @@ export class MobInfo implements IDrawingItem {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public actionSubject: Subject<string>;
|
||||||
public activateFunction?: (mob: MobInfo, msgBoxService: MsgBoxService, heros: MD2HeroInfo[]) => void;
|
public activateFunction?: (mob: MobInfo, msgBoxService: MsgBoxService, heros: MD2HeroInfo[]) => void;
|
||||||
}
|
}
|
||||||
export interface MD2HeroProfile {
|
export interface MD2HeroProfile {
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import { MsgBoxService } from '../../../services/msg-box.service';
|
|||||||
import { DropDownOption } from '../../../entity/dropDownOption';
|
import { DropDownOption } from '../../../entity/dropDownOption';
|
||||||
import { MD2Icon } from '../massive-darkness2.model';
|
import { MD2Icon } from '../massive-darkness2.model';
|
||||||
import { first } from 'rxjs/operators';
|
import { first } from 'rxjs/operators';
|
||||||
|
import { MD2StateService } from '../../../services/MD2/md2-state.service';
|
||||||
import { MD2IconPickerDlgComponent } from './md2-icon-picker-dlg.component';
|
import { MD2IconPickerDlgComponent } from './md2-icon-picker-dlg.component';
|
||||||
import { NbDialogService } from '@nebular/theme';
|
import { NbDialogService } from '@nebular/theme';
|
||||||
import { DOMParser as ProseMirrorDOMParser } from 'prosemirror-model';
|
import { DOMParser as ProseMirrorDOMParser } from 'prosemirror-model';
|
||||||
@ -58,6 +59,7 @@ export class MD2HtmlEditorComponent implements ControlValueAccessor, AfterViewIn
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private msgBoxService: MsgBoxService,
|
private msgBoxService: MsgBoxService,
|
||||||
|
private md2StateService: MD2StateService,
|
||||||
private dialogService: DialogService,
|
private dialogService: DialogService,
|
||||||
private cdr: ChangeDetectorRef,
|
private cdr: ChangeDetectorRef,
|
||||||
elementRef: ElementRef, ngZone: NgZone, @Inject(PLATFORM_ID) platformId: Object) {
|
elementRef: ElementRef, ngZone: NgZone, @Inject(PLATFORM_ID) platformId: Object) {
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { NbDialogRef } from '@nebular/theme';
|
import { NbDialogRef } from '@nebular/theme';
|
||||||
import { MD2Icon } from '../massive-darkness2.model';
|
import { MD2Icon } from '../massive-darkness2.model';
|
||||||
|
import { MD2StateService } from '../../../services/MD2/md2-state.service';
|
||||||
import { DialogRef } from '@progress/kendo-angular-dialog';
|
import { DialogRef } from '@progress/kendo-angular-dialog';
|
||||||
import { MD2Service } from '../../../services/MD2/md2.service';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'md2-icon-picker-dlg',
|
selector: 'md2-icon-picker-dlg',
|
||||||
@ -63,7 +63,7 @@ export class MD2IconPickerDlgComponent implements OnInit {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private dlgRef: DialogRef,
|
private dlgRef: DialogRef,
|
||||||
private md2Service: MD2Service
|
private md2StateService: MD2StateService
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
@ -72,7 +72,7 @@ export class MD2IconPickerDlgComponent implements OnInit {
|
|||||||
this.iconList.push({
|
this.iconList.push({
|
||||||
icon: icon,
|
icon: icon,
|
||||||
name: MD2Icon[icon],
|
name: MD2Icon[icon],
|
||||||
html: this.md2Service.iconHtml(icon)
|
html: this.md2StateService.iconHtml(icon)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import { MD2Icon, TreasureType } from '../massive-darkness2.model';
|
import { MD2Icon, TreasureType } from '../massive-darkness2.model';
|
||||||
import { MD2Service } from '../../../services/MD2/md2.service';
|
import { MD2StateService } from '../../../services/MD2/md2-state.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'md2-icon',
|
selector: 'md2-icon',
|
||||||
@ -44,7 +44,7 @@ export class MD2IconComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
@Input() size: string = 'sm';
|
@Input() size: string = 'sm';
|
||||||
iconName: string;
|
iconName: string;
|
||||||
constructor(private md2Service: MD2Service) { }
|
constructor(private md2StateService: MD2StateService) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
}
|
}
|
||||||
@ -52,10 +52,10 @@ export class MD2IconComponent implements OnInit {
|
|||||||
private initIcon(icon: MD2Icon): void {
|
private initIcon(icon: MD2Icon): void {
|
||||||
if (icon < MD2Icon.TreasureToken) {
|
if (icon < MD2Icon.TreasureToken) {
|
||||||
this.isImageIcon = false;
|
this.isImageIcon = false;
|
||||||
this.iconHtml = this.md2Service.iconHtml(icon);
|
this.iconHtml = this.md2StateService.iconHtml(icon);
|
||||||
} else {
|
} else {
|
||||||
this.isImageIcon = true;
|
this.isImageIcon = true;
|
||||||
this.imgUrl = this.md2Service.iconHtml(icon);
|
this.imgUrl = this.md2StateService.iconHtml(icon);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -57,6 +57,7 @@ export class MD2MobInfoDetailComponent extends DialogContentBase implements OnIn
|
|||||||
private msgBoxService: MsgBoxService
|
private msgBoxService: MsgBoxService
|
||||||
) {
|
) {
|
||||||
super(dialog);
|
super(dialog);
|
||||||
|
this.initializeEnums();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
@ -67,7 +68,6 @@ export class MD2MobInfoDetailComponent extends DialogContentBase implements OnIn
|
|||||||
}
|
}
|
||||||
this.loadSkills();
|
this.loadSkills();
|
||||||
}
|
}
|
||||||
this.initializeEnums();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeEnums(): void {
|
private initializeEnums(): void {
|
||||||
@ -140,9 +140,6 @@ export class MD2MobInfoDetailComponent extends DialogContentBase implements OnIn
|
|||||||
attackInfo: lastLevel.attackInfo
|
attackInfo: lastLevel.attackInfo
|
||||||
? { ...lastLevel.attackInfo }
|
? { ...lastLevel.attackInfo }
|
||||||
: { type: MobSkillType.Attack, yellow: null, orange: null, red: null, blue: null, green: null, black: null },
|
: { type: MobSkillType.Attack, yellow: null, orange: null, red: null, blue: null, green: null, black: null },
|
||||||
alterAttackInfo: lastLevel.alterAttackInfo
|
|
||||||
? { ...lastLevel.alterAttackInfo }
|
|
||||||
: null,
|
|
||||||
defenceInfo: lastLevel.defenceInfo
|
defenceInfo: lastLevel.defenceInfo
|
||||||
? { ...lastLevel.defenceInfo }
|
? { ...lastLevel.defenceInfo }
|
||||||
: { type: MobSkillType.Defense, yellow: null, orange: null, red: null, blue: null, green: null, black: null }
|
: { type: MobSkillType.Defense, yellow: null, orange: null, red: null, blue: null, green: null, black: null }
|
||||||
@ -161,7 +158,6 @@ export class MD2MobInfoDetailComponent extends DialogContentBase implements OnIn
|
|||||||
hpPerHero: 0,
|
hpPerHero: 0,
|
||||||
actions: actions,
|
actions: actions,
|
||||||
attackInfo: { type: MobSkillType.Attack, yellow: null, orange: null, red: null, blue: null, green: null, black: null },
|
attackInfo: { type: MobSkillType.Attack, yellow: null, orange: null, red: null, blue: null, green: null, black: null },
|
||||||
alterAttackInfo: { type: MobSkillType.Attack, yellow: null, orange: null, red: null, blue: null, green: null, black: null },
|
|
||||||
defenceInfo: { type: MobSkillType.Defense, yellow: null, orange: null, red: null, blue: null, green: null, black: null }
|
defenceInfo: { type: MobSkillType.Defense, yellow: null, orange: null, red: null, blue: null, green: null, black: null }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -190,20 +186,14 @@ export class MD2MobInfoDetailComponent extends DialogContentBase implements OnIn
|
|||||||
case 1:
|
case 1:
|
||||||
newLevel.rewardTokens = 2;
|
newLevel.rewardTokens = 2;
|
||||||
newLevel.fixedRareTreasure = 1;
|
newLevel.fixedRareTreasure = 1;
|
||||||
newLevel.fixedEpicTreasure = 0;
|
|
||||||
newLevel.fixedLegendTreasure = 0;
|
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
newLevel.rewardTokens = 2;
|
newLevel.rewardTokens = 2;
|
||||||
newLevel.fixedRareTreasure = 0;
|
|
||||||
newLevel.fixedEpicTreasure = 1;
|
newLevel.fixedEpicTreasure = 1;
|
||||||
newLevel.fixedLegendTreasure = 0;
|
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
newLevel.rewardTokens = 0;
|
newLevel.rewardTokens = 0;
|
||||||
newLevel.fixedRareTreasure = 0;
|
|
||||||
newLevel.fixedEpicTreasure = 3;
|
newLevel.fixedEpicTreasure = 3;
|
||||||
newLevel.fixedLegendTreasure = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -319,11 +309,11 @@ export class MD2MobInfoDetailComponent extends DialogContentBase implements OnIn
|
|||||||
level: level,
|
level: level,
|
||||||
mobInfoId: this.mobInfo.id,
|
mobInfoId: this.mobInfo.id,
|
||||||
type: type,
|
type: type,
|
||||||
skillTarget: lastLevel?.skillTarget || MobSkillTarget.Random,
|
skillTarget: MobSkillTarget.Random,
|
||||||
clawRoll: lastLevel?.clawRoll || 0,
|
clawRoll: 0,
|
||||||
skillRoll: lastLevel?.skillRoll || 1,
|
skillRoll: 1,
|
||||||
name: lastLevel?.name || 'Combat Skill',
|
name: 'Basic Skill',
|
||||||
skillCondition: lastLevel?.skillCondition || '',
|
skillCondition: '',
|
||||||
description: lastLevel?.description || ''
|
description: lastLevel?.description || ''
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -20,15 +20,10 @@
|
|||||||
<kendo-grid-column field="name" title="Name" [width]="200">
|
<kendo-grid-column field="name" title="Name" [width]="200">
|
||||||
</kendo-grid-column>
|
</kendo-grid-column>
|
||||||
|
|
||||||
<kendo-grid-column field="type" title="Type" [width]="1">
|
<kendo-grid-column field="type" title="Type" [width]="150">
|
||||||
<ng-template kendoGridCellTemplate let-dataItem>
|
|
||||||
<ng-template kendoGridCellTemplate let-dataItem>
|
<ng-template kendoGridCellTemplate let-dataItem>
|
||||||
{{ getMobTypeName(dataItem.type) }}
|
{{ getMobTypeName(dataItem.type) }}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template kendoGridGroupHeaderTemplate let-value="value">
|
|
||||||
{{ getMobTypeName(value) }}
|
|
||||||
</ng-template>
|
|
||||||
</ng-template>
|
|
||||||
</kendo-grid-column>
|
</kendo-grid-column>
|
||||||
|
|
||||||
<kendo-grid-column field="from" title="Game Bundle" [width]="150">
|
<kendo-grid-column field="from" title="Game Bundle" [width]="150">
|
||||||
|
|||||||
@ -119,22 +119,6 @@
|
|||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<h5>Attack Info</h5>
|
<h5>Attack Info</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="k-label">
|
|
||||||
<md2-icon [icon]="MD2Icon.Attack"></md2-icon>Attack Type</label>
|
|
||||||
<!-- Dropdown list for attack type , the text is html string-->
|
|
||||||
<kendo-dropdownlist [(ngModel)]="selectedAttackType" name="attackInfo.type" [data]="attackTypes"
|
|
||||||
[textField]="'text'" [valueField]="'value'">
|
|
||||||
<ng-template kendoDropDownListItemTemplate let-dataItem>
|
|
||||||
<span [innerHTML]="dataItem.text"></span>
|
|
||||||
</ng-template>
|
|
||||||
<ng-template kendoDropDownListValueTemplate let-dataItem>
|
|
||||||
<span [innerHTML]="dataItem?.text || ''"></span>
|
|
||||||
</ng-template>
|
|
||||||
</kendo-dropdownlist>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="k-label">
|
<label class="k-label">
|
||||||
@ -173,63 +157,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row" *ngIf="mobType!=MobType.Mob">
|
|
||||||
<div class="col-md-12">
|
|
||||||
<h5>Alter Attack Info</h5>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-3">
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="k-label">
|
|
||||||
<md2-icon [icon]="MD2Icon.Attack"></md2-icon>Alter Attack Type</label>
|
|
||||||
<!-- Dropdown list for attack type , the text is html string-->
|
|
||||||
<kendo-dropdownlist [(ngModel)]="selectedAlterAttackType" name="alterAttackInfo.type"
|
|
||||||
[data]="attackTypes" [textField]="'text'" [valueField]="'value'">
|
|
||||||
<ng-template kendoDropDownListItemTemplate let-dataItem>
|
|
||||||
<span [innerHTML]="dataItem.text"></span>
|
|
||||||
</ng-template>
|
|
||||||
<ng-template kendoDropDownListValueTemplate let-dataItem>
|
|
||||||
<span [innerHTML]="dataItem?.text || ''"></span>
|
|
||||||
</ng-template>
|
|
||||||
</kendo-dropdownlist>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-2">
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="k-label">
|
|
||||||
<md2-icon [icon]="MD2Icon.YellowDice"></md2-icon>Yellow Dice</label>
|
|
||||||
<kendo-numerictextbox [(ngModel)]="model.alterAttackInfo.yellow" name="alterAttackInfo.yellow"
|
|
||||||
[min]="0" [decimals]="0" [format]="'n0'">
|
|
||||||
</kendo-numerictextbox>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-2">
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="k-label">
|
|
||||||
<md2-icon [icon]="MD2Icon.OrangeDice"></md2-icon>Orange Dice</label>
|
|
||||||
<kendo-numerictextbox [(ngModel)]="model.alterAttackInfo.orange" name="alterAttackInfo.orange"
|
|
||||||
[min]="0" [decimals]="0" [format]="'n0'">
|
|
||||||
</kendo-numerictextbox>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-2">
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="k-label">
|
|
||||||
<md2-icon [icon]="MD2Icon.RedDice"></md2-icon>Red Dice</label>
|
|
||||||
<kendo-numerictextbox [(ngModel)]="model.alterAttackInfo.red" name="alterAttackInfo.red" [min]="0"
|
|
||||||
[decimals]="0" [format]="'n0'">
|
|
||||||
</kendo-numerictextbox>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-2">
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="k-label">
|
|
||||||
<md2-icon [icon]="MD2Icon.BlackDice"></md2-icon>Black Dice</label>
|
|
||||||
<kendo-numerictextbox [(ngModel)]="model.alterAttackInfo.black" name="alterAttackInfo.black"
|
|
||||||
[min]="0" [decimals]="0" [format]="'n0'">
|
|
||||||
</kendo-numerictextbox>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,6 @@ import { MD2MobLevelInfo } from '../../massive-darkness2.db.model';
|
|||||||
import { MobSkillType } from '../../massive-darkness2.model.boss';
|
import { MobSkillType } from '../../massive-darkness2.model.boss';
|
||||||
import { MD2MobLevelInfoService } from '../../service/massive-darkness2.service';
|
import { MD2MobLevelInfoService } from '../../service/massive-darkness2.service';
|
||||||
import { MD2Icon, MobType } from '../../massive-darkness2.model';
|
import { MD2Icon, MobType } from '../../massive-darkness2.model';
|
||||||
import { MD2Service } from '../../../../services/MD2/md2.service';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ngx-md2-mob-level-editor',
|
selector: 'ngx-md2-mob-level-editor',
|
||||||
@ -21,35 +20,21 @@ export class MD2MobLevelEditorComponent extends DialogContentBase implements OnI
|
|||||||
@Input() public mobInfoId: string;
|
@Input() public mobInfoId: string;
|
||||||
@Input() public isAdding: boolean = false;
|
@Input() public isAdding: boolean = false;
|
||||||
|
|
||||||
public selectedAttackType: { value: MobSkillType; text: string } | null = null;
|
|
||||||
public model: MD2MobLevelInfo;
|
public model: MD2MobLevelInfo;
|
||||||
public processing: boolean = false;
|
public processing: boolean = false;
|
||||||
public attackTypes: Array<{ value: MobSkillType; text: string }> = [];
|
|
||||||
public selectedAlterAttackType: { value: MobSkillType; text: string } | null = null;
|
|
||||||
constructor(
|
constructor(
|
||||||
public dialog: DialogRef,
|
public dialog: DialogRef,
|
||||||
private mobLevelInfoService: MD2MobLevelInfoService,
|
private mobLevelInfoService: MD2MobLevelInfoService,
|
||||||
private cdr: ChangeDetectorRef,
|
private cdr: ChangeDetectorRef
|
||||||
private md2Service: MD2Service
|
|
||||||
) {
|
) {
|
||||||
super(dialog);
|
super(dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.initializeModel();
|
this.initializeModel();
|
||||||
this.initializeEnums();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public initializeEnums(): void {
|
|
||||||
this.attackTypes = [
|
|
||||||
{ value: MobSkillType.Attack, text: 'None' },
|
|
||||||
{ value: MobSkillType.MeleeAttack, text: this.md2Service.iconHtml(MD2Icon.Melee) + ' Melee Attack' },
|
|
||||||
{ value: MobSkillType.RangeAttack, text: this.md2Service.iconHtml(MD2Icon.Range) + ' Range Attack' },
|
|
||||||
{ value: MobSkillType.MagicAttack, text: this.md2Service.iconHtml(MD2Icon.Magic) + ' Magic Attack' },
|
|
||||||
];
|
|
||||||
this.selectedAttackType = this.attackTypes.find(t => t.value === this.model.attackInfo.type) || this.attackTypes[0] || null;
|
|
||||||
this.selectedAlterAttackType = this.attackTypes.find(t => t.value === this.model.alterAttackInfo?.type) || this.attackTypes[0] || null;
|
|
||||||
}
|
|
||||||
public initializeModel(): void {
|
public initializeModel(): void {
|
||||||
this.model = {
|
this.model = {
|
||||||
id: this.data?.id || '',
|
id: this.data?.id || '',
|
||||||
@ -65,9 +50,6 @@ export class MD2MobLevelEditorComponent extends DialogContentBase implements OnI
|
|||||||
attackInfo: this.data?.attackInfo
|
attackInfo: this.data?.attackInfo
|
||||||
? { ...this.data.attackInfo }
|
? { ...this.data.attackInfo }
|
||||||
: { type: MobSkillType.Attack, yellow: null, orange: null, red: null, blue: null, green: null, black: null },
|
: { type: MobSkillType.Attack, yellow: null, orange: null, red: null, blue: null, green: null, black: null },
|
||||||
alterAttackInfo: this.data?.alterAttackInfo
|
|
||||||
? { ...this.data.alterAttackInfo }
|
|
||||||
: { type: MobSkillType.Attack, yellow: null, orange: null, red: null, blue: null, green: null, black: null },
|
|
||||||
defenceInfo: this.data?.defenceInfo
|
defenceInfo: this.data?.defenceInfo
|
||||||
? { ...this.data.defenceInfo }
|
? { ...this.data.defenceInfo }
|
||||||
: { type: MobSkillType.Defense, yellow: null, orange: null, red: null, blue: null, green: null, black: null }
|
: { type: MobSkillType.Defense, yellow: null, orange: null, red: null, blue: null, green: null, black: null }
|
||||||
@ -91,10 +73,7 @@ export class MD2MobLevelEditorComponent extends DialogContentBase implements OnI
|
|||||||
if (!this.model.defenceInfo) {
|
if (!this.model.defenceInfo) {
|
||||||
this.model.defenceInfo = { type: MobSkillType.Defense, yellow: null, orange: null, red: null, blue: null, green: null, black: null };
|
this.model.defenceInfo = { type: MobSkillType.Defense, yellow: null, orange: null, red: null, blue: null, green: null, black: null };
|
||||||
}
|
}
|
||||||
this.model.attackInfo.type = this.selectedAttackType?.value ?? MobSkillType.Attack;
|
|
||||||
if (this.model.alterAttackInfo) {
|
|
||||||
this.model.alterAttackInfo.type = this.selectedAlterAttackType?.value ?? MobSkillType.Attack;
|
|
||||||
}
|
|
||||||
this.mobLevelInfoService.createOrUpdate(this.model).pipe(first()).subscribe(result => {
|
this.mobLevelInfoService.createOrUpdate(this.model).pipe(first()).subscribe(result => {
|
||||||
this.processing = false;
|
this.processing = false;
|
||||||
this.dialog.close(result);
|
this.dialog.close(result);
|
||||||
|
|||||||
@ -20,12 +20,13 @@
|
|||||||
<md2-icon icon="blackDice" size="lg"></md2-icon> {{skillTriggerHtml}} <md2-icon icon="enemySkill" size="md">
|
<md2-icon icon="blackDice" size="lg"></md2-icon> {{skillTriggerHtml}} <md2-icon icon="enemySkill" size="md">
|
||||||
</md2-icon>
|
</md2-icon>
|
||||||
</label> -->
|
</label> -->
|
||||||
<ng-container *ngFor="let skill of mob.skills">
|
<div *ngFor="let skill of mob.skills" class=" g-brd-bottom--dashed g-brd-gray-light-v2">
|
||||||
<div *ngIf="skill.uiDisplay" class=" g-brd-bottom--dashed g-brd-gray-light-v2">
|
<div *ngIf="skill.uiDisplay">
|
||||||
<label for='' class='MD2text g-font-size-22 label mb-2'>
|
<label for='' class='MD2text g-font-size-22 label mb-2'>
|
||||||
{{MobSkillType[skill.type]}} {{skill.skillRoll}} <md2-icon icon="enemySkill" size="md"></md2-icon>
|
{{MobSkillType[skill.type]}} {{skill.skillRoll}} <md2-icon icon="enemySkill" size="md"></md2-icon>
|
||||||
</label>
|
</label>
|
||||||
<div class='g-font-size-20 skillDesc MD2text' [innerHtml]="skill.description"></div>
|
<div class='g-font-size-20 skillDesc MD2text' [innerHtml]="skill.description"></div>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -22,13 +22,12 @@ export class MobCombatInfoComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Input() mode: MobDlgType = MobDlgType.PreView;
|
@Input() mode: MobDlgType = MobDlgType.PreView;
|
||||||
showAllSkill: boolean = false;
|
showSkill: boolean = false;
|
||||||
showBlackDice: boolean
|
showBlackDice: boolean
|
||||||
skillTriggerHtml: string = '';
|
skillTriggerHtml: string = '';
|
||||||
constructor() { }
|
constructor() { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.showAllSkill = [MobDlgType.PreView, MobDlgType.Dashboard].includes(this.mode);
|
|
||||||
if (this.mob.skills && this.mob.skills.length > 0) {
|
if (this.mob.skills && this.mob.skills.length > 0) {
|
||||||
this.mob.skills.forEach(element => {
|
this.mob.skills.forEach(element => {
|
||||||
switch (this.mode) {
|
switch (this.mode) {
|
||||||
@ -39,8 +38,7 @@ export class MobCombatInfoComponent implements OnInit {
|
|||||||
element.uiDisplay = [MobSkillType.Combat, MobSkillType.Defense].includes(element.type);
|
element.uiDisplay = [MobSkillType.Combat, MobSkillType.Defense].includes(element.type);
|
||||||
break;
|
break;
|
||||||
case MobDlgType.PreView:
|
case MobDlgType.PreView:
|
||||||
case MobDlgType.Dashboard:
|
element.uiDisplay = true;
|
||||||
element.uiDisplay = [MobSkillType.Combat, MobSkillType.Attack, MobSkillType.Defense].includes(element.type);
|
|
||||||
break;
|
break;
|
||||||
case MobDlgType.Spawn:
|
case MobDlgType.Spawn:
|
||||||
element.uiDisplay = false;
|
element.uiDisplay = false;
|
||||||
|
|||||||
@ -8,8 +8,8 @@
|
|||||||
<div class="pl-2 col-md-6" *ngIf="mob.mobAmount">
|
<div class="pl-2 col-md-6" *ngIf="mob.mobAmount">
|
||||||
|
|
||||||
<ng-container>
|
<ng-container>
|
||||||
<label class='label g-text-nowrap'>Minions <b
|
<label class='label g-text-nowrap'>Alive Units <b
|
||||||
class="MD2text g-font-size-18">{{mob.mobAmount-1}}</b></label><br>
|
class="MD2text g-font-size-18">{{mob.mobAmount}}</b></label><br>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -34,21 +34,11 @@
|
|||||||
|
|
||||||
|
|
||||||
<ng-container *ngIf="showAdjustment">
|
<ng-container *ngIf="showAdjustment">
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-6">
|
|
||||||
|
|
||||||
<adj-number-input name="mob{{mob.name}}" [ngModel]="mob.unitRemainHp" [maximum]="mob.hp" minimum="1"
|
<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)"
|
title="Target Unit HP" (hitChange)="adjustMobHp($event)" (hitMinimum)="adjustMobHp(-1)"
|
||||||
(hitMaximum)="adjustMobHp(1)">
|
(hitMaximum)="adjustMobHp(1)">
|
||||||
</adj-number-input>
|
</adj-number-input>
|
||||||
</div>
|
|
||||||
<div class="col-md-6" *ngIf="mode==MobDlgType.Activating">
|
|
||||||
|
|
||||||
<adj-number-input name="mob{{mob.name}}Actions" [(ngModel)]="mob.actions" title="Remaining Actions"
|
|
||||||
hideIncreaseBtn>
|
|
||||||
</adj-number-input>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
|
||||||
@ -60,8 +50,8 @@
|
|||||||
<md2-mob-attack-info [mob]="mob" [mode]="mode">
|
<md2-mob-attack-info [mob]="mob" [mode]="mode">
|
||||||
</md2-mob-attack-info>
|
</md2-mob-attack-info>
|
||||||
<md2-mob-def-info [mob]="mob" [mode]="mode"></md2-mob-def-info>
|
<md2-mob-def-info [mob]="mob" [mode]="mode"></md2-mob-def-info>
|
||||||
<md2-mob-combat-info *ngIf="!hideCombatInfo" [mob]="mob" [mode]="mode"></md2-mob-combat-info>
|
<md2-mob-combat-info [mob]="mob" [mode]="mode"></md2-mob-combat-info>
|
||||||
<div *ngIf="!hideCombatInfo && mob.extraRule">
|
<div *ngIf="mob.extraRule">
|
||||||
<div class="alert alert-warning" role="alert" [innerHtml]="mob.extraRule">
|
<div class="alert alert-warning" role="alert" [innerHtml]="mob.extraRule">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -12,7 +12,7 @@ import { MD2ComponentBase } from '../../MD2Base';
|
|||||||
styleUrls: ['./mob-detail-info.component.scss']
|
styleUrls: ['./mob-detail-info.component.scss']
|
||||||
})
|
})
|
||||||
export class MobDetailInfoComponent extends MD2ComponentBase implements OnInit {
|
export class MobDetailInfoComponent extends MD2ComponentBase implements OnInit {
|
||||||
MobDlgType = MobDlgType;
|
|
||||||
MD2Icon = MD2Icon;
|
MD2Icon = MD2Icon;
|
||||||
private _mob: MobInfo;
|
private _mob: MobInfo;
|
||||||
public get mob(): MobInfo {
|
public get mob(): MobInfo {
|
||||||
@ -33,10 +33,6 @@ export class MobDetailInfoComponent extends MD2ComponentBase implements OnInit {
|
|||||||
return this.mode == MobDlgType.Spawn;
|
return this.mode == MobDlgType.Spawn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get hideCombatInfo(): boolean {
|
|
||||||
return this.mode == MobDlgType.Dashboard;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
showAttackingInfo: boolean = false;
|
showAttackingInfo: boolean = false;
|
||||||
@Input("showAttackingInfo")
|
@Input("showAttackingInfo")
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
<img class="g-width-95x img-thumbnail mobBg" src="{{imgUrl('/Mobs/BG.png')}}" />
|
<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" />
|
<img class="mobImg roamingMonster" src="{{getMobImageUrl(mob)}}" (click)="showMobImage(mob)" *ngIf="!isMob" />
|
||||||
<div *ngIf="isMob">
|
<div *ngIf="isMob">
|
||||||
<img class="mobImg mobLeader" src="{{mob.leaderImgUrl}}" (click)="showMobImage(mob)"
|
<img class="mobImg mobLeader" src="{{mob.leaderImgUrl}}" (click)="showMobImage(mob)" />
|
||||||
[ngClass]="{'noMinions': mob.mobAmount==1}" />
|
<img class="mobImg mobMinion" src="{{mob.minionImgUrl}}" (click)="showMobImage(mob)" />
|
||||||
<img class="mobImg mobMinion" src="{{mob.minionImgUrl}}" (click)="showMobImage(mob)" *ngIf="mob.mobAmount>1" />
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -1,31 +1,23 @@
|
|||||||
.mobImg {
|
.mobImg {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
object-fit: contain;
|
|
||||||
&.roamingMonster {
|
&.roamingMonster {
|
||||||
width: 95%;
|
width: 95%;
|
||||||
max-height: 80%;
|
max-height: 80%;
|
||||||
left: 0;
|
|
||||||
}
|
}
|
||||||
&.mobLeader {
|
&.mobLeader {
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
width: 70%;
|
width: 70%;
|
||||||
max-height: 80%;
|
max-height: 80%;
|
||||||
top: 40px;
|
top: 40px;
|
||||||
left: 0;
|
|
||||||
&.noMinions {
|
|
||||||
width: 95%;
|
|
||||||
max-height: 90%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
&.mobMinion {
|
&.mobMinion {
|
||||||
width: 60%;
|
width: 60%;
|
||||||
max-height: 80%;
|
max-height: 80%;
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.mobBg {
|
.mobBg {
|
||||||
position: relative;
|
position: absolute;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,12 +29,6 @@
|
|||||||
<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>
|
<md2-mob-stand-info [mob]="mob"></md2-mob-stand-info>
|
||||||
|
|
||||||
<md2-mob-combat-info [mob]="mob" [mode]="MobDlgType.Dashboard"></md2-mob-combat-info>
|
|
||||||
<div *ngIf="mob.extraRule">
|
|
||||||
<div class="alert alert-warning" role="alert" [innerHtml]="mob.extraRule">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class=" col-12 col-md-4">
|
<div class=" col-12 col-md-4">
|
||||||
|
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import { StateService } from '../../../services/state.service';
|
|||||||
import { ADButtons, ADIcon } from '../../../ui/alert-dlg/alert-dlg.model';
|
import { ADButtons, 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 { StringUtils } from '../../../utilities/string-utils';
|
||||||
|
import { CoreGameRMFactories } from '../factorys/roamingMonsters/CoreGame';
|
||||||
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';
|
||||||
@ -88,7 +89,7 @@ export class MobsComponent extends MD2ComponentBase implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
spawnSpecificMob() {
|
spawnSpecificMob() {
|
||||||
let mobOptions = this.isRoamingMonster ? this.md2Service.allRoamingMonsterInfos.map(f => new DropDownOption(f.name, f.name)) : this.md2Service.allMobInfos.map(f => new DropDownOption(f.name, f.name));
|
let mobOptions = this.isRoamingMonster ? CoreGameRMFactories.map(f => new DropDownOption(f.mobName, f.mobName)) : this.md2Service.allMobInfos.map(f => new DropDownOption(f.name, f.name));
|
||||||
this.msgBoxService.showInputbox('Spawn', '',
|
this.msgBoxService.showInputbox('Spawn', '',
|
||||||
{
|
{
|
||||||
inputType: 'dropdown', dropDownOptions: mobOptions,
|
inputType: 'dropdown', dropDownOptions: mobOptions,
|
||||||
@ -119,7 +120,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 });
|
||||||
}
|
}
|
||||||
@ -150,7 +151,7 @@ export class MobsComponent extends MD2ComponentBase implements OnInit {
|
|||||||
if (attacker) {
|
if (attacker) {
|
||||||
attacker.exp += 1;
|
attacker.exp += 1;
|
||||||
this.msgBoxService.show(`${attacker.heroFullName} Gain 1 Exp`, { icon: ADIcon.INFO }).pipe(first()).subscribe(result => {
|
this.msgBoxService.show(`${attacker.heroFullName} Gain 1 Exp`, { icon: ADIcon.INFO }).pipe(first()).subscribe(result => {
|
||||||
this.md2Service.broadcastHeroInfoToOwner(attacker);
|
this.md2Service.broadcastService.broadcastHeroInfoToOwner(attacker);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,33 +5,20 @@
|
|||||||
</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>
|
<md2-mob-stand-info [mob]="mob" [mode]="mode"></md2-mob-stand-info>
|
||||||
|
|
||||||
<div *ngIf="activeSkill">
|
|
||||||
<!-- <div class="alert alert-warning" role="alert">
|
|
||||||
<h4>{{activeSkill.name}}</h4>
|
|
||||||
<div [innerHtml]="activeSkill.description"></div>
|
|
||||||
</div> -->
|
|
||||||
<details class="skill-card" open>
|
|
||||||
<summary>
|
|
||||||
<h3 class="skill-name">{{ activeSkill.name }}</h3>
|
|
||||||
<!-- <span class="rarity" [ngClass]="rarity.toLowerCase()">{{ rarity }}</span> -->
|
|
||||||
</summary>
|
|
||||||
<div class="skill-body" [innerHtml]="activeSkill.description">
|
|
||||||
<!-- <p>{{ description }}</p>
|
|
||||||
<ul>
|
|
||||||
<li *ngFor="let s of stats"><strong>{{ s.label }}:</strong> {{ s.value }}</li>
|
|
||||||
</ul> -->
|
|
||||||
</div>
|
|
||||||
</details>
|
|
||||||
</div>
|
|
||||||
</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">
|
||||||
|
|||||||
@ -2,122 +2,3 @@
|
|||||||
width: 885px;
|
width: 885px;
|
||||||
height: 95vh !important;
|
height: 95vh !important;
|
||||||
}
|
}
|
||||||
.skill-card {
|
|
||||||
border-radius: 16px;
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
border: 1px solid #252a34;
|
|
||||||
background: radial-gradient(120% 180% at 50% -40%, rgba(217, 143, 43, 0.08), transparent 60%),
|
|
||||||
linear-gradient(180deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0.01)), #14161b;
|
|
||||||
transition:
|
|
||||||
transform 0.12s ease,
|
|
||||||
box-shadow 0.25s ease,
|
|
||||||
filter 0.2s ease;
|
|
||||||
margin-top: -130px;
|
|
||||||
z-index: 1;
|
|
||||||
width: 96%;
|
|
||||||
}
|
|
||||||
.skill-card::before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
pointer-events: none;
|
|
||||||
border-radius: 16px;
|
|
||||||
padding: 1px;
|
|
||||||
background: linear-gradient(
|
|
||||||
180deg,
|
|
||||||
rgba(246, 230, 185, 0.6),
|
|
||||||
rgba(176, 136, 46, 0.35) 55%,
|
|
||||||
rgba(246, 230, 185, 0.6)
|
|
||||||
);
|
|
||||||
-webkit-mask:
|
|
||||||
linear-gradient(#000 0 0) content-box,
|
|
||||||
linear-gradient(#000 0 0);
|
|
||||||
-webkit-mask-composite: xor;
|
|
||||||
mask-composite: exclude;
|
|
||||||
}
|
|
||||||
.skill-card[open] {
|
|
||||||
box-shadow:
|
|
||||||
0 0 0 2px rgba(217, 143, 43, 0.25),
|
|
||||||
0 12px 28px rgba(0, 0, 0, 0.6);
|
|
||||||
}
|
|
||||||
|
|
||||||
summary {
|
|
||||||
list-style: none;
|
|
||||||
cursor: pointer;
|
|
||||||
position: relative;
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr auto;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.75rem;
|
|
||||||
padding: 6px 1rem;
|
|
||||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0));
|
|
||||||
}
|
|
||||||
summary::-webkit-details-marker {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
summary:hover {
|
|
||||||
filter: saturate(1.08);
|
|
||||||
box-shadow:
|
|
||||||
0 0 0 2px rgba(155, 28, 28, 0.25),
|
|
||||||
0 0 18px rgba(217, 143, 43, 0.18) inset;
|
|
||||||
}
|
|
||||||
summary:focus-visible {
|
|
||||||
outline: 2px solid #d98f2b;
|
|
||||||
outline-offset: 2px;
|
|
||||||
box-shadow: 0 0 18px rgba(217, 143, 43, 0.35);
|
|
||||||
}
|
|
||||||
|
|
||||||
.skill-name {
|
|
||||||
margin: 0;
|
|
||||||
font-size: 2rem;
|
|
||||||
letter-spacing: 0.04em;
|
|
||||||
background: linear-gradient(180deg, #f6e6b9, #b0882e 50%, #f6e6b9);
|
|
||||||
-webkit-background-clip: text;
|
|
||||||
background-clip: text;
|
|
||||||
color: transparent;
|
|
||||||
font-family: "DwarvenAxeBBW00-Regular", sans-serif !important;
|
|
||||||
}
|
|
||||||
.rarity {
|
|
||||||
font-size: 0.75rem;
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: 0.12em;
|
|
||||||
padding: 0.25rem 0.5rem;
|
|
||||||
border-radius: 999px;
|
|
||||||
border: 1px solid rgba(240, 217, 154, 0.45);
|
|
||||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.02));
|
|
||||||
color: #e8e5de;
|
|
||||||
}
|
|
||||||
.rarity.legendary {
|
|
||||||
border-color: rgba(217, 143, 43, 0.6);
|
|
||||||
box-shadow: inset 0 0 10px rgba(217, 143, 43, 0.25);
|
|
||||||
}
|
|
||||||
.rarity.epic {
|
|
||||||
border-color: rgba(155, 28, 28, 0.6);
|
|
||||||
box-shadow: inset 0 0 10px rgba(155, 28, 28, 0.3);
|
|
||||||
}
|
|
||||||
.rarity.rare {
|
|
||||||
border-color: rgba(148, 164, 58, 0.6);
|
|
||||||
box-shadow: inset 0 0 10px rgba(148, 164, 58, 0.28);
|
|
||||||
}
|
|
||||||
::ng-deep {
|
|
||||||
.skill-body {
|
|
||||||
padding: 0 1rem 1rem;
|
|
||||||
color: #cfcab7;
|
|
||||||
}
|
|
||||||
.skill-body p {
|
|
||||||
margin: 0.6rem 0 0.4rem;
|
|
||||||
color: #ddd6bf;
|
|
||||||
}
|
|
||||||
.skill-body ul {
|
|
||||||
margin: 0.25rem 0 0;
|
|
||||||
padding-left: 1.1rem;
|
|
||||||
}
|
|
||||||
.skill-body li {
|
|
||||||
margin: 0.25rem 0;
|
|
||||||
color: #a7a196;
|
|
||||||
}
|
|
||||||
.skill-body strong {
|
|
||||||
color: #efe7cf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,7 +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 { concatMap, find, defaultIfEmpty, first, map, switchMap } from 'rxjs/operators';
|
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';
|
||||||
@ -9,12 +9,6 @@ import { StateService } from '../../../../services/state.service';
|
|||||||
import { StringUtils } from '../../../../utilities/string-utils';
|
import { StringUtils } from '../../../../utilities/string-utils';
|
||||||
import { AttackInfo, AttackTarget, AttackType, MD2HeroInfo, MD2Icon, MobDlgType, MobInfo, MobType } from '../../massive-darkness2.model';
|
import { AttackInfo, AttackTarget, AttackType, MD2HeroInfo, MD2Icon, MobDlgType, MobInfo, MobType } from '../../massive-darkness2.model';
|
||||||
import { MD2ComponentBase } from '../../MD2Base';
|
import { MD2ComponentBase } from '../../MD2Base';
|
||||||
import { ADButtons, ADIcon } from '../../../../ui/alert-dlg/alert-dlg.model';
|
|
||||||
import { MobSkillType } from '../../massive-darkness2.model.boss';
|
|
||||||
import { Observable, from, of } from 'rxjs';
|
|
||||||
import { MD2MobSkill } from '../../massive-darkness2.db.model';
|
|
||||||
|
|
||||||
type SkillResolutionResult = { result: boolean; skill: MD2MobSkill | null };
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ngx-spawn-mob-dlg',
|
selector: 'ngx-spawn-mob-dlg',
|
||||||
@ -44,34 +38,16 @@ export class SpawnMobDlgComponent extends MD2ComponentBase implements OnInit {
|
|||||||
) {
|
) {
|
||||||
super(md2Service, stateService, route, cdRef);
|
super(md2Service, stateService, route, cdRef);
|
||||||
}
|
}
|
||||||
activeSkill: MD2MobSkill = null;;
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
//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) {
|
} else if (this.mode == MobDlgType.Activating) {
|
||||||
if (this.mob.skills) {
|
if (this.mob.actionSubject) {
|
||||||
|
this.mob.actionSubject.pipe(first()).subscribe(result => {
|
||||||
//this.mobActivate(this.mob, this.md2Service.info.heros);
|
this.actionInfoHtml = result;
|
||||||
//this.mob.activateFunction(this.mob, this.md2Service.msgBoxService, this.md2Service.info.heros);
|
|
||||||
this.mobActivate(this.mob, this.md2Service.info.heros).pipe(first()).subscribe(result => {
|
|
||||||
if (result && result.skill) {
|
|
||||||
this.activeSkill = result.skill;
|
|
||||||
//this.actionInfoHtml = `<h4>${result.skill.name}</h4><div>${result.skill.description}</div>`;
|
|
||||||
}
|
|
||||||
if (this.mob.type == MobType.Mob) {
|
|
||||||
this.mob.actions = 2;
|
|
||||||
} else {
|
|
||||||
if (result && result.skill) {
|
|
||||||
this.mob.actions = 1;
|
|
||||||
} else {
|
|
||||||
this.mob.actions = 2;
|
|
||||||
this.activeSkill = { name: 'Normal Action', description: `${this.mob.name} Gains 2 Actions.` } as MD2MobSkill;
|
|
||||||
//this.actionInfoHtml = `${this.mob.name} Gains 2 Actions.`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
this.mob.activateFunction(this.mob, this.md2Service.msgBoxService, this.md2Service.info.heros);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.mob.uiWounds = 0;
|
this.mob.uiWounds = 0;
|
||||||
@ -79,52 +55,6 @@ export class SpawnMobDlgComponent extends MD2ComponentBase implements OnInit {
|
|||||||
this.mob.uiFrozenTokens = 0;
|
this.mob.uiFrozenTokens = 0;
|
||||||
this.initTitleHtml();
|
this.initTitleHtml();
|
||||||
}
|
}
|
||||||
|
|
||||||
mobActivate(mob: MobInfo, heros: MD2HeroInfo[]): Observable<SkillResolutionResult> {
|
|
||||||
switch (mob.type) {
|
|
||||||
case MobType.Mob:
|
|
||||||
return of({ result: false, skill: null } as SkillResolutionResult);
|
|
||||||
case MobType.RoamingMonster:
|
|
||||||
if (!mob.skills || mob.skills.length === 0) {
|
|
||||||
return of({ result: false, skill: null } as SkillResolutionResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
const orderedSkills = mob.skills
|
|
||||||
.filter(s => [MobSkillType.ConditionalSkill, MobSkillType.OtherWiseSkill].includes(s.type))
|
|
||||||
.sort((a, b) => (a.seq ?? Number.MAX_SAFE_INTEGER) - (b.seq ?? Number.MAX_SAFE_INTEGER));
|
|
||||||
|
|
||||||
if (orderedSkills.length === 0) {
|
|
||||||
return of({ result: false, skill: null } as SkillResolutionResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
return from(orderedSkills).pipe(
|
|
||||||
concatMap(skill => this.resolveSkillPrompt(skill)),
|
|
||||||
find(resolution => resolution.result === true),
|
|
||||||
defaultIfEmpty({ result: false, skill: null } as SkillResolutionResult)
|
|
||||||
);
|
|
||||||
case MobType.Boss:
|
|
||||||
default:
|
|
||||||
return of({ result: false, skill: null } as SkillResolutionResult);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private resolveSkillPrompt(skill: MD2MobSkill): Observable<SkillResolutionResult> {
|
|
||||||
if (skill.type === MobSkillType.OtherWiseSkill) {
|
|
||||||
return of({ result: true, skill } as SkillResolutionResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
const title = 'Resolve Skill?';
|
|
||||||
const prompt = skill.skillCondition;
|
|
||||||
|
|
||||||
return this.msgBoxService.show(title, {
|
|
||||||
text: prompt,
|
|
||||||
icon: ADIcon.QUESTION,
|
|
||||||
buttons: ADButtons.YesNo
|
|
||||||
}).pipe(
|
|
||||||
map(answer => ({ result: !!answer, skill } as SkillResolutionResult))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
if (this.mode == MobDlgType.Spawn) {
|
if (this.mode == MobDlgType.Spawn) {
|
||||||
|
|
||||||
|
|||||||
16
src/app/services/MD2/md2-broadcast.service.spec.ts
Normal file
16
src/app/services/MD2/md2-broadcast.service.spec.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { MD2BroadcastService } from './md2-broadcast.service';
|
||||||
|
|
||||||
|
describe('MD2BroadcastService', () => {
|
||||||
|
let service: MD2BroadcastService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(MD2BroadcastService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
110
src/app/services/MD2/md2-broadcast.service.ts
Normal file
110
src/app/services/MD2/md2-broadcast.service.ts
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { NbDialogService } from '@nebular/theme';
|
||||||
|
import { first } from 'rxjs/operators';
|
||||||
|
import { MD2HeroInfo } from '../../games/massive-darkness2/massive-darkness2.model';
|
||||||
|
import { FileService } from '../file.service';
|
||||||
|
import { GameRoomService } from '../game-room.service';
|
||||||
|
import { LoginUserService } from '../login-user.service';
|
||||||
|
import { SignalRService, SignalRSession, SignalRMessage } from '../signal-r.service';
|
||||||
|
import { MD2StateService } from './md2-state.service';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class MD2BroadcastService {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public fileService: FileService,
|
||||||
|
private gameRoomService: GameRoomService,
|
||||||
|
private loginUserService: LoginUserService,
|
||||||
|
public stateService: MD2StateService,
|
||||||
|
public signalRService: SignalRService,
|
||||||
|
public dlgService: NbDialogService
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public get playerHero(): MD2HeroInfo {
|
||||||
|
return this.stateService.playerHero;
|
||||||
|
}
|
||||||
|
public broadcastAllHeroInfoToAll() {
|
||||||
|
this.stateService.info.heros.forEach(element => {
|
||||||
|
this.broadcastHeroInfoToAll(element);
|
||||||
|
});
|
||||||
|
this.broadcastMobsInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
public broadcastHeroAction(action: string, extraValue: any = null) {
|
||||||
|
let parameters = {};
|
||||||
|
parameters['tabId'] = this.loginUserService.sessionTabId;
|
||||||
|
parameters['extraValue'] = JSON.stringify(extraValue);
|
||||||
|
this.broadcastMessage('heroAction', action, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public broadcastHeroInfoToAll(hero: MD2HeroInfo) {
|
||||||
|
let message = {
|
||||||
|
receiver: { isGroup: true, sessionId: this.gameRoomService.gameRoomId } as SignalRSession,
|
||||||
|
from: { isGroup: false, sessionId: hero.playerInfo.signalRClientId },
|
||||||
|
actionType: 'hero',
|
||||||
|
actionName: 'update',
|
||||||
|
} as SignalRMessage;
|
||||||
|
message.parameters = { hero: JSON.stringify(hero) };
|
||||||
|
this.gameRoomService.sendMessage(message).pipe(first()).subscribe(result => {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public broadcastHeroInfoToOwner(hero: MD2HeroInfo) {
|
||||||
|
let message = {
|
||||||
|
receiver: { isGroup: false, sessionId: hero.playerInfo.signalRClientId } as SignalRSession,
|
||||||
|
from: { isGroup: true, sessionId: this.gameRoomService.gameRoomId },
|
||||||
|
actionType: 'hero',
|
||||||
|
actionName: 'updateMyHero',
|
||||||
|
} as SignalRMessage;
|
||||||
|
message.parameters = { hero: JSON.stringify(hero) };
|
||||||
|
this.gameRoomService.sendMessage(message).pipe(first()).subscribe(result => {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `sessionId` = null means broadcast to all
|
||||||
|
*/
|
||||||
|
public broadcastMessage(actionType: string,
|
||||||
|
actionName: string,
|
||||||
|
parameters: { [key: string]: string; } = {},
|
||||||
|
sessionId: string = null) {
|
||||||
|
let message = {
|
||||||
|
receiver: { isGroup: !sessionId, sessionId: sessionId } as SignalRSession,
|
||||||
|
from: { isGroup: false, sessionId: this.loginUserService.userAccess.signalRSessionId },
|
||||||
|
actionType: actionType,
|
||||||
|
actionName: actionName,
|
||||||
|
parameters: parameters
|
||||||
|
} as SignalRMessage;
|
||||||
|
|
||||||
|
if (sessionId == null) {
|
||||||
|
message.receiver = { isGroup: true, sessionId: this.gameRoomService.gameRoomId } as SignalRSession
|
||||||
|
} else {
|
||||||
|
message.receiver = { isGroup: false, sessionId: this.gameRoomService.gameRoomId } as SignalRSession
|
||||||
|
}
|
||||||
|
this.gameRoomService.sendMessage(message).pipe(first()).subscribe(result => {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public broadcastGameInfo() {
|
||||||
|
let parameters = {};
|
||||||
|
parameters['gameInfo'] = JSON.stringify(this.stateService.info);
|
||||||
|
this.broadcastMessage('GameRoom', 'update', parameters);
|
||||||
|
}
|
||||||
|
public broadcastRoundPhase() {
|
||||||
|
let parameters = {};
|
||||||
|
parameters['phase'] = JSON.stringify(this.stateService.info.roundPhase);
|
||||||
|
this.broadcastMessage('GameRoom', 'phase', parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public broadcastMobsInfo() {
|
||||||
|
let parameters = {};
|
||||||
|
parameters['roamingMonsters'] = JSON.stringify(this.stateService.info.roamingMonsters);
|
||||||
|
parameters['mobs'] = JSON.stringify(this.stateService.info.mobs);
|
||||||
|
this.broadcastMessage('mobs', 'update', parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public broadcastMyHeroInfo() {
|
||||||
|
this.broadcastHeroInfoToAll(this.playerHero);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,8 +1,9 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { DrawingBag, MobInfo, MobType, TreasureItem, TreasureType } from '../../games/massive-darkness2/massive-darkness2.model';
|
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';
|
||||||
import { MD2MobInfoService } from '../../games/massive-darkness2/service/massive-darkness2.service';
|
import { MD2MobInfoService } from '../../games/massive-darkness2/service/massive-darkness2.service';
|
||||||
import { first } from 'rxjs/operators';
|
import { first } from 'rxjs/operators';
|
||||||
import { MD2Service } from './md2.service';
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@ -10,18 +11,28 @@ import { MD2Service } from './md2.service';
|
|||||||
export class MD2InitService {
|
export class MD2InitService {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private md2Service: MD2Service,
|
private stateService: MD2StateService,
|
||||||
private mobInfoService: MD2MobInfoService,
|
private mobInfoService: MD2MobInfoService,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
public initMobDecks() {
|
public initMobDecks() {
|
||||||
this.md2Service.mobDeck = new DrawingBag();
|
this.stateService.mobDeck = new DrawingBag();
|
||||||
this.md2Service.roamingMobDeck = new DrawingBag();
|
this.stateService.roamingMobDeck = new DrawingBag();
|
||||||
|
|
||||||
this.initCoreGameMobAndRoamingMonsters();
|
this.initCoreGameMobs();
|
||||||
|
this.initCoreGameRoamingMonsters();
|
||||||
}
|
}
|
||||||
|
|
||||||
private initCoreGameMobAndRoamingMonsters() {
|
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 => {
|
// CoreGameMobFactories.forEach(factory => {
|
||||||
// for (let i = 1; i <= 5; i++) {
|
// for (let i = 1; i <= 5; i++) {
|
||||||
// this.stateService.mobDeck.AddItem(new MobInfo({ name: factory.mobName, level: i, drawingWeight: 1 }));
|
// this.stateService.mobDeck.AddItem(new MobInfo({ name: factory.mobName, level: i, drawingWeight: 1 }));
|
||||||
@ -29,20 +40,13 @@ export class MD2InitService {
|
|||||||
// }
|
// }
|
||||||
// });
|
// });
|
||||||
this.mobInfoService.getAll().pipe(first()).subscribe(result => {
|
this.mobInfoService.getAll().pipe(first()).subscribe(result => {
|
||||||
this.md2Service.mobInfos = result.filter(m => m.type == MobType.Mob);
|
this.stateService.mobInfos = result;
|
||||||
this.md2Service.roamingMobInfos = result.filter(m => m.type == MobType.RoamingMonster);
|
|
||||||
for (let i = 0; i < result.length; i++) {
|
for (let i = 0; i < result.length; i++) {
|
||||||
const mobInfo = result[i];
|
const mobInfo = result[i];
|
||||||
for (let j = 0; j < mobInfo.mobLevelInfos.length; j++) {
|
for (let j = 0; j < mobInfo.mobLevelInfos.length; j++) {
|
||||||
const levelInfo = mobInfo.mobLevelInfos[j];
|
const levelInfo = mobInfo.mobLevelInfos[j];
|
||||||
switch (mobInfo.type) {
|
|
||||||
case MobType.Mob:
|
this.stateService.mobDeck.AddItem(new MobInfo({ name: mobInfo.name, level: levelInfo.level, drawingWeight: 1 }));
|
||||||
this.md2Service.mobDeck.AddItem(new MobInfo({ name: mobInfo.name, level: levelInfo.level, drawingWeight: 1 }));
|
|
||||||
break;
|
|
||||||
case MobType.RoamingMonster:
|
|
||||||
this.md2Service.roamingMobDeck.AddItem(new MobInfo({ name: mobInfo.name, level: levelInfo.level, drawingWeight: 1 }));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,12 +57,12 @@ export class MD2InitService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public initTreasureBag() {
|
public initTreasureBag() {
|
||||||
this.md2Service.treasureBag.ClearAllItems();
|
this.stateService.treasureBag.ClearAllItems();
|
||||||
this.addTreasure(TreasureType.Common, 15);
|
this.addTreasure(TreasureType.Common, 15);
|
||||||
this.addTreasure(TreasureType.Rare, 5);
|
this.addTreasure(TreasureType.Rare, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
public addTreasure(type: TreasureType, amount: number = 1) {
|
public addTreasure(type: TreasureType, amount: number = 1) {
|
||||||
this.md2Service.treasureBag.AddItem(new TreasureItem(type, amount));
|
this.stateService.treasureBag.AddItem(new TreasureItem(type, amount));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { first } from 'rxjs/operators';
|
|||||||
import { MobInfo, MobType } from '../../games/massive-darkness2/massive-darkness2.model';
|
import { MobInfo, MobType } from '../../games/massive-darkness2/massive-darkness2.model';
|
||||||
import { ADIcon } from '../../ui/alert-dlg/alert-dlg.model';
|
import { ADIcon } from '../../ui/alert-dlg/alert-dlg.model';
|
||||||
import { MsgBoxService } from '../msg-box.service';
|
import { MsgBoxService } from '../msg-box.service';
|
||||||
|
import { MD2StateService } from './md2-state.service';
|
||||||
import { MD2Service } from './md2.service';
|
import { MD2Service } from './md2.service';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
@ -15,13 +16,14 @@ export class MD2MobService {
|
|||||||
attackingAttackerReward: string = '';
|
attackingAttackerReward: string = '';
|
||||||
constructor(
|
constructor(
|
||||||
private md2Service: MD2Service,
|
private md2Service: MD2Service,
|
||||||
|
private stateService: MD2StateService,
|
||||||
private msgBoxService: MsgBoxService
|
private msgBoxService: MsgBoxService
|
||||||
) { }
|
) { }
|
||||||
public get roamingMonsters() {
|
public get roamingMonsters() {
|
||||||
return this.md2Service.info.roamingMonsters;
|
return this.stateService.info.roamingMonsters;
|
||||||
}
|
}
|
||||||
public get mobs() {
|
public get mobs() {
|
||||||
return this.md2Service.info.mobs;
|
return this.stateService.info.mobs;
|
||||||
}
|
}
|
||||||
|
|
||||||
addOneUnit(mob: MobInfo) {
|
addOneUnit(mob: MobInfo) {
|
||||||
@ -118,14 +120,14 @@ export class MD2MobService {
|
|||||||
}
|
}
|
||||||
this.attackingAllExp = 0;
|
this.attackingAllExp = 0;
|
||||||
this.attackingAttackerExp = 0;
|
this.attackingAttackerExp = 0;
|
||||||
this.md2Service.broadcastAllHeroInfoToAll();
|
this.md2Service.broadcastService.broadcastAllHeroInfoToAll();
|
||||||
this.md2Service.refreshUI$.next();
|
this.md2Service.refreshUI$.next();
|
||||||
});
|
});
|
||||||
} else if (this.attackingAttackerExp > 0 && attacker) {
|
} else if (this.attackingAttackerExp > 0 && attacker) {
|
||||||
this.msgBoxService.show(`<b>${attackerTitle}</b> Gains ${this.attackingAttackerExp} Exp`, { icon: ADIcon.INFO }).pipe(first()).subscribe(result => {
|
this.msgBoxService.show(`<b>${attackerTitle}</b> Gains ${this.attackingAttackerExp} Exp`, { icon: ADIcon.INFO }).pipe(first()).subscribe(result => {
|
||||||
attacker.exp += this.attackingAttackerExp;
|
attacker.exp += this.attackingAttackerExp;
|
||||||
this.attackingAttackerExp = 0;
|
this.attackingAttackerExp = 0;
|
||||||
this.md2Service.broadcastHeroInfoToOwner(attacker);
|
this.md2Service.broadcastService.broadcastHeroInfoToOwner(attacker);
|
||||||
this.md2Service.refreshUI$.next();
|
this.md2Service.refreshUI$.next();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
16
src/app/services/MD2/md2-state.service.spec.ts
Normal file
16
src/app/services/MD2/md2-state.service.spec.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { MD2StateService } from './md2-state.service';
|
||||||
|
|
||||||
|
describe('MD2StateService', () => {
|
||||||
|
let service: MD2StateService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(MD2StateService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
85
src/app/services/MD2/md2-state.service.ts
Normal file
85
src/app/services/MD2/md2-state.service.ts
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { DrawingBag, MD2HeroInfo, MD2Icon, MobInfo, TreasureItem, TreasureType } from '../../games/massive-darkness2/massive-darkness2.model';
|
||||||
|
import { FileService } from '../file.service';
|
||||||
|
import { MD2GameInfo } from './md2.service';
|
||||||
|
import { MD2MobInfo } from '../../games/massive-darkness2/massive-darkness2.db.model';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class MD2StateService {
|
||||||
|
|
||||||
|
private _highestPlayerLevel: number = 1;
|
||||||
|
private _playerAmount: number = 2;
|
||||||
|
|
||||||
|
public info: MD2GameInfo;
|
||||||
|
public playerHero: MD2HeroInfo;
|
||||||
|
public mobInfos: MD2MobInfo[] = [];
|
||||||
|
public mobDeck: DrawingBag<MobInfo>;
|
||||||
|
public roamingMobDeck: DrawingBag<MobInfo>;
|
||||||
|
public treasureBag: DrawingBag<TreasureItem> = new DrawingBag<TreasureItem>();
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public fileService: FileService,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public iconHtml(icon: MD2Icon, cssClass = '') {
|
||||||
|
|
||||||
|
|
||||||
|
if (icon == MD2Icon.Fire) {
|
||||||
|
cssClass += ' g-color-google-plus ';
|
||||||
|
}
|
||||||
|
if (icon == MD2Icon.Frost || icon == MD2Icon.Mana) {
|
||||||
|
cssClass += ' g-color-aqua ';
|
||||||
|
}
|
||||||
|
if (icon < MD2Icon.RedDice) {
|
||||||
|
return `<span md2-icon='${String.fromCharCode(65 + icon)}' class='MD2Icon ${cssClass}'>${String.fromCharCode(65 + icon)}</span>`
|
||||||
|
} else if (icon < MD2Icon.TreasureToken) {
|
||||||
|
return `<span md2-icon='${String.fromCharCode(65 + icon)}' class='MD2Icon dice ${MD2Icon[icon].replace('Dice', '')} ${cssClass}'></span>`;
|
||||||
|
} else {
|
||||||
|
if (!cssClass) {
|
||||||
|
cssClass = 'g-height-25 mr-1';
|
||||||
|
}
|
||||||
|
//image based icons
|
||||||
|
switch (icon) {
|
||||||
|
|
||||||
|
case MD2Icon.HP_Color:
|
||||||
|
return this.imgHtml('HeartIcon.png', cssClass);
|
||||||
|
case MD2Icon.Mana_Color:
|
||||||
|
return this.imgHtml('ManaIcon.png', cssClass);
|
||||||
|
case MD2Icon.CorruptToken:
|
||||||
|
return this.imgHtml('Tokens/CorruptToken.png', cssClass);
|
||||||
|
case MD2Icon.TimeToken:
|
||||||
|
return this.imgHtml('Tokens/TimeToken.png', cssClass);
|
||||||
|
case MD2Icon.FireToken:
|
||||||
|
return this.imgHtml('Tokens/FireToken.png', cssClass);
|
||||||
|
case MD2Icon.FrozenToken:
|
||||||
|
return this.imgHtml('Tokens/FrozenToken.png', cssClass);
|
||||||
|
case MD2Icon.TreasureToken:
|
||||||
|
return this.imgHtml('TreasureToken/Cover.png', cssClass);
|
||||||
|
case MD2Icon.TreasureToken_Common:
|
||||||
|
return this.imgHtml('TreasureToken/Common.png', cssClass);
|
||||||
|
case MD2Icon.TreasureToken_Rare:
|
||||||
|
return this.imgHtml('TreasureToken/Rare.png', cssClass);
|
||||||
|
case MD2Icon.TreasureToken_Epic:
|
||||||
|
return this.imgHtml('TreasureToken/Epic.png', cssClass);
|
||||||
|
case MD2Icon.TreasureToken_Legendary:
|
||||||
|
return this.imgHtml('TreasureToken/Legendary.png', cssClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public imgHtml(imgPath: string, cssClass = 'g-height-25 mr-1') {
|
||||||
|
return `<img src='${this.imgUrl(imgPath)}' class='${cssClass}'>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
public imgUrl(imgPath: string) {
|
||||||
|
return this.fileService.ImageUrl('MD2/' + imgPath);
|
||||||
|
}
|
||||||
|
public treasureImage(type: TreasureType) {
|
||||||
|
return this.imgUrl(`TreasureToken/${TreasureType[type]}.png`);
|
||||||
|
}
|
||||||
|
public treasureImageHtml(type: TreasureType) {
|
||||||
|
return this.imgHtml(`TreasureToken/${TreasureType[type]}.png`, 'g-height-40 mr-1');
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -11,12 +11,15 @@ import { FileService } from '../file.service';
|
|||||||
import { GameRoomService } from '../game-room.service';
|
import { GameRoomService } from '../game-room.service';
|
||||||
import { LoginUserService } from '../login-user.service';
|
import { LoginUserService } from '../login-user.service';
|
||||||
import { MsgBoxService } from '../msg-box.service';
|
import { MsgBoxService } from '../msg-box.service';
|
||||||
import { SignalRService, SignalRClient, SignalRMessage } from '../signal-r.service';
|
import { SignalRService, SignalRSession, SignalRMessage } from '../signal-r.service';
|
||||||
|
import { MD2StateService } from './md2-state.service';
|
||||||
|
import { MD2BroadcastService } from './md2-broadcast.service';
|
||||||
import { MD2Logic } from '../../games/massive-darkness2/massive-darkness2.logic';
|
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 { MD2InitService } from './md2-init.service';
|
||||||
import { ArrayUtils } from '../../utilities/array-utils';
|
import { ArrayUtils } from '../../utilities/array-utils';
|
||||||
import { DropDownOption } from '../../entity/dropDownOption';
|
import { DropDownOption } from '../../entity/dropDownOption';
|
||||||
import { GameBundle, MD2DiceSet, MD2MobInfo } from '../../games/massive-darkness2/massive-darkness2.db.model';
|
import { GameBundle, MD2MobInfo } from '../../games/massive-darkness2/massive-darkness2.db.model';
|
||||||
import { environment } from '../../../environments/environment';
|
import { environment } from '../../../environments/environment';
|
||||||
|
|
||||||
|
|
||||||
@ -27,17 +30,6 @@ const MD2_IMG_URL = (id: string = null) => { return `${environment.apiUrl}/Files
|
|||||||
export class MD2Service {
|
export class MD2Service {
|
||||||
// #region Properties (24)
|
// #region Properties (24)
|
||||||
|
|
||||||
private _highestPlayerLevel: number = 1;
|
|
||||||
private _playerAmount: number = 2;
|
|
||||||
|
|
||||||
public info: MD2GameInfo;
|
|
||||||
public playerHero: MD2HeroInfo;
|
|
||||||
public mobInfos: MD2MobInfo[] = [];
|
|
||||||
public roamingMobInfos: MD2MobInfo[] = [];
|
|
||||||
public mobDeck: DrawingBag<MobInfo>;
|
|
||||||
public roamingMobDeck: DrawingBag<MobInfo>;
|
|
||||||
public treasureBag: DrawingBag<TreasureItem> = new DrawingBag<TreasureItem>();
|
|
||||||
|
|
||||||
public darknessPhaseRule: IDarknessPhaseRule;
|
public darknessPhaseRule: IDarknessPhaseRule;
|
||||||
public enemyPhaseMobs: MobInfo[];
|
public enemyPhaseMobs: MobInfo[];
|
||||||
public enemyPhaseSubject = new Subject<MobInfo>();
|
public enemyPhaseSubject = new Subject<MobInfo>();
|
||||||
@ -51,34 +43,42 @@ export class MD2Service {
|
|||||||
|
|
||||||
|
|
||||||
public get heros() {
|
public get heros() {
|
||||||
return this.info.heros;
|
return this.stateService.info.heros;
|
||||||
}
|
}
|
||||||
public get roamingMonsters() {
|
public get roamingMonsters() {
|
||||||
return this.info.roamingMonsters;
|
return this.stateService.info.roamingMonsters;
|
||||||
}
|
}
|
||||||
public get mobs() {
|
public get mobs() {
|
||||||
return this.info.mobs;
|
return this.stateService.info.mobs;
|
||||||
}
|
|
||||||
public get allRoamingMonsterInfos() {
|
|
||||||
return this.roamingMobInfos;
|
|
||||||
}
|
}
|
||||||
public get allMobInfos() {
|
public get allMobInfos() {
|
||||||
return this.mobInfos;
|
return this.stateService.mobInfos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public get info(): MD2GameInfo {
|
||||||
|
return this.stateService.info;
|
||||||
|
}
|
||||||
|
public set info(v: MD2GameInfo) {
|
||||||
|
this.stateService.info = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
// #endregion Properties (24)
|
// #endregion Properties (24)
|
||||||
|
|
||||||
// #region Constructors (1)
|
// #region Constructors (1)
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public fileService: FileService,
|
public fileService: FileService,
|
||||||
public msgBoxService: MsgBoxService,
|
public msgBoxService: MsgBoxService,
|
||||||
public gameRoomService: GameRoomService,
|
private gameRoomService: GameRoomService,
|
||||||
public loginUserService: LoginUserService,
|
private loginUserService: LoginUserService,
|
||||||
|
public stateService: MD2StateService,
|
||||||
public signalRService: SignalRService,
|
public signalRService: SignalRService,
|
||||||
public dlgService: NbDialogService
|
public dlgService: NbDialogService,
|
||||||
|
public broadcastService: MD2BroadcastService
|
||||||
) {
|
) {
|
||||||
this.darknessPhaseRule = new CoreGameDarknessPhaseRule();
|
this.darknessPhaseRule = new CoreGameDarknessPhaseRule();
|
||||||
this.info = new MD2GameInfo();
|
this.stateService.info = new MD2GameInfo();
|
||||||
this.darknessPhaseRule.addTreasureToken.subscribe(treasureType => {
|
this.darknessPhaseRule.addTreasureToken.subscribe(treasureType => {
|
||||||
this.addTreasure(treasureType, 1);
|
this.addTreasure(treasureType, 1);
|
||||||
});
|
});
|
||||||
@ -103,8 +103,11 @@ export class MD2Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get playerHero(): MD2HeroInfo {
|
||||||
|
return this.stateService.playerHero;
|
||||||
|
}
|
||||||
public get currentActivateHero(): MD2HeroInfo {
|
public get currentActivateHero(): MD2HeroInfo {
|
||||||
return this.info.heros.find(h => h.uiActivating);
|
return this.stateService.info.heros.find(h => h.uiActivating);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -114,6 +117,9 @@ export class MD2Service {
|
|||||||
|
|
||||||
// #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));
|
||||||
@ -123,17 +129,17 @@ export class MD2Service {
|
|||||||
public darknessPhase() {
|
public darknessPhase() {
|
||||||
this.heros.forEach(hero => {
|
this.heros.forEach(hero => {
|
||||||
hero.remainActions = 3;
|
hero.remainActions = 3;
|
||||||
this.broadcastHeroInfoToOwner(hero);
|
this.broadcastService.broadcastHeroInfoToOwner(hero);
|
||||||
});
|
});
|
||||||
this.info.roundPhase = RoundPhase.HeroPhase;
|
this.stateService.info.roundPhase = RoundPhase.HeroPhase;
|
||||||
if (!this.info.isBossFight) {
|
if (!this.stateService.info.isBossFight) {
|
||||||
this.info.round++;
|
this.stateService.info.round++;
|
||||||
if (this.darknessPhaseRule.runDarknessPhase()) {
|
if (this.darknessPhaseRule.runDarknessPhase()) {
|
||||||
this.msgBoxService.show(`${NumberUtils.Ordinal(this.info.round)} Hero Phase`, { icon: ADIcon.INFO });
|
this.msgBoxService.show(`${NumberUtils.Ordinal(this.stateService.info.round)} Hero Phase`, { icon: ADIcon.INFO });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.info.boss.darknessPhase();
|
this.stateService.info.boss.darknessPhase();
|
||||||
this.msgBoxService.show(`Boss Fight - ${NumberUtils.Ordinal(this.info.boss.rounds)} Hero Phase`, { icon: ADIcon.INFO });
|
this.msgBoxService.show(`Boss Fight - ${NumberUtils.Ordinal(this.stateService.info.boss.rounds)} Hero Phase`, { icon: ADIcon.INFO });
|
||||||
}
|
}
|
||||||
|
|
||||||
//this.runNextPhase();
|
//this.runNextPhase();
|
||||||
@ -149,9 +155,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)
|
||||||
@ -178,10 +184,13 @@ export class MD2Service {
|
|||||||
exitingMob.skills = newSpawnMob.skills;
|
exitingMob.skills = newSpawnMob.skills;
|
||||||
} else {
|
} else {
|
||||||
if (isRoamingMonster) {
|
if (isRoamingMonster) {
|
||||||
newSpawnMob = this.generateMob(isRoamingMonster, newSpawnMob.name, level);
|
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);
|
this.roamingMonsters.push(newSpawnMob);
|
||||||
} else {
|
} else {
|
||||||
newSpawnMob = this.generateMob(isRoamingMonster, newSpawnMob.name, level);
|
newSpawnMob = this.generateMob(newSpawnMob.name, level);
|
||||||
this.mobs.push(newSpawnMob);
|
this.mobs.push(newSpawnMob);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,12 +202,16 @@ export class MD2Service {
|
|||||||
|
|
||||||
return { exitingMob, mob: newSpawnMob };
|
return { exitingMob, mob: newSpawnMob };
|
||||||
}
|
}
|
||||||
private generateMob(isRoamingMonster: boolean, mobName: string, level: number) {
|
private generateMob(mobName: string, level: number) {
|
||||||
let dbMobInfo = isRoamingMonster ? this.allRoamingMonsterInfos.find(m => m.name == mobName) : this.allMobInfos.find(m => m.name == mobName);
|
let dbMobInfo = this.allMobInfos.find(m => m.name == mobName);
|
||||||
let levelInfo = dbMobInfo.mobLevelInfos.find(l => l.level <= level);
|
let levelInfo = dbMobInfo.mobLevelInfos.find(l => l.level <= level);
|
||||||
let skills = dbMobInfo.skills.filter(s => s.level <= level).sort((a, b) => b.seq - a.seq);
|
let skills = dbMobInfo.skills.filter(s => s.level <= level).sort((a, b) => b.level - a.level);
|
||||||
//Distinct by SkillType and Skill Name, take the one with the highest level
|
//Distinct by SkillType and Skill Name, take the one with the highest level
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let mobInfo = new MobInfo({
|
let mobInfo = new MobInfo({
|
||||||
name: dbMobInfo.name,
|
name: dbMobInfo.name,
|
||||||
hp: levelInfo.hpPerHero,
|
hp: levelInfo.hpPerHero,
|
||||||
@ -206,7 +219,6 @@ export class MD2Service {
|
|||||||
level: level,
|
level: level,
|
||||||
rewardTokens: levelInfo.rewardTokens,
|
rewardTokens: levelInfo.rewardTokens,
|
||||||
defenseInfo: levelInfo.defenceInfo,
|
defenseInfo: levelInfo.defenceInfo,
|
||||||
type: dbMobInfo.type,
|
|
||||||
skills: []
|
skills: []
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -217,52 +229,18 @@ export class MD2Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mobInfo.skills = mobInfo.skills.sort((a, b) => b.seq - a.seq);
|
mobInfo.skills = mobInfo.skills.sort((a, b) => b.seq - a.seq);
|
||||||
switch (dbMobInfo.type) {
|
|
||||||
case MobType.Mob:
|
|
||||||
mobInfo.leaderImgUrl = mobInfo.leaderImgUrl || MD2_IMG_URL(`/${GameBundle[dbMobInfo.from]}/Mobs/${mobInfo.name}/Leader.png`);
|
mobInfo.leaderImgUrl = mobInfo.leaderImgUrl || MD2_IMG_URL(`/${GameBundle[dbMobInfo.from]}/Mobs/${mobInfo.name}/Leader.png`);
|
||||||
mobInfo.minionImgUrl = mobInfo.minionImgUrl || MD2_IMG_URL(`/${GameBundle[dbMobInfo.from]}/Mobs/${mobInfo.name}/Minion.png`);
|
mobInfo.minionImgUrl = mobInfo.minionImgUrl || MD2_IMG_URL(`/${GameBundle[dbMobInfo.from]}/Mobs/${mobInfo.name}/Minion.png`);
|
||||||
break;
|
|
||||||
case MobType.RoamingMonster:
|
|
||||||
mobInfo.leaderImgUrl = mobInfo.leaderImgUrl || MD2_IMG_URL(`/${GameBundle[dbMobInfo.from]}/RoamingMonsters/${mobInfo.name}/Stand.png`);
|
|
||||||
mobInfo.minionImgUrl = null;
|
|
||||||
break;
|
|
||||||
case MobType.Boss:
|
|
||||||
mobInfo.leaderImgUrl = mobInfo.leaderImgUrl || MD2_IMG_URL(`/Boss/${mobInfo.name}-Stand.png`);
|
|
||||||
mobInfo.minionImgUrl = null;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
mobInfo.fixedCarriedTreasure = [];
|
mobInfo.fixedCarriedTreasure = [];
|
||||||
levelInfo.fixedRareTreasure > 0 && mobInfo.fixedCarriedTreasure.push(new TreasureItem(TreasureType.Rare, levelInfo.fixedRareTreasure));
|
levelInfo.fixedRareTreasure > 0 && mobInfo.fixedCarriedTreasure.push(new TreasureItem(TreasureType.Rare, levelInfo.fixedRareTreasure));
|
||||||
levelInfo.fixedEpicTreasure > 0 && mobInfo.fixedCarriedTreasure.push(new TreasureItem(TreasureType.Epic, levelInfo.fixedEpicTreasure));
|
levelInfo.fixedEpicTreasure > 0 && mobInfo.fixedCarriedTreasure.push(new TreasureItem(TreasureType.Epic, levelInfo.fixedEpicTreasure));
|
||||||
levelInfo.fixedLegendTreasure > 0 && mobInfo.fixedCarriedTreasure.push(new TreasureItem(TreasureType.Legendary, levelInfo.fixedLegendTreasure));
|
levelInfo.fixedLegendTreasure > 0 && mobInfo.fixedCarriedTreasure.push(new TreasureItem(TreasureType.Legendary, levelInfo.fixedLegendTreasure));
|
||||||
|
|
||||||
|
|
||||||
switch (dbMobInfo.type) {
|
|
||||||
case MobType.Mob:
|
|
||||||
//Maybe add more mobs later
|
//Maybe add more mobs later
|
||||||
mobInfo.mobAmount = this.playerAmount + 1;
|
mobInfo.mobAmount = this.playerAmount + 1;
|
||||||
break;
|
|
||||||
case MobType.RoamingMonster:
|
|
||||||
case MobType.Boss:
|
|
||||||
mobInfo.hp = levelInfo.hpPerHero * this.playerAmount;
|
|
||||||
mobInfo.unitRemainHp = mobInfo.hp;
|
|
||||||
mobInfo.mobAmount = 0;
|
|
||||||
mobInfo.attackInfos = [this.getAttackInfo(levelInfo.attackInfo)];
|
|
||||||
let altAttackInfo = levelInfo.alterAttackInfo;
|
|
||||||
if (altAttackInfo
|
|
||||||
&& (altAttackInfo.black > 0 || altAttackInfo.blue > 0 || altAttackInfo.green > 0 || altAttackInfo.orange > 0 || altAttackInfo.red > 0 || altAttackInfo.yellow > 0)
|
|
||||||
) {
|
|
||||||
mobInfo.attackInfos.push(this.getAttackInfo(altAttackInfo));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return mobInfo;
|
return mobInfo;
|
||||||
}
|
}
|
||||||
private getAttackInfo(attackInfo: MD2DiceSet): AttackInfo {
|
|
||||||
return new AttackInfo(attackInfo.type as unknown as MD2Icon, attackInfo.yellow, attackInfo.orange, attackInfo.red, attackInfo.black);
|
|
||||||
}
|
|
||||||
public enemyPhase() {
|
public enemyPhase() {
|
||||||
//this.msgBoxService
|
//this.msgBoxService
|
||||||
this.enemyPhaseMobs = this.roamingMonsters.concat(this.mobs);
|
this.enemyPhaseMobs = this.roamingMonsters.concat(this.mobs);
|
||||||
@ -290,9 +268,9 @@ export class MD2Service {
|
|||||||
} else {
|
} else {
|
||||||
this.info.boss = new BossMicheal(this);
|
this.info.boss = new BossMicheal(this);
|
||||||
}
|
}
|
||||||
this.info.roamingMonsters = [];
|
this.stateService.info.roamingMonsters = [];
|
||||||
this.info.mobs = [];
|
this.stateService.info.mobs = [];
|
||||||
this.info.isBossFight = true;
|
this.stateService.info.isBossFight = true;
|
||||||
this.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.hp = this.info.boss.info.hpPerHero * this.info.heros.length;
|
||||||
this.info.boss.info.unitRemainHp = this.info.boss.info.hp;
|
this.info.boss.info.unitRemainHp = this.info.boss.info.hp;
|
||||||
@ -306,14 +284,14 @@ export class MD2Service {
|
|||||||
hero.uiActivating = false;
|
hero.uiActivating = false;
|
||||||
hero.uiBossFight = true;
|
hero.uiBossFight = true;
|
||||||
});
|
});
|
||||||
this.broadcastGameInfo();
|
this.broadcastService.broadcastAllHeroInfoToAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
//this.sendMsgboxMsg
|
//this.sendMsgboxMsg
|
||||||
}
|
}
|
||||||
public activateBoss() {
|
public activateBoss() {
|
||||||
this.info.boss.activating();
|
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);
|
||||||
@ -334,8 +312,8 @@ export class MD2Service {
|
|||||||
hero.mp += levelUpInfo.extraMp;
|
hero.mp += levelUpInfo.extraMp;
|
||||||
hero.mpMaximum += levelUpInfo.extraMp;
|
hero.mpMaximum += levelUpInfo.extraMp;
|
||||||
hero.exp = levelUpInfo.currentExp;
|
hero.exp = levelUpInfo.currentExp;
|
||||||
this.broadcastHeroInfoToOwner(hero);
|
this.broadcastService.broadcastHeroInfoToOwner(hero);
|
||||||
this.sendMsgboxMsg(hero.playerInfo.signalRClientId, { title: `Level Up Lv.${hero.level}`, text: 'Please do a skill level up!', icon: ADIcon.INFO });
|
this.sendMsgboxMsg(hero.playerInfo.signalRClientId, { title: 'Level Up', text: 'Please do a skill level up!', icon: ADIcon.INFO });
|
||||||
levelUpInfo = MD2Rules.checkCoreGameLevelup(hero.level, hero.exp);
|
levelUpInfo = MD2Rules.checkCoreGameLevelup(hero.level, hero.exp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -354,9 +332,9 @@ export class MD2Service {
|
|||||||
level = 3;
|
level = 3;
|
||||||
}
|
}
|
||||||
if (isRoamingMonsters) {
|
if (isRoamingMonsters) {
|
||||||
return this.imgUrl(`Mobs/CoreGame/RoamingMonsters/${name}/${level}.png`);
|
return this.stateService.imgUrl(`Mobs/CoreGame/RoamingMonsters/${name}/${level}.png`);
|
||||||
} else {
|
} else {
|
||||||
return this.imgUrl(`Mobs/CoreGame/Mobs/${name}/${level}.png`);
|
return this.stateService.imgUrl(`Mobs/CoreGame/Mobs/${name}/${level}.png`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,7 +344,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.playerHero = hero;
|
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 },
|
||||||
@ -381,12 +359,12 @@ export class MD2Service {
|
|||||||
|
|
||||||
|
|
||||||
public runNextPhase() {
|
public runNextPhase() {
|
||||||
this.info.roundPhase++;
|
this.stateService.info.roundPhase++;
|
||||||
switch (this.info.roundPhase) {
|
switch (this.stateService.info.roundPhase) {
|
||||||
case RoundPhase.HeroPhase:
|
case RoundPhase.HeroPhase:
|
||||||
this.heros.forEach(hero => {
|
this.heros.forEach(hero => {
|
||||||
hero.remainActions = 3;
|
hero.remainActions = 3;
|
||||||
this.broadcastHeroInfoToOwner(hero);
|
this.broadcastService.broadcastHeroInfoToOwner(hero);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case RoundPhase.EnemyPhase:
|
case RoundPhase.EnemyPhase:
|
||||||
@ -401,14 +379,14 @@ export class MD2Service {
|
|||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
let parameters = {};
|
let parameters = {};
|
||||||
parameters['phase'] = this.info.roundPhase;
|
parameters['phase'] = this.stateService.info.roundPhase;
|
||||||
this.broadcastMessage('roundPhase', '', parameters);
|
this.broadcastService.broadcastMessage('roundPhase', '', parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
public sendMsgboxMsg(playerSessionId: string, msg: Partial<MessageBoxConfig>) {
|
public sendMsgboxMsg(playerSessionId: string, msg: Partial<MessageBoxConfig>) {
|
||||||
let message = {
|
let message = {
|
||||||
receiver: { isGroup: false, connectionId: playerSessionId } as SignalRClient,
|
receiver: { isGroup: false, sessionId: playerSessionId } as SignalRSession,
|
||||||
from: { isGroup: false, connectionId: this.loginUserService.userAccess.signalRConnectionId },
|
from: { isGroup: false, sessionId: this.loginUserService.userAccess.signalRSessionId },
|
||||||
actionType: 'message',
|
actionType: 'message',
|
||||||
actionName: 'popup',
|
actionName: 'popup',
|
||||||
} as SignalRMessage;
|
} as SignalRMessage;
|
||||||
@ -418,7 +396,7 @@ export class MD2Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getTargetHerosByFilter(targetType: AttackTarget, onlyOne: boolean = false) {
|
public getTargetHerosByFilter(targetType: AttackTarget, onlyOne: boolean = false) {
|
||||||
return MD2Logic.getTargetHerosByFilter(this.info.heros, targetType, onlyOne);
|
return MD2Logic.getTargetHerosByFilter(this.stateService.info.heros, targetType, onlyOne);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getTargetHerosHtml(beenAttackedHero: MD2HeroInfo[]) {
|
public getTargetHerosHtml(beenAttackedHero: MD2HeroInfo[]) {
|
||||||
@ -441,193 +419,32 @@ export class MD2Service {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this.broadcastHeroInfoToAll(this.currentActivateHero, true);
|
this.broadcastService.broadcastHeroInfoToAll(this.currentActivateHero);
|
||||||
//this.broadcastHeroInfoToOwner(this.currentActivateHero);
|
this.broadcastService.broadcastHeroInfoToOwner(this.currentActivateHero);
|
||||||
this.msgBoxService.show(
|
this.msgBoxService.show(
|
||||||
this.imgHtml('/Fountain/Cover.png', '')
|
this.stateService.imgHtml('/Fountain/Cover.png', '')
|
||||||
, { text: `${this.currentActivateHero.heroFullName} Recovered ${result.description}.` });
|
, { text: `${this.currentActivateHero.heroFullName} Recovered ${result.description}.` });
|
||||||
}
|
}
|
||||||
|
|
||||||
public openTreasureChest() {
|
public openTreasureChest() {
|
||||||
let result = new DrawingBag<DrawingItem>([
|
let result = new DrawingBag<DrawingItem>([
|
||||||
new DrawingItem('Common', `${this.treasureImageHtml(TreasureType.Common)} x 2`, '', 10),
|
new DrawingItem('Common', `${this.stateService.treasureImageHtml(TreasureType.Common)} x 2`, '', 10),
|
||||||
new DrawingItem('Open Treasure Chest', `${this.treasureImageHtml(TreasureType.Rare)} x 2`, '', 5),
|
new DrawingItem('Open Treasure Chest', `${this.stateService.treasureImageHtml(TreasureType.Rare)} x 2`, '', 5),
|
||||||
])
|
])
|
||||||
.Draw(1)[0];
|
.Draw(1)[0];
|
||||||
|
|
||||||
this.msgBoxService.show(
|
this.msgBoxService.show(
|
||||||
this.imgHtml('/TreasureChest/SmallTresureChest.jpg', ''), { text: `${this.currentActivateHero.heroFullName} gets ${result.description}.` });
|
this.stateService.imgHtml('/TreasureChest/SmallTresureChest.jpg', ''), { text: `${this.currentActivateHero.heroFullName} gets ${result.description}.` });
|
||||||
}
|
}
|
||||||
public openGreatTreasureChest() {
|
public openGreatTreasureChest() {
|
||||||
let result = new DrawingBag<DrawingItem>([
|
let result = new DrawingBag<DrawingItem>([
|
||||||
new DrawingItem('Common', `${this.treasureImageHtml(TreasureType.Rare)} x 3`, '', 3),
|
new DrawingItem('Common', `${this.stateService.treasureImageHtml(TreasureType.Rare)} x 3`, '', 3),
|
||||||
new DrawingItem('Open Treasure Chest', `${this.treasureImageHtml(TreasureType.Epic)} x 3`, '', 1),
|
new DrawingItem('Open Treasure Chest', `${this.stateService.treasureImageHtml(TreasureType.Epic)} x 3`, '', 1),
|
||||||
]).Draw(1)[0];
|
]).Draw(1)[0];
|
||||||
|
|
||||||
this.msgBoxService.show(
|
this.msgBoxService.show(
|
||||||
this.imgHtml('/TreasureChest/BigTresureChest.png', ''), { text: `${this.currentActivateHero.heroFullName} gets ${result.description}.` });
|
this.stateService.imgHtml('/TreasureChest/BigTresureChest.png', ''), { text: `${this.currentActivateHero.heroFullName} gets ${result.description}.` });
|
||||||
}
|
}
|
||||||
|
|
||||||
public iconHtml(icon: MD2Icon, cssClass = '') {
|
|
||||||
|
|
||||||
|
|
||||||
if (icon == MD2Icon.Fire) {
|
|
||||||
cssClass += ' g-color-google-plus ';
|
|
||||||
}
|
|
||||||
if (icon == MD2Icon.Frost || icon == MD2Icon.Mana) {
|
|
||||||
cssClass += ' g-color-aqua ';
|
|
||||||
}
|
|
||||||
if (icon < MD2Icon.RedDice) {
|
|
||||||
return `<span md2-icon='${String.fromCharCode(65 + icon)}' class='MD2Icon ${cssClass}'>${String.fromCharCode(65 + icon)}</span>`
|
|
||||||
} else if (icon < MD2Icon.TreasureToken) {
|
|
||||||
return `<span md2-icon='${String.fromCharCode(65 + icon)}' class='MD2Icon dice ${MD2Icon[icon].replace('Dice', '')} ${cssClass}'></span>`;
|
|
||||||
} else {
|
|
||||||
if (!cssClass) {
|
|
||||||
cssClass = 'g-height-25 mr-1';
|
|
||||||
}
|
|
||||||
//image based icons
|
|
||||||
switch (icon) {
|
|
||||||
|
|
||||||
case MD2Icon.HP_Color:
|
|
||||||
return this.imgHtml('HeartIcon.png', cssClass);
|
|
||||||
case MD2Icon.Mana_Color:
|
|
||||||
return this.imgHtml('ManaIcon.png', cssClass);
|
|
||||||
case MD2Icon.CorruptToken:
|
|
||||||
return this.imgHtml('Tokens/CorruptToken.png', cssClass);
|
|
||||||
case MD2Icon.TimeToken:
|
|
||||||
return this.imgHtml('Tokens/TimeToken.png', cssClass);
|
|
||||||
case MD2Icon.FireToken:
|
|
||||||
return this.imgHtml('Tokens/FireToken.png', cssClass);
|
|
||||||
case MD2Icon.FrozenToken:
|
|
||||||
return this.imgHtml('Tokens/FrozenToken.png', cssClass);
|
|
||||||
case MD2Icon.TreasureToken:
|
|
||||||
return this.imgHtml('TreasureToken/Cover.png', cssClass);
|
|
||||||
case MD2Icon.TreasureToken_Common:
|
|
||||||
return this.imgHtml('TreasureToken/Common.png', cssClass);
|
|
||||||
case MD2Icon.TreasureToken_Rare:
|
|
||||||
return this.imgHtml('TreasureToken/Rare.png', cssClass);
|
|
||||||
case MD2Icon.TreasureToken_Epic:
|
|
||||||
return this.imgHtml('TreasureToken/Epic.png', cssClass);
|
|
||||||
case MD2Icon.TreasureToken_Legendary:
|
|
||||||
return this.imgHtml('TreasureToken/Legendary.png', cssClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public imgHtml(imgPath: string, cssClass = 'g-height-25 mr-1') {
|
|
||||||
return `<img src='${this.imgUrl(imgPath)}' class='${cssClass}'>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
public imgUrl(imgPath: string) {
|
|
||||||
return this.fileService.ImageUrl('MD2/' + imgPath);
|
|
||||||
}
|
|
||||||
public treasureImage(type: TreasureType) {
|
|
||||||
return this.imgUrl(`TreasureToken/${TreasureType[type]}.png`);
|
|
||||||
}
|
|
||||||
public treasureImageHtml(type: TreasureType) {
|
|
||||||
return this.imgHtml(`TreasureToken/${TreasureType[type]}.png`, 'g-height-40 mr-1');
|
|
||||||
}
|
|
||||||
|
|
||||||
public broadcastAllHeroInfoToAll() {
|
|
||||||
let message = {
|
|
||||||
receiver: { isGroup: true, connectionId: this.gameRoomService.gameRoomId } as SignalRClient,
|
|
||||||
from: { isGroup: false, connectionId: this.loginUserService.userAccess.signalRConnectionId },
|
|
||||||
actionType: 'heroes',
|
|
||||||
actionName: 'updateAll',
|
|
||||||
} as SignalRMessage;
|
|
||||||
message.parameters = { heros: JSON.stringify(this.info.heros) };
|
|
||||||
this.gameRoomService.sendMessage(message).pipe(first()).subscribe(result => {
|
|
||||||
});
|
|
||||||
this.broadcastMobsInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
public broadcastHeroAction(action: string, extraValue: any = null) {
|
|
||||||
let parameters = {};
|
|
||||||
parameters['tabId'] = this.loginUserService.sessionTabId;
|
|
||||||
parameters['extraValue'] = JSON.stringify(extraValue);
|
|
||||||
this.broadcastMessage('heroAction', action, parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
public broadcastHeroInfoToAll(hero: MD2HeroInfo, fromDashboard: boolean = false) {
|
|
||||||
let message = {
|
|
||||||
receiver: { isGroup: true, connectionId: this.gameRoomService.gameRoomId } as SignalRClient,
|
|
||||||
from: { isGroup: fromDashboard, connectionId: fromDashboard ? this.gameRoomService.gameRoomId : hero.playerInfo.signalRClientId },
|
|
||||||
actionType: 'hero',
|
|
||||||
actionName: 'update',
|
|
||||||
} as SignalRMessage;
|
|
||||||
message.parameters = { hero: JSON.stringify(hero) };
|
|
||||||
this.gameRoomService.sendMessage(message).pipe(first()).subscribe(result => {
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public broadcastHeroInfoToOwner(hero: MD2HeroInfo) {
|
|
||||||
let message = {
|
|
||||||
receiver: { isGroup: false, connectionId: hero.playerInfo.signalRClientId } as SignalRClient,
|
|
||||||
from: { isGroup: true, connectionId: this.gameRoomService.gameRoomId },
|
|
||||||
actionType: 'hero',
|
|
||||||
actionName: 'updateMyHero',
|
|
||||||
} as SignalRMessage;
|
|
||||||
message.parameters = { hero: JSON.stringify(hero) };
|
|
||||||
this.gameRoomService.sendMessage(message).pipe(first()).subscribe(result => {
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* `sessionId` = null means broadcast to all
|
|
||||||
*/
|
|
||||||
public broadcastMessage(actionType: string,
|
|
||||||
actionName: string,
|
|
||||||
parameters: { [key: string]: string; } = {},
|
|
||||||
sessionId: string = null) {
|
|
||||||
let message = {
|
|
||||||
receiver: { isGroup: !sessionId, connectionId: sessionId } as SignalRClient,
|
|
||||||
from: { isGroup: false, connectionId: this.loginUserService.userAccess.signalRConnectionId },
|
|
||||||
actionType: actionType,
|
|
||||||
actionName: actionName,
|
|
||||||
parameters: parameters
|
|
||||||
} as SignalRMessage;
|
|
||||||
|
|
||||||
if (sessionId == null) {
|
|
||||||
message.receiver = { isGroup: true, connectionId: this.gameRoomService.gameRoomId } as SignalRClient
|
|
||||||
} else {
|
|
||||||
message.receiver = { isGroup: false, connectionId: this.gameRoomService.gameRoomId } as SignalRClient
|
|
||||||
}
|
|
||||||
this.gameRoomService.sendMessage(message).pipe(first()).subscribe(result => {
|
|
||||||
});
|
|
||||||
}
|
|
||||||
public broadcastGameInfo() {
|
|
||||||
let parameters = {};
|
|
||||||
if (this.info.boss) {
|
|
||||||
this.info.boss.md2Service = undefined;
|
|
||||||
}
|
|
||||||
parameters['gameInfo'] = JSON.stringify(this.info);
|
|
||||||
|
|
||||||
if (this.info.boss) {
|
|
||||||
this.info.boss.md2Service = this;
|
|
||||||
}
|
|
||||||
this.broadcastMessage('GameRoom', 'update', parameters);
|
|
||||||
}
|
|
||||||
broadcastFetchGameInfo() {
|
|
||||||
this.broadcastMessage('GameRoom', 'getGameInfo', {});
|
|
||||||
}
|
|
||||||
public broadcastRoundPhase() {
|
|
||||||
let parameters = {};
|
|
||||||
parameters['phase'] = JSON.stringify(this.info.roundPhase);
|
|
||||||
this.broadcastMessage('GameRoom', 'phase', parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
public broadcastMobsInfo() {
|
|
||||||
let parameters = {};
|
|
||||||
parameters['roamingMonsters'] = JSON.stringify(this.info.roamingMonsters);
|
|
||||||
parameters['mobs'] = JSON.stringify(this.info.mobs);
|
|
||||||
this.broadcastMessage('mobs', 'update', parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
public broadcastMyHeroInfo() {
|
|
||||||
this.broadcastHeroInfoToAll(this.playerHero);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #endregion Public Methods (27)
|
// #endregion Public Methods (27)
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -644,7 +461,7 @@ export class MD2GameInfo {
|
|||||||
|
|
||||||
this.mobs = this.mobs.map(m => new MobInfo(m));
|
this.mobs = this.mobs.map(m => new MobInfo(m));
|
||||||
this.roamingMonsters = this.roamingMonsters.map(m => new MobInfo(m));
|
this.roamingMonsters = this.roamingMonsters.map(m => new MobInfo(m));
|
||||||
if (this.boss && this.boss.info) {
|
if (this.boss.info) {
|
||||||
this.boss.info = new MobInfo(this.boss.info);
|
this.boss.info = new MobInfo(this.boss.info);
|
||||||
}
|
}
|
||||||
this.heros = this.heros.map(h => new MD2HeroInfo(h));
|
this.heros = this.heros.map(h => new MD2HeroInfo(h));
|
||||||
@ -655,7 +472,6 @@ export class MD2GameInfo {
|
|||||||
public mobs: MobInfo[] = [];
|
public mobs: MobInfo[] = [];
|
||||||
public roamingMonsters: MobInfo[] = [];
|
public roamingMonsters: MobInfo[] = [];
|
||||||
public heros: MD2HeroInfo[] = [];
|
public heros: MD2HeroInfo[] = [];
|
||||||
public disconnectedHeroes: MD2HeroInfo[] = [];
|
|
||||||
public round = 1;
|
public round = 1;
|
||||||
public roundPhase: RoundPhase = RoundPhase.HeroPhase;
|
public roundPhase: RoundPhase = RoundPhase.HeroPhase;
|
||||||
public showAttackBtn: boolean = false;
|
public showAttackBtn: boolean = false;
|
||||||
|
|||||||
15
src/app/services/MD2/md2.spawn.mob.service.ts
Normal file
15
src/app/services/MD2/md2.spawn.mob.service.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { Injectable } from "@angular/core";
|
||||||
|
import { MD2StateService } from "./md2-state.service";
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class MD2SpawnMobService {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
public stateService: MD2StateService,) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -23,19 +23,18 @@ export class GameRoomService {
|
|||||||
return {
|
return {
|
||||||
name: this.loginUserService.userAccess.firstName,
|
name: this.loginUserService.userAccess.firstName,
|
||||||
id: this.loginUserService.userAccess.memberId,
|
id: this.loginUserService.userAccess.memberId,
|
||||||
signalRClientId: this.loginUserService.userAccess.signalRConnectionId,
|
signalRClientId: this.loginUserService.userAccess.signalRSessionId,
|
||||||
isPlayer: true,
|
isPlayer: true,
|
||||||
gameRoomId: this.gameRoomId,
|
gameRoomId: this.gameRoomId,
|
||||||
tabId: this.loginUserService.sessionTabId
|
tabId: this.loginUserService.sessionTabId
|
||||||
} as IGamePlayer;
|
} as IGamePlayer;
|
||||||
}
|
}
|
||||||
createGameRoom(name: string) {
|
createGameRoom(name: string) {
|
||||||
//Using current player to create game room
|
let gameRoom = this.currentPlayer();
|
||||||
let currentPlayer = this.currentPlayer();
|
gameRoom.gameRoomId = gameRoom.id;
|
||||||
currentPlayer.gameRoomId = currentPlayer.id;
|
this.gameRoomId = gameRoom.id;
|
||||||
this.gameRoomId = currentPlayer.id;
|
|
||||||
this.http.post<boolean>(GAME_ROOM_URL,
|
this.http.post<boolean>(GAME_ROOM_URL,
|
||||||
JSON.stringify(currentPlayer), {
|
JSON.stringify(gameRoom), {
|
||||||
headers: {
|
headers: {
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
|||||||
@ -14,14 +14,14 @@ export class LoginUserService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setSignalRConnectionId(id: string) {
|
setSignalRConnectionId(id: string) {
|
||||||
this.userAccess.signalRConnectionId = id;
|
this.userAccess.signalRSessionId = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get sessionTabId(): string {
|
public get sessionTabId(): string {
|
||||||
return localStorage.getItem('tabId');
|
return sessionStorage.getItem('tabId');
|
||||||
}
|
}
|
||||||
public set sessionTabId(v: string) {
|
public set sessionTabId(v: string) {
|
||||||
localStorage.setItem('tabId', v);
|
sessionStorage.setItem('tabId', v);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ const SIGNAL_R_URL = (id: string = null) => { return `${environment.apiUrl}/${id
|
|||||||
})
|
})
|
||||||
export class SignalRService {
|
export class SignalRService {
|
||||||
ReceivedSignalRMessageSubject = new Subject<SignalRMessage>();
|
ReceivedSignalRMessageSubject = new Subject<SignalRMessage>();
|
||||||
signalRMessageConnSubject = new Subject<SignalRConnectionState>();
|
signalRMessageConnSubject = new Subject<any>();
|
||||||
private hubConnection: signalR.HubConnection
|
private hubConnection: signalR.HubConnection
|
||||||
constructor(
|
constructor(
|
||||||
private loginUserService: LoginUserService,
|
private loginUserService: LoginUserService,
|
||||||
@ -42,10 +42,7 @@ export class SignalRService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
public startSignalRConnection(gameRoomId: string = '') {
|
public startSignalRConnection(gameRoomId: string = '') {
|
||||||
this.signalRMessageConnSubject.next({ status: 'connecting' });
|
|
||||||
if (!this.loginUserService.sessionTabId) {
|
|
||||||
this.loginUserService.sessionTabId = UuidUtils.generate();
|
this.loginUserService.sessionTabId = UuidUtils.generate();
|
||||||
}
|
|
||||||
|
|
||||||
const tree = this.router.createUrlTree([], {
|
const tree = this.router.createUrlTree([], {
|
||||||
queryParams: {
|
queryParams: {
|
||||||
@ -66,21 +63,13 @@ export class SignalRService {
|
|||||||
.withUrl(`${SIGNAL_R_URL('GameRoomHub')}?${params.toString()}`)
|
.withUrl(`${SIGNAL_R_URL('GameRoomHub')}?${params.toString()}`)
|
||||||
.withAutomaticReconnect()
|
.withAutomaticReconnect()
|
||||||
.build();
|
.build();
|
||||||
this.registerHubConnectionLifecycleHandlers();
|
|
||||||
let me = this
|
let me = this
|
||||||
this.hubConnection
|
this.hubConnection
|
||||||
.start()
|
.start()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
me.setSignalRConnectionId(this.hubConnection.connectionId);
|
me.setSignalRConnectionId(this.hubConnection.connectionId);
|
||||||
this.signalRMessageConnSubject.next({
|
|
||||||
status: 'connected',
|
|
||||||
connectionId: this.hubConnection.connectionId
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.log('Error while starting connection: ' + err);
|
|
||||||
this.signalRMessageConnSubject.next({ status: 'error', error: err });
|
|
||||||
})
|
})
|
||||||
|
.catch(err => console.log('Error while starting connection: ' + err))
|
||||||
this.hubConnection.on("ReceivedMessage", (jsonString) => {
|
this.hubConnection.on("ReceivedMessage", (jsonString) => {
|
||||||
this.BroadcastAPIMessageReceive(JSON.parse(jsonString));
|
this.BroadcastAPIMessageReceive(JSON.parse(jsonString));
|
||||||
});
|
});
|
||||||
@ -88,37 +77,12 @@ export class SignalRService {
|
|||||||
}
|
}
|
||||||
public setSignalRConnectionId(connectionId: string) {
|
public setSignalRConnectionId(connectionId: string) {
|
||||||
|
|
||||||
this.loginUserService.userAccess.signalRConnectionId = connectionId;
|
this.loginUserService.userAccess.signalRSessionId = connectionId;
|
||||||
this.loginUserService.signalRInitialized.next(connectionId);
|
this.loginUserService.signalRInitialized.next(connectionId);
|
||||||
console.log('GameRoomHub start connection: ' + this.hubConnection.connectionId)
|
console.log('GameRoomHub start connection: ' + this.hubConnection.connectionId)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private registerHubConnectionLifecycleHandlers() {
|
|
||||||
this.hubConnection.onreconnecting(error => {
|
|
||||||
console.warn('SignalR reconnecting...', error);
|
|
||||||
this.signalRMessageConnSubject.next({ status: 'reconnecting', error });
|
|
||||||
});
|
|
||||||
|
|
||||||
this.hubConnection.onreconnected(connectionId => {
|
|
||||||
console.log('SignalR reconnected with new connectionId', connectionId);
|
|
||||||
this.setSignalRConnectionId(connectionId);
|
|
||||||
this.signalRMessageConnSubject.next({ status: 'reconnected', connectionId });
|
|
||||||
});
|
|
||||||
|
|
||||||
this.hubConnection.onclose(error => {
|
|
||||||
console.warn('SignalR connection closed', error);
|
|
||||||
this.clearSignalRConnectionId();
|
|
||||||
this.signalRMessageConnSubject.next({ status: 'closed', error });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private clearSignalRConnectionId() {
|
|
||||||
if (this.loginUserService?.userAccess) {
|
|
||||||
this.loginUserService.userAccess.signalRConnectionId = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BroadcastAPIMessageReceive(msg: SignalRMessage) {
|
BroadcastAPIMessageReceive(msg: SignalRMessage) {
|
||||||
@ -136,23 +100,16 @@ export class SignalRService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
export interface SignalRMessage {
|
export interface SignalRMessage {
|
||||||
from: SignalRClient;
|
from: SignalRSession;
|
||||||
receiver: SignalRClient;
|
receiver: SignalRSession;
|
||||||
actionType: string;
|
actionType: string;
|
||||||
actionName: string;
|
actionName: string;
|
||||||
parameters: { [key: string]: string; };
|
parameters: { [key: string]: string; };
|
||||||
value: any;
|
|
||||||
jsonValue: string;
|
jsonValue: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SignalRClient {
|
export interface SignalRSession {
|
||||||
connectionId: string;
|
sessionId: string;
|
||||||
name: string;
|
name: string;
|
||||||
isGroup: boolean;
|
isGroup: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SignalRConnectionState {
|
|
||||||
status: 'connecting' | 'connected' | 'reconnecting' | 'reconnected' | 'closed' | 'error';
|
|
||||||
connectionId?: string;
|
|
||||||
error?: any;
|
|
||||||
}
|
|
||||||
@ -24,9 +24,3 @@ p {
|
|||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
button,
|
|
||||||
a,
|
|
||||||
input {
|
|
||||||
touch-action: manipulation;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ const urls = [
|
|||||||
'https://api.golife.love'
|
'https://api.golife.love'
|
||||||
];
|
];
|
||||||
const LINE_CLIENT_ID = '1657422139';
|
const LINE_CLIENT_ID = '1657422139';
|
||||||
const dockerDebug = urls[2];
|
const dockerDebug = urls[0];
|
||||||
export const environment = {
|
export const environment = {
|
||||||
production: false,
|
production: false,
|
||||||
apiUrl: dockerDebug,
|
apiUrl: dockerDebug,
|
||||||
|
|||||||
@ -6,9 +6,8 @@
|
|||||||
<title>真幸福的幸福小組</title>
|
<title>真幸福的幸福小組</title>
|
||||||
|
|
||||||
<base href="/">
|
<base href="/">
|
||||||
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
|
||||||
<link rel="icon" type="image/png" href="favicon.png">
|
<link rel="icon" type="image/png" href="favicon.png">
|
||||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||||
<script defer
|
<script defer
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user