This commit is contained in:
Chris Chen 2024-03-22 11:06:42 -07:00
parent b46392bc41
commit 6a031ca478
38 changed files with 993 additions and 376 deletions

View File

@ -2,7 +2,7 @@ import { ChangeDetectorRef, Injectable } from "@angular/core";
import { ActivatedRoute } from "@angular/router";
import { Subject } from "rxjs";
import { first, takeUntil } from "rxjs/operators";
import { MD2GameInfo, MD2Service } from "../../services/md2.service";
import { MD2GameInfo, MD2Service } from "../../services/MD2/md2.service";
import { SignalRMessage } from "../../services/signal-r.service";
import { StateService } from "../../services/state.service";
import { ADIcon, MessageBoxConfig } from "../../ui/alert-dlg/alert-dlg.model";
@ -55,14 +55,14 @@ export abstract class MD2Base {
}
imgUrl(imgPath: string) {
return this.md2Service.imgUrl(imgPath);
return this.md2Service.stateService.imgUrl(imgPath);
}
fileList(folderPath: string) {
return this.md2Service.fileList(folderPath);
}
iconHtml(icon: MD2Icon, cssClass = '') {
return this.md2Service.iconHtml(icon, cssClass);
return this.md2Service.stateService.iconHtml(icon, cssClass);
}
imgHtml(imgFile: string, cssClass = '') {
@ -218,13 +218,13 @@ export abstract class MD2ComponentBase {
this.destroy$.complete();
}
imgUrl(imgPath: string) {
return this.md2Service.imgUrl(imgPath);
return this.md2Service.stateService.imgUrl(imgPath);
}
fileList(folderPath: string) {
return this.md2Service.fileList(folderPath);
}
iconHtml(icon: MD2Icon, cssClass = '') {
return this.md2Service.iconHtml(icon, cssClass);
return this.md2Service.stateService.iconHtml(icon, cssClass);
}
}

View File

@ -16,6 +16,10 @@
<label class="g-font-size-20 mt-3" [innerHtml]="bossAction.skillDescription">
</label>
<md2-mob-attack-info [mob]="boss.info">
</md2-mob-attack-info>
<md2-mob-combat-info [mob]="boss.info"></md2-mob-combat-info>
</div>
</div>
</nb-card-body>

View File

@ -1,7 +1,7 @@
import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { NbDialogRef } from '@nebular/theme';
import { MD2Service } from '../../../../services/md2.service';
import { MD2Service } from '../../../../services/MD2/md2.service';
import { MsgBoxService } from '../../../../services/msg-box.service';
import { StateService } from '../../../../services/state.service';
import { MobDlgType, MD2Icon, MD2HeroInfo } from '../../massive-darkness2.model';

View File

@ -17,10 +17,10 @@
</adj-number-input>
<button nbButton hero status="danger" size="small" (click)="attack(boss.info)">Attack It</button>
<label class="MD2Text mt-3" [innerHtml]="boss.combatInfo.skillName">
</label>
<label class="MD2Text" [innerHtml]="boss.combatInfo.skillDescription">
<!-- <label class="MD2Text mt-3" [innerHtml]="boss.info.combatSkill.skillName">
</label>
<label class="MD2Text" [innerHtml]="boss.info.combatInfo.skillDescription">
</label> -->
</div>
</div>

View File

@ -3,7 +3,7 @@ import { ActivatedRoute } from '@angular/router';
import { NbDialogService } from '@nebular/theme';
import { Subject, Observable } from 'rxjs';
import { first } from 'rxjs/operators';
import { MD2Service } from '../../../services/md2.service';
import { MD2Service } from '../../../services/MD2/md2.service';
import { MsgBoxService } from '../../../services/msg-box.service';
import { StateService } from '../../../services/state.service';
import { ADIcon } from '../../../ui/alert-dlg/alert-dlg.model';

View File

@ -5,7 +5,7 @@ import { ADButtons } from '../../../ui/alert-dlg/alert-dlg.model';
import { DrawingBag, DrawingItem } from '../massive-darkness2.model';
import { first } from 'rxjs/operators';
import { ActivatedRoute } from '@angular/router';
import { MD2Service } from '../../../services/md2.service';
import { MD2Service } from '../../../services/MD2/md2.service';
import { StateService } from '../../../services/state.service';
import { MD2Base, MD2ComponentBase } from '../MD2Base';
import { SignalRMessage } from '../../../services/signal-r.service';

View File

@ -0,0 +1,212 @@
import { environment } from "../../../../../environments/environment";
import { DefenseInfo, IMobFactory, MD2Icon, MobInfo } from "../../massive-darkness2.model";
import { MobSkill, MobSkillType } from "../../massive-darkness2.model.boss";
const MD2_IMG_URL = (id: string = null) => { return `${environment.apiUrl}/Files/Images/MD2/Mobs${(id ? `${encodeURI(id)}` : '')}` }
const CORE_GAME_MOB_LEVEL = [
{ name: 'Gargoyles', level: 1, hp: 2, rewardTokens: 1, defBlue: 1 },
{ name: 'Gargoyles', level: 3, hp: 3, rewardTokens: 1, defBlue: 2 },
{ name: 'Gargoyles', level: 5, hp: 6, rewardTokens: 2, defBlue: 3 },
{ name: 'Demons', level: 1, hp: 3, rewardTokens: 1, defBlue: 1 },
{ name: 'Demons', level: 3, hp: 4, rewardTokens: 1, defBlue: 2 },
{ name: 'Demons', level: 5, hp: 6, rewardTokens: 2, defBlue: 4 },
{ name: 'Undead', level: 1, hp: 4, rewardTokens: 1, defBlue: 1 },
{ name: 'Undead', level: 3, hp: 5, rewardTokens: 1, defBlue: 1 },
{ name: 'Undead', level: 5, hp: 8, rewardTokens: 2, defBlue: 1 },
{ name: 'Fire Entities', level: 1, hp: 3, rewardTokens: 1, defBlue: 1 },
{ name: 'Fire Entities', level: 3, hp: 4, rewardTokens: 1, defBlue: 2 },
{ name: 'Fire Entities', level: 5, hp: 7, rewardTokens: 2, defBlue: 3 },
{ name: 'Fallen Angels', level: 1, hp: 2, rewardTokens: 1, defBlue: 2 },
{ name: 'Fallen Angels', level: 3, hp: 3, rewardTokens: 1, defBlue: 3 },
{ name: 'Fallen Angels', level: 5, hp: 5, rewardTokens: 2, defBlue: 5 },
{ name: 'Infernal Imps', level: 1, hp: 3, rewardTokens: 1, defBlue: 1 },
{ name: 'Infernal Imps', level: 3, hp: 4, rewardTokens: 1, defBlue: 1 },
{ name: 'Infernal Imps', level: 5, hp: 5, rewardTokens: 2, defBlue: 3 },
{ name: 'Skeletons', level: 1, hp: 2, rewardTokens: 1, defBlue: 1 },
{ name: 'Skeletons', level: 3, hp: 3, rewardTokens: 1, defBlue: 2 },
{ name: 'Skeletons', level: 5, hp: 5, rewardTokens: 2, defBlue: 4 },
{ name: 'Satyrs', level: 1, hp: 3, rewardTokens: 1, defBlue: 1 },
{ name: 'Satyrs', level: 3, hp: 4, rewardTokens: 1, defBlue: 2 },
{ name: 'Satyrs', level: 5, hp: 6, rewardTokens: 2, defBlue: 4 }]
export abstract class MobFactory implements IMobFactory {
abstract generate(level: number): MobInfo
protected mob: MobInfo;
protected loadLevelInfo(mobName: string, level: number) {
let levelInfo = CORE_GAME_MOB_LEVEL.find(m => m.name == mobName && level >= m.level);
this.mob = new MobInfo({
name: mobName, hp: levelInfo.hp, level: level, rewardTokens: levelInfo.rewardTokens,
defenseInfo: new DefenseInfo(levelInfo.defBlue)
});
this.mob.leaderImgUrl = MD2_IMG_URL(`CoreGame/Mobs/${encodeURI(this.mob.name)}/Leader.png`);
this.mob.minionImgUrl = MD2_IMG_URL(`CoreGame/Mobs/${encodeURI(this.mob.name)}/Minion.png`);
}
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 class='MD2Icon ${cssClass}'>${String.fromCharCode(65 + icon)}</span>`
}
else {
return `<span class='MD2Icon dice ${MD2Icon[icon].replace('Dice', '')} ${cssClass}'></span>`;
}
}
}
export class MobDemonsFactory extends MobFactory {
generate(level: number): MobInfo {
this.loadLevelInfo('Demons', level);
this.mob.combatSkill = new MobSkill(
{
description: `Attacking or defending Hero discards 1 ${this.iconHtml(MD2Icon.Mana)}`
}
)
return this.mob;
}
}
export class MobFallenAngelFactory extends MobFactory {
generate(level: number): MobInfo {
this.loadLevelInfo('FallenAngels', level);
this.mob.combatSkill = new MobSkill(
{
description: `Defender -${level == 1 ? 1 : 2} ${this.iconHtml(MD2Icon.Defense)}`,
type: MobSkillType.Attack
}
)
return this.mob;
}
}
export class MobFireEntitiesFactory extends MobFactory {
generate(level: number): MobInfo {
this.loadLevelInfo('Fire Entities', level);
this.mob.combatSkill = new MobSkill(
{
description: `Add 1 ${this.iconHtml(MD2Icon.Fire)} to the attacking or defending Hero.`,
type: MobSkillType.Combat
}
)
return this.mob;
}
}
export class MobGargoylesFactory extends MobFactory {
generate(level: number): MobInfo {
this.loadLevelInfo('Gargoyles', level);
this.mob.combatSkill = new MobSkill(
{
description: `+ ${level < 5 ? 1 : 2} ${this.iconHtml(MD2Icon.Defense)}`,
type: MobSkillType.Defense
}
)
return this.mob;
}
}
export class MobInfernalImpsFactory extends MobFactory {
generate(level: number): MobInfo {
this.loadLevelInfo('Infernal Imps', level);
let damage = 1;
switch (level) {
case 1:
case 2:
damage = 1;
break;
case 3:
case 4:
damage = 2;
break;
case 5:
damage = 3;
break;
default:
damage = 1;
break;
}
this.mob.combatSkill = new MobSkill(
{
description: `Kill 1 Imp, then deal ${damage} Wound to each Hero in the attacker's Zone(once per roll).`,
type: MobSkillType.Defense
}
)
return this.mob;
}
}
export class MobSatyrsFactory extends MobFactory {
generate(level: number): MobInfo {
this.loadLevelInfo('Satyrs', level);
this.mob.combatSkill = new MobSkill(
{
description: `+ ${level < 3 ? 1 : 2} ${this.iconHtml(MD2Icon.Attack)}`,
type: MobSkillType.Attack
}
)
return this.mob;
}
}
export class MobSkeletonsFactory extends MobFactory {
generate(level: number): MobInfo {
this.loadLevelInfo('Skeletons', level);
this.mob.combatSkill = new MobSkill(
{
description: `Add 1 minion to this Mob(if possible) unless the Hero discards ${level < 5 ? 1 : 2} ${this.iconHtml(MD2Icon.Mana)}.`,
type: MobSkillType.Defense,
skillRoll: 2
}
)
return this.mob;
}
}
export class MobUndeadFactory extends MobFactory {
generate(level: number): MobInfo {
this.loadLevelInfo('Undead', level);
let skillDesc = '';
if (level < 3) {
skillDesc = `+1 ${this.iconHtml(MD2Icon.YellowDice)}`;
} else if (level < 5) {
skillDesc = `+2 ${this.iconHtml(MD2Icon.YellowDice)}`;
} else {
skillDesc = `+1 ${this.iconHtml(MD2Icon.YellowDice)} 1 ${this.iconHtml(MD2Icon.OrangeDice)}`;
}
skillDesc += ' and this Mob takes 2 wounds';
this.mob.combatSkill = new MobSkill(
{
description: skillDesc,
type: MobSkillType.Attack
}
)
return this.mob;
}
}
export const CoreGameMobFactories = [
new MobDemonsFactory(),
new MobFallenAngelFactory(),
new MobFireEntitiesFactory(),
new MobGargoylesFactory(),
new MobInfernalImpsFactory(),
new MobSatyrsFactory(),
new MobSkeletonsFactory(),
new MobUndeadFactory(),
];

