Implement InventoryActions for Interactions
All checks were successful
E2E Testing / test (push) Successful in 1m16s

This commit is contained in:
Sebastian Boeckelmann 2024-06-15 14:44:20 +02:00
parent bc0617eb85
commit 64786efce0
10 changed files with 252 additions and 9 deletions

View File

@ -119,6 +119,7 @@ import {
import { import {
ItemSelectorComponent ItemSelectorComponent
} from "./editor/interaction-editor/conditions/item-condition-editor/item-selector/item-selector.component"; } from "./editor/interaction-editor/conditions/item-condition-editor/item-selector/item-selector.component";
import {ItemActionEditorComponent} from "./editor/interaction-editor/item-action-editor/item-action-editor.component";
// AoT requires an exported function for factories // AoT requires an exported function for factories
const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new TranslateHttpLoader(http, './assets/i18n/', '.json'); const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new TranslateHttpLoader(http, './assets/i18n/', '.json');
@ -157,7 +158,8 @@ const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new Transl
CharacterInteractionEditorComponent, CharacterInteractionEditorComponent,
GamesystemConditionEditorComponent, GamesystemConditionEditorComponent,
ItemConditionEditorComponent, ItemConditionEditorComponent,
ItemSelectorComponent ItemSelectorComponent,
ItemActionEditorComponent
], ],
imports: [ imports: [
BrowserModule, BrowserModule,

View File

@ -129,10 +129,10 @@
></app-scriptaccount-action-editor> ></app-scriptaccount-action-editor>
</mat-tab> </mat-tab>
<mat-tab label="Inventory Itemgroup Actions"> <mat-tab label="Inventory Itemgroup Actions">
<app-item-action-editor [interaction]="element" [gameModel]="gameModel" [group]="true"></app-item-action-editor>
</mat-tab> </mat-tab>
<mat-tab label="Inventory Item Actions"> <mat-tab label="Inventory Item Actions">
<app-item-action-editor [interaction]="element" [gameModel]="gameModel" [group]="false"></app-item-action-editor>
</mat-tab> </mat-tab>
<mat-tab label="Gamesystem Actions"> <mat-tab label="Gamesystem Actions">
<p>Gamesystem Actions</p> <p>Gamesystem Actions</p>

View File

@ -0,0 +1,65 @@
<table mat-table class="mat-elevation-z8" [dataSource]="actionDatasource">
<ng-container matColumnDef="item">
<th mat-header-cell *matHeaderCellDef>{{group? 'Itemgroup':'Item'}}</th>
<td mat-cell *matCellDef="let action">
@if(group) {
@if(action == editedAction) {
<mat-form-field appearance="fill" class="long-form">
<mat-label>Itemgroup</mat-label>
<mat-select [(ngModel)]="actionAsItemgroupAction(action)!.itemgroup">
<mat-option *ngFor="let itemgroup of gameModel!.itemgroupsAsList" [value]="itemgroup">{{itemgroup.componentName}}</mat-option>
</mat-select>
</mat-form-field>
} @else {
<p *ngIf="actionAsItemgroupAction(action)!.itemgroup != undefined">
{{actionAsItemgroupAction(action)!.itemgroup!.componentName}}
</p>
}
} @else {
@if(action == editedAction) {
<app-item-selector [itemgroups]="gameModel!.itemgroupsAsList" [selectedItem]="actionAsItemAction(action)!.item"
(onSelectedItemChange)="onSelectedItemChange(action, $event)"
></app-item-selector>
} @else {
<p *ngIf="actionAsItemAction(action)!.item != undefined">
{{actionAsItemAction(action)!.item!.componentName}}
</p>
}
}
</td>
</ng-container>
<ng-container matColumnDef="delta">
<th mat-header-cell *matHeaderCellDef>Min</th>
<td mat-cell *matCellDef="let action">
@if(action == editedAction) {
<mat-form-field appearance="fill" class="long-form">
<mat-label>Min Value</mat-label>
<input matInput [(ngModel)]="action!.valueChange">
</mat-form-field>
} @else {
{{action.valueChange}}
}
</td>
</ng-container>
<ng-container matColumnDef="edit">
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let action">
<button mat-icon-button *ngIf="action !== editedAction" [disabled]="editedAction != undefined" (click)="editAction(action)"><mat-icon>edit</mat-icon></button>
<button mat-icon-button *ngIf="action === editedAction" (click)="finishEditing()"><mat-icon>done</mat-icon></button>
</td>
</ng-container>
<ng-container matColumnDef="delete">
<th mat-header-cell *matHeaderCellDef>
<button mat-icon-button (click)="addAction()"><mat-icon>add</mat-icon></button>
</th>
<td mat-cell *matCellDef="let action">
<button mat-icon-button (click)="deleteAction(action)" color="warn"><mat-icon>delete</mat-icon></button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

View File

@ -0,0 +1,3 @@
.mat-column-edit, .mat-column-delete {
width: 32px;
}

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ItemActionEditorComponent } from './item-action-editor.component';
describe('ItemActionEditorComponent', () => {
let component: ItemActionEditorComponent;
let fixture: ComponentFixture<ItemActionEditorComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ItemActionEditorComponent]
})
.compileComponents();
fixture = TestBed.createComponent(ItemActionEditorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,109 @@
import {Component, Input} from '@angular/core';
import {
MatCell,
MatCellDef,
MatColumnDef,
MatHeaderCell,
MatHeaderRow,
MatHeaderRowDef,
MatRow, MatRowDef, MatTable, MatTableDataSource
} from "@angular/material/table";
import {MatFormField, MatLabel} from "@angular/material/form-field";
import {MatIcon} from "@angular/material/icon";
import {MatIconButton} from "@angular/material/button";
import {MatInput} from "@angular/material/input";
import {MatOption} from "@angular/material/autocomplete";
import {MatSelect} from "@angular/material/select";
import {NgForOf, NgIf} from "@angular/common";
import {ReactiveFormsModule} from "@angular/forms";
import {AbstractInteraction} from "../../../project/game-model/interactions/AbstractInteraction";
import {GameModel} from "../../../project/game-model/GameModel";
import {InventoryCondition} from "../../../project/game-model/interactions/condition/InventoryCondition";
import {
InventoryItemgroupCondition
} from "../../../project/game-model/interactions/condition/InventoryItemgroupCondition";
import {CharacterDependency} from "../../../project/game-model/interactions/CharacterDependency";
import {InventoryItemCondition} from "../../../project/game-model/interactions/condition/InventoryItemCondition";
import {Item} from "../../../project/game-model/inventory/Item";
import {Interaction} from "../../../project/game-model/interactions/Interaction";
import {InventoryAction} from "../../../project/game-model/interactions/actions/InventoryAction";
import {InventoryItemGroupAction} from "../../../project/game-model/interactions/actions/InventoryItemgroupAction";
import {InventoryItemAction} from "../../../project/game-model/interactions/actions/InventoryItemAction";
@Component({
selector: 'app-item-action-editor',
templateUrl: './item-action-editor.component.html',
styleUrl: './item-action-editor.component.scss'
})
export class ItemActionEditorComponent {
@Input() interaction: Interaction | undefined
@Input() gameModel: GameModel | undefined
@Input() group: boolean = false;
actionDatasource: MatTableDataSource<InventoryAction> = new MatTableDataSource();
displayedColumns: string[] = ["item", "delta", "edit", "delete"];
editedAction: InventoryAction | undefined
addedAction: InventoryAction | undefined
ngOnInit() {
this.actionDatasource.data = this.interaction!.inventoryActions;
}
addAction() {
if(this.group) {
this.addedAction = new InventoryItemGroupAction(CharacterDependency.NONE, 0, undefined);
} else {
this.addedAction = new InventoryItemAction(CharacterDependency.NONE, 0, undefined);
}
this.editedAction = this.addedAction;
const displayedColumns = this.actionDatasource.data;
displayedColumns.push(this.addedAction);
this.actionDatasource.data = displayedColumns;
}
editAction(action: InventoryAction) {
this.editedAction = action;
}
finishEditing() {
if(this.editedAction == undefined) {
return;
}
if(this.editedAction.validate()) {
if(this.addedAction != undefined) {
this.interaction!.addAction(this.addedAction);
this.addedAction = undefined;
}
this.editedAction = undefined;
}
}
deleteAction(deletedAction: InventoryAction) {
this.interaction!.removeAction(deletedAction);
this.actionDatasource.data = this.actionDatasource.data.filter(action => action !== deletedAction);
}
actionAsItemAction(action: InventoryAction) {
if(action instanceof InventoryItemAction) {
return action;
} else {
return undefined;
}
}
actionAsItemgroupAction(action: InventoryAction) {
if(action instanceof InventoryItemGroupAction) {
return action;
} else {
return undefined;
}
}
onSelectedItemChange(action: InventoryItemAction, item: Item) {
(action as InventoryItemAction).item = item;
}
}

View File

@ -5,6 +5,7 @@ import {AbstractInteraction} from "./AbstractInteraction";
import {ScriptAccountCondition} from "../gamesystems/conditions/ScriptAccountCondition"; import {ScriptAccountCondition} from "../gamesystems/conditions/ScriptAccountCondition";
import {ScriptAccountAction} from "../gamesystems/actions/ScriptAccountAction"; import {ScriptAccountAction} from "../gamesystems/actions/ScriptAccountAction";
import {InventoryCondition} from "./condition/InventoryCondition"; import {InventoryCondition} from "./condition/InventoryCondition";
import {InventoryItemAction} from "./actions/InventoryItemAction";
export class Interaction extends AbstractInteraction{ export class Interaction extends AbstractInteraction{
@ -41,6 +42,9 @@ export class Interaction extends AbstractInteraction{
return this.actions.filter(condition => condition instanceof ScriptAccountAction).map(condition => condition as ScriptAccountAction) return this.actions.filter(condition => condition instanceof ScriptAccountAction).map(condition => condition as ScriptAccountAction)
} }
get inventoryActions(): InventoryItemAction[] {
return this.actions.filter(action => action instanceof InventoryItemAction).map(action => action as InventoryItemAction);
}
addAction(action: Action) { addAction(action: Action) {
this.actions.push(action); this.actions.push(action);

View File

@ -0,0 +1,13 @@
import {Action} from "./Action";
import {CharacterDependency} from "../CharacterDependency";
export abstract class InventoryAction extends Action {
valueChange: number;
protected constructor(characterDependency: CharacterDependency, valueChange: number) {
super(characterDependency);
this.valueChange = valueChange;
}
public abstract validate(): boolean;
}

View File

@ -1,15 +1,20 @@
import {Action} from "./Action"; import {Action} from "./Action";
import {Item} from "../../inventory/Item"; import {Item} from "../../inventory/Item";
import {CharacterDependency} from "../CharacterDependency"; import {CharacterDependency} from "../CharacterDependency";
import {InventoryAction} from "./InventoryAction";
export class InventoryItemAction extends Action { export class InventoryItemAction extends InventoryAction {
item: Item item: Item | undefined
valueChange: number
constructor(characterDependency: CharacterDependency, item: Item, valueChange: number) {
super(characterDependency); constructor(characterDependency: CharacterDependency, valueChange: number, item: Item | undefined) {
super(characterDependency, valueChange);
this.item = item; this.item = item;
this.valueChange = valueChange;
} }
validate(): boolean {
return this.item != undefined;
}
} }

View File

@ -0,0 +1,19 @@
import {Action} from "./Action";
import {ItemGroup} from "../../inventory/ItemGroup";
import {CharacterDependency} from "../CharacterDependency";
import {InventoryAction} from "./InventoryAction";
export class InventoryItemGroupAction extends InventoryAction{
itemgroup: ItemGroup | undefined
constructor(characterDependency: CharacterDependency, valueChange: number, itemgroup: ItemGroup | undefined) {
super(characterDependency, valueChange);
this.itemgroup = itemgroup;
}
validate(): boolean {
return this.itemgroup != undefined;
}
}