diff --git a/CHANGELOG.md b/CHANGELOG.md index 88b05a45..14ff149f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] + +### Added +- Added proper support for the event steps `SHOW_MODAL_CHOICE` and `SET_MSG_EXPRESSION`. +- Added rendering of text colors in relevant events (such as `SHOW_MSG`). + +### Changed +- `VarConditions` now use the string editor, as opposed to the JSON editor. +- Improved support for event/action step property previews - specifically for `Vec2`, `Vec3`, `Offset`, `Entity`, `EnemyType`, `NumberExpression`, `StringExpression`, `BooleanExpression`, `VarName`, `Effect`, and `Animation`. + +### Fixed +- Events with children/branching steps (such as `IF`, `SHOW_CHOICE`, `SHOW_MODAL_CHOICE`, etc.) will no longer fully refresh upon any edits, causing focus to be reset. + ## [1.3.1] 2024-02-09 ### Changed - Updated Angular and Electron versions. diff --git a/webapp/src/app/components/widgets/enemy-type-widget/enemy-type-overlay/enemy-type-overlay.component.ts b/webapp/src/app/components/widgets/enemy-type-widget/enemy-type-overlay/enemy-type-overlay.component.ts index 75728905..f4240f14 100644 --- a/webapp/src/app/components/widgets/enemy-type-widget/enemy-type-overlay/enemy-type-overlay.component.ts +++ b/webapp/src/app/components/widgets/enemy-type-widget/enemy-type-overlay/enemy-type-overlay.component.ts @@ -16,7 +16,7 @@ export class EnemyTypeWidgetOverlayComponent extends AbstractWidget implements O 'OTHER' ]; readonly partyAttributes: AttributeValue = { - type: 'string', + type: 'String', description: '', withNull: true, options: this.makeOptions(this.partyOptions) @@ -32,7 +32,7 @@ export class EnemyTypeWidgetOverlayComponent extends AbstractWidget implements O 'NORTH_WEST' ]; readonly faceAttributes: AttributeValue = { - type: 'string', + type: 'String', description: '', withNull: true, options: this.makeOptions(this.faceOptions) diff --git a/webapp/src/app/components/widgets/event-widget/event-editor/detail/event-detail.component.ts b/webapp/src/app/components/widgets/event-widget/event-editor/detail/event-detail.component.ts index 669a1970..ad045289 100644 --- a/webapp/src/app/components/widgets/event-widget/event-editor/detail/event-detail.component.ts +++ b/webapp/src/app/components/widgets/event-widget/event-editor/detail/event-detail.component.ts @@ -44,8 +44,10 @@ export class EventDetailComponent implements OnDestroy { } public loadEvent(event: AbstractEvent) { - this.event = event; - this.loadSettings(); + if(this.event !== event) { + this.event = event; + this.loadSettings(); + } } private clearSubscriptions() { @@ -94,6 +96,7 @@ export class EventDetailComponent implements OnDestroy { instance.key = key; instance.attribute = val; const sub = instance.onChange.subscribe(() => this.update()); + this.changeSubscriptions.push(sub); return instance; } diff --git a/webapp/src/app/components/widgets/event-widget/event-editor/event-helper.service.ts b/webapp/src/app/components/widgets/event-widget/event-editor/event-helper.service.ts index 0f3f7018..8133437c 100644 --- a/webapp/src/app/components/widgets/event-widget/event-editor/event-helper.service.ts +++ b/webapp/src/app/components/widgets/event-widget/event-editor/event-helper.service.ts @@ -27,7 +27,7 @@ export class EventHelperService { if (valIf.elseStep) { valIf.elseStep = valIf.elseStep.map((v: EventType) => this.getEventFromType(v, actionStep)); } - } else if (val.type === 'SHOW_CHOICE') { + } else if (val.type === 'SHOW_CHOICE' || val.type === 'SHOW_MODAL_CHOICE') { const valChoice = val as any; valChoice.options.forEach((option: any, index: number) => { valChoice[index] = valChoice[index].map((v: EventType) => this.getEventFromType(v, actionStep)); diff --git a/webapp/src/app/components/widgets/event-widget/event-registry/abstract-event.ts b/webapp/src/app/components/widgets/event-widget/event-registry/abstract-event.ts index 4ef03ecb..758dbfa6 100644 --- a/webapp/src/app/components/widgets/event-widget/event-registry/abstract-event.ts +++ b/webapp/src/app/components/widgets/event-widget/event-registry/abstract-event.ts @@ -1,6 +1,157 @@ import { SecurityContext } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser'; import { EntityAttributes } from '../../../../services/phaser/entities/cc-entity'; +import { Label } from '../../../../models/events'; +import { Point, Point3, PartialPoint3 } from '../../../../models/cross-code-map'; + +export type WMTypeNames = 'Action' + | 'Actor' + | 'Analyzable' + | 'AnimSheetRef' + | 'Animation' + | 'Area' + | 'Array' + | 'AttackInfo' + | 'BallChangerType' + | 'Boolean' + | 'BooleanExpression' + | 'BounceAction' + | 'CallEvent' + | 'Character' + | 'ChoiceOptions' + | 'CollabLabelFilter' + | 'Color' + | 'CombatConditions' + | 'CondAnims' + | 'CreditsTriggerSelect' + | 'DoorVariations' + | 'DropSelect' + | 'DynamicPlatformDests' + | 'Effect' + | 'EffectSelect' + | 'ElevatorDests' + | 'EnemyActionRef' + | 'EnemySearch' + | 'EnemyState' + | 'EnemyType' + | 'EnemyTypeList' + | 'Entity' + | 'EntityAnim' + | 'EntityAnimArray' + | 'Event' + | 'EventLoadCondition' + | 'EventSheetCall' + | 'Face' + | 'FlexibleTable' + | 'GUI' + | 'GUIState' + | 'GuiState' + | 'Image' + | 'Integer' + | 'Item' + | 'ItemsDropRate' + | 'Landmarks' + | 'LangLabel' + | 'LoreEntrySelect' + | 'LoreSelect' + | 'LorryAltTypes' + | 'MagnetAltDirs' + | 'Maps' + | 'Marker' + | 'ModalChoiceOptions' + | 'NPC' + | 'NPCStates' + | 'Number' + | 'NumberExpression' + | 'NumberVary' + | 'Object' + | 'Offset' + | 'OlPlatformStates' + | 'PersonExpression' + | 'PoiFilter' + | 'PropInteract' + | 'PropType' + | 'ProxyRef' + | 'Quest' + | 'QuestHub' + | 'QuestLabelSelect' + | 'QuestNameSelect' + | 'QuestResetSelect' + | 'QuestRewards' + | 'QuestTaskList' + | 'RandomDistribution' + | 'Reaction' + | 'ScalablePropConfig' + | 'Select' + | 'Shield' + | 'Shop' + | 'SoundT' + | 'String' + | 'StringExpression' + | 'TaskIndex' + | 'TileSheet' + | 'Timer' + | 'TrackerRef' + | 'TraderSelect' + | 'TrophySelect' + | 'VarCondition' + | 'VarName' + | 'Vec2' + | 'Vec2Expression' + | 'Vec3' + | 'Vec3Expression' + | 'WalkAnimConfig' + | 'XenoDialog'; + + +export namespace WMTypes { + export type VarExpression = + T | + {indirect: string} | + {varName: string} | + {actorAttrib: string} + ; + + export type Color = string; + + export type Vec2 = Point; + export type Vec2Expression = VarExpression; + export type Vec3 = PartialPoint3 & {lvl?: number}; + export type Vec3Expression = VarExpression; + + export type NumberExpression = VarExpression; + export type StringExpression = VarExpression; + export type BooleanExpression = VarExpression; + + export type Offset = Point3; + + export type VarName = string | { + actorAttrib?: string; + indirect?: string; + }; + + export interface Entity { + player?: boolean; + self?: boolean; + name?: string; + varName?: string; + party?: string; + } + + export interface EnemyType { + type: string; + } + + export interface Effect { + sheet: string; + name: string; + } + + export interface Animation { + sheet: string; + name: string; + } +} export interface EventType { type: string; @@ -53,18 +204,87 @@ export abstract class AbstractEvent { } protected getPropString(key: string, value?: any): string { - if (!value) { + if (value === undefined) { value = this.data[key as keyof T]; } const attr = this.getAttributes(); if (attr && attr[key]) { const type = attr[key].type; - if (type === 'Color') { - value = this.getColorRectangle(value); - } else if (type === 'Vec2' && value) { - value = this.getVec2String(value.x, value.y); - } else if (type === 'Entity') { - value = '[' + value.name + ']'; + switch (type as WMTypeNames) { + case 'Color': + value = this.getColorRectangle(value as WMTypes.Color); + break; + case 'Vec2': + case 'Vec2Expression': { + value = this.getVarExpressionValue(value as WMTypes.Vec2Expression, true); + if(typeof value !== 'string') { + const vec2 = value as WMTypes.Vec2; + value = this.getVec2String(vec2.x, vec2.y); + } + break; + } + case 'Vec3': + case 'Vec3Expression': + value = this.getVarExpressionValue(value as WMTypes.Vec3Expression, true); + if(typeof value !== 'string') { + const vec3 = value as WMTypes.Vec3; + value = this.getVec3String(vec3.x, vec3.y, vec3.z, vec3.lvl); + } + break; + case 'Offset': + if(value) { + const offset = value as WMTypes.Offset; + value = this.getVec3String(offset.x, offset.y, offset.z); + } + break; + case 'Entity': { + const entity = value as WMTypes.Entity; + if(entity.player){ + value = 'player'; + } else if(entity.self) { + value = 'self'; + } else if(entity.name) { + value = '[' + entity.name + ']'; + } else if (entity.varName) { + value = `[Var: ${entity.varName}]`; + } else if (entity.party) { + value = `[Party: ${entity.party}]`; + } + break; + } + case 'EnemyType': { + const enemyType = value as WMTypes.EnemyType; + value = '[' + enemyType.type + ']'; + break; + } + case 'NumberExpression': + case 'StringExpression': + case 'BooleanExpression': { + const expression = value as WMTypes.NumberExpression + | WMTypes.StringExpression + | WMTypes.BooleanExpression; + value = this.getVarExpressionValue(expression); + break; + } + case 'VarName': { + const varName = value as WMTypes.VarName; + if(typeof varName === 'object') { + if(varName.indirect) { + value = `[indirect: ${value.indirect}]`; + } else if (varName.actorAttrib) { + value = `[actorAttrib: ${value.indirect}]`; + } + } + break; + } + case 'Effect': + case 'Animation':{ + const obj = value as WMTypes.Effect | WMTypes.Animation; + if(obj) { + value = `${obj.sheet}/${obj.name}`; + } + break; + } } } @@ -73,9 +293,30 @@ export abstract class AbstractEvent { return `${key}: ${value}`; } + protected getVarExpressionValue(value: WMTypes.VarExpression, supportsActorAttrib = false): T | string { + if(value && typeof value == 'object') { + if('indirect' in value) { + return `[indirect: ${value.indirect}]`; + } else if('varName' in value) { + return `[varName: ${value.varName}]`; + } else if('actorAttrib' in value && supportsActorAttrib) { + return `[actorAttrib: ${value.actorAttrib}]`; + } + } + return value as T; + } + protected getVec2String(x: number, y: number): string { return `(${this.sanitize(x)}, ${this.sanitize(y)})`; } + + protected getVec3String(x: number, y: number, z?: number, level?: number): string { + if(level !== undefined) { + return `(${this.sanitize(x)}, ${this.sanitize(y)}, lvl ${this.sanitize(level)})`; + } else { + return `(${this.sanitize(x)}, ${this.sanitize(y)}, ${this.sanitize(z!)})`; + } + } protected getTypeString(color: string): string { color = this.sanitize(color); @@ -93,6 +334,38 @@ export abstract class AbstractEvent { protected getColorRectangle(color: string): string { return `       `; } + + protected getProcessedText(langLabel: Label): string { + const textColors = [ + null, // \c[0] White + '#ff6969', // \c[1] Red + '#65ff89', // \c[2] Green + '#ffe430', // \c[3] Yellow + '#808080', // \c[4] Gray + //'#ff8932', \c[5] Orange, only used for small font in vanilla + ]; + let text = langLabel?.en_US ?? ''; + + let inSpan = false; + text = text.replace(/\\c\[(\d+)\]|$/g, (substr, colorIndex) => { + const color = textColors[+colorIndex]; + let replacement = ''; + if(inSpan) { + replacement += ''; + inSpan = false; + } + if(color) { + replacement += ``; + inSpan = true; + } else if (color !== null) { + //preserve the original color code untouched. + replacement += substr; + } + return replacement; + }); + + return text; + } private sanitize(val: string | number) { return this.domSanitizer.sanitize(SecurityContext.HTML, val) || ''; diff --git a/webapp/src/app/components/widgets/event-widget/event-registry/add-msg-person.ts b/webapp/src/app/components/widgets/event-widget/event-registry/add-msg-person.ts index 7f1e5796..9011d8db 100644 --- a/webapp/src/app/components/widgets/event-widget/event-registry/add-msg-person.ts +++ b/webapp/src/app/components/widgets/event-widget/event-registry/add-msg-person.ts @@ -1,5 +1,6 @@ import { Person } from '../../../../models/events'; import { AbstractEvent, EventType } from './abstract-event'; +import { EntityAttributes } from '../../../../services/phaser/entities/cc-entity'; interface AddMsgPersonData extends EventType { person: Person; @@ -10,7 +11,7 @@ interface AddMsgPersonData extends EventType { } export class AddMsgPerson extends AbstractEvent { - private attributes = { + private attributes: EntityAttributes = { person: { type: 'PersonExpression', description: 'Person + Expression to add' diff --git a/webapp/src/app/components/widgets/event-widget/event-registry/clear-slow-motion.ts b/webapp/src/app/components/widgets/event-widget/event-registry/clear-slow-motion.ts index 357868c5..28b50b2f 100644 --- a/webapp/src/app/components/widgets/event-widget/event-registry/clear-slow-motion.ts +++ b/webapp/src/app/components/widgets/event-widget/event-registry/clear-slow-motion.ts @@ -1,7 +1,8 @@ import { AbstractEvent } from './abstract-event'; +import { EntityAttributes } from '../../../../services/phaser/entities/cc-entity'; export class ClearSlowMotion extends AbstractEvent { - private attributes = { + private attributes: EntityAttributes = { name: { type: 'String', description: 'Name of slow motion to be removed' diff --git a/webapp/src/app/components/widgets/event-widget/event-registry/do-action.ts b/webapp/src/app/components/widgets/event-widget/event-registry/do-action.ts index cc0f9966..0a052850 100644 --- a/webapp/src/app/components/widgets/event-widget/event-registry/do-action.ts +++ b/webapp/src/app/components/widgets/event-widget/event-registry/do-action.ts @@ -1,7 +1,8 @@ import { AbstractEvent } from './abstract-event'; +import { EntityAttributes } from '../../../../services/phaser/entities/cc-entity'; export class DoAction extends AbstractEvent { - private attributes = { + private attributes: EntityAttributes = { entity: { type: 'Entity', description: 'Entity to move', @@ -37,6 +38,7 @@ export class DoAction extends AbstractEvent { update() { this.info = this.combineStrings( this.getTypeString('#8fe174'), + this.getPropString('entity'), this.getPropString('actions', '[' + this.data.action.length + ']'), this.getPropString('repeating'), this.getPropString('wait'), diff --git a/webapp/src/app/components/widgets/event-widget/event-registry/event-registry.service.ts b/webapp/src/app/components/widgets/event-widget/event-registry/event-registry.service.ts index 512dab48..0a244c28 100644 --- a/webapp/src/app/components/widgets/event-widget/event-registry/event-registry.service.ts +++ b/webapp/src/app/components/widgets/event-widget/event-registry/event-registry.service.ts @@ -21,6 +21,8 @@ import { ShowMsg } from './show-msg'; import { StartNpcTradeMenu } from './start-npc-trade-menu'; import { Wait } from './wait'; import { ShowSideMsg } from './show-side-msg'; +import { ShowModalChoice } from './show-modal-choice'; +import { SetMsgExpression } from './set-msg-expression'; type EventConstructor = new (domSanitizer: DomSanitizer, data: T, actionStep: boolean) => AbstractEvent; @@ -52,6 +54,8 @@ export class EventRegistryService { this.register('START_NPC_TRADE_MENU', StartNpcTradeMenu); this.register('OPEN_QUEST_DIALOG', OpenQuestDialog); this.register('SHOW_SIDE_MSG', ShowSideMsg); + this.register('SHOW_MODAL_CHOICE', ShowModalChoice); + this.register('SET_MSG_EXPRESSION', SetMsgExpression); } diff --git a/webapp/src/app/components/widgets/event-widget/event-registry/goto-label.ts b/webapp/src/app/components/widgets/event-widget/event-registry/goto-label.ts index 89f0014b..cb227ead 100644 --- a/webapp/src/app/components/widgets/event-widget/event-registry/goto-label.ts +++ b/webapp/src/app/components/widgets/event-widget/event-registry/goto-label.ts @@ -1,4 +1,5 @@ import { AbstractEvent, EventType } from './abstract-event'; +import { EntityAttributes } from '../../../../services/phaser/entities/cc-entity'; export interface GotoLabelData extends EventType { @@ -6,7 +7,7 @@ export interface GotoLabelData extends EventType { } export class GotoLabel extends AbstractEvent { - private attributes = { + private attributes: EntityAttributes = { name : { type: 'String', description: 'Label to goto.' diff --git a/webapp/src/app/components/widgets/event-widget/event-registry/if.ts b/webapp/src/app/components/widgets/event-widget/event-registry/if.ts index db3287f7..cbc4b5fc 100644 --- a/webapp/src/app/components/widgets/event-widget/event-registry/if.ts +++ b/webapp/src/app/components/widgets/event-widget/event-registry/if.ts @@ -1,4 +1,5 @@ import { AbstractEvent, EventType } from './abstract-event'; +import { EntityAttributes } from '../../../../services/phaser/entities/cc-entity'; export interface IfData extends EventType { withElse: boolean; @@ -8,7 +9,7 @@ export interface IfData extends EventType { } export class If extends AbstractEvent { - private attributes = { + private attributes: EntityAttributes = { condition: { type: 'VarCondition', description: 'Condition for IF statement' diff --git a/webapp/src/app/components/widgets/event-widget/event-registry/label.ts b/webapp/src/app/components/widgets/event-widget/event-registry/label.ts index da830620..0864536a 100644 --- a/webapp/src/app/components/widgets/event-widget/event-registry/label.ts +++ b/webapp/src/app/components/widgets/event-widget/event-registry/label.ts @@ -1,4 +1,5 @@ import { AbstractEvent, EventType } from './abstract-event'; +import { EntityAttributes } from '../../../../services/phaser/entities/cc-entity'; export interface LabelData extends EventType { @@ -6,7 +7,7 @@ export interface LabelData extends EventType { } export class Label extends AbstractEvent { - private attributes = { + private attributes: EntityAttributes = { name : { type: 'String', description: 'Name to reference this label by.' diff --git a/webapp/src/app/components/widgets/event-widget/event-registry/set-camera-between.ts b/webapp/src/app/components/widgets/event-widget/event-registry/set-camera-between.ts index e0e57e27..0dac54a0 100644 --- a/webapp/src/app/components/widgets/event-widget/event-registry/set-camera-between.ts +++ b/webapp/src/app/components/widgets/event-widget/event-registry/set-camera-between.ts @@ -1,7 +1,8 @@ import { AbstractEvent } from './abstract-event'; +import { EntityAttributes } from '../../../../services/phaser/entities/cc-entity'; export class SetCameraBetween extends AbstractEvent { - private attributes = { + private attributes: EntityAttributes = { entity1: { type: 'Entity', description: 'First entity' diff --git a/webapp/src/app/components/widgets/event-widget/event-registry/set-camera-pos.ts b/webapp/src/app/components/widgets/event-widget/event-registry/set-camera-pos.ts index 0caf4874..b2f29180 100644 --- a/webapp/src/app/components/widgets/event-widget/event-registry/set-camera-pos.ts +++ b/webapp/src/app/components/widgets/event-widget/event-registry/set-camera-pos.ts @@ -1,7 +1,8 @@ import { AbstractEvent } from './abstract-event'; +import { EntityAttributes } from '../../../../services/phaser/entities/cc-entity'; export class SetCameraPos extends AbstractEvent { - private attributes = { + private attributes: EntityAttributes = { pos: { type: 'Vec2', description: 'Position to focus camera on', diff --git a/webapp/src/app/components/widgets/event-widget/event-registry/set-camera-target.ts b/webapp/src/app/components/widgets/event-widget/event-registry/set-camera-target.ts index d6b13c50..7163f155 100644 --- a/webapp/src/app/components/widgets/event-widget/event-registry/set-camera-target.ts +++ b/webapp/src/app/components/widgets/event-widget/event-registry/set-camera-target.ts @@ -1,7 +1,8 @@ import { AbstractEvent } from './abstract-event'; +import { EntityAttributes } from '../../../../services/phaser/entities/cc-entity'; export class SetCameraTarget extends AbstractEvent { - private attributes = { + private attributes: EntityAttributes = { entity: { type: 'Entity', description: 'Entity to focus camera on' diff --git a/webapp/src/app/components/widgets/event-widget/event-registry/set-camera-zoom.ts b/webapp/src/app/components/widgets/event-widget/event-registry/set-camera-zoom.ts index b389dde3..82787e85 100644 --- a/webapp/src/app/components/widgets/event-widget/event-registry/set-camera-zoom.ts +++ b/webapp/src/app/components/widgets/event-widget/event-registry/set-camera-zoom.ts @@ -1,7 +1,8 @@ import { AbstractEvent } from './abstract-event'; +import { EntityAttributes } from '../../../../services/phaser/entities/cc-entity'; export class SetCameraZoom extends AbstractEvent { - private attributes = { + private attributes: EntityAttributes = { zoom: { type: 'Number', description: 'Zoom Value. 1=default, 2=twice pixel size', diff --git a/webapp/src/app/components/widgets/event-widget/event-registry/set-msg-expression.ts b/webapp/src/app/components/widgets/event-widget/event-registry/set-msg-expression.ts new file mode 100644 index 00000000..5396d269 --- /dev/null +++ b/webapp/src/app/components/widgets/event-widget/event-registry/set-msg-expression.ts @@ -0,0 +1,22 @@ +import { Person } from '../../../../models/events'; +import { EventType } from './abstract-event'; +import { DefaultEvent } from './default-event'; + +interface SetMsgExpressionData extends EventType { + person: Person; +} + +export class SetMsgExpression extends DefaultEvent { + override update() { + this.info = this.combineStrings( + this.getTypeString('#7ea3ff'), + this.getPropString('person', this.data.person.person + '>​' + this.data.person.expression), + ); + } + + override generateNewDataInternal() { + return { + person: {} + }; + } +} diff --git a/webapp/src/app/components/widgets/event-widget/event-registry/set-overlay.ts b/webapp/src/app/components/widgets/event-widget/event-registry/set-overlay.ts index 635a5ad3..3af33bf5 100644 --- a/webapp/src/app/components/widgets/event-widget/event-registry/set-overlay.ts +++ b/webapp/src/app/components/widgets/event-widget/event-registry/set-overlay.ts @@ -1,7 +1,8 @@ import { AbstractEvent } from './abstract-event'; +import { EntityAttributes } from '../../../../services/phaser/entities/cc-entity'; export class SetOverlay extends AbstractEvent { - private attributes = { + private attributes: EntityAttributes = { color: { type: 'Color', description: 'Color of overlay' diff --git a/webapp/src/app/components/widgets/event-widget/event-registry/set-player-core.ts b/webapp/src/app/components/widgets/event-widget/event-registry/set-player-core.ts index d1c40712..34a174c5 100644 --- a/webapp/src/app/components/widgets/event-widget/event-registry/set-player-core.ts +++ b/webapp/src/app/components/widgets/event-widget/event-registry/set-player-core.ts @@ -1,7 +1,8 @@ import { AbstractEvent } from './abstract-event'; +import { EntityAttributes } from '../../../../services/phaser/entities/cc-entity'; export class SetPlayerCore extends AbstractEvent { - private attributes = { + private attributes: EntityAttributes = { core: { type: 'String', description: 'Type of Core.', diff --git a/webapp/src/app/components/widgets/event-widget/event-registry/show-choice.ts b/webapp/src/app/components/widgets/event-widget/event-registry/show-choice.ts index bf75ac0e..e0962929 100644 --- a/webapp/src/app/components/widgets/event-widget/event-registry/show-choice.ts +++ b/webapp/src/app/components/widgets/event-widget/event-registry/show-choice.ts @@ -1,6 +1,8 @@ +import { Helper } from '../../../../services/phaser/helper'; import { Label, Person } from '../../../../models/events'; import { EntityAttributes } from '../../../../services/phaser/entities/cc-entity'; import { AbstractEvent, EventType } from './abstract-event'; +import { DefaultEvent } from './default-event'; export interface ShowChoiceData extends EventType { [key: number]: AbstractEvent[]; @@ -14,35 +16,8 @@ export interface ShowChoiceData extends EventType { forceWidth: number; } -export class ShowChoice extends AbstractEvent { - private attributes: EntityAttributes = { - person: { - type: 'PersonExpression', - description: 'Talking person' - }, - options: { - type: 'ChoiceOptions', - description: 'List of options', - C2: true - }, - columns: { - type: 'Integer', - description: 'Number of buttons columns.', - I: true, - min: 2 - }, - forceWidth: { - type: 'Integer', - description: 'Override the default button width. NOTE: Buttons still get matched when a text is to large.', - I: true - } - }; - - getAttributes(): EntityAttributes { - return this.attributes; - } - - update() { +export class ShowChoice extends DefaultEvent { + override update() { this.children = []; this.info = this.combineStrings( this.getTypeString('#7ea3ff'), @@ -51,7 +26,7 @@ export class ShowChoice extends AbstractEvent { this.data.options.forEach((option, index) => { this.children[index] = { - title: this.getColoredString('Choice. ' + option.label.en_US, '#838383'), + title: this.getColoredString('Choice: ', '#838383') + this.getProcessedText(option.label), events: this.data[index] || [], draggable: false }; @@ -74,16 +49,20 @@ export class ShowChoice extends AbstractEvent { out[index] = child.events.map(v => v.export()); }); - return JSON.parse(JSON.stringify(out)); + return Helper.copy(out); } - protected generateNewDataInternal() { + protected override generateNewDataInternal() { return { person: {}, options: [{ - label: {} + label: { + en_US: 'Choice 1' + } }, { - label: {} + label: { + en_US: 'Choice 2' + } }] }; } diff --git a/webapp/src/app/components/widgets/event-widget/event-registry/show-modal-choice.ts b/webapp/src/app/components/widgets/event-widget/event-registry/show-modal-choice.ts new file mode 100644 index 00000000..edff393c --- /dev/null +++ b/webapp/src/app/components/widgets/event-widget/event-registry/show-modal-choice.ts @@ -0,0 +1,62 @@ +import { Helper } from '../../../../services/phaser/helper'; +import { Label } from '../../../../models/events'; +import { AbstractEvent, EventType } from './abstract-event'; +import { DefaultEvent } from './default-event'; + +export interface ShowModalChoiceData extends EventType { + [key: number]: AbstractEvent[]; + + text: Label; + options: { + label: Label; + }[]; +} + +export class ShowModalChoice extends DefaultEvent { + override update() { + this.children = []; + this.info = this.combineStrings( + this.getTypeString('#7774e8'), + this.getPropString('text', this.getProcessedText(this.data.text)) + ); + + this.data.options.forEach((option, index) => { + this.children[index] = { + title: this.getColoredString('Choice: ', '#838383') + this.getProcessedText(option.label), + events: this.data[index] || [], + draggable: false + }; + }); + } + + override export(): ShowModalChoiceData { + const out: ShowModalChoiceData = { + type: this.data.type, + text: this.data.text, + options: this.data.options, + }; + this.children.forEach((child, index) => { + if (!child.events) { + console.error('wtf', this); + } + out[index] = child.events.map(v => v.export()); + }); + + return Helper.copy(out); + } + + protected override generateNewDataInternal() { + return { + text: {}, + options: [{ + label: { + en_US: 'Choice 1' + } + }, { + label: { + en_US: 'Choice 2' + } + }] + }; + } +} diff --git a/webapp/src/app/components/widgets/event-widget/event-registry/show-msg.ts b/webapp/src/app/components/widgets/event-widget/event-registry/show-msg.ts index be1ec202..9998f134 100644 --- a/webapp/src/app/components/widgets/event-widget/event-registry/show-msg.ts +++ b/webapp/src/app/components/widgets/event-widget/event-registry/show-msg.ts @@ -1,5 +1,6 @@ import { Label, Person } from '../../../../models/events'; import { AbstractEvent, EventType } from './abstract-event'; +import { EntityAttributes } from '../../../../services/phaser/entities/cc-entity'; interface ShowMsgData extends EventType { message: Label; @@ -8,7 +9,7 @@ interface ShowMsgData extends EventType { } export class ShowMsg extends AbstractEvent { - private attributes = { + private attributes: EntityAttributes = { person: { type: 'PersonExpression', description: 'Talking person' @@ -31,7 +32,7 @@ export class ShowMsg extends AbstractEvent { update() { this.info = this.combineStrings( this.getColoredString(this.data.person.person + '>​' + this.data.person.expression, '#ffe188'), - this.data.message?.en_US + this.getProcessedText(this.data.message) ); } diff --git a/webapp/src/app/components/widgets/event-widget/event-registry/show-side-msg.ts b/webapp/src/app/components/widgets/event-widget/event-registry/show-side-msg.ts index 5cc7ac96..9116cb31 100644 --- a/webapp/src/app/components/widgets/event-widget/event-registry/show-side-msg.ts +++ b/webapp/src/app/components/widgets/event-widget/event-registry/show-side-msg.ts @@ -13,7 +13,7 @@ export class ShowSideMsg extends DefaultEvent { this.info = this.combineStrings( this.getTypeString('#fa5aff'), this.getColoredString(this.data.person?.person + '>​' + this.data.person?.expression, '#ffe188'), - this.data.message?.en_US + this.getProcessedText(this.data.message) ); } diff --git a/webapp/src/app/components/widgets/event-widget/event-registry/wait.ts b/webapp/src/app/components/widgets/event-widget/event-registry/wait.ts index 4e5e6ded..424fd083 100644 --- a/webapp/src/app/components/widgets/event-widget/event-registry/wait.ts +++ b/webapp/src/app/components/widgets/event-widget/event-registry/wait.ts @@ -1,7 +1,8 @@ import { AbstractEvent } from './abstract-event'; +import { EntityAttributes } from '../../../../services/phaser/entities/cc-entity'; export class Wait extends AbstractEvent { - private attributes = { + private attributes: EntityAttributes = { time: { type: 'Number', description: 'Time to wait' diff --git a/webapp/src/app/components/widgets/widget-registry.service.ts b/webapp/src/app/components/widgets/widget-registry.service.ts index 821bc8d9..2c0499f4 100644 --- a/webapp/src/app/components/widgets/widget-registry.service.ts +++ b/webapp/src/app/components/widgets/widget-registry.service.ts @@ -39,6 +39,7 @@ export class WidgetRegistryService { this.register('LangLabel', LangLabelWidgetComponent); this.register('EntityAnim', StringWidgetComponent); this.register('CustomDesType', CustomDesTypeWidgetComponent); + this.register('VarCondition', StringWidgetComponent); } private setDefaultWidget(widget: any) { diff --git a/webapp/src/app/models/events.ts b/webapp/src/app/models/events.ts index c037a5d1..88e89435 100644 --- a/webapp/src/app/models/events.ts +++ b/webapp/src/app/models/events.ts @@ -36,6 +36,8 @@ export type EventArray = {trade: TraderEvent} ; + + export function destructureEventArray(events: EventArray): {events: EventType[], type: EventArrayType, trader?: string} { if (Array.isArray(events)) { return {events: events, type: EventArrayType.Simple}; diff --git a/webapp/src/app/services/phaser/entities/cc-entity.ts b/webapp/src/app/services/phaser/entities/cc-entity.ts index 2cbef319..6b268ff2 100644 --- a/webapp/src/app/services/phaser/entities/cc-entity.ts +++ b/webapp/src/app/services/phaser/entities/cc-entity.ts @@ -9,6 +9,7 @@ import { AbstractWidget } from '../../../components/widgets/abstract-widget'; import { Globals } from '../../globals'; import { BaseObject } from '../base-object'; + export interface ScaleSettings { scalableX: boolean; scalableY: boolean;