View File

@ -0,0 +1,212 @@
import { environment } from "../../../../../environments/environment";
import { DefenseInfo, IMobFactory, MD2Icon, MobInfo } from "../../massive-darkness2.model";
import { MobSkill, MobSkillType } from "../../massive-darkness2.model.boss";
const MD2_IMG_URL = (id: string = null) => { return `${environment.apiUrl}/Files/Images/MD2/Mobs${(id ? `${encodeURI(id)}` : '')}` }
const CORE_GAME_MOB_LEVEL = [
{ name: 'Gargoyles', level: 1, hp: 2, rewardTokens: 1, defBlue: 1 },
{ name: 'Gargoyles', level: 3, hp: 3, rewardTokens: 1, defBlue: 2 },
{ name: 'Gargoyles', level: 5, hp: 6, rewardTokens: 2, defBlue: 3 },
{ name: 'Demons', level: 1, hp: 3, rewardTokens: 1, defBlue: 1 },
{ name: 'Demons', level: 3, hp: 4, rewardTokens: 1, defBlue: 2 },
{ name: 'Demons', level: 5, hp: 6, rewardTokens: 2, defBlue: 4 },
{ name: 'Undead', level: 1, hp: 4, rewardTokens: 1, defBlue: 1 },
{ name: 'Undead', level: 3, hp: 5, rewardTokens: 1, defBlue: 1 },
{ name: 'Undead', level: 5, hp: 8, rewardTokens: 2, defBlue: 1 },
{ name: 'Fire Entities', level: 1, hp: 3, rewardTokens: 1, defBlue: 1 },
{ name: 'Fire Entities', level: 3, hp: 4, rewardTokens: 1, defBlue: 2 },
{ name: 'Fire Entities', level: 5, hp: 7, rewardTokens: 2, defBlue: 3 },
{ name: 'Fallen Angels', level: 1, hp: 2, rewardTokens: 1, defBlue: 2 },
{ name: 'Fallen Angels', level: 3, hp: 3, rewardTokens: 1, defBlue: 3 },
{ name: 'Fallen Angels', level: 5, hp: 5, rewardTokens: 2, defBlue: 5 },
{ name: 'Infernal Imps', level: 1, hp: 3, rewardTokens: 1, defBlue: 1 },
{ name: 'Infernal Imps', level: 3, hp: 4, rewardTokens: 1, defBlue: 1 },
{ name: 'Infernal Imps', level: 5, hp: 5, rewardTokens: 2, defBlue: 3 },
{ name: 'Skeletons', level: 1, hp: 2, rewardTokens: 1, defBlue: 1 },
{ name: 'Skeletons', level: 3, hp: 3, rewardTokens: 1, defBlue: 2 },
{ name: 'Skeletons', level: 5, hp: 5, rewardTokens: 2, defBlue: 4 },
{ name: 'Satyrs', level: 1, hp: 3, rewardTokens: 1, defBlue: 1 },
{ name: 'Satyrs', level: 3, hp: 4, rewardTokens: 1, defBlue: 2 },
{ name: 'Satyrs', level: 5, hp: 6, rewardTokens: 2, defBlue: 4 }]
export abstract class MobFactory implements IMobFactory {
abstract generate(level: number): MobInfo
protected mob: MobInfo;
protected loadLevelInfo(mobName: string, level: number) {
let levelInfo = CORE_GAME_MOB_LEVEL.find(m => m.name == mobName && level >= m.level);
this.mob = new MobInfo({
name: mobName, hp: levelInfo.hp, level: level, rewardTokens: levelInfo.rewardTokens,
defenseInfo: new DefenseInfo(levelInfo.defBlue)
});
this.mob.leaderImgUrl = MD2_IMG_URL(`CoreGame/Mobs/${encodeURI(this.mob.name)}/Leader.png`);
this.mob.minionImgUrl = MD2_IMG_URL(`CoreGame/Mobs/${encodeURI(this.mob.name)}/Minion.png`);
}
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 class='MD2Icon ${cssClass}'>${String.fromCharCode(65 + icon)}</span>`
}
else {
return `<span class='MD2Icon dice ${MD2Icon[icon].replace('Dice', '')} ${cssClass}'></span>`;
}
}
}
export class MobDemonsFactory extends MobFactory {
generate(level: number): MobInfo {
this.loadLevelInfo('Demons', level);
this.mob.combatSkill = new MobSkill(
{
description: `Attacking or defending Hero discards 1 ${this.iconHtml(MD2Icon.Mana)}`
}
)
return this.mob;
}
}
export class MobFallenAngelFactory extends MobFactory {
generate(level: number): MobInfo {
this.loadLevelInfo('FallenAngels', level);
this.mob.combatSkill = new MobSkill(
{
description: `Defender -${level == 1 ? 1 : 2} ${this.iconHtml(MD2Icon.Defense)}`,
type: MobSkillType.Attack
}
)
return this.mob;
}
}
export class MobFireEntitiesFactory extends MobFactory {
generate(level: number): MobInfo {
this.loadLevelInfo('Fire Entities', level);
this.mob.combatSkill = new MobSkill(
{
description: `Add 1 ${this.iconHtml(MD2Icon.Fire)} to the attacking or defending Hero.`,
type: MobSkillType.Combat
}
)
return this.mob;
}
}
export class MobGargoylesFactory extends MobFactory {
generate(level: number): MobInfo {
this.loadLevelInfo('Gargoyles', level);
this.mob.combatSkill = new MobSkill(
{
description: `+ ${level < 5 ? 1 : 2} ${this.iconHtml(MD2Icon.Defense)}`,
type: MobSkillType.Defense
}
)
return this.mob;
}
}
export class MobInfernalImpsFactory extends MobFactory {
generate(level: number): MobInfo {
this.loadLevelInfo('Infernal Imps', level);
let damage = 1;
switch (level) {
case 1:
case 2:
damage = 1;
break;
case 3:
case 4:
damage = 2;
break;
case 5:
damage = 3;
break;
default:
damage = 1;
break;
}
this.mob.combatSkill = new MobSkill(
{
description: `Kill 1 Imp, then deal ${damage} Wound to each Hero in the attacker's Zone(once per roll).`,
type: MobSkillType.Defense
}
)
return this.mob;
}
}
export class MobSatyrsFactory extends MobFactory {
generate(level: number): MobInfo {
this.loadLevelInfo('Satyrs', level);
this.mob.combatSkill = new MobSkill(
{
description: `+ ${level < 3 ? 1 : 2} ${this.iconHtml(MD2Icon.Attack)}`,
type: MobSkillType.Attack
}
)
return this.mob;
}
}
export class MobSkeletonsFactory extends MobFactory {
generate(level: number): MobInfo {
this.loadLevelInfo('Skeletons', level);
this.mob.combatSkill = new MobSkill(
{
description: `Add 1 minion to this Mob(if possible) unless the Hero discards ${level < 5 ? 1 : 2} ${this.iconHtml(MD2Icon.Mana)}.`,
type: MobSkillType.Defense,
skillRoll: 2
}
)
return this.mob;
}
}
export class MobUndeadFactory extends MobFactory {
generate(level: number): MobInfo {
this.loadLevelInfo('Undead', level);
let skillDesc = '';
if (level < 3) {
skillDesc = `+1 ${this.iconHtml(MD2Icon.YellowDice)}`;
} else if (level < 5) {
skillDesc = `+2 ${this.iconHtml(MD2Icon.YellowDice)}`;
} else {
skillDesc = `+1 ${this.iconHtml(MD2Icon.YellowDice)} 1 ${this.iconHtml(MD2Icon.OrangeDice)}`;
}
skillDesc += ' and this Mob takes 2 wounds';
this.mob.combatSkill = new MobSkill(
{
description: skillDesc,
type: MobSkillType.Attack
}
)
return this.mob;
}
}
export const CoreGameMobFactories = [
new MobDemonsFactory(),
new MobFallenAngelFactory(),
new MobFireEntitiesFactory(),
new MobGargoylesFactory(),
new MobInfernalImpsFactory(),
new MobSatyrsFactory(),
new MobSkeletonsFactory(),
new MobUndeadFactory(),
];

View File

@ -4,7 +4,7 @@ import { ActivatedRoute } from '@angular/router';
import { first } from 'rxjs/operators';
import { DropDownOption } from '../../../entity/dropDownOption';
import { GameRoomService } from '../../../services/game-room.service';
import { MD2Service } from '../../../services/md2.service';
import { MD2Service } from '../../../services/MD2/md2.service';
import { MsgBoxService } from '../../../services/msg-box.service';
import { StateService } from '../../../services/state.service';
import { ADButtonColor, ADButtons } from '../../../ui/alert-dlg/alert-dlg.model';

View File

@ -6,7 +6,7 @@ import { ArrayUtils } from '../../utilities/array-utils';
import { ObjectUtils } from '../../utilities/object-utils';
import { first, map, take, takeUntil } from 'rxjs/operators';
import { TreasureType, DrawingBag, DrawingItem, HeroClass, MD2HeroInfo, RoundPhase, MobInfo, MobDlgType } from './massive-darkness2.model';
import { MD2Service } from '../../services/md2.service';
import { MD2Service } from '../../services/MD2/md2.service';
import { GameRoomService } from '../../services/game-room.service';
import { MD2Base } from './MD2Base';
import { StateService } from '../../services/state.service';

View File

@ -1,9 +1,10 @@
import { stringify } from "querystring"
import { Subject } from "rxjs"
import { first } from "rxjs/operators"
import { MD2Service } from "../../services/md2.service"
import { MD2Service } from "../../services/MD2/md2.service"
import { StringUtils } from "../../utilities/string-utils"
import { BossActivationComponent } from "./boss-fight/boss-activation/boss-activation.component"
import { TreasureType, AttackInfo, DefenseInfo, AttackType, MD2Icon, MD2HeroInfo, AttackTarget, MobInfo } from "./massive-darkness2.model"
import { TreasureType, AttackInfo, DefenseInfo, AttackType, MD2Icon, MD2HeroInfo, AttackTarget, MobInfo, MobType } from "./massive-darkness2.model"
import { RollingBlackDice } from "./massive-darkness2.model.dice"
@ -19,7 +20,6 @@ export interface IBossFight {
actionBlackDice: number
imgUrl: string
standUrl: string
combatInfo: MobSkill
activating(): boolean
prepareForBossFight(): void
nextRound(): void
@ -27,25 +27,27 @@ export interface IBossFight {
export class BossMicheal implements IBossFight {
constructor(private md2Service: MD2Service) {
this.corruptionTokenHtml = this.md2Service.stateService.imgHtml('Tokens/CorruptToken.png');
this.name = 'Michael - The Corrupted Archangel';
this.imgUrl = md2Service.imgUrl('/Boss/Michael - The Corrupted Archangel.jpg');
this.standUrl = md2Service.imgUrl('/Boss/Michael.png');
this.imgUrl = md2Service.stateService.imgUrl('/Boss/Michael - The Corrupted Archangel.jpg');
this.standUrl = md2Service.stateService.imgUrl('/Boss/Michael.png');
this.hpPerHero = 15;
this.info = new MobInfo({
isRoamingMonster: true,
description: this.name,
type: MobType.Boss,
hp: this.md2Service.heros.length * this.hpPerHero,
level: 10
unitRemainHp: this.md2Service.heros.length * this.hpPerHero,
level: 10,
combatSkill: new MobSkill(`Combat 1 ${this.md2Service.stateService.iconHtml(MD2Icon.EnemySkill)}`,
`Deal 1 Wound for each ${this.corruptionTokenHtml} on the attacking or defending Hero. Discard the tokens afterwards(once per combat).`),
imageUrl: md2Service.stateService.imgUrl('/Boss/Michael.png')
});
this.info.defenseInfos = new DefenseInfo(5, 1);
this.info.defenseInfo = new DefenseInfo(5, 1);
this.info.attackInfos = [new AttackInfo(MD2Icon.Melee, 2, 2, 0, 1)];
this.actions = 1;
this.rounds = 0;
this.actionBlackDice = 2;
this.corruptionTokenHtml = this.md2Service.imgHtml('Tokens/CorruptToken.png');
this.combatInfo = new MobSkill(`Combat 1${this.md2Service.iconHtml(MD2Icon.EnemySkill)}`,
`Deal 1 Wound for each ${this.corruptionTokenHtml} on the attacking or defending Hero. Discard the tokens afterwards(once per combat).`);;
}
name: string
addTreasureToken: Subject<TreasureType>
@ -58,7 +60,6 @@ export class BossMicheal implements IBossFight {
actionBlackDice: number
imgUrl: string
standUrl: string
combatInfo: MobSkill
corruptionTokenHtml: string
activating(): boolean {
@ -71,20 +72,20 @@ export class BossMicheal implements IBossFight {
//Justice From Above
beenAttackedHero = this.md2Service.getTargetHerosByFilter(AttackTarget.MostCorruption, true);
bossAction = new MobSkill('Justice From Above',
`Place Michael in the Zone at ${this.md2Service.getTargetHerosHtml(beenAttackedHero)} and attack Him/Her.`, beenAttackedHero);
`Place Michael in the Zone at ${this.md2Service.getTargetHerosHtml(beenAttackedHero)} and attack Him/Her.`);
break;
case 1:
//Lance Dash
beenAttackedHero = this.md2Service.getTargetHerosByFilter(AttackTarget.LeastCorruption, true);
bossAction = new MobSkill('Lance Dash',
`Move Michael and Place 1 ${this.corruptionTokenHtml} in the Zone at ${this.md2Service.getTargetHerosHtml(beenAttackedHero)} and attack Him/Her.`, beenAttackedHero);
`Move Michael and Place 1 ${this.corruptionTokenHtml} in the Zone at ${this.md2Service.getTargetHerosHtml(beenAttackedHero)} and attack Him/Her.`);
break;
case 2:
//Dark Blessing
bossAction = new MobSkill('Dark Blessing',
`Place Michael ion the central Zone and add 1 ${this.corruptionTokenHtml} to the Corruption Stone Zone with the least amount of ${this.corruptionTokenHtml}.<br>` +
`Deal <b>${this.darkBlessingCorruptionAmt}</b> Wounds per ${this.corruptionTokenHtml} to all Heros in each Tiles <b>distributed as they wish</b>.`, beenAttackedHero);
`Place Michael on the central Zone and add 1 ${this.corruptionTokenHtml} to the Corruption Stone Zone with the least amount of ${this.corruptionTokenHtml}.<br>` +
`Deal <b>${this.darkBlessingCorruptionAmt}</b> Wounds per ${this.corruptionTokenHtml} to all Heros in each Tiles <b>distributed as they wish</b>.`);
break;
default:
@ -109,7 +110,7 @@ export class BossMicheal implements IBossFight {
break;
case 2:
case 4:
this.info.defenseInfos[0].black += 1;
this.info.defenseInfo[0].black += 1;
this.info.attackInfos[0].black += 1;
break;
// case 4:
@ -122,14 +123,27 @@ export class BossMicheal implements IBossFight {
}
}
}
export class MobSkill {
constructor(skillName: string, skillDescription: string, targetHeros: MD2HeroInfo[] = []) {
this.skillName = skillName
this.skillDescription = skillDescription
this.targetHeros = targetHeros
export enum MobSkillType {
Attack,
Defense,
Combat
}
skillName: string
skillDescription: string
export class MobSkill {
constructor(config: Partial<MobSkill> = {}) {
let defaultConfig = {
type: MobSkillType.Combat,
skillRoll: 1
} as Partial<MobSkill>;
Object.assign(defaultConfig, config);
Object.assign(this, defaultConfig);
// if (StringUtils.isNullOrWhitespace(this.name)) {
// this.name=`${MobSkillType[this.type]} ${this.skillRoll} ${}`
// }
}
type: MobSkillType;
clawRoll: number;
skillRoll: number;
name: string
description: string
targetHeros: MD2HeroInfo[]
}

View File

@ -1,8 +1,10 @@
import { Subject } from "rxjs";
import { environment } from "../../../environments/environment";
import { ObjectUtils } from "../../utilities/object-utils";
import { GamePlayer } from "../games.model";
import { MobSkill } from "./massive-darkness2.model.boss";
const MD2_IMG_URL = (id: string = null) => { return `${environment.apiUrl}/Files/Images/MD2/${(id ? `${encodeURI(id)}` : '')}` }
export enum MobDlgType {
Spawn,
Activating,
@ -30,6 +32,12 @@ export enum HeroClass {
Shaman,
Paladin,
}
export enum MobType {
Mob,
RoamingMonster,
Boss
}
export enum MD2Icon {
Attack,
Defense,
@ -95,7 +103,6 @@ export class AttackInfo {
red: number
yellow: number
black: number
attackSkill: MobSkill
}
export class DefenseInfo {
constructor(blue: number, black: number = 0) {
@ -104,7 +111,6 @@ export class DefenseInfo {
}
blue: number
black: number
defenseSkill: MobSkill
}
export class MD2LevelUpReward {
constructor(config: Partial<MD2LevelUpReward>) {
@ -207,7 +213,9 @@ export class DrawingBag<T extends IDrawingItem> {
this.removedItems = [];
}
}
export interface IMobFactory {
generate(level: number): MobInfo;
}
export interface IDrawingItem {
imageUrl: string
name: string
@ -231,7 +239,17 @@ export class DrawingItem implements IDrawingItem {
description: string
drawingWeight: number
}
export class TreasureItem extends DrawingItem {
constructor(type: TreasureType, itemAmount: number = 1) {
super(`${TreasureType[type]} Treasure`,
`It's a ${TreasureType[type]} Treasure!`,
MD2_IMG_URL(`TreasureToken/${TreasureType[type]}.png`), itemAmount);
this.type = type;
this.itemAmount = itemAmount;
}
type: TreasureType;
itemAmount: number;
}
export class MobInfo implements IDrawingItem {
constructor(
config: Partial<MobInfo> = {}
@ -241,8 +259,11 @@ export class MobInfo implements IDrawingItem {
this.drawingWeight = 1;
this.unitRemainHp = config.hp
}
type: MobType = MobType.Mob;
imageUrl: string
standUrl: string
leaderImgUrl: string
minionImgUrl: string
name: string
description: string
drawingWeight: number
@ -250,12 +271,14 @@ export class MobInfo implements IDrawingItem {
rewardTokens: number;
hp: number;
mobAmount: number;
carriedTreasure: DrawingItem[];
fixedCarriedTreasure: DrawingItem[];
carriedTreasure: TreasureItem[];
fixedCarriedTreasure: TreasureItem[];
unitRemainHp: number;
isRoamingMonster: boolean = false;
attackInfos: AttackInfo[];
defenseInfos: DefenseInfo;
defenseInfo: DefenseInfo;
combatSkill: MobSkill
fireToken: number = 0;
frozenToken: number = 0;
corruptionToken: number = 0;
@ -268,44 +291,43 @@ export class MobInfo implements IDrawingItem {
public get carriedTreasureHtml(): string {
if (!this.carriedTreasure) return '';
return this.carriedTreasure.map(i => `<img src="${i.imageUrl}" class='mr-1' width="40px">`)
.concat(this.fixedCarriedTreasure?.map(i => `<img src="${i.imageUrl}" class='mr-1' width="40px">`)).join();
.concat(this.fixedCarriedTreasure?.map(i => `<img src="${i.imageUrl}" class='mr-1' width="40px">`.repeat(i.drawingWeight))).join();
}
public get totalHp(): number {
return this.isRoamingMonster ? this.unitRemainHp : (this.mobAmount - 1) * this.hp + this.unitRemainHp;
switch (this.type) {
case MobType.Mob:
return (this.mobAmount - 1) * this.hp + this.unitRemainHp;
case MobType.RoamingMonster:
return this.unitRemainHp;
case MobType.Boss:
default:
return this.unitRemainHp;
}
}
public get minionAmount(): number {
switch (this.type) {
case MobType.Mob:
return (this.mobAmount - 1);
case MobType.RoamingMonster:
case MobType.Boss:
default:
return 0;
}
}
public get leaderExp(): number {
return this.isRoamingMonster ? 4 : 2;
switch (this.type) {
case MobType.Mob:
return 2;
case MobType.RoamingMonster:
return 4;
case MobType.Boss:
default:
return 0;
}
}
public get mobInfoHtml(): string {
let html = `<img src="${this.imageUrl}" class="g-height-50vh">`
+ `<br>Target Unit HP:${this.unitRemainHp}`;
if (this.isRoamingMonster) {
html += `<br><label class="label">Alive Units:${this.mobAmount}`;
} else {
html += `<br>Total HP:${this.totalHp}`;
}
return html;
}
public getCssClass(): string {
let levelString = '';
if (this.level < 3) {
levelString = '-lv1-2';
} else if (this.level < 5) {
levelString = '-lv3-4';
} else {
levelString = '-lv5';
}
return `${this.name.replace(' ', '')}${levelString}`;
}
}
export class MD2HeroInfo {
@ -344,7 +366,7 @@ export class MD2Rules {
public static CoreGameLevelBoard = [
new MD2LevelUpReward({ level: 2, needExp: 5, extraHp: 1, extraMp: 0, extraRareToken: 1 }),
new MD2LevelUpReward({ level: 3, needExp: 10, extraHp: 1, extraMp: 1, extraEpicToken: 1 }),
new MD2LevelUpReward({ level: 4, needExp: 12, extraHp: 2, extraMp: 2, extraEpicToken: 1 }),
new MD2LevelUpReward({ level: 4, needExp: 12, extraHp: 2, extraMp: 1, extraEpicToken: 1 }),
new MD2LevelUpReward({ level: 5, needExp: 18, extraHp: 2, extraMp: 2, extraEpicToken: 1 }),
];
public static checkCoreGameLevelup(currentLevel: number, currentExp: number): MD2LevelUpReward {

View File

@ -3,7 +3,7 @@ import { ControlValueAccessor, Validator, AbstractControl, ValidationErrors, NG_
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { DropDownOption } from '../../../entity/dropDownOption';
import { MD2Service } from '../../../services/md2.service';
import { MD2Service } from '../../../services/MD2/md2.service';
import { ArrayUtils } from '../../../utilities/array-utils';
import { HeroClass, MD2HeroInfo } from '../massive-darkness2.model';

View File

@ -1 +1 @@
<span class="MD2Icon {{icon}} {{iconClass}}"></span>
<span class="MD2Icon {{icon}} {{iconClass}} {{sizeClass}}"></span>

View File

@ -8,14 +8,33 @@ import { MD2Icon } from '../massive-darkness2.model';
})
export class MD2IconComponent implements OnInit {
@Input() iconClass: string = '';
@Input() iconClass: string = 'mr-1';
@Input("icon") icon: MD2Icon;
@Input("icon") icon: string;
@Input() size: string = 'sm';
constructor() { }
ngOnInit(): void {
}
public get sizeClass(): string {
switch (this.size) {
case 'sm':
return 'g-font-size-18'
break;
case 'med':
return 'g-font-size-30'
break;
case 'lg':
return 'g-font-size-50'
break;
default:
return 'g-font-size-' + this.size;
break;
}
}
}

View File

@ -1,7 +1,7 @@
<label class='label'>Weapon Info</label>
<div class="g-brd-3 g-brd-bottom--dashed g-brd-gray-light-v2 mb-3 mt-2 row" *ngFor="let info of mob.attackInfos">
<div class="col-md-4">
<span class=" g-font-size-50" [innerHtml]="iconHtml(info.type)"></span>
<md2-icon icon="attack" size="lg"></md2-icon>
</div>
<div class="col-md-8">
<div *ngIf="info.yellow" class="g-height-45">
@ -19,5 +19,10 @@
<span class="MD2text diceAmount">x{{info.red}}</span>
</span>
</div>
<div *ngIf="mob.defenseInfo.black" class="g-height-45 mt-1">
<span class="MD2Icon Black dice g-font-size-50">
<span class="MD2text diceAmount">x{{mob.defenseInfo.black}}</span>
</span>
</div>
</div>
</div>

View File

@ -0,0 +1,19 @@
.diceAmount {
color: white;
z-index: 2;
position: absolute;
left: 25px;
font-size: 30px;
}
.dice {
&::before {
position: absolute;
}
}
.blackDiceAmount {
color: white;
z-index: 2;
position: absolute;
left: 26px;
font-size: 30px;
}

View File

@ -1,8 +1,8 @@
import { Component, Input, OnInit } from '@angular/core';
import { MD2Icon, MobInfo } from '../../../massive-darkness2.model';
import { MD2Icon, MobDlgType, MobInfo } from '../../../massive-darkness2.model';
@Component({
selector: 'ngx-mob-attack-info',
selector: 'md2-mob-attack-info',
templateUrl: './mob-attack-info.component.html',
styleUrls: ['./mob-attack-info.component.scss']
})
@ -20,6 +20,7 @@ export class MobAttackInfoComponent implements OnInit {
}
}
@Input() mode: MobDlgType = MobDlgType.PreView;
constructor() { }

View File

@ -1 +1,5 @@
<p>mob-combat-info works!</p>
<div class='form-group row' *ngIf="showSkill">
<label class='label col-sm-3 form-control-label MD2text g-font-size-30'
[innerHtml]="mob.combatSkill.skillName"></label>
<div class='col-sm' [innerHtml]="mob.combatSkill.skillDescription"></div>
</div>

View File

@ -0,0 +1,19 @@
.diceAmount {
color: white;
z-index: 2;
position: absolute;
left: 25px;
font-size: 30px;
}
.dice {
&::before {
position: absolute;
}
}
.blackDiceAmount {
color: white;
z-index: 2;
position: absolute;
left: 26px;
font-size: 30px;
}

View File

@ -1,15 +1,47 @@
import { Component, OnInit } from '@angular/core';
import { Component, Input, OnInit } from '@angular/core';
import { MD2Icon, MobDlgType, MobInfo } from '../../../massive-darkness2.model';
import { MobSkillType } from '../../../massive-darkness2.model.boss';
@Component({
selector: 'ngx-mob-combat-info',
selector: 'md2-mob-combat-info',
templateUrl: './mob-combat-info.component.html',
styleUrls: ['./mob-combat-info.component.scss']
})
export class MobCombatInfoComponent implements OnInit {
MD2Icon = MD2Icon;
private _mob: MobInfo;
public get mob(): MobInfo {
return this._mob;
}
@Input() public set mob(v: MobInfo) {
if (this._mob != v) {
this._mob = v;
}
}
@Input() mode: MobDlgType = MobDlgType.PreView;
constructor() { }
ngOnInit(): void {
if (this.mob.combatSkill) {
switch (this.mode) {
case MobDlgType.Activating:
this.showSkill = [MobSkillType.Combat, MobSkillType.Attack].includes(this.mob.combatSkill.type);
break;
case MobDlgType.BeenAttacked:
this.showSkill = [MobSkillType.Combat, MobSkillType.Defense].includes(this.mob.combatSkill.type);
break;
case MobDlgType.PreView:
case MobDlgType.Spawn:
default:
this.showSkill = true;
break;
}
}
}
showSkill: boolean = false;;
}

View File

@ -1 +1,18 @@
<p>mob-def-info works!</p>
<label class='label'>Defense Info</label>
<div class="g-brd-3 g-brd-bottom--dashed g-brd-gray-light-v2 mb-3 mt-2 row">
<div class="col-md-4">
<md2-icon icon="defense" size="lg"></md2-icon>
</div>
<div class="col-md-8">
<div *ngIf="mob.defenseInfo.blue" class="g-height-45">
<span class="MD2Icon Blue dice g-font-size-50">
<span class="MD2text diceAmount">x{{mob.defenseInfo.blue}}</span>
</span>
</div>
<div *ngIf="mob.defenseInfo.black" class="g-height-45 mt-1">
<span class="MD2Icon Black dice g-font-size-50">
<span class="MD2text diceAmount">x{{mob.defenseInfo.black}}</span>
</span>
</div>
</div>
</div>

View File

@ -0,0 +1,19 @@
.diceAmount {
color: white;
z-index: 2;
position: absolute;
left: 25px;
font-size: 30px;
}
.dice {
&::before {
position: absolute;
}
}
.blackDiceAmount {
color: white;
z-index: 2;
position: absolute;
left: 26px;
font-size: 30px;
}

View File

@ -1,14 +1,27 @@
import { Component, OnInit } from '@angular/core';
import { Component, Input, OnInit } from '@angular/core';
import { MD2Icon, MobInfo, MobDlgType } from '../../../massive-darkness2.model';
@Component({
selector: 'ngx-mob-def-info',
selector: 'md2-mob-def-info',
templateUrl: './mob-def-info.component.html',
styleUrls: ['./mob-def-info.component.scss']
})
export class MobDefInfoComponent implements OnInit {
constructor() { }
MD2Icon = MD2Icon;
private _mob: MobInfo;
public get mob(): MobInfo {
return this._mob;
}
@Input() public set mob(v: MobInfo) {
if (this._mob != v) {
this._mob = v;
}
}
@Input() mode: MobDlgType = MobDlgType.PreView;
constructor() { }
ngOnInit(): void {
}

View File

@ -10,35 +10,14 @@
<label class='label'>Carried Treasure</label><br>
<div [innerHtml]="mob.carriedTreasureHtml"></div>
</ng-container>
<ng-container *ngIf="mob.attackInfos&&mob.attackInfos.length>0&& !hideWeaponInfo">
</ng-container>
<ng-container *ngIf="mob.defenseInfos&& !hideWeaponInfo">
<label class='label'>Defense Info</label>
<div class="g-brd-3 g-brd-bottom--dashed g-brd-gray-light-v2 mb-3 mt-2 row">
<div class="col-md-4">
<span class="g-font-size-50" [innerHtml]="iconHtml(MD2Icon.Defense)"></span>
</div>
<div class="col-md-8">
<div *ngIf="mob.defenseInfos.blue" class="g-height-45">
<span class="MD2Icon Blue dice g-font-size-50">
<span class="MD2text diceAmount">x{{mob.defenseInfos.blue}}</span>
</span>
</div>
<div *ngIf="mob.defenseInfos.black" class="g-height-45 mt-1">
<span class="MD2Icon Black dice g-font-size-50">
<span class="MD2text diceAmount">x{{mob.defenseInfos.black}}</span>
</span>
</div>
</div>
</div>
</ng-container>
<md2-mob-attack-info [mob]="mob" [mode]="mode" *ngIf="mob.attackInfos&&mob.attackInfos.length>0&& !hideWeaponInfo">
</md2-mob-attack-info>
<md2-mob-def-info [mob]="mob" [mode]="mode" *ngIf="mob.defenseInfo&& !hideWeaponInfo"></md2-mob-def-info>
<md2-mob-combat-info [mob]="mob" [mode]="mode"></md2-mob-combat-info>
<div *ngIf="showBlackDice" class="row">
<!-- <md2-icon></md2-icon> -->
<div class="col-md-4">
<span class=" g-font-size-50" [innerHtml]="iconHtml(MD2Icon.EnemySkill)"></span>
<md2-icon icon="enemySkill" size="lg"></md2-icon>
</div>
<div class="col-md-8">
<span class="MD2Icon Black dice g-font-size-50">

View File

@ -1,6 +1,6 @@
import { ChangeDetectorRef, Component, Input, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { MD2Service } from '../../../../services/md2.service';
import { MD2Service } from '../../../../services/MD2/md2.service';
import { StateService } from '../../../../services/state.service';
import { MD2Icon, MobDlgType, MobInfo } from '../../massive-darkness2.model';
import { MD2ComponentBase } from '../../MD2Base';

View File

@ -3,7 +3,7 @@ import { ActivatedRoute } from '@angular/router';
import { NbDialogService } from '@nebular/theme';
import { first } from 'rxjs/operators';
import { FileService } from '../../../services/file.service';
import { MD2Service } from '../../../services/md2.service';
import { MD2Service } from '../../../services/MD2/md2.service';
import { MsgBoxService } from '../../../services/msg-box.service';
import { StateService } from '../../../services/state.service';
import { ADIcon } from '../../../ui/alert-dlg/alert-dlg.model';
@ -71,20 +71,14 @@ export class MobsComponent extends MD2ComponentBase implements OnInit {
});
}
spawnMob() {
let result = this.md2Service.drawMob(this.isRoamingMonster);
if (result.exitingMob) {
this.dlgService.open(SpawnMobDlgComponent, { context: { title: `${result.mob.description} Activate One Action Now!`, mode: MobDlgType.Activating, mob: result.mob } })
.onClose.pipe(first()).subscribe(result => {
this.afterSpawn()
});
} else {
this.md2Service.refreshTreasureBagSubject.next(this.md2Service.treasureBag);
//this.msgBoxService.show(`${newSpawnMob.description} Shows Up`, { text: actionText });
this.dlgService.open(SpawnMobDlgComponent, { context: { title: `${result.mob.description} Shows Up`, mode: MobDlgType.Spawn, mob: result.mob } })
let result = this.md2Service.spawnMob(this.isRoamingMonster);
let titleText = result.exitingMob == null ? `${result.mob.description} Shows Up` : `${result.mob.description} Activate One Action Now!`;
let actType = result.exitingMob == null ? MobDlgType.Spawn : MobDlgType.Activating;
this.dlgService.open(SpawnMobDlgComponent, { context: { title: titleText, mode: actType, mob: result.mob } })
.onClose.pipe(first()).subscribe(result => {
this.afterSpawn();
});
}
this.cdRef.detectChanges();
}
afterSpawn() {
@ -214,7 +208,6 @@ export class MobsComponent extends MD2ComponentBase implements OnInit {
.onClose.pipe(first()).subscribe(result => {
});
//this.msgBoxService.show('', { text: mob.mobInfoHtml.replace('g-height-50vh', 'g-height-70vh') });
}
weaponHtml(mob: MobInfo) {
let html = '<br>';

View File

@ -1,6 +1,6 @@
<nb-card status="{{headerStatus}}" class="mobCard" size="giant">
<nb-card-header>
<img src="{{imgUrl('Mobs/MobToken.png')}}" width="40px"> {{(mob.isRoamingMonster?'Roaming Monster':'Mob')}}
<img src="{{imgUrl('Mobs/MobToken.png')}}" width="40px"> {{cardTitle}}
<span [innerHtml]="titleHtml"></span>
</nb-card-header>
<nb-card-body>
@ -12,7 +12,7 @@
<md2-mob-detail-info [mob]="mob" [mode]="mode">
</md2-mob-detail-info>
<ng-container *ngIf="mode==MobDlgType.Spawn&&!mob.isRoamingMonster">
<ng-container *ngIf="mode==MobDlgType.Spawn&&mob.type==MobType.Mob">
<div class="row form-group mt-2">
<div class="col-md-2">
<span class="MD2Icon melee g-font-size-40"></span>

View File

@ -2,11 +2,11 @@ import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { NbDialogRef } from '@nebular/theme';
import { FileService } from '../../../../services/file.service';
import { MD2Service } from '../../../../services/md2.service';
import { MD2Service } from '../../../../services/MD2/md2.service';
import { MsgBoxService } from '../../../../services/msg-box.service';
import { StateService } from '../../../../services/state.service';
import { StringUtils } from '../../../../utilities/string-utils';
import { AttackInfo, AttackTarget, AttackType, MD2HeroInfo, MD2Icon, MobDlgType, MobInfo } from '../../massive-darkness2.model';
import { AttackInfo, AttackTarget, AttackType, MD2HeroInfo, MD2Icon, MobDlgType, MobInfo, MobType } from '../../massive-darkness2.model';
import { MD2ComponentBase } from '../../MD2Base';
@Component({
@ -16,8 +16,9 @@ import { MD2ComponentBase } from '../../MD2Base';
})
export class SpawnMobDlgComponent extends MD2ComponentBase implements OnInit {
MobDlgType = MobDlgType;
MobType = MobType;
mode: MobDlgType;
cardTitle: string;
title: string;
titleHtml: string;
MD2Icon = MD2Icon;
@ -38,28 +39,8 @@ export class SpawnMobDlgComponent extends MD2ComponentBase implements OnInit {
}
ngOnInit(): void {
//this.mob = new MobInfo(this.mob);
if (this.mode == MobDlgType.Spawn) {
this.mob.attackInfos = [
{
type: MD2Icon.Melee,
red: 0,
yellow: 0,
orange: 0
} as AttackInfo,
{
type: MD2Icon.Range,
red: 0,
yellow: 0,
orange: 0
} as AttackInfo,
{
type: MD2Icon.Magic,
red: 0,
yellow: 0,
orange: 0
} as AttackInfo
]
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.uiWounds = 0;
this.mob.uiFrozenTokens = 0;
@ -93,6 +74,9 @@ export class SpawnMobDlgComponent extends MD2ComponentBase implements OnInit {
this.dlgRef.close();
}
initTitleHtml() {
this.cardTitle = MobType[this.mob.type];
let htmlText = '';
if (this.mode == MobDlgType.Spawn) {
htmlText = `${this.mob.description} Shows Up`;

View File

@ -3,7 +3,7 @@ import { ActivatedRoute } from '@angular/router';
import { Subject } from 'rxjs-compat';
import { first, takeUntil } from 'rxjs/operators';
import { FileService } from '../../../services/file.service';
import { MD2Service } from '../../../services/md2.service';
import { MD2Service } from '../../../services/MD2/md2.service';
import { MsgBoxService } from '../../../services/msg-box.service';
import { StateService } from '../../../services/state.service';
import { ADButtons, ADIcon } from '../../../ui/alert-dlg/alert-dlg.model';

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

View File

@ -0,0 +1,103 @@
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.info.heros.find(h => h.playerInfo.signalRClientId == this.loginUserService.userAccess.signalRSessionId);
}
public broadcastAllHeroInfoToAll() {
this.stateService.info.heros.forEach(element => {
this.broadcastHeroInfoToAll(element);
});
}
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: 'update',
} 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 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);
}
}

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

View File

@ -0,0 +1,38 @@
import { Injectable } from '@angular/core';
import { MD2Icon, TreasureType } from '../../games/massive-darkness2/massive-darkness2.model';
import { FileService } from '../file.service';
import { MD2GameInfo } from './md2.service';
@Injectable({
providedIn: 'root'
})
export class MD2StateService {
private _highestPlayerLevel: number = 1;
private _playerAmount: number = 2;
public info: MD2GameInfo;
constructor(
public fileService: FileService,
) { }
public iconHtml(icon: MD2Icon, cssClass = '') {
if (icon < MD2Icon.RedDice) {
return `<span class='MD2Icon ${cssClass}'>${String.fromCharCode(65 + icon)}</span>`
} else {
return `<span class='MD2Icon dice ${MD2Icon[icon].replace('Dice', '')} ${cssClass}'></span>`;
}
}
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`);
}
}

View File

@ -1,19 +1,21 @@
import { Injectable } from '@angular/core';
import { AttackInfo, AttackTarget, CoreGameDarknessPhaseRule, DefenseInfo, DrawingBag, DrawingItem, HeroClass, IDarknessPhaseRule, MD2HeroInfo, MD2Icon, MD2Rules, MobInfo, RoundPhase, TreasureType } from '../games/massive-darkness2/massive-darkness2.model';
import { AttackInfo, AttackTarget, CoreGameDarknessPhaseRule, DefenseInfo, DrawingBag, DrawingItem, HeroClass, IDarknessPhaseRule, MD2HeroInfo, MD2Icon, MD2Rules, MobInfo, MobType, RoundPhase, TreasureItem, TreasureType } from '../../games/massive-darkness2/massive-darkness2.model';
import { first, map, reduce } from "rxjs/operators";
import { Subject } from 'rxjs';
import { FileService } from './file.service';
import { StringUtils } from '../utilities/string-utils';
import { MsgBoxService } from './msg-box.service';
import { ADButtons, ADIcon, MessageBoxConfig } from '../ui/alert-dlg/alert-dlg.model';
import { GameRoomService } from './game-room.service';
import { SignalRMessage, SignalRService, SignalRSession } from './signal-r.service';
import { LoginUserService } from './login-user.service';
import { NumberUtils } from '../utilities/number-utils';
import { SpawnMobDlgComponent } from '../games/massive-darkness2/mobs/spawn-mob-dlg/spawn-mob-dlg.component';
import { stringify } from 'querystring';
import { NbDialogService } from '@nebular/theme';
import { IBossFight } from '../games/massive-darkness2/massive-darkness2.model.boss';
import { Subject } from 'rxjs';
import { IBossFight } from '../../games/massive-darkness2/massive-darkness2.model.boss';
import { ADIcon, MessageBoxConfig } from '../../ui/alert-dlg/alert-dlg.model';
import { NumberUtils } from '../../utilities/number-utils';
import { StringUtils } from '../../utilities/string-utils';
import { FileService } from '../file.service';
import { GameRoomService } from '../game-room.service';
import { LoginUserService } from '../login-user.service';
import { MsgBoxService } from '../msg-box.service';
import { SignalRService, SignalRSession, SignalRMessage } from '../signal-r.service';
import { MD2StateService } from './md2-state.service';
import { MD2BroadcastService } from './md2-broadcast.service';
import { CoreGameMobFactories } from '../../games/massive-darkness2/factorys/mobs/CoreGame';
@Injectable({
providedIn: 'root'
@ -21,11 +23,6 @@ import { IBossFight } from '../games/massive-darkness2/massive-darkness2.model.b
export class MD2Service {
// #region Properties (24)
private _highestPlayerLevel: number = 1;
private _playerAmount: number = 2;
public info: MD2GameInfo;
public darknessPhaseRule: IDarknessPhaseRule;
public enemyPhaseMobs: MobInfo[];
public enemyPhaseSubject = new Subject<MobInfo>();
@ -33,20 +30,28 @@ export class MD2Service {
public mobBeenKilledSubject = new Subject<MobInfo>();
public mobDeck: DrawingBag<MobInfo>;
public roamingMobDeck: DrawingBag<MobInfo>;
public treasureBag: DrawingBag<DrawingItem> = new DrawingBag<DrawingItem>();
public treasureBag: DrawingBag<TreasureItem> = new DrawingBag<TreasureItem>();
public refreshUI$: Subject<void> = new Subject<void>();
public refreshTreasureBagSubject = new Subject<DrawingBag<DrawingItem>>();
public refreshTreasureBagSubject = new Subject<DrawingBag<TreasureItem>>();
public get heros() {
return this.info.heros;
return this.stateService.info.heros;
}
public get roamingMonsters() {
return this.info.roamingMonsters;
return this.stateService.info.roamingMonsters;
}
public get mobs() {
return this.info.mobs;
return this.stateService.info.mobs;
}
public get info(): MD2GameInfo {
return this.stateService.info;
}
public set info(v: MD2GameInfo) {
this.stateService.info = v;
}
// #endregion Properties (24)
@ -58,11 +63,13 @@ export class MD2Service {
public msgBoxService: MsgBoxService,
private gameRoomService: GameRoomService,
private loginUserService: LoginUserService,
public stateService: MD2StateService,
public signalRService: SignalRService,
public dlgService: NbDialogService
public dlgService: NbDialogService,
public broadcastService: MD2BroadcastService
) {
this.darknessPhaseRule = new CoreGameDarknessPhaseRule();
this.info = new MD2GameInfo();
this.stateService.info = new MD2GameInfo();
this.darknessPhaseRule.addTreasureToken.subscribe(treasureType => {
this.addTreasure(treasureType, 1);
});
@ -71,56 +78,64 @@ export class MD2Service {
// #endregion Constructors (1)
private initCoreGameRoamingMonsters() {
let mobs = [];
this.roamingMobDeck.AddItem(new MobInfo({ name: 'Andra', hp: 5, level: 1, rewardTokens: 2, isRoamingMonster: true, fixedCarriedTreasure: [this.getTreasureDrawingItem(TreasureType.Rare)] }));
this.roamingMobDeck.AddItem(new MobInfo({ name: 'Andra', hp: 7, level: 3, rewardTokens: 2, isRoamingMonster: true, fixedCarriedTreasure: [this.getTreasureDrawingItem(TreasureType.Epic)] }));
this.roamingMobDeck.AddItem(new MobInfo({ name: 'Andra', hp: 5, level: 5, rewardTokens: 0, isRoamingMonster: true, fixedCarriedTreasure: [this.getTreasureDrawingItem(TreasureType.Epic), this.getTreasureDrawingItem(TreasureType.Epic), this.getTreasureDrawingItem(TreasureType.Epic)] }));
this.roamingMobDeck.AddItem(new MobInfo({ name: 'Andra', hp: 5, level: 1, rewardTokens: 2, type: MobType.RoamingMonster, fixedCarriedTreasure: [new TreasureItem(TreasureType.Rare)] }));
this.roamingMobDeck.AddItem(new MobInfo({ name: 'Andra', hp: 7, level: 3, rewardTokens: 2, type: MobType.RoamingMonster, fixedCarriedTreasure: [new TreasureItem(TreasureType.Epic)] }));
this.roamingMobDeck.AddItem(new MobInfo({ name: 'Andra', hp: 5, level: 5, rewardTokens: 0, type: MobType.RoamingMonster, fixedCarriedTreasure: [new TreasureItem(TreasureType.Epic, 3)] }));
this.roamingMobDeck.AddItem(new MobInfo({
name: 'Ytheria, Undead Queen', hp: 4, level: 1, rewardTokens: 2,
attackInfos: [new AttackInfo(MD2Icon.Melee, 1), new AttackInfo(MD2Icon.Rage, 2, 0, 0, 1)],
defenseInfos: new DefenseInfo(1, 1),
isRoamingMonster: true, fixedCarriedTreasure: [this.getTreasureDrawingItem(TreasureType.Rare)]
defenseInfo: new DefenseInfo(1, 1),
type: MobType.RoamingMonster, fixedCarriedTreasure: [new TreasureItem(TreasureType.Rare)]
}));
this.roamingMobDeck.AddItem(new MobInfo({
name: 'Ytheria, Undead Queen', hp: 6, level: 3, rewardTokens: 2,
attackInfos: [new AttackInfo(MD2Icon.Melee, 0, 1), new AttackInfo(MD2Icon.Rage, 1, 1, 0, 1)],
defenseInfos: new DefenseInfo(2, 1),
isRoamingMonster: true, fixedCarriedTreasure: [this.getTreasureDrawingItem(TreasureType.Epic)]
defenseInfo: new DefenseInfo(2, 1),
type: MobType.RoamingMonster, fixedCarriedTreasure: [new TreasureItem(TreasureType.Epic)]
}));
this.roamingMobDeck.AddItem(new MobInfo({
name: 'Ytheria, Undead Queen', hp: 8, level: 5, rewardTokens: 0,
attackInfos: [new AttackInfo(MD2Icon.Melee, 2, 1), new AttackInfo(MD2Icon.Rage, 2, 1, 1, 1)],
defenseInfos: new DefenseInfo(4, 1),
isRoamingMonster: true, fixedCarriedTreasure: [this.getTreasureDrawingItem(TreasureType.Epic), this.getTreasureDrawingItem(TreasureType.Epic), this.getTreasureDrawingItem(TreasureType.Epic)]
defenseInfo: new DefenseInfo(4, 1),
type: MobType.RoamingMonster, fixedCarriedTreasure: [new TreasureItem(TreasureType.Epic, 3)]
}));
this.roamingMobDeck.AddItem(new MobInfo({
name: 'Lyidan, Incubus Lord', hp: 7, level: 1, rewardTokens: 2,
isRoamingMonster: true, fixedCarriedTreasure: [this.getTreasureDrawingItem(TreasureType.Rare)]
type: MobType.RoamingMonster, fixedCarriedTreasure: [new TreasureItem(TreasureType.Rare)]
}));
this.roamingMobDeck.AddItem(new MobInfo({
name: 'Lyidan, Incubus Lord', hp: 10, level: 3, rewardTokens: 2,
isRoamingMonster: true, fixedCarriedTreasure: [this.getTreasureDrawingItem(TreasureType.Epic)]
type: MobType.RoamingMonster, fixedCarriedTreasure: [new TreasureItem(TreasureType.Epic)]
}));
this.roamingMobDeck.AddItem(new MobInfo({
name: 'Lyidan, Incubus Lord', hp: 7, level: 5, rewardTokens: 0,
isRoamingMonster: true, fixedCarriedTreasure: [this.getTreasureDrawingItem(TreasureType.Epic), this.getTreasureDrawingItem(TreasureType.Epic), this.getTreasureDrawingItem(TreasureType.Epic)]
type: MobType.RoamingMonster, fixedCarriedTreasure: [new TreasureItem(TreasureType.Epic, 3)]
}));
this.roamingMobDeck.AddItem(new MobInfo({
name: 'The Ghoul', hp: 5, level: 1, rewardTokens: 2,
isRoamingMonster: true, fixedCarriedTreasure: [this.getTreasureDrawingItem(TreasureType.Rare)]
type: MobType.RoamingMonster, fixedCarriedTreasure: [new TreasureItem(TreasureType.Rare)]
}));
this.roamingMobDeck.AddItem(new MobInfo({
name: 'The Ghoul', hp: 8, level: 3, rewardTokens: 2,
isRoamingMonster: true, fixedCarriedTreasure: [this.getTreasureDrawingItem(TreasureType.Epic)]
type: MobType.RoamingMonster, fixedCarriedTreasure: [new TreasureItem(TreasureType.Epic)]
}));
this.roamingMobDeck.AddItem(new MobInfo({
name: 'The Ghoul', hp: 5, level: 5, rewardTokens: 0,
isRoamingMonster: true, fixedCarriedTreasure: [this.getTreasureDrawingItem(TreasureType.Epic), this.getTreasureDrawingItem(TreasureType.Epic), this.getTreasureDrawingItem(TreasureType.Epic)]
type: MobType.RoamingMonster, fixedCarriedTreasure: [new TreasureItem(TreasureType.Epic, 3)]
}));
}
private initCoreGameMobs() {
CoreGameMobFactories.forEach(factory => {
for (let i = 1; i <= 5; i++) {
this.mobDeck.AddItem(factory.generate(i));
i++;
}
});
}
// #region Public Getters And Setters (5)
@ -128,26 +143,18 @@ export class MD2Service {
if (this.heros.length > 0) {
return Math.max(...this.heros.map(h => h.level));
} else {
return this._highestPlayerLevel;
return 1;
}
}
public set highestPlayerLevel(v: number) {
this._highestPlayerLevel = v;
}
public get playerAmount(): number {
if (this.heros.length > 0) {
return this.heros.length;
} else {
return this._playerAmount;
return 1;
}
}
public set playerAmount(v: number) {
this._playerAmount = v;
}
public get playerHero(): MD2HeroInfo {
return this.heros.find(h => h.playerInfo.signalRClientId == this.loginUserService.userAccess.signalRSessionId);
}
@ -157,87 +164,10 @@ export class MD2Service {
// #region Public Methods (27)
public addTreasure(type: TreasureType, amount: number = 1) {
let item = this.getTreasureDrawingItem(type, amount);
this.treasureBag.AddItem(item);
this.treasureBag.AddItem(new TreasureItem(type, amount));
this.refreshTreasureBagSubject.next(this.treasureBag);
}
public broadcastAllHeroInfoToAll() {
this.heros.forEach(element => {
this.broadcastHeroInfoToAll(element);
});
}
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: 'update',
} 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.info);
this.broadcastMessage('GameRoom', 'update', parameters);
}
public broadcastMobsInfo() {
let parameters = {};
parameters['roamingMonsters'] = JSON.stringify(this.roamingMonsters);
parameters['mobs'] = JSON.stringify(this.mobs);
this.broadcastMessage('mobs', 'update', parameters);
}
public broadcastMyHeroInfo() {
this.broadcastHeroInfoToAll(this.playerHero);
}
public darknessPhase() {
this.heros.forEach(hero => {
hero.remainActions = 3;
@ -246,15 +176,15 @@ export class MD2Service {
hero.frozenToken = remainFrozenToken;
this.broadcastHeroInfoToOwner(hero);
});
this.info.roundPhase = RoundPhase.HeroPhase;
this.info.round++;
this.stateService.info.roundPhase = RoundPhase.HeroPhase;
this.stateService.info.round++;
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 });
}
//this.runNextPhase();
}
public drawMob(isRoamingMonster: boolean) {
public spawnMob(isRoamingMonster: boolean) {
let mobDeck = null as DrawingBag<MobInfo>;
let level = 1;
if (this.highestPlayerLevel < 3) {
@ -277,7 +207,7 @@ export class MD2Service {
let newSpawnMob = new MobInfo(mobDeck.DrawAndRemove(1, m => m.level == level)[0]);
if (isRoamingMonster) {
newSpawnMob.unitRemainHp = newSpawnMob.hp * this.playerAmount;
newSpawnMob.mobAmount = 1;
newSpawnMob.mobAmount = 0;
} else {
newSpawnMob.mobAmount = this.playerAmount + 1;
}
@ -292,6 +222,7 @@ export class MD2Service {
} else {
this.mobs.push(newSpawnMob);
newSpawnMob.carriedTreasure = this.treasureBag.DrawAndRemove(newSpawnMob.rewardTokens);
this.refreshTreasureBagSubject.next(this.treasureBag);
}
@ -323,61 +254,16 @@ export class MD2Service {
return this.fileService.FileList('Images/MD2/' + folderPath);
}
public getTreasureDrawingItem(type: TreasureType, amount: number = 1) {
return new DrawingItem(`${TreasureType[type]} Treasure`, `It's a ${TreasureType[type]} Treasure!`, this.treasureImage(type), amount);
}
public heroFullName(hero: MD2HeroInfo) {
if (!hero) return '';
return `${hero.playerInfo.name} (${HeroClass[hero.class]} - ${hero.name})`
}
public iconHtml(icon: MD2Icon, cssClass = '') {
if (icon < MD2Icon.RedDice) {
return `<span class='MD2Icon ${cssClass}'>${String.fromCharCode(65 + icon)}</span>`
} else {
return `<span class='MD2Icon dice ${MD2Icon[icon].replace('Dice', '')} ${cssClass}'></span>`;
}
}
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 initMobDecks() {
this.mobDeck = new DrawingBag();
this.roamingMobDeck = new DrawingBag();
this.mobDeck.AddItem(new MobInfo({ name: 'Gargoyles', hp: 2, level: 1, rewardTokens: 1 }));
this.mobDeck.AddItem(new MobInfo({ name: 'Demons', hp: 3, level: 1, rewardTokens: 1 }));
this.mobDeck.AddItem(new MobInfo({ name: 'Undead', hp: 4, level: 1, rewardTokens: 1 }));
this.mobDeck.AddItem(new MobInfo({ name: 'Fire Entities', hp: 3, level: 1, rewardTokens: 1 }));
this.mobDeck.AddItem(new MobInfo({ name: 'Fallen Angels', hp: 2, level: 1, rewardTokens: 1 }));
this.mobDeck.AddItem(new MobInfo({ name: 'Infernal Imps', hp: 3, level: 1, rewardTokens: 1 }));
this.mobDeck.AddItem(new MobInfo({ name: 'Skeletons', hp: 2, level: 1, rewardTokens: 1 }));
this.mobDeck.AddItem(new MobInfo({ name: 'Satyrs', hp: 3, level: 1, rewardTokens: 1 }));
this.mobDeck.AddItem(new MobInfo({ name: 'Gargoyles', hp: 3, level: 3, rewardTokens: 1 }));
this.mobDeck.AddItem(new MobInfo({ name: 'Demons', hp: 4, level: 3, rewardTokens: 1 }));
this.mobDeck.AddItem(new MobInfo({ name: 'Undead', hp: 5, level: 3, rewardTokens: 1 }));
this.mobDeck.AddItem(new MobInfo({ name: 'Fire Entities', hp: 4, level: 3, rewardTokens: 1 }));
this.mobDeck.AddItem(new MobInfo({ name: 'Fallen Angels', hp: 3, level: 3, rewardTokens: 1 }));
this.mobDeck.AddItem(new MobInfo({ name: 'Infernal Imps', hp: 4, level: 3, rewardTokens: 1 }));
this.mobDeck.AddItem(new MobInfo({ name: 'Skeletons', hp: 3, level: 3, rewardTokens: 1 }));
this.mobDeck.AddItem(new MobInfo({ name: 'Satyrs', hp: 4, level: 3, rewardTokens: 1 }));
this.mobDeck.AddItem(new MobInfo({ name: 'Gargoyles', hp: 6, level: 5, rewardTokens: 2 }));
this.mobDeck.AddItem(new MobInfo({ name: 'Demons', hp: 6, level: 5, rewardTokens: 2 }));
this.mobDeck.AddItem(new MobInfo({ name: 'Undead', hp: 8, level: 5, rewardTokens: 2 }));
this.mobDeck.AddItem(new MobInfo({ name: 'Fire Entities', hp: 7, level: 5, rewardTokens: 2 }));
this.mobDeck.AddItem(new MobInfo({ name: 'Fallen Angels', hp: 5, level: 5, rewardTokens: 2 }));
this.mobDeck.AddItem(new MobInfo({ name: 'Infernal Imps', hp: 5, level: 5, rewardTokens: 2 }));
this.mobDeck.AddItem(new MobInfo({ name: 'Skeletons', hp: 5, level: 5, rewardTokens: 2 }));
this.mobDeck.AddItem(new MobInfo({ name: 'Satyrs', hp: 6, level: 5, rewardTokens: 2 }));
this.initCoreGameMobs();
this.initCoreGameRoamingMonsters();
}
@ -398,7 +284,7 @@ export class MD2Service {
hero.mp += levelUpInfo.extraMp;
hero.mpMaximum += levelUpInfo.extraMp;
hero.exp = levelUpInfo.currentExp;
this.broadcastHeroInfoToOwner(hero);
this.broadcastService.broadcastHeroInfoToOwner(hero);
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);
}
@ -416,9 +302,9 @@ export class MD2Service {
level = 3;
}
if (isRoamingMonsters) {
return this.imgUrl(`Mobs/CoreGame/RoamingMonsters/${name}/${level}.png`);
return this.stateService.imgUrl(`Mobs/CoreGame/RoamingMonsters/${name}/${level}.png`);
} else {
return this.imgUrl(`Mobs/CoreGame/Mobs/${name}/${level}.png`);
return this.stateService.imgUrl(`Mobs/CoreGame/Mobs/${name}/${level}.png`);
}
}
@ -440,39 +326,17 @@ export class MD2Service {
});
}
public rollBlackDice(times: number) {
let wounds = 0;
let claws = 0;
//miss 33%
//1 claw 33%
//1 wound 17%
//1 claw, 1 wound 17%
for (let i = 0; i < times; i++) {
let result = Math.random() * 100;
if (result <= 33) {
} else if (result <= 67) {
claws += 1;
} else if (result <= 83) {
wounds += 1;
} else {
claws += 1;
wounds += 1;
}
}
return { claws, wounds };
}
public runNextPhase() {
this.info.roundPhase++;
switch (this.info.roundPhase) {
this.stateService.info.roundPhase++;
switch (this.stateService.info.roundPhase) {
case RoundPhase.HeroPhase:
this.heros.forEach(hero => {
hero.remainActions = 3;
let remainFrozenToken = Math.max(0, hero.frozenToken - hero.remainActions);
hero.remainActions = Math.max(0, hero.remainActions - hero.frozenToken);
hero.frozenToken = remainFrozenToken;
this.broadcastHeroInfoToOwner(hero);
this.broadcastService.broadcastHeroInfoToOwner(hero);
});
break;
case RoundPhase.EnemyPhase:
@ -487,8 +351,8 @@ export class MD2Service {
default: break;
}
let parameters = {};
parameters['phase'] = this.info.roundPhase;
this.broadcastMessage('roundPhase', '', parameters);
parameters['phase'] = this.stateService.info.roundPhase;
this.broadcastService.broadcastMessage('roundPhase', '', parameters);
}
public sendMsgboxMsg(playerSessionId: string, msg: Partial<MessageBoxConfig>) {
@ -503,9 +367,6 @@ export class MD2Service {
});
}
public treasureImage(type: TreasureType) {
return this.imgUrl(`TreasureToken/${TreasureType[type]}.png`);
}
public getTargetHerosByFilter(targetType: AttackTarget, onlyOne: boolean = false) {
let beenAttackedHero = [] as MD2HeroInfo[];
switch (targetType) {

View 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,) {
}
}

View File

@ -19,10 +19,10 @@
font-family: "Massive Darkness 2", sans-serif !important;
//font-size: 50px;
&.atk::before {
&.attack::before {
content: "A";
}
&.def::before {
&.defense::before {
content: "B";
}
&.mana::before {
@ -34,7 +34,7 @@
&.enemySkill::before {
content: "E";
}
&.enemyAtk::before {
&.enemyAttack::before {
content: "F";
}
&.reroll::before {