Skip to content

Commit

Permalink
add monster icon component, monster fight action, ability to block ex…
Browse files Browse the repository at this point in the history
…plore for secondary actions, fight store/actions
  • Loading branch information
seiyria committed Aug 15, 2023
1 parent 51a77d3 commit 08e2eaa
Show file tree
Hide file tree
Showing 34 changed files with 473 additions and 12 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ God, am I getting tired of typing that.
- `COLLECTIBLE_FIND_PERCENT_BOOST` - the percent boost to collectible find events happening (default: 0)
- `RESOURCE_FIND_PERCENT_BOOST` - the percent boost to resource find events happening (default: 0)
- `LOCATION_FIND_PERCENT_BOOST` - the percent boost to location find events happening (default: 0)
- `MONSTER_FIND_PERCENT_BOOST` - the percent boost to monster find events happening (default: 0)
- `CRAFTING_SPEED_MULTIPLIER` - the multiplier for crafting speed [percent] (default: 100)
- `GAMEANALYTICS_KEY` - the game key for GameAnalytics
- `GAMEANALYTICS_SECRET` - the secret key for GameAnalytics
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Component, Input, OnInit } from '@angular/core';
import { IEquipment, IItem } from '@interfaces';
import { Element, IEquipment, IItem } from '@interfaces';

