@rpg-engine/long-bow 0.8.48 → 0.8.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ import { Meta } from '@storybook/react';
2
+ import { ICharacterSkinSelectionModalProps } from '../../../components/Character/CharacterSkinSelectionModal';
3
+ declare const meta: Meta;
4
+ export default meta;
5
+ export declare const KnightSkins: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, ICharacterSkinSelectionModalProps>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpg-engine/long-bow",
3
- "version": "0.8.48",
3
+ "version": "0.8.50",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -0,0 +1,151 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import styled from 'styled-components';
3
+ import { Button, ButtonTypes } from '../Button';
4
+ import { ErrorBoundary } from '../Item/Inventory/ErrorBoundary';
5
+ import PropertySelect, {
6
+ IPropertiesProps,
7
+ } from '../PropertySelect/PropertySelect';
8
+ import { SpriteFromAtlas } from '../shared/SpriteFromAtlas';
9
+ import { ICharacterProps } from './CharacterSelection';
10
+
11
+ export interface ICharacterSkinSelectionModalProps {
12
+ isOpen: boolean;
13
+ onClose: () => void;
14
+ onConfirm: (textureKey: string) => void;
15
+ availableCharacters: ICharacterProps[];
16
+ atlasJSON: any;
17
+ atlasIMG: any;
18
+ initialSelectedSkin?: string;
19
+ }
20
+
21
+ export const CharacterSkinSelectionModal: React.FC<ICharacterSkinSelectionModalProps> = ({
22
+ isOpen,
23
+ onClose,
24
+ onConfirm,
25
+ availableCharacters,
26
+ atlasJSON,
27
+ atlasIMG,
28
+ initialSelectedSkin = '',
29
+ }) => {
30
+ // Convert availableCharacters to the format used by PropertySelect
31
+ const propertySelectValues = availableCharacters.map(item => ({
32
+ id: item.textureKey,
33
+ name: item.name,
34
+ }));
35
+
36
+ // State to store the selected skin and the sprite key
37
+ const [selectedValue, setSelectedValue] = useState<
38
+ IPropertiesProps | undefined
39
+ >();
40
+ const [selectedSpriteKey, setSelectedSpriteKey] = useState('');
41
+
42
+ // Update sprite when the selected value changes
43
+ const updateSelectedSpriteKey = () => {
44
+ const textureKey = selectedValue ? selectedValue.id : '';
45
+ const spriteKey = textureKey ? textureKey + '/down/standing/0.png' : '';
46
+
47
+ if (spriteKey === selectedSpriteKey) {
48
+ return;
49
+ }
50
+
51
+ setSelectedSpriteKey(spriteKey);
52
+ };
53
+
54
+ // Update sprite when selectedValue changes
55
+ useEffect(() => {
56
+ updateSelectedSpriteKey();
57
+ }, [selectedValue]);
58
+
59
+ // Initialize selectedValue
60
+ useEffect(() => {
61
+ if (initialSelectedSkin) {
62
+ const initialProperty = propertySelectValues.find(
63
+ prop => prop.id === initialSelectedSkin
64
+ );
65
+ setSelectedValue(initialProperty || propertySelectValues[0]);
66
+ } else if (propertySelectValues.length > 0) {
67
+ setSelectedValue(propertySelectValues[0]);
68
+ }
69
+ }, [initialSelectedSkin, availableCharacters]);
70
+
71
+ // Functions to handle confirmation and cancellation
72
+ const handleConfirm = () => {
73
+ if (selectedValue) {
74
+ onConfirm(selectedValue.id);
75
+ onClose();
76
+ }
77
+ };
78
+
79
+ const handleCancel = () => {
80
+ onClose();
81
+ };
82
+
83
+ if (!isOpen) return null;
84
+
85
+ return (
86
+ <Container>
87
+ {selectedSpriteKey && atlasIMG && atlasJSON && (
88
+ <ErrorBoundary>
89
+ <SpriteFromAtlas
90
+ spriteKey={selectedSpriteKey}
91
+ atlasIMG={atlasIMG}
92
+ atlasJSON={atlasJSON}
93
+ imgScale={4}
94
+ height={80}
95
+ width={64}
96
+ containerStyle={{
97
+ display: 'flex',
98
+ alignItems: 'center',
99
+ paddingBottom: '15px',
100
+ }}
101
+ imgStyle={{
102
+ left: '22px',
103
+ }}
104
+ />
105
+ </ErrorBoundary>
106
+ )}
107
+
108
+ <PropertySelect
109
+ availableProperties={propertySelectValues}
110
+ onChange={value => {
111
+ setSelectedValue(value);
112
+ }}
113
+ />
114
+
115
+ <ButtonsContainer>
116
+ <Button buttonType={ButtonTypes.RPGUIButton} onClick={handleCancel}>
117
+ Cancel
118
+ </Button>
119
+ <Button
120
+ buttonType={ButtonTypes.RPGUIButton}
121
+ onClick={handleConfirm}
122
+ disabled={!selectedValue}
123
+ >
124
+ Confirm
125
+ </Button>
126
+ </ButtonsContainer>
127
+ </Container>
128
+ );
129
+ };
130
+
131
+ // Styled components
132
+
133
+ const Container = styled.div`
134
+ display: flex;
135
+ flex-direction: column;
136
+ align-items: center;
137
+ image-rendering: pixelated;
138
+ `;
139
+
140
+ const ButtonsContainer = styled.div`
141
+ display: flex;
142
+ justify-content: center;
143
+ gap: 0.8rem;
144
+ width: 100%;
145
+ margin: 3rem 0 0.75rem;
146
+
147
+ button {
148
+ min-width: 95px;
149
+ font-size: 0.9rem;
150
+ }
151
+ `;
@@ -71,7 +71,7 @@ export const DailyRewardsTooltip: React.FC<IDailyRewardsTooltipProps> = ({
71
71
  <ItemContent>
72
72
  <RewardLabel>
73
73
  <Ellipsis maxWidth="100%" maxLines={2}>
74
- {formatTaskKey(reward.key ?? '')}:
74
+ {formatTaskKey(reward.key ?? reward.type)}:
75
75
  </Ellipsis>
76
76
  </RewardLabel>
77
77
  </ItemContent>
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  ICharacterDailyTask,
3
+ ICollectGlobalRewardRequest,
3
4
  ITaskIdentifier,
4
5
  TaskStatus,
5
6
  TaskType,
@@ -17,6 +18,7 @@ import { getTaskIcon } from './utils/dailyTasks.utils';
17
18
  export interface IDailyTasksProps {
18
19
  tasks: ICharacterDailyTask[];
19
20
  onClaimReward: (task: ITaskIdentifier) => void;
21
+ onClaimGlobalReward: (tasks: ICollectGlobalRewardRequest) => void;
20
22
  onClose: () => void;
21
23
  scale?: number;
22
24
  itemsAtlasJSON: Record<string, any>;
@@ -28,6 +30,7 @@ export interface IDailyTasksProps {
28
30
  export const DailyTasks: React.FC<IDailyTasksProps> = ({
29
31
  tasks,
30
32
  onClaimReward,
33
+ onClaimGlobalReward,
31
34
  onClose,
32
35
  scale = 1,
33
36
  itemsAtlasJSON,
@@ -48,12 +51,14 @@ export const DailyTasks: React.FC<IDailyTasksProps> = ({
48
51
  };
49
52
 
50
53
  const handleClaimAllRewards = () => {
51
- localTasks.forEach(task => {
52
- if (task.status === TaskStatus.Completed && !task.claimed) {
53
- const { type, key } = task;
54
- onClaimReward({ type, taskKey: key });
55
- }
56
- });
54
+ const tasksToReward = localTasks
55
+ .filter(task => task.status === TaskStatus.Completed && !task.claimed)
56
+ .map(task => ({
57
+ type: task.type,
58
+ taskKey: task.key,
59
+ }));
60
+
61
+ onClaimGlobalReward({ tasks: tasksToReward });
57
62
  };
58
63
 
59
64
  if (!size) return null;
@@ -48,7 +48,7 @@ export const TaskProgressDetails: React.FC<ITaskProgressDetailsProps> = ({
48
48
  return Object.entries((progress as ICollectProgress).collected || {}).map(
49
49
  ([key, value], index) => (
50
50
  <ProgressItem key={index}>
51
- <span>{key}:</span>
51
+ <span>{formatTaskKey(key)}:</span>
52
52
  <ProgressCount>
53
53
  {value}/
54
54
  {(task.requirements as ICollectItemsRequirement).targets.find(
package/src/index.tsx CHANGED
@@ -2,6 +2,7 @@ export * from './components/Arrow/SelectArrow';
2
2
  export * from './components/AsyncDropdown';
3
3
  export * from './components/Button';
4
4
  export * from './components/Character/CharacterSelection';
5
+ export * from './components/Character/CharacterSkinSelectionModal';
5
6
  export * from './components/Chat/Chat';
6
7
  export * from './components/Chatdeprecated/ChatDeprecated';
7
8
  export * from './components/ChatRevamp/ChatRevamp';
@@ -36,7 +36,6 @@ export const mockTasks: ICharacterDailyTask[] = [
36
36
  },
37
37
  {
38
38
  type: RewardType.Experience,
39
- key: 'exp',
40
39
  quantity: 100
41
40
  }
42
41
  ]
@@ -51,7 +50,7 @@ export const mockTasks: ICharacterDailyTask[] = [
51
50
  type: TaskType.CollectItems,
52
51
  targets: [
53
52
  {
54
- key: 'Wood',
53
+ key: 'wooden-log',
55
54
  quantity: 10
56
55
  }
57
56
  ]
@@ -73,7 +72,6 @@ export const mockTasks: ICharacterDailyTask[] = [
73
72
  },
74
73
  {
75
74
  type: RewardType.Experience,
76
- key: 'exp',
77
75
  quantity: 250
78
76
  }
79
77
  ],
@@ -112,7 +110,6 @@ export const mockTasks: ICharacterDailyTask[] = [
112
110
  },
113
111
  {
114
112
  type: RewardType.Experience,
115
- key: 'exp',
116
113
  quantity: 1000
117
114
  }
118
115
  ],
@@ -132,8 +129,6 @@ export const mockTasks: ICharacterDailyTask[] = [
132
129
  rewards: [
133
130
  {
134
131
  type: RewardType.Experience,
135
- key: 'exp',
136
- texturePath: 'others/royal-chalice.png',
137
132
  quantity: 10000
138
133
  },
139
134
  {
@@ -202,7 +197,6 @@ export const mockTasks: ICharacterDailyTask[] = [
202
197
  },
203
198
  {
204
199
  type: RewardType.Experience,
205
- key: 'exp',
206
200
  quantity: 200
207
201
  }
208
202
  ],
@@ -0,0 +1,52 @@
1
+ import { Meta, Story } from '@storybook/react';
2
+ import React from 'react';
3
+ import { RPGUIRoot } from '../../..';
4
+ import {
5
+ CharacterSkinSelectionModal,
6
+ ICharacterSkinSelectionModalProps,
7
+ } from '../../../components/Character/CharacterSkinSelectionModal';
8
+ import atlasJSON from '../../../mocks/atlas/entities/entities.json';
9
+ import atlasIMG from '../../../mocks/atlas/entities/entities.png';
10
+
11
+ const meta: Meta = {
12
+ title: 'Character/Character/Skin Selection',
13
+ component: CharacterSkinSelectionModal,
14
+ };
15
+
16
+ export default meta;
17
+
18
+ const Template: Story<ICharacterSkinSelectionModalProps> = (
19
+ args: ICharacterSkinSelectionModalProps
20
+ ) => (
21
+ <RPGUIRoot>
22
+ <CharacterSkinSelectionModal {...args} />
23
+ </RPGUIRoot>
24
+ );
25
+
26
+ export const KnightSkins = Template.bind({});
27
+
28
+ // Example of different knight skins
29
+ const knightCharacters = [
30
+ {
31
+ name: 'Black Knight',
32
+ textureKey: 'black-knight',
33
+ },
34
+ {
35
+ name: 'Dragon Knight',
36
+ textureKey: 'dragon-knight',
37
+ },
38
+ {
39
+ name: 'Senior Knight',
40
+ textureKey: 'senior-knight-1',
41
+ },
42
+ ];
43
+
44
+ KnightSkins.args = {
45
+ isOpen: true,
46
+ onClose: () => console.log('Modal closed'),
47
+ onConfirm: (textureKey: string) => console.log('Selected skin:', textureKey),
48
+ availableCharacters: knightCharacters,
49
+ atlasJSON: atlasJSON,
50
+ atlasIMG: atlasIMG,
51
+ initialSelectedSkin: 'black-knight',
52
+ };