diff --git a/src/app/games/massive-darkness2/MD2Base.ts b/src/app/games/massive-darkness2/MD2Base.ts
index af6e15c..b80c3cf 100644
--- a/src/app/games/massive-darkness2/MD2Base.ts
+++ b/src/app/games/massive-darkness2/MD2Base.ts
@@ -7,6 +7,7 @@ import { SignalRMessage } from "../../services/signal-r.service";
import { StateService } from "../../services/state.service";
import { ADIcon, MessageBoxConfig } from "../../ui/alert-dlg/alert-dlg.model";
import { MD2HeroInfo, MD2Icon, MobInfo, RoundPhase } from "./massive-darkness2.model";
+import { LoginUserService } from "../../services/login-user.service";
@Injectable()
export abstract class MD2Base {
@@ -95,38 +96,7 @@ export abstract class MD2Base {
this.md2Service.heros.push(heroInfo);
break;
case 'update':
- let exitingHero = this.md2Service.heros.find(h => h.playerInfo.signalRClientId == heroInfo.playerInfo.signalRClientId);
- if (exitingHero) {
- let activateBoss = exitingHero.uiActivating && !heroInfo.uiActivating;
-
- this.md2Service.heros[this.md2Service.heros.indexOf(exitingHero)] = heroInfo;
- if (this.isHeroDashboard && this.md2Service.stateService.playerHero.playerInfo.tabId == heroInfo.playerInfo.tabId) {
- this.md2Service.stateService.playerHero = heroInfo;
- }
- if (!this.isHeroDashboard && this.md2Service.info.isBossFight && activateBoss) {
- this.md2Service.activateBoss();
- }
- } else {
- this.md2Service.heros.push(heroInfo);
- }
- if (!this.isHeroDashboard) {
- if (this.gameInfo.roundPhase == RoundPhase.HeroPhase) {
- if (!this.md2Service.heros.some(h => h.remainActions > 0) && !this.md2Service.heros.some(h => h.uiActivating)) {
- if (!this.md2Service.info.isBossFight) {
- if (this.md2Service.mobs.length > 0 || this.md2Service.roamingMonsters.length > 0) {
- this.md2Service.msgBoxService.show('Enemy Phase', { icon: ADIcon.WARNING }).pipe(first()).subscribe(result => {
- this.md2Service.runNextPhase();
- });
- } else {
- this.md2Service.runNextPhase();
- }
- }
-
-
- }
- }
- }
-
+ this.updateHeroInfo(heroInfo);
//Object.assign(heroInfo, exitingHero);
break;
case 'updateMyHero':
@@ -140,6 +110,18 @@ export abstract class MD2Base {
}
this.detectChanges();
break;
+ case 'heroes':
+ switch (message.actionName) {
+ case 'updateAll':
+ let allHeroes = (JSON.parse(message.parameters['heros']) as MD2HeroInfo[]).map(h => new MD2HeroInfo(h));
+ //Remove heroes that are not in the list
+ this.md2Service.info.heros = this.md2Service.heros.filter(h => !allHeroes.some(h2 => h2.playerInfo.tabId == h.playerInfo.tabId));
+ allHeroes.forEach(heroInfo => {
+ this.updateHeroInfo(heroInfo);
+ });
+ break;
+ }
+ break;
case 'GameRoom':
switch (message.actionName) {
case 'Leaving':
@@ -229,6 +211,40 @@ export abstract class MD2Base {
break;
}
}
+ updateHeroInfo(heroInfo: MD2HeroInfo) {
+ let exitingHero = this.md2Service.heros.find(h => h.playerInfo.signalRClientId == heroInfo.playerInfo.signalRClientId);
+ if (exitingHero) {
+ let activateBoss = exitingHero.uiActivating && !heroInfo.uiActivating;
+
+ this.md2Service.heros[this.md2Service.heros.indexOf(exitingHero)] = heroInfo;
+ //My hero update
+ if (this.isHeroDashboard && this.md2Service.loginUserService.sessionTabId == heroInfo.playerInfo.tabId) {
+ this.md2Service.stateService.playerHero = heroInfo;
+ }
+ if (!this.isHeroDashboard && this.md2Service.info.isBossFight && activateBoss) {
+ this.md2Service.activateBoss();
+ }
+ } else {
+ this.md2Service.heros.push(heroInfo);
+ }
+ if (!this.isHeroDashboard) {
+ if (this.gameInfo.roundPhase == RoundPhase.HeroPhase) {
+ if (!this.md2Service.heros.some(h => h.remainActions > 0) && !this.md2Service.heros.some(h => h.uiActivating)) {
+ if (!this.md2Service.info.isBossFight) {
+ if (this.md2Service.mobs.length > 0 || this.md2Service.roamingMonsters.length > 0) {
+ this.md2Service.msgBoxService.show('Enemy Phase', { icon: ADIcon.WARNING }).pipe(first()).subscribe(result => {
+ this.md2Service.runNextPhase();
+ });
+ } else {
+ this.md2Service.runNextPhase();
+ }
+ }
+
+
+ }
+ }
+ }
+ }
abstract heroAction(hero: MD2HeroInfo, action: string);
}
diff --git a/src/app/games/massive-darkness2/hero-dashboard/hero-dashboard.component.html b/src/app/games/massive-darkness2/hero-dashboard/hero-dashboard.component.html
index a1c0b48..7d874f4 100644
--- a/src/app/games/massive-darkness2/hero-dashboard/hero-dashboard.component.html
+++ b/src/app/games/massive-darkness2/hero-dashboard/hero-dashboard.component.html
@@ -126,9 +126,10 @@
-
Abilities
+
Abilities
-
Shadow Abilities
+
+ Shadow Abilities
diff --git a/src/app/games/massive-darkness2/hero-dashboard/hero-dashboard.component.ts b/src/app/games/massive-darkness2/hero-dashboard/hero-dashboard.component.ts
index 4221ded..66445fc 100644
--- a/src/app/games/massive-darkness2/hero-dashboard/hero-dashboard.component.ts
+++ b/src/app/games/massive-darkness2/hero-dashboard/hero-dashboard.component.ts
@@ -55,6 +55,10 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
new DropDownOption(HeroClass.Wizard, 'Wizard'),
new DropDownOption(HeroClass.Shaman, 'Shaman'),
new DropDownOption(HeroClass.Druid, 'Druid'),
+ new DropDownOption(HeroClass.Necromancer, 'Necromancer'),
+ new DropDownOption(HeroClass.Monk, 'Monk'),
+ new DropDownOption(HeroClass.Thinker, 'Thinker'),
+ new DropDownOption(HeroClass.Bard, 'Bard'),
];
heros = [] as MD2HeroInfo[];
heroProfiles: MD2HeroProfile[] = [];
@@ -100,6 +104,7 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
}
initHero() {
this.gameRoomService.gameRoomId = this.roomId;
+ this.gameRoomService.joinGameRoom(this.roomId);
if (!this.md2Service.heros.some(h => h.playerInfo.signalRClientId == this.stateService.loginUserService.userAccess.signalRSessionId)) {
this.msgBoxService.showInputbox('Select Hero Class', '', { dropDownOptions: this.classOptions, inputType: 'dropdown' })
@@ -156,12 +161,18 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
selectCurrentHero() {
if (this.currentSelectingHero) {
this.md2Service.playerJoin(this.currentSelectingHero);
+ this.md2Service.broadcastService.broadcastMyHeroInfo();
this.isSelectingHero = false;
this.detectChanges();
- this.gameRoomService.joinGameRoom(this.roomId);
}
}
-
+ showSkills(type: string) {
+ if (type == 'abilities') {
+ this.msgBoxService.show('Abilities', { text: this.currentSelectingHero.skillHtml });
+ } else {
+ this.msgBoxService.show('Shadow Abilities', { text: this.currentSelectingHero.shadowSkillHtml });
+ }
+ }
nextHero() {
this.currentHeroIndex++;
if (this.currentHeroIndex >= this.heros.length) {
@@ -189,7 +200,7 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
}
openDoor() {
this.md2Service.broadcastService.broadcastHeroAction('openDoor');
- this.showMoveAction = false;
+ //this.showMoveAction = false;
this.detectChanges();
}
moveAction() {
diff --git a/src/app/games/massive-darkness2/massive-darkness2.component.html b/src/app/games/massive-darkness2/massive-darkness2.component.html
index 9f92ff7..2922952 100644
--- a/src/app/games/massive-darkness2/massive-darkness2.component.html
+++ b/src/app/games/massive-darkness2/massive-darkness2.component.html
@@ -63,19 +63,20 @@
HP: {{hero.hp}}/{{hero.hpMaximum}}
Mana: {{hero.mp}}/{{hero.mpMaximum}}
Exp: {{hero.exp}}
-
- {{hero.fireToken}}
+
+ {{hero.fireToken}}
-
- {{hero.frozenToken}}
+
+ {{hero.frozenToken}}
0">Actions:
{{hero.remainActions}}
Inactive
Activating
-
+
+ X
+
diff --git a/src/app/games/massive-darkness2/massive-darkness2.component.ts b/src/app/games/massive-darkness2/massive-darkness2.component.ts
index 5ae0385..dedfd99 100644
--- a/src/app/games/massive-darkness2/massive-darkness2.component.ts
+++ b/src/app/games/massive-darkness2/massive-darkness2.component.ts
@@ -5,7 +5,7 @@ import { MsgBoxService } from '../../services/msg-box.service';
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 { TreasureType, DrawingBag, DrawingItem, HeroClass, MD2HeroInfo, RoundPhase, MobInfo, MobDlgType, MD2Icon } from './massive-darkness2.model';
import { MD2Service } from '../../services/MD2/md2.service';
import { GameRoomService } from '../../services/game-room.service';
import { MD2Base } from './MD2Base';
@@ -25,6 +25,7 @@ import { NumberUtils } from '../../utilities/number-utils';
changeDetection: ChangeDetectionStrategy.OnPush
})
export class MassiveDarkness2Component extends MD2Base implements OnInit {
+ MD2Icon = MD2Icon;
HeroClass = HeroClass;
constructor(
private fileService: FileService,
@@ -148,7 +149,12 @@ export class MassiveDarkness2Component extends MD2Base implements OnInit {
this.md2Service.broadcastService.broadcastAllHeroInfoToAll();
}
removeHero(hero) {
- this.md2Service.info.heros.splice(this.md2Service.info.heros.indexOf(hero));
+ this.msgBoxService.showConfirmDeleteBox().pipe(first()).subscribe(result => {
+ if (result) {
+ this.md2Service.info.heros.splice(this.md2Service.info.heros.indexOf(hero));
+ this.cdRef.detectChanges();
+ }
+ });
}
diff --git a/src/app/games/massive-darkness2/massive-darkness2.model.ts b/src/app/games/massive-darkness2/massive-darkness2.model.ts
index a96dd9b..601231d 100644
--- a/src/app/games/massive-darkness2/massive-darkness2.model.ts
+++ b/src/app/games/massive-darkness2/massive-darkness2.model.ts
@@ -37,6 +37,10 @@ export enum HeroClass {
Shaman,
Paladin,
Druid,
+ Necromancer,
+ Monk,
+ Thinker,
+ Bard
}
export enum MobType {
Mob,
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 64da57e..f8939d8 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
@@ -20,13 +20,12 @@
{{skillTriggerHtml}}
-->
-
-
+
+
{{MobSkillType[skill.type]}} {{skill.skillRoll}}
-
-
+
\ No newline at end of file
diff --git a/src/app/games/massive-darkness2/mobs/spawn-mob-dlg/spawn-mob-dlg.component.html b/src/app/games/massive-darkness2/mobs/spawn-mob-dlg/spawn-mob-dlg.component.html
index fa2205f..836d360 100644
--- a/src/app/games/massive-darkness2/mobs/spawn-mob-dlg/spawn-mob-dlg.component.html
+++ b/src/app/games/massive-darkness2/mobs/spawn-mob-dlg/spawn-mob-dlg.component.html
@@ -10,10 +10,22 @@
-
+
+
+
+ {{ activeSkill.name }}
+
+
+
+
+
+
diff --git a/src/app/games/massive-darkness2/mobs/spawn-mob-dlg/spawn-mob-dlg.component.scss b/src/app/games/massive-darkness2/mobs/spawn-mob-dlg/spawn-mob-dlg.component.scss
index e3beee8..528b514 100644
--- a/src/app/games/massive-darkness2/mobs/spawn-mob-dlg/spawn-mob-dlg.component.scss
+++ b/src/app/games/massive-darkness2/mobs/spawn-mob-dlg/spawn-mob-dlg.component.scss
@@ -2,3 +2,122 @@
width: 885px;
height: 95vh !important;
}
+.skill-card {
+ border-radius: 16px;
+ overflow: hidden;
+ position: relative;
+ border: 1px solid #252a34;
+ background: radial-gradient(120% 180% at 50% -40%, rgba(217, 143, 43, 0.08), transparent 60%),
+ linear-gradient(180deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0.01)), #14161b;
+ transition:
+ transform 0.12s ease,
+ box-shadow 0.25s ease,
+ filter 0.2s ease;
+ margin-top: -130px;
+ z-index: 1;
+ width: 96%;
+}
+.skill-card::before {
+ content: "";
+ position: absolute;
+ inset: 0;
+ pointer-events: none;
+ border-radius: 16px;
+ padding: 1px;
+ background: linear-gradient(
+ 180deg,
+ rgba(246, 230, 185, 0.6),
+ rgba(176, 136, 46, 0.35) 55%,
+ rgba(246, 230, 185, 0.6)
+ );
+ -webkit-mask:
+ linear-gradient(#000 0 0) content-box,
+ linear-gradient(#000 0 0);
+ -webkit-mask-composite: xor;
+ mask-composite: exclude;
+}
+.skill-card[open] {
+ box-shadow:
+ 0 0 0 2px rgba(217, 143, 43, 0.25),
+ 0 12px 28px rgba(0, 0, 0, 0.6);
+}
+
+summary {
+ list-style: none;
+ cursor: pointer;
+ position: relative;
+ display: grid;
+ grid-template-columns: 1fr auto;
+ align-items: center;
+ gap: 0.75rem;
+ padding: 6px 1rem;
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0));
+}
+summary::-webkit-details-marker {
+ display: none;
+}
+summary:hover {
+ filter: saturate(1.08);
+ box-shadow:
+ 0 0 0 2px rgba(155, 28, 28, 0.25),
+ 0 0 18px rgba(217, 143, 43, 0.18) inset;
+}
+summary:focus-visible {
+ outline: 2px solid #d98f2b;
+ outline-offset: 2px;
+ box-shadow: 0 0 18px rgba(217, 143, 43, 0.35);
+}
+
+.skill-name {
+ margin: 0;
+ font-size: 2rem;
+ letter-spacing: 0.04em;
+ background: linear-gradient(180deg, #f6e6b9, #b0882e 50%, #f6e6b9);
+ -webkit-background-clip: text;
+ background-clip: text;
+ color: transparent;
+ font-family: "DwarvenAxeBBW00-Regular", sans-serif !important;
+}
+.rarity {
+ font-size: 0.75rem;
+ text-transform: uppercase;
+ letter-spacing: 0.12em;
+ padding: 0.25rem 0.5rem;
+ border-radius: 999px;
+ border: 1px solid rgba(240, 217, 154, 0.45);
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.02));
+ color: #e8e5de;
+}
+.rarity.legendary {
+ border-color: rgba(217, 143, 43, 0.6);
+ box-shadow: inset 0 0 10px rgba(217, 143, 43, 0.25);
+}
+.rarity.epic {
+ border-color: rgba(155, 28, 28, 0.6);
+ box-shadow: inset 0 0 10px rgba(155, 28, 28, 0.3);
+}
+.rarity.rare {
+ border-color: rgba(148, 164, 58, 0.6);
+ box-shadow: inset 0 0 10px rgba(148, 164, 58, 0.28);
+}
+::ng-deep {
+ .skill-body {
+ padding: 0 1rem 1rem;
+ color: #cfcab7;
+ }
+ .skill-body p {
+ margin: 0.6rem 0 0.4rem;
+ color: #ddd6bf;
+ }
+ .skill-body ul {
+ margin: 0.25rem 0 0;
+ padding-left: 1.1rem;
+ }
+ .skill-body li {
+ margin: 0.25rem 0;
+ color: #a7a196;
+ }
+ .skill-body strong {
+ color: #efe7cf;
+ }
+}
diff --git a/src/app/games/massive-darkness2/mobs/spawn-mob-dlg/spawn-mob-dlg.component.ts b/src/app/games/massive-darkness2/mobs/spawn-mob-dlg/spawn-mob-dlg.component.ts
index da0812a..bc3f16f 100644
--- a/src/app/games/massive-darkness2/mobs/spawn-mob-dlg/spawn-mob-dlg.component.ts
+++ b/src/app/games/massive-darkness2/mobs/spawn-mob-dlg/spawn-mob-dlg.component.ts
@@ -66,7 +66,7 @@ export class SpawnMobDlgComponent extends MD2ComponentBase implements OnInit {
this.mob.actions = 1;
} else {
this.mob.actions = 2;
- this.activeSkill = { name: 'Normal Action', description: '${this.mob.name} Gains 2 Actions.' } as MD2MobSkill;
+ this.activeSkill = { name: 'Normal Action', description: `${this.mob.name} Gains 2 Actions.` } as MD2MobSkill;
//this.actionInfoHtml = `${this.mob.name} Gains 2 Actions.`;
}
}
@@ -113,8 +113,8 @@ export class SpawnMobDlgComponent extends MD2ComponentBase implements OnInit {
return of({ result: true, skill } as SkillResolutionResult);
}
- const title = skill.name || 'Resolve Skill?';
- const prompt = skill.skillCondition || skill.description || 'Resolve this skill?';
+ const title = 'Resolve Skill?';
+ const prompt = skill.skillCondition;
return this.msgBoxService.show(title, {
text: prompt,
diff --git a/src/app/services/MD2/md2-broadcast.service.ts b/src/app/services/MD2/md2-broadcast.service.ts
index 0b13772..222db78 100644
--- a/src/app/services/MD2/md2-broadcast.service.ts
+++ b/src/app/services/MD2/md2-broadcast.service.ts
@@ -26,8 +26,14 @@ export class MD2BroadcastService {
return this.stateService.playerHero;
}
public broadcastAllHeroInfoToAll() {
- this.stateService.info.heros.forEach(element => {
- this.broadcastHeroInfoToAll(element);
+ let message = {
+ receiver: { isGroup: true, sessionId: this.gameRoomService.gameRoomId } as SignalRSession,
+ from: { isGroup: false, sessionId: this.loginUserService.userAccess.signalRSessionId },
+ actionType: 'heroes',
+ actionName: 'updateAll',
+ } as SignalRMessage;
+ message.parameters = { heros: JSON.stringify(this.stateService.info.heros) };
+ this.gameRoomService.sendMessage(message).pipe(first()).subscribe(result => {
});
this.broadcastMobsInfo();
}
diff --git a/src/app/services/MD2/md2.service.ts b/src/app/services/MD2/md2.service.ts
index 7e80815..39de9be 100644
--- a/src/app/services/MD2/md2.service.ts
+++ b/src/app/services/MD2/md2.service.ts
@@ -73,7 +73,7 @@ export class MD2Service {
public fileService: FileService,
public msgBoxService: MsgBoxService,
private gameRoomService: GameRoomService,
- private loginUserService: LoginUserService,
+ public loginUserService: LoginUserService,
public stateService: MD2StateService,
public signalRService: SignalRService,
public dlgService: NbDialogService,
diff --git a/src/app/services/login-user.service.ts b/src/app/services/login-user.service.ts
index deb4530..87b49b2 100644
--- a/src/app/services/login-user.service.ts
+++ b/src/app/services/login-user.service.ts
@@ -18,10 +18,10 @@ export class LoginUserService {
}
public get sessionTabId(): string {
- return sessionStorage.getItem('tabId');
+ return localStorage.getItem('tabId');
}
public set sessionTabId(v: string) {
- sessionStorage.setItem('tabId', v);
+ localStorage.setItem('tabId', v);
}
}
diff --git a/src/app/services/signal-r.service.ts b/src/app/services/signal-r.service.ts
index abaa2a9..156b055 100644
--- a/src/app/services/signal-r.service.ts
+++ b/src/app/services/signal-r.service.ts
@@ -42,7 +42,9 @@ export class SignalRService {
}
public startSignalRConnection(gameRoomId: string = '') {
- this.loginUserService.sessionTabId = UuidUtils.generate();
+ if (!this.loginUserService.sessionTabId) {
+ this.loginUserService.sessionTabId = UuidUtils.generate();
+ }
const tree = this.router.createUrlTree([], {
queryParams: {
diff --git a/src/environments/environment.ts b/src/environments/environment.ts
index c198d5a..fe5d828 100644
--- a/src/environments/environment.ts
+++ b/src/environments/environment.ts
@@ -13,7 +13,7 @@ const urls = [
'https://api.golife.love'
];
const LINE_CLIENT_ID = '1657422139';
-const dockerDebug = urls[0];
+const dockerDebug = urls[2];
export const environment = {
production: false,
apiUrl: dockerDebug,