@Component({
selector: 'app-item-elements',
templateUrl: './item-elements.component.html',
styleUrls: ['./item-elements.component.scss'],
})
export class ItemElementsComponent implements OnInit {
public elements: string[] = [];
public elements: Element[] = [];

@Input({ required: true }) item!: IItem;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ export class LocationStatsModalComponent implements OnInit {
public readonly displayStats: LocationStat[] = [
LocationStat.XPGain,
LocationStat.CoinGain,
LocationStat.TaxRate,
LocationStat.ExploreSpeed,
LocationStat.ItemFind,
LocationStat.Wave,
LocationStat.NPCEncounter,
LocationStat.LocationFind,
LocationStat.CollectibleFind,
LocationStat.ResourceFind,
LocationStat.MonsterFind,
];

public readonly statNames: Record<LocationStat, string> = {
Expand All @@ -32,6 +34,7 @@ export class LocationStatsModalComponent implements OnInit {
[LocationStat.LocationFind]: 'Location Find Chance',
[LocationStat.CollectibleFind]: 'Collectible Find Chance',
[LocationStat.ResourceFind]: 'Resource Find Chance',
[LocationStat.MonsterFind]: 'Monster Find Chance',
[LocationStat.TaxRate]: 'Tax Rate',
};

Expand All @@ -48,6 +51,7 @@ export class LocationStatsModalComponent implements OnInit {
[LocationStat.LocationFind]: (value) => `${value}%`,
[LocationStat.CollectibleFind]: (value) => `${value}%`,
[LocationStat.ResourceFind]: (value) => `${value}%`,
[LocationStat.MonsterFind]: (value) => `${value}%`,
[LocationStat.TaxRate]: (value) => `${value}%`,
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<app-icon
spritesheet="monsters"
[sprite]="monster.sprite"
[size]="size"
*ngIf="monster"
></app-icon>
23 changes: 23 additions & 0 deletions client/src/app/components/monster-icon/monster-icon.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@

:host {
display: inline-block;

width: 64px;
height: 64px;
max-width: 64px;
max-height: 64px;

&.xsmall {
width: 16px;
height: 16px;
max-width: 16px;
max-height: 16px;
}

&.small {
width: 32px;
height: 32px;
max-width: 32px;
max-height: 32px;
}
}
20 changes: 20 additions & 0 deletions client/src/app/components/monster-icon/monster-icon.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Component, HostBinding, Input, OnInit } from '@angular/core';
import { IMonster } from '@interfaces';

@Component({
selector: 'app-monster-icon',
templateUrl: './monster-icon.component.html',
styleUrls: ['./monster-icon.component.scss'],
})
export class MonsterIconComponent implements OnInit {
@Input({ required: true }) monster!: IMonster;
@Input() size: 'xsmall' | 'small' | 'normal' = 'normal';

@HostBinding('class') get sizeClass() {
return this.size;
}

constructor() {}

ngOnInit() {}
}
11 changes: 11 additions & 0 deletions client/src/app/helpers/data-grabber.interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
ApplyDiscoveriesPatches,
SetDiscoveries,
} from '@stores/discoveries/discoveries.actions';
import { ApplyFightPatches, SetFight } from '@stores/fight/fight.actions';
import {
ApplyInventoryPatches,
SetInventory,
Expand Down Expand Up @@ -116,6 +117,16 @@ export class DataGrabberInterceptor implements HttpInterceptor {
}
}

if (body.fight) {
if (isArray(body.fight)) {
if (body.fight.length > 0) {
this.store.dispatch(new ApplyFightPatches(body.fight));
}
} else {
this.store.dispatch(new SetFight(body.fight));
}
}

if (body.notifications) {
this.store.dispatch(new SetNotifications(body.notifications));
}
Expand Down
63 changes: 61 additions & 2 deletions client/src/app/pages/explore/explore.page.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@
</ion-card-header>

<ion-card-content>
<div class="action" *ngIf="data.action as actionInfo">
<div
class="action"
*ngIf="data.action as actionInfo; else noAction"
>
<ion-card
class="wave-card action-card"
*ngIf="actionInfo.action === 'wave'"
Expand Down Expand Up @@ -170,8 +173,64 @@
</div>
</ion-card-content>
</ion-card>

<ion-card
class="action-card formation-card"
*ngIf="actionInfo.action === 'fight'"
>
<ion-card-content>
<div class="intro">
You came across
<strong>
{{ actionInfo.actionData.formation.name }}!
</strong>
Prepare for combat!
</div>

<div class="info full-width">
<ion-row>
<ion-col sizeXs="8">
<ion-row>
<ion-col sizeXs="4" class="action-avatar">
<app-monster-icon
[monster]="getMonster(actionInfo.actionData.formation.monsters[0].monster)"
></app-monster-icon>
</ion-col>

<ion-col sizeXs="8" class="action-center">
<div class="formation-name">
{{ actionInfo.actionData.formation.name }}
</div>

<div class="formation-count">
{{
actionInfo.actionData.formation.monsters.length
}} monsters
</div>
</ion-col>
</ion-row>
</ion-col>

<ion-col sizeXs="4" class="action-action">
<ion-button
color="secondary"
(click)="actionsService.doAction(actionInfo)"
>
{{ actionInfo.text }}!
</ion-button>
</ion-col>
</ion-row>
</div>
</ion-card-content>
</ion-card>
</div>

<ng-template #noAction>
<ion-card class="action-card text-only">
You didn't find anything of interest.
</ion-card>
</ng-template>

<div class="earned">
<span class="xp">
<span
Expand All @@ -197,7 +256,7 @@
color="primary"
class="explore"
(click)="explore()"
[disabled]="!canExplore"
[disabled]="!canExplore || data.action?.actionData.stopExplore"
>
<span *ngIf="canExplore">Go!</span>

Expand Down
12 changes: 12 additions & 0 deletions client/src/app/pages/explore/explore.page.scss
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@
}

.action-card {
&.text-only {
padding: 8px;
}

.action-avatar, .action-center, .action-action {
display: flex;
flex-direction: column;
Expand Down Expand Up @@ -73,3 +77,11 @@
}
}
}

