diff --git a/src/app/games/massive-darkness2/massive-darkness2.component.ts b/src/app/games/massive-darkness2/massive-darkness2.component.ts
index 9edf77b..53ad224 100644
--- a/src/app/games/massive-darkness2/massive-darkness2.component.ts
+++ b/src/app/games/massive-darkness2/massive-darkness2.component.ts
@@ -15,6 +15,7 @@ import { QRCodeService } from '../../services/qrcode.service';
import { StringUtils } from '../../utilities/string-utils';
import { SpawnMobDlgComponent } from './mobs/spawn-mob-dlg/spawn-mob-dlg.component';
import { BossMicheal } from './massive-darkness2.model.boss';
+import { MD2InitService } from '../../services/MD2/md2-init.service';
@Component({
selector: 'ngx-massive-darkness2',
@@ -26,6 +27,7 @@ export class MassiveDarkness2Component extends MD2Base implements OnInit {
HeroClass: HeroClass
constructor(
private fileService: FileService,
+ private initService: MD2InitService,
private msgBoxService: MsgBoxService,
private qrCodeService: QRCodeService,
public gameRoomService: GameRoomService,
@@ -42,7 +44,8 @@ export class MassiveDarkness2Component extends MD2Base implements OnInit {
this.md2Service.enemyPhaseSubject.pipe(takeUntil(this.destroy$)).subscribe(result => {
this.showEnemyPhaseAction(0);
});
-
+ this.initService.initMobDecks();
+ this.initService.initTreasureBag();
}
override signalRInitialized() {
@@ -64,7 +67,7 @@ export class MassiveDarkness2Component extends MD2Base implements OnInit {
}
showEnemyPhaseAction(index: number) {
- let mob = new MobInfo(this.md2Service.enemyPhaseMobs[index]);
+ let mob = this.md2Service.enemyPhaseMobs[index];
let enemyInfo = ` `;
let extraRule = '';
@@ -85,7 +88,13 @@ export class MassiveDarkness2Component extends MD2Base implements OnInit {
// break;
// }
- this.msgBoxService.dlgService.open(SpawnMobDlgComponent, { context: { title: `Enemy Phase(${(index + 1)}/${this.md2Service.enemyPhaseMobs.length})`, mode: MobDlgType.Activating, mob: mob } })
+ this.msgBoxService.dlgService.open(SpawnMobDlgComponent, {
+ context: {
+ title: `Enemy Phase(${(index + 1)}/${this.md2Service.enemyPhaseMobs.length})`,
+ mode: MobDlgType.Activating,
+ mob: mob
+ }
+ })
.onClose.pipe(first()).subscribe(result => {
index++;
if (index < this.md2Service.enemyPhaseMobs.length) {
@@ -125,10 +134,7 @@ export class MassiveDarkness2Component extends MD2Base implements OnInit {
}
enterBossFight() {
- this.msgBoxService.showInputbox('Boss Fight', 'Choose the boss').pipe(first()).subscribe(result => {
- this.md2Service.info.isBossFight = true;
- this.md2Service.info.boss = new BossMicheal(this.md2Service);
- this.detectChanges();
- });
+ this.md2Service.enterBossFight();
+
}
}
\ No newline at end of file
diff --git a/src/app/games/massive-darkness2/massive-darkness2.logic.ts b/src/app/games/massive-darkness2/massive-darkness2.logic.ts
new file mode 100644
index 0000000..0106c95
--- /dev/null
+++ b/src/app/games/massive-darkness2/massive-darkness2.logic.ts
@@ -0,0 +1,69 @@
+import { Observable, Subject } from "rxjs";
+import { environment } from "../../../environments/environment";
+import { MsgBoxService } from "../../services/msg-box.service";
+import { ObjectUtils } from "../../utilities/object-utils";
+import { StringUtils } from "../../utilities/string-utils";
+import { GamePlayer } from "../games.model";
+import { MD2HeroInfo, AttackTarget, HeroClass } from "./massive-darkness2.model";
+import { MobSkill } from "./massive-darkness2.model.boss";
+export class MD2Logic {
+
+ public static getTargetHerosByFilter(heros: MD2HeroInfo[], targetType: AttackTarget, onlyOne: boolean = false) {
+ let beenAttackedHero = [] as MD2HeroInfo[];
+ switch (targetType) {
+ case AttackTarget.LeastHp:
+ let lowestHp = Math.min(...heros.map(h => h.hp));
+ beenAttackedHero = heros.filter(h => h.hp == lowestHp);
+ //this.otherAttackTarget = 'attacking the other Lowest HP hero.';
+ break;
+ case AttackTarget.LeastMp:
+ let lowestMp = Math.min(...heros.map(h => h.mp));
+ beenAttackedHero = heros.filter(h => h.hp == lowestMp);
+ //this.otherAttackTarget = 'attacking the other Lowest HP hero.';
+ break;
+
+ case AttackTarget.HighestHp:
+ let highestHp = Math.max(...heros.map(h => h.hp));
+ beenAttackedHero = heros.filter(h => h.hp == highestHp);
+ //this.otherAttackTarget = 'attacking the other Highest HP hero.';
+ break;
+ case AttackTarget.HighestMp:
+ let highestMp = Math.max(...heros.map(h => h.mp));
+ beenAttackedHero = heros.filter(h => h.mp == highestMp);
+ //this.otherAttackTarget = 'attacking the other Highest Mp hero.';
+ break;
+ case AttackTarget.LowestLevel:
+ let lowestLevel = Math.max(...heros.map(h => h.level));
+ beenAttackedHero = heros.filter(h => h.level == lowestLevel);
+ //this.otherAttackTarget = 'attacking the other Lowest Level hero.';
+ break;
+ case AttackTarget.LeastCorruption:
+
+ let leastCor = Math.min(...heros.map(h => h.corruptionToken));
+ beenAttackedHero = heros.filter(h => h.corruptionToken == leastCor);
+ break;
+ case AttackTarget.MostCorruption:
+ let mostCor = Math.max(...heros.map(h => h.corruptionToken));
+ beenAttackedHero = heros.filter(h => h.corruptionToken == mostCor);
+ break;
+ case AttackTarget.Random:
+ default:
+ beenAttackedHero = [heros[Math.round(Math.random() * (heros.length - 1))]];
+ //this.otherAttackTarget = 'Just act like normal.';
+ break;
+ }
+ if (onlyOne && beenAttackedHero.length > 1) {
+ beenAttackedHero = [beenAttackedHero[Math.round(Math.random() * (beenAttackedHero.length - 1))]];
+ }
+ return beenAttackedHero;
+ }
+
+ public static getTargetHerosHtml(beenAttackedHero: MD2HeroInfo[]) {
+ return `${StringUtils.makeCommaSeparatedString(beenAttackedHero.map(h => this.heroFullName(h)), false, true)}`;
+ }
+
+ public static heroFullName(hero: MD2HeroInfo) {
+ if (!hero) return '';
+ return `${hero.playerInfo.name} (${HeroClass[hero.class]} - ${hero.name})`
+ }
+}
\ No newline at end of file
diff --git a/src/app/games/massive-darkness2/massive-darkness2.model.boss.ts b/src/app/games/massive-darkness2/massive-darkness2.model.boss.ts
index d4b8430..342e9aa 100644
--- a/src/app/games/massive-darkness2/massive-darkness2.model.boss.ts
+++ b/src/app/games/massive-darkness2/massive-darkness2.model.boss.ts
@@ -1,5 +1,5 @@
import { stringify } from "querystring"
-import { Subject } from "rxjs"
+import { Observable, Subject, Subscription } from "rxjs"
import { first } from "rxjs/operators"
import { MD2Service } from "../../services/MD2/md2.service"
import { StringUtils } from "../../utilities/string-utils"
@@ -8,121 +8,6 @@ import { TreasureType, AttackInfo, DefenseInfo, AttackType, MD2Icon, MD2HeroInfo
import { RollingBlackDice } from "./massive-darkness2.model.dice"
-export interface IBossFight {
- name: string
- addTreasureToken: Subject
- spawnMob: Subject
- spawnRoamingMonster: Subject
- rounds: number
- actions: number
- hpPerHero: number
- info: MobInfo
- actionBlackDice: number
- imgUrl: string
- standUrl: string
- activating(): boolean
- prepareForBossFight(): void
- nextRound(): void
-}
-export class BossMicheal implements IBossFight {
-
- constructor(private md2Service: MD2Service) {
- this.corruptionTokenHtml = this.md2Service.stateService.imgHtml('Tokens/CorruptToken.png');
-
- this.name = 'Michael - The Corrupted Archangel';
- this.imgUrl = md2Service.stateService.imgUrl('/Boss/Michael - The Corrupted Archangel.jpg');
- this.standUrl = md2Service.stateService.imgUrl('/Boss/Michael.png');
- this.hpPerHero = 15;
- this.info = new MobInfo({
- description: this.name,
- type: MobType.Boss,
- hp: this.md2Service.heros.length * this.hpPerHero,
- unitRemainHp: this.md2Service.heros.length * this.hpPerHero,
- level: 10,
- combatSkill: new MobSkill(`Combat 1 ${this.md2Service.stateService.iconHtml(MD2Icon.EnemySkill)}`,
- `Deal 1 Wound for each ${this.corruptionTokenHtml} on the attacking or defending Hero. Discard the tokens afterwards(once per combat).`),
- imageUrl: md2Service.stateService.imgUrl('/Boss/Michael.png')
- });
- this.info.defenseInfo = new DefenseInfo(5, 1);
- this.info.attackInfos = [new AttackInfo(MD2Icon.Melee, 2, 2, 0, 1)];
- this.actions = 1;
- this.rounds = 0;
- this.actionBlackDice = 2;
- }
- name: string
- addTreasureToken: Subject
- spawnMob: Subject
- spawnRoamingMonster: Subject
- rounds: number
- actions: number
- hpPerHero: number
- info: MobInfo
- actionBlackDice: number
- imgUrl: string
- standUrl: string
- corruptionTokenHtml: string
- activating(): boolean {
-
- let actionResult = new RollingBlackDice().roll(this.actionBlackDice);
- let actionHtml = '';
- let beenAttackedHero = [] as MD2HeroInfo[];
- let bossAction: MobSkill;
- switch (actionResult.claws) {
- case 0:
- //Justice From Above
- beenAttackedHero = this.md2Service.getTargetHerosByFilter(AttackTarget.MostCorruption, true);
- bossAction = new MobSkill('Justice From Above',
- `Place Michael in the Zone at ${this.md2Service.getTargetHerosHtml(beenAttackedHero)} and attack Him/Her.`);
-
- break;
- case 1:
- //Lance Dash
- beenAttackedHero = this.md2Service.getTargetHerosByFilter(AttackTarget.LeastCorruption, true);
- bossAction = new MobSkill('Lance Dash',
- `Move Michael and Place 1 ${this.corruptionTokenHtml} in the Zone at ${this.md2Service.getTargetHerosHtml(beenAttackedHero)} and attack Him/Her.`);
- break;
- case 2:
- //Dark Blessing
- bossAction = new MobSkill('Dark Blessing',
- `Place Michael on the central Zone and add 1 ${this.corruptionTokenHtml} to the Corruption Stone Zone with the least amount of ${this.corruptionTokenHtml}. ` +
- `Deal ${this.darkBlessingCorruptionAmt} Wounds per ${this.corruptionTokenHtml} to all Heros in each Tiles distributed as they wish.`);
- break;
-
- default:
- break;
- }
- this.md2Service.dlgService.open(BossActivationComponent, { context: { boss: this, bossAction: bossAction } }).onClose
- .pipe(first()).subscribe(result => {
-
- });
- return true;
- }
- prepareForBossFight(): void {
-
- }
- darkBlessingCorruptionAmt: number = 1;
- nextRound(): void {
- this.rounds++;
- switch (this.rounds) {
- case 3:
- case 5:
- this.darkBlessingCorruptionAmt++;
- break;
- case 2:
- case 4:
- this.info.defenseInfo[0].black += 1;
- this.info.attackInfos[0].black += 1;
- break;
- // case 4:
- // this.defInfo.black += 2;
- // this.atkInfos[0].black += 2;
- // break;
-
- default:
- break;
- }
- }
-}
export enum MobSkillType {
Attack,
Defense,
@@ -146,4 +31,287 @@ export class MobSkill {
name: string
description: string
targetHeros: MD2HeroInfo[]
+}
+export interface IBossFight {
+ name: string
+ addTreasureToken: Subject
+ spawnMob: Subject
+ spawnRoamingMonster: Subject
+ rounds: number
+ actions: number
+ activatedTimes: number
+ info: MobInfo
+ actionBlackDice: number
+ imgUrl: string
+ standUrl: string
+ extraRules: string
+ activating(): boolean
+ prepareForBossFight(): void
+ darknessPhase(): void
+}
+
+export abstract class BossFight implements IBossFight {
+ name: string
+ addTreasureToken: Subject
+ spawnMob: Subject
+ spawnRoamingMonster: Subject
+ rounds: number
+ actions: number
+ activatedTimes: number
+ info: MobInfo
+ actionBlackDice: number
+ imgUrl: string
+ standUrl: string
+ extraRules: string
+ protected subscription: Subscription
+
+ constructor(protected md2Service: MD2Service) {
+ this.rounds = 1;
+ }
+ activating(): boolean {
+ this.activatedTimes = this.actions;
+ this.runAction();
+ return true;
+ }
+
+ runAction() {
+ this.bossAction().pipe(first()).subscribe(result => {
+ this.activatedTimes--;
+ if (this.activatedTimes) {
+ this.runAction();
+ } else {
+ if (false == this.md2Service.heros.some(h => h.remainActions > 0)) {
+ this.md2Service.darknessPhase();
+ }
+ }
+ });
+ }
+ abstract bossAction(): Observable;
+ protected actionEnd
+ prepareForBossFight(): void {
+ throw new Error("Method not implemented.")
+ }
+ darknessPhase(): void {
+ throw new Error("Method not implemented.")
+ }
+
+}
+export class BossMicheal extends BossFight {
+ constructor(protected md2Service: MD2Service) {
+ super(md2Service);
+ this.corruptionTokenHtml = this.md2Service.stateService.imgHtml('Tokens/CorruptToken.png');
+
+ this.name = 'Michael - The Corrupted Archangel';
+ this.imgUrl = md2Service.stateService.imgUrl('/Boss/Michael - The Corrupted Archangel.jpg');
+ this.standUrl = md2Service.stateService.imgUrl('/Boss/Michael.png');
+
+ this.info = new MobInfo({
+ description: this.name,
+ type: MobType.Boss,
+ hpPerHero: 15,
+ level: 10,
+ combatSkill: new MobSkill(
+ {
+ name: `Combat 1 ${this.md2Service.stateService.iconHtml(MD2Icon.EnemySkill)}`,
+ description: `Deal 1 Wound for each ${this.corruptionTokenHtml} on the attacking or defending Hero. Discard the tokens afterwards(once per combat).`
+ }),
+ imageUrl: md2Service.stateService.imgUrl('/Boss/Michael.png')
+ });
+ this.info.defenseInfo = new DefenseInfo(5, 1);
+ this.info.attackInfos = [new AttackInfo(MD2Icon.Melee, 2, 2, 0, 1)];
+ this.actions = 1;
+ this.actionBlackDice = 2;
+
+ this.extraRules = `Archangel Michael can’t be the target of any attack, skill, ability or take Wounds until there are no Corruption tokens in the whole Tile.
` +
+ `Any Hero on a Zone with a ${this.corruptionTokenHtml} may spend 1 action to remove it. Each time a Hero removes a ${this.corruptionTokenHtml} from a Zone they must roll 1 ${this.md2Service.stateService.iconHtml(MD2Icon.BlackDice)}.` +
+ `If ${this.md2Service.stateService.iconHtml(MD2Icon.EnemyClaw)} the Hero takes 1 Wound. If ${this.md2Service.stateService.iconHtml(MD2Icon.EnemySkill)} place 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
+ acted: number
+ name: string
+ addTreasureToken: Subject
+ spawnMob: Subject
+ spawnRoamingMonster: Subject
+ rounds: number
+ actions: number
+ info: MobInfo
+ actionBlackDice: number
+ imgUrl: string
+ standUrl: string
+ corruptionTokenHtml: string
+
+ bossAction(): Observable {
+
+ let actionResult = new RollingBlackDice().roll(this.actionBlackDice);
+ let actionHtml = '';
+ let beenAttackedHero = [] as MD2HeroInfo[];
+ let bossAction: MobSkill;
+ switch (actionResult.claws) {
+ case 0:
+ //Justice From Above
+ beenAttackedHero = this.md2Service.getTargetHerosByFilter(AttackTarget.MostCorruption, true);
+ bossAction = new MobSkill(
+ {
+ name: 'Justice From Above',
+ description: `Place Michael in the Zone at ${this.md2Service.getTargetHerosHtml(beenAttackedHero)} and attack Him/Her.`
+ });
+
+ break;
+ case 1:
+ //Lance Dash
+ beenAttackedHero = this.md2Service.getTargetHerosByFilter(AttackTarget.LeastCorruption, true);
+ bossAction = new MobSkill({
+ name: 'Lance Dash',
+ description:
+ `Move Michael and Place 1 ${this.corruptionTokenHtml} in the Zone at ${this.md2Service.getTargetHerosHtml(beenAttackedHero)} and attack Him/Her.`
+ });
+ break;
+ case 2:
+ //Dark Blessing
+ bossAction = new MobSkill({
+ name: 'Dark Blessing',
+ description:
+ `Place Michael on the central Zone and add 1 ${this.corruptionTokenHtml} to the Corruption Stone Zone with the least amount of ${this.corruptionTokenHtml}. ` +
+ `Deal ${this.darkBlessingCorruptionAmt} Wounds per ${this.corruptionTokenHtml} to all Heros in each Tiles distributed as they wish.`
+ });
+ break;
+
+ default:
+ break;
+ }
+ return this.md2Service.dlgService.open(BossActivationComponent, { context: { boss: this, bossAction: bossAction, currentAction: this.activatedTimes, allActions: this.actions } }).onClose;
+
+ }
+ prepareForBossFight(): void {
+ this.md2Service.heros.forEach(hero => {
+ hero.uiShowCorruptionToken = true;
+ });
+ this.md2Service.msgBoxService.show('Prepare Boss Fight', {
+ text: `
Place ${this.md2Service.heros.length * 2} ${this.corruptionTokenHtml} on the Corruption Stone Zones (Shadow
+ Zones). Players choose the Zones, but must distribute
+ the tokens as equally as possible among them.
`
+ });
+ }
+ darkBlessingCorruptionAmt: number = 1;
+ darknessPhase(): void {
+ this.rounds++;
+ switch (this.rounds) {
+ case 3:
+ case 5:
+ this.darkBlessingCorruptionAmt++;
+ break;
+ case 2:
+ case 4:
+ this.info.defenseInfo.black += 1;
+ this.info.attackInfos[0].black += 1;
+ break;
+ // case 4:
+ // this.defInfo.black += 2;
+ // this.atkInfos[0].black += 2;
+ // break;
+
+ default:
+ break;
+ }
+ }
+}
+
+
+export class BossReaper extends BossFight {
+
+ constructor(protected md2Service: MD2Service) {
+ super(md2Service);
+ this.timeTokenHtml = this.md2Service.stateService.imgHtml('Tokens/TimeToken.png');
+
+ this.name = 'The Reaper';
+ this.imgUrl = md2Service.stateService.imgUrl('/Boss/The Reaper.jpg');
+ this.standUrl = md2Service.stateService.imgUrl('/Boss/The Reaper-Stand.png');
+
+ this.info = new MobInfo({
+ description: this.name,
+ type: MobType.Boss,
+ hpPerHero: 25,
+ level: 10,
+ combatSkill: new MobSkill(
+ {
+ description: `If the Hero has no ${this.md2Service.stateService.iconHtml(MD2Icon.Mana)}, they take 1 ${this.md2Service.stateService.iconHtml(MD2Icon.Frost)}`,
+ type: MobSkillType.Attack,
+
+ }),
+ imageUrl: md2Service.stateService.imgUrl('/Boss/The Reaper-Stand.png')
+ });
+ this.info.defenseInfo = new DefenseInfo(4, 3);
+ this.info.attackInfos = [new AttackInfo(MD2Icon.Melee, 1, 2, 0, 3)];
+ this.actions = 1;
+ this.actionBlackDice = 2;
+ this.extraRules = `A Hero standing in the Hourglass Zone may spend 1 action to add 1 ${this.timeTokenHtml} in each Hourglass Zone.`;
+ }
+ name: string
+ addTreasureToken: Subject
+ spawnMob: Subject
+ spawnRoamingMonster: Subject
+ rounds: number
+ actions: number
+ info: MobInfo
+ actionBlackDice: number
+ imgUrl: string
+ standUrl: string
+ timeTokenHtml: string
+ bossAction() {
+
+ let actionResult = new RollingBlackDice().roll(this.actionBlackDice);
+ let actionHtml = '';
+ let beenAttackedHero = [] as MD2HeroInfo[];
+ let bossAction: MobSkill;
+ switch (actionResult.claws) {
+ case 0:
+ //Justice From Above
+ beenAttackedHero = this.md2Service.getTargetHerosByFilter(AttackTarget.LeastMp, true);
+ bossAction = new MobSkill(
+ {
+ name: 'Soul Drain',
+ description: `Place The Reaper in the Zone at ${this.md2Service.getTargetHerosHtml(beenAttackedHero)} and attack Him/Her.`
+ });
+
+ break;
+ case 1:
+ //Lance Dash
+ beenAttackedHero = this.md2Service.getTargetHerosByFilter(AttackTarget.LeastCorruption, true);
+ bossAction = new MobSkill({
+ name: 'Time Ticking',
+ description:
+ `Place The Reaper in the Hourglass Zone withe the least ${this.timeTokenHtml} and remove 1 ${this.timeTokenHtml} from The OtherHourglass Zone.`
+ });
+ break;
+ case 2:
+ //Dark Blessing
+ bossAction = new MobSkill({
+ name: 'Death Is Coming',
+ description:
+ `Place The Reaper in the central Zone. ` +
+ `Roll 1 ${this.md2Service.stateService.iconHtml(MD2Icon.YellowDice)}. Remove ${this.timeTokenHtml} equal to ${this.md2Service.stateService.iconHtml(MD2Icon.Melee)} rolled from both Hourglass Zone. ` +
+ `Each Hero discards ${this.md2Service.stateService.iconHtml(MD2Icon.MP)} equal to ${this.md2Service.stateService.iconHtml(MD2Icon.Melee)} rolled.`
+ });
+ break;
+
+ default:
+ break;
+ }
+ return this.md2Service.dlgService.open(BossActivationComponent, { context: { boss: this, bossAction: bossAction, currentAction: this.activatedTimes, allActions: this.actions } }).onClose;
+ }
+ prepareForBossFight(): void {
+ this.md2Service.msgBoxService.show('Prepare Boss Fight', {
+ text: `
Place 2 ${this.timeTokenHtml} in each Hourglass Zone.
`
+ })
+ }
+ darkBlessingCorruptionAmt: number = 1;
+ darknessPhase(): void {
+ this.rounds++;
+ if (this.rounds > 4) {
+ this.actions = 3;
+ } else if (this.rounds > 1) {
+ this.actions = 2;
+ }
+ }
}
\ No newline at end of file
diff --git a/src/app/games/massive-darkness2/massive-darkness2.model.ts b/src/app/games/massive-darkness2/massive-darkness2.model.ts
index d5a98c5..07b2b31 100644
--- a/src/app/games/massive-darkness2/massive-darkness2.model.ts
+++ b/src/app/games/massive-darkness2/massive-darkness2.model.ts
@@ -1,7 +1,9 @@
-import { Subject } from "rxjs";
+import { Observable, Subject } from "rxjs";
import { environment } from "../../../environments/environment";
+import { MsgBoxService } from "../../services/msg-box.service";
import { ObjectUtils } from "../../utilities/object-utils";
import { GamePlayer } from "../games.model";
+import { MD2Clone } from "./factorys/md2-clone";
import { MobSkill } from "./massive-darkness2.model.boss";
const MD2_IMG_URL = (id: string = null) => { return `${environment.apiUrl}/Files/Images/MD2/${(id ? `${encodeURI(id)}` : '')}` }
@@ -9,7 +11,8 @@ export enum MobDlgType {
Spawn,
Activating,
BeenAttacked,
- PreView
+ PreView,
+ Dashboard
}
export enum RoundPhase {
HeroPhase,
@@ -31,6 +34,7 @@ export enum HeroClass {
Ranger,
Shaman,
Paladin,
+ Druid,
}
export enum MobType {
Mob,
@@ -68,14 +72,16 @@ export enum MD2Icon {
RedDice,
BlueDice,
YellowDice,
- OrangeDice
+ OrangeDice,
+ BlackDice
}
export enum AttackTarget {
Random = 40,
- LowestHp = 50,
- HighestHp = 60,
- HighestMp = 70,
- LowestLevel = 80,
+ LeastHp = 50,
+ LeastMp = 60,
+ HighestHp = 70,
+ HighestMp = 80,
+ LowestLevel = 90,
MostCorruption = 200,
LeastCorruption = 201
}
@@ -132,8 +138,12 @@ export class DrawingBag {
}
drawingItems: IDrawingItem[]
removedItems: IDrawingItem[]
- public bagIsEmpty() {
- return this.drawingItems.reduce((sum, current) => sum + current.drawingWeight, 0) == 0;
+ public bagIsEmpty(predicate: (value: T) => boolean = undefined) {
+ if (predicate) {
+ return this.drawingItems.filter(predicate).reduce((sum, current) => sum + current.drawingWeight, 0) == 0;
+ } else {
+ return this.drawingItems.reduce((sum, current) => sum + current.drawingWeight, 0) == 0;
+ }
}
public Draw(amount: number): T[] {
@@ -144,7 +154,7 @@ export class DrawingBag {
public DrawAndRemove(amount: number = 1, predicate: (value: T) => boolean = undefined): T[] {
let drawItems: T[] = [];
for (let i = 0; i < amount; i++) {
- if (!this.bagIsEmpty()) {
+ if (!this.bagIsEmpty(predicate)) {
let drawItem = null as T;
let drawingPool = [] as T[];
if (predicate) {
@@ -159,7 +169,7 @@ export class DrawingBag {
const item = drawingPool[i];
drawCalc += item.drawingWeight;
if (drawCalc >= drawIndex) {
- drawItem = ObjectUtils.CloneValue(item);
+ drawItem = MD2Clone.CloneDrawingItem(item);
drawItem.drawingWeight = 1;
break;
}
@@ -183,7 +193,7 @@ export class DrawingBag {
this.removedItems = [];
}
public AddItem(item: IDrawingItem) {
- let existingItem = this.drawingItems.find(i => i.name == item.name);
+ let existingItem = this.drawingItems.find(i => i.identifyName == item.identifyName);
if (existingItem) {
existingItem.drawingWeight += item.drawingWeight;
} else {
@@ -193,17 +203,34 @@ export class DrawingBag {
public RemoveItem(item: IDrawingItem) {
if (item) {
- let existingItem = this.drawingItems.find(i => i.name == item.name);
- if (existingItem) {
- existingItem.drawingWeight -= item.drawingWeight;
- let removedItem = this.removedItems.find(i => i.name == item.name);
- if (removedItem) {
- removedItem.drawingWeight += item.drawingWeight;
- } else {
- this.removedItems.push(item);
+ if (item.identifyName) {
+ let existingItem = this.drawingItems.find(i => i.identifyName == item.identifyName);
+ if (existingItem) {
+ existingItem.drawingWeight -= item.drawingWeight;
+
+ let removedItem = this.removedItems.find(i => i.identifyName == item.identifyName);
+ if (removedItem) {
+ removedItem.drawingWeight += item.drawingWeight;
+ } else {
+ this.removedItems.push(item);
+ }
}
+ } else {
+ let existingItem = this.drawingItems.find(i => i.name == item.name);
+ if (existingItem) {
+ existingItem.drawingWeight -= item.drawingWeight;
+
+ let removedItem = this.removedItems.find(i => i.name == item.name);
+ if (removedItem) {
+ removedItem.drawingWeight += item.drawingWeight;
+ } else {
+ this.removedItems.push(item);
+ }
+ }
+
}
+
}
}
@@ -214,11 +241,13 @@ export class DrawingBag {
}
}
export interface IMobFactory {
+ mobName: string;
generate(level: number): MobInfo;
}
export interface IDrawingItem {
imageUrl: string
name: string
+ get identifyName(): string
description: string
drawingWeight: number
}
@@ -234,6 +263,9 @@ export class DrawingItem implements IDrawingItem {
this.description = description
this.drawingWeight = drawingWeight
}
+ get identifyName(): string {
+ return this.name;
+ }
imageUrl: string
name: string
description: string
@@ -249,6 +281,9 @@ export class TreasureItem extends DrawingItem {
}
type: TreasureType;
itemAmount: number;
+ get identifyName(): string {
+ return this.name;
+ }
}
export class MobInfo implements IDrawingItem {
constructor(
@@ -270,13 +305,15 @@ export class MobInfo implements IDrawingItem {
level: number;
rewardTokens: number;
hp: number;
+ hpPerHero: number;
mobAmount: number;
carriedTreasure: TreasureItem[];
fixedCarriedTreasure: TreasureItem[];
unitRemainHp: number;
attackInfos: AttackInfo[];
defenseInfo: DefenseInfo;
-
+ actions: number = 0;
+ activateDescription: string;
combatSkill: MobSkill
fireToken: number = 0;
@@ -288,6 +325,9 @@ export class MobInfo implements IDrawingItem {
uiCorruptionTokens: number;
uiAttackedBy: string;
+ get identifyName(): string {
+ return `${this.name}_${this.level}`;
+ }
public get carriedTreasureHtml(): string {
if (!this.carriedTreasure) return '';
return this.carriedTreasure.map(i => ``)
@@ -327,7 +367,8 @@ export class MobInfo implements IDrawingItem {
return 0;
}
}
-
+ public actionSubject: Subject;
+ public activateFunction?: (mob: MobInfo, msgBoxService: MsgBoxService, heros: MD2HeroInfo[]) => void;
}
export class MD2HeroInfo {
@@ -354,10 +395,12 @@ export class MD2HeroInfo {
shadowSkillHtml: string;
remainActions: number = 3;
rage: number = 0;
-
+ uiActivating = false;
+ uiShowCorruptionToken = false;
+ uiBossFight = false;
public get heroFullName(): string {
- return `${this.playerInfo.name} (${HeroClass[this.class]} - ${this.name}`
+ return `${this.playerInfo.name} (${HeroClass[this.class]} - ${this.name})`
}
}
@@ -403,6 +446,9 @@ export class MD2EnemyPhaseSpecialRule implements IDrawingItem {
this.title = title
this.description = description
}
+ get identifyName(): string {
+ return this.name;
+ }
imageUrl: string;
name: string;
drawingWeight: number;
diff --git a/src/app/games/massive-darkness2/md2-icon/md2-icon.component.html b/src/app/games/massive-darkness2/md2-icon/md2-icon.component.html
index b6d0770..ac3e628 100644
--- a/src/app/games/massive-darkness2/md2-icon/md2-icon.component.html
+++ b/src/app/games/massive-darkness2/md2-icon/md2-icon.component.html
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/app/games/massive-darkness2/md2-icon/md2-icon.component.ts b/src/app/games/massive-darkness2/md2-icon/md2-icon.component.ts
index 2a93e19..97a9df8 100644
--- a/src/app/games/massive-darkness2/md2-icon/md2-icon.component.ts
+++ b/src/app/games/massive-darkness2/md2-icon/md2-icon.component.ts
@@ -10,10 +10,26 @@ export class MD2IconComponent implements OnInit {
@Input() iconClass: string = 'mr-1';
- @Input("icon") icon: string;
+ private _icon: string | MD2Icon;
+
+ @Input() public set icon(v: string | MD2Icon) {
+ if (this._icon != v) {
+ this._icon = v;
+
+ }
+ if (this.isMD2Icon(v)) {
+ this.iconName = MD2Icon[v].toLowerCase();
+ } else {
+ this.iconName = v;
+ }
+ }
+
+ isMD2Icon(icon: MD2Icon | string): icon is MD2Icon {
+ return Number.isInteger(icon);
+ }
@Input() size: string = 'sm';
-
+ iconName: string;
constructor() { }
ngOnInit(): void {
diff --git a/src/app/games/massive-darkness2/mobs/mob-detail-info/mob-attack-info/mob-attack-info.component.html b/src/app/games/massive-darkness2/mobs/mob-detail-info/mob-attack-info/mob-attack-info.component.html
index eb6b62b..12646d4 100644
--- a/src/app/games/massive-darkness2/mobs/mob-detail-info/mob-attack-info/mob-attack-info.component.html
+++ b/src/app/games/massive-darkness2/mobs/mob-detail-info/mob-attack-info/mob-attack-info.component.html
@@ -1,28 +1,30 @@
-Weapon Info
-
-
-
-
-
-
-
- x{{info.yellow}}
-
+
+
+
+
+
-
-
- x{{info.orange}}
-
-
-
-
- x{{info.red}}
-
-
-
-
- x{{mob.defenseInfo.black}}
-
+
+
+
+ x{{info.yellow}}
+
+
+
+
+ x{{info.orange}}
+
+
+
+
+ x{{info.red}}
+
+
+
+
+ x{{mob.defenseInfo.black}}
+
+
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/app/games/massive-darkness2/mobs/mob-detail-info/mob-attack-info/mob-attack-info.component.ts b/src/app/games/massive-darkness2/mobs/mob-detail-info/mob-attack-info/mob-attack-info.component.ts
index 55bb80c..8e88f9a 100644
--- a/src/app/games/massive-darkness2/mobs/mob-detail-info/mob-attack-info/mob-attack-info.component.ts
+++ b/src/app/games/massive-darkness2/mobs/mob-detail-info/mob-attack-info/mob-attack-info.component.ts
@@ -1,5 +1,5 @@
import { Component, Input, OnInit } from '@angular/core';
-import { MD2Icon, MobDlgType, MobInfo } from '../../../massive-darkness2.model';
+import { MD2Icon, MobDlgType, MobInfo, MobType } from '../../../massive-darkness2.model';
@Component({
selector: 'md2-mob-attack-info',
@@ -22,9 +22,23 @@ export class MobAttackInfoComponent implements OnInit {
}
@Input() mode: MobDlgType = MobDlgType.PreView;
- constructor() { }
+ display: boolean = false;
+ constructor() { }
ngOnInit(): void {
+ switch (this.mode) {
+ case MobDlgType.Spawn:
+ this.display = this.mob.type != MobType.Mob;
+ break;
+ case MobDlgType.Activating:
+ case MobDlgType.PreView:
+ case MobDlgType.Dashboard:
+ this.display = true;
+ break;
+ default:
+ this.display = false;
+ break;
+ }
}
}
diff --git a/src/app/games/massive-darkness2/mobs/mob-detail-info/mob-combat-info/mob-combat-info.component.html b/src/app/games/massive-darkness2/mobs/mob-detail-info/mob-combat-info/mob-combat-info.component.html
index ae8bbd3..c0fe413 100644
--- a/src/app/games/massive-darkness2/mobs/mob-detail-info/mob-combat-info/mob-combat-info.component.html
+++ b/src/app/games/massive-darkness2/mobs/mob-detail-info/mob-combat-info/mob-combat-info.component.html
@@ -1,5 +1,24 @@
-