.formation-card {
.action-center {
.formation-name {
font-weight: bold;
}
}
}
6 changes: 6 additions & 0 deletions client/src/app/pages/explore/explore.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { INotificationAction, IPlayerLocation } from '@interfaces';
import { Select } from '@ngxs/store';
import { ActionsService } from '@services/actions.service';
import { ContentService } from '@services/content.service';
import { GameplayService } from '@services/gameplay.service';
import { VisualService } from '@services/visual.service';
import { PlayerStore } from '@stores';
Expand All @@ -28,6 +29,7 @@ export class ExplorePage implements OnInit {

constructor(
private gameplayService: GameplayService,
private contentService: ContentService,
public actionsService: ActionsService,
public visualService: VisualService,
) {}
Expand Down Expand Up @@ -56,4 +58,8 @@ export class ExplorePage implements OnInit {
explore() {
this.gameplayService.explore().subscribe();
}

getMonster(monsterId: string) {
return this.contentService.getMonster(monsterId)!;
}
}
30 changes: 30 additions & 0 deletions client/src/app/services/content.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ import { Injectable } from '@angular/core';
import { environment } from '@environment';
import {
ICollectible,
ICombatAbility,
IEquipment,
IItem,
IJob,
ILocation,
IMonster,
IMonsterFormation,
IRecipe,
IResource,
} from '@interfaces';
Expand All @@ -22,6 +25,9 @@ export class ContentService {
equipment: {},
resources: {},
recipes: {},
abilities: {},
monsters: {},
formations: {},
};

public get maxPortraits() {
Expand Down Expand Up @@ -56,6 +62,18 @@ export class ContentService {
return this.content.recipes;
}

public get abilities(): Record<string, ICombatAbility> {
return this.content.abilities;
}

public get monsters(): Record<string, IMonster> {
return this.content.monsters;
}

public get formations(): Record<string, IMonsterFormation> {
return this.content.formations;
}

constructor(private assetService: AssetService) {}

public async init() {
Expand Down Expand Up @@ -117,4 +135,16 @@ export class ContentService {
public getRecipes(): IRecipe[] {
return Object.values(this.recipes);
}

public getFormation(formation: string): IMonsterFormation | undefined {
return this.formations[formation];
}

public getMonster(monster: string): IMonster | undefined {
return this.monsters[monster];
}

public getAbility(ability: string): ICombatAbility | undefined {
return this.abilities[ability];
}
}
2 changes: 2 additions & 0 deletions client/src/app/shared.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { ChooseAvatarModalComponent } from '@components/modals/choose-avatar/cho
import { CompareItemsModalComponent } from '@components/modals/compare-items/compare-items.component';
import { LocationStatsModalComponent } from '@components/modals/location-stats/location-stats.component';
import { MarketModalComponent } from '@components/modals/market/market.component';
import { MonsterIconComponent } from '@components/monster-icon/monster-icon.component';
import { StoreTextComponent } from '@components/store-text/store-text.component';
import { RelativeTimePipe } from '@helpers/relativetime.pipe';
import { IonicModule } from '@ionic/angular';
Expand All @@ -36,6 +37,7 @@ const components = [
HeaderBarComponent,
AvatarComponent,
ItemIconComponent,
MonsterIconComponent,
ItemRarityComponent,
ItemStatsComponent,
ItemElementsComponent,
Expand Down
12 changes: 12 additions & 0 deletions client/src/stores/fight/fight.actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { IFight } from '@interfaces';
import * as jsonpatch from 'fast-json-patch';

export class SetFight {
static type = '[Fight] Set';
constructor(public fight: IFight) {}
}

export class ApplyFightPatches {
static type = '[Fight] Apply Patches';
constructor(public patches: jsonpatch.Operation[]) {}
}
8 changes: 8 additions & 0 deletions client/src/stores/fight/fight.attachments.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { applyFightPatches, setFight } from '@stores/fight/fight.functions';
import { IAttachment } from '../../interfaces';
import { ApplyFightPatches, SetFight } from './fight.actions';

export const attachments: IAttachment[] = [
{ action: SetFight, handler: setFight },
{ action: ApplyFightPatches, handler: applyFightPatches },
];
30 changes: 30 additions & 0 deletions client/src/stores/fight/fight.functions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { IFightStore } from '@interfaces';
import { StateContext } from '@ngxs/store';
import { applyPatch } from 'fast-json-patch';
import { ApplyFightPatches, SetFight } from './fight.actions';

export const defaultStore: () => IFightStore = () => ({
version: 0,
fight: {
id: '',
attackers: [],
defenders: [],
involvedPlayers: [],
tiles: [],
},
});

export function setFight(ctx: StateContext<IFightStore>, { fight }: SetFight) {
ctx.patchState({ fight });
}

export function applyFightPatches(
ctx: StateContext<IFightStore>,
{ patches }: ApplyFightPatches,
) {
const fight = ctx.getState().fight;

applyPatch(fight, patches);

ctx.patchState({ fight });
}
Loading

0 comments on commit 08e2eaa

Please sign in to comment.