@rpg-engine/long-bow 0.2.6 → 0.2.8
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.
- package/dist/components/Character/CharacterSelection.d.ts +2 -3
- package/dist/components/QuestInfo/QuestInfo.d.ts +5 -6
- package/dist/components/QuestList.d.ts +11 -0
- package/dist/long-bow.cjs.development.js +140 -51
- package/dist/long-bow.cjs.development.js.map +1 -1
- package/dist/long-bow.cjs.production.min.js +1 -1
- package/dist/long-bow.cjs.production.min.js.map +1 -1
- package/dist/long-bow.esm.js +140 -51
- package/dist/long-bow.esm.js.map +1 -1
- package/dist/stories/QuestList.stories.d.ts +8 -0
- package/package.json +6 -6
- package/src/components/Character/CharacterSelection.tsx +22 -28
- package/src/components/Item/Inventory/ItemSlot.tsx +31 -11
- package/src/components/PropertySelect/PropertySelect.tsx +9 -1
- package/src/components/QuestInfo/QuestInfo.tsx +135 -42
- package/src/components/QuestList.tsx +124 -0
- package/src/mocks/equipmentSet.mocks.ts +4 -6
- package/src/mocks/itemContainer.mocks.ts +10 -33
- package/src/stories/CharacterSelection.stories.tsx +2 -4
- package/src/stories/QuestInfo.stories.tsx +64 -35
- package/src/stories/QuestList.stories.tsx +54 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { IQuestListProps } from '../components/QuestList';
|
|
3
|
+
declare const _default: {
|
|
4
|
+
title: string;
|
|
5
|
+
component: React.FC<IQuestListProps>;
|
|
6
|
+
};
|
|
7
|
+
export default _default;
|
|
8
|
+
export declare const Default: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, IQuestListProps>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rpg-engine/long-bow",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"typings": "dist/index.d.ts",
|
|
@@ -56,11 +56,11 @@
|
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@babel/core": "^7.17.7",
|
|
58
58
|
"@size-limit/preset-small-lib": "^7.0.8",
|
|
59
|
-
"@storybook/addon-essentials": "^6.5.
|
|
59
|
+
"@storybook/addon-essentials": "^6.5.10",
|
|
60
60
|
"@storybook/addon-info": "^5.3.21",
|
|
61
|
-
"@storybook/addon-links": "^6.5.
|
|
62
|
-
"@storybook/addons": "^6.5.
|
|
63
|
-
"@storybook/react": "^6.5.
|
|
61
|
+
"@storybook/addon-links": "^6.5.10",
|
|
62
|
+
"@storybook/addons": "^6.5.10",
|
|
63
|
+
"@storybook/react": "^6.5.10",
|
|
64
64
|
"@types/react": "^18.0.14",
|
|
65
65
|
"@types/react-dom": "^18.0.5",
|
|
66
66
|
"@types/styled-components": "^5.1.24",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
},
|
|
84
84
|
"dependencies": {
|
|
85
85
|
"@rollup/plugin-image": "^2.1.1",
|
|
86
|
-
"@rpg-engine/shared": "^0.4.
|
|
86
|
+
"@rpg-engine/shared": "^0.4.40",
|
|
87
87
|
"dayjs": "^1.11.2",
|
|
88
88
|
"fs-extra": "^10.1.0",
|
|
89
89
|
"lodash": "^4.17.21",
|
|
@@ -10,55 +10,49 @@ import PropertySelect, {
|
|
|
10
10
|
} from '../PropertySelect/PropertySelect';
|
|
11
11
|
|
|
12
12
|
export interface ICharacterProps {
|
|
13
|
-
id: string;
|
|
14
13
|
name: string;
|
|
15
|
-
|
|
14
|
+
textureKey: string;
|
|
16
15
|
}
|
|
17
16
|
|
|
18
17
|
export interface ICharacterSelectionProps {
|
|
19
18
|
availableCharacters: ICharacterProps[];
|
|
20
|
-
onChange: (
|
|
19
|
+
onChange: (textureKey: string) => void;
|
|
21
20
|
}
|
|
22
21
|
|
|
23
22
|
export const CharacterSelection: React.FC<ICharacterSelectionProps> = ({
|
|
24
23
|
availableCharacters,
|
|
25
24
|
onChange,
|
|
26
25
|
}) => {
|
|
27
|
-
const
|
|
28
|
-
return
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
});
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const [propertySelectValues] = useState<IPropertiesProps[]>(
|
|
37
|
-
getPropertySelectValues()
|
|
38
|
-
);
|
|
26
|
+
const propertySelectValues = availableCharacters.map(item => {
|
|
27
|
+
return {
|
|
28
|
+
id: item.textureKey,
|
|
29
|
+
name: item.name,
|
|
30
|
+
};
|
|
31
|
+
});
|
|
39
32
|
|
|
33
|
+
const [selectedValue, setSelectedValue] = useState<IPropertiesProps>();
|
|
40
34
|
const [selectedSpriteKey, setSelectedSpriteKey] = useState('');
|
|
41
|
-
const [selectedValue, setSelectedValue] = useState<IPropertiesProps>(
|
|
42
|
-
propertySelectValues[0]
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
const getSelectedCharacterSpriteKey = () => {
|
|
46
|
-
const character = availableCharacters.filter(
|
|
47
|
-
item => item.id === selectedValue.id
|
|
48
|
-
)[0];
|
|
49
|
-
return character ? character.spriteKey : '';
|
|
50
|
-
};
|
|
51
35
|
|
|
52
36
|
const onSelectedValueChange = () => {
|
|
53
|
-
const
|
|
37
|
+
const textureKey = selectedValue ? selectedValue.id : '';
|
|
38
|
+
const spriteKey = textureKey ? textureKey + '/down/standing/0.png' : '';
|
|
39
|
+
|
|
40
|
+
if (spriteKey == selectedSpriteKey) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
54
44
|
setSelectedSpriteKey(spriteKey);
|
|
55
|
-
onChange(
|
|
45
|
+
onChange(textureKey);
|
|
56
46
|
};
|
|
57
47
|
|
|
58
48
|
useEffect(() => {
|
|
59
49
|
onSelectedValueChange();
|
|
60
50
|
}, [selectedValue]);
|
|
61
51
|
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
setSelectedValue(propertySelectValues[0]);
|
|
54
|
+
}, [availableCharacters]);
|
|
55
|
+
|
|
62
56
|
return (
|
|
63
57
|
<Container>
|
|
64
58
|
{selectedSpriteKey && (
|
|
@@ -70,7 +64,7 @@ export const CharacterSelection: React.FC<ICharacterSelectionProps> = ({
|
|
|
70
64
|
height={50}
|
|
71
65
|
width={50}
|
|
72
66
|
containerStyle={{
|
|
73
|
-
padding: '25px 10px 5px
|
|
67
|
+
padding: '25px 10px 5px 27px',
|
|
74
68
|
}}
|
|
75
69
|
/>
|
|
76
70
|
)}
|
|
@@ -83,9 +83,23 @@ export const ItemSlot: React.FC<IProps> = observer(
|
|
|
83
83
|
return '2.5rem';
|
|
84
84
|
};
|
|
85
85
|
|
|
86
|
+
const getStackInfo = (itemId: string, stackQty: number) => {
|
|
87
|
+
// if (itemToRender?.isStackable && itemToRender?.stackQty) {
|
|
88
|
+
if (stackQty > 1) {
|
|
89
|
+
return (
|
|
90
|
+
<ItemQty left={getLeftPositionValue(stackQty)} key={`qty-${itemId}`}>
|
|
91
|
+
{' '}
|
|
92
|
+
{stackQty}{' '}
|
|
93
|
+
</ItemQty>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
return undefined;
|
|
97
|
+
};
|
|
98
|
+
|
|
86
99
|
const renderItem = (itemToRender: IItem | null) => {
|
|
87
100
|
const element = [];
|
|
88
101
|
if (itemToRender?.texturePath) {
|
|
102
|
+
console.table(itemToRender);
|
|
89
103
|
element.push(
|
|
90
104
|
<SpriteFromAtlas
|
|
91
105
|
key={itemToRender._id}
|
|
@@ -96,17 +110,14 @@ export const ItemSlot: React.FC<IProps> = observer(
|
|
|
96
110
|
/>
|
|
97
111
|
);
|
|
98
112
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
{' '}
|
|
106
|
-
{itemToRender.stackQty}{' '}
|
|
107
|
-
</ItemQty>
|
|
108
|
-
);
|
|
113
|
+
const stackInfo = getStackInfo(
|
|
114
|
+
itemToRender?._id ?? '',
|
|
115
|
+
itemToRender?.stackQty ?? 0
|
|
116
|
+
);
|
|
117
|
+
if (stackInfo) {
|
|
118
|
+
element.push(stackInfo);
|
|
109
119
|
}
|
|
120
|
+
|
|
110
121
|
return element;
|
|
111
122
|
};
|
|
112
123
|
|
|
@@ -115,7 +126,8 @@ export const ItemSlot: React.FC<IProps> = observer(
|
|
|
115
126
|
itemToRender?.texturePath &&
|
|
116
127
|
itemToRender.allowedEquipSlotType?.includes(slotSpriteMask!)
|
|
117
128
|
) {
|
|
118
|
-
|
|
129
|
+
const element = [];
|
|
130
|
+
element.push(
|
|
119
131
|
<SpriteFromAtlas
|
|
120
132
|
key={itemToRender._id}
|
|
121
133
|
atlasIMG={atlasIMG}
|
|
@@ -124,6 +136,14 @@ export const ItemSlot: React.FC<IProps> = observer(
|
|
|
124
136
|
imgScale={3}
|
|
125
137
|
/>
|
|
126
138
|
);
|
|
139
|
+
const stackInfo = getStackInfo(
|
|
140
|
+
itemToRender?._id ?? '',
|
|
141
|
+
itemToRender?.stackQty ?? 0
|
|
142
|
+
);
|
|
143
|
+
if (stackInfo) {
|
|
144
|
+
element.push(stackInfo);
|
|
145
|
+
}
|
|
146
|
+
return element;
|
|
127
147
|
} else {
|
|
128
148
|
return (
|
|
129
149
|
<SpriteFromAtlas
|
|
@@ -37,10 +37,18 @@ export const PropertySelect: React.FC<IPropertySelectProps> = ({
|
|
|
37
37
|
onChange(availableProperties[currentIndex]);
|
|
38
38
|
}, [currentIndex]);
|
|
39
39
|
|
|
40
|
+
const getCurrentSelectionName = () => {
|
|
41
|
+
const item = availableProperties[currentIndex];
|
|
42
|
+
if (item) {
|
|
43
|
+
return item.name;
|
|
44
|
+
}
|
|
45
|
+
return '';
|
|
46
|
+
};
|
|
47
|
+
|
|
40
48
|
return (
|
|
41
49
|
<Container>
|
|
42
50
|
<TextOverlay>
|
|
43
|
-
<Item>{
|
|
51
|
+
<Item>{getCurrentSelectionName()}</Item>
|
|
44
52
|
</TextOverlay>
|
|
45
53
|
<div className="rpgui-progress-track"></div>
|
|
46
54
|
<LeftArrow onClick={onLeftClick}></LeftArrow>
|
|
@@ -1,33 +1,45 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { IQuest } from '@rpg-engine/shared';
|
|
2
|
+
import React, { useState } from 'react';
|
|
2
3
|
import styled from 'styled-components';
|
|
3
4
|
import { Button, ButtonTypes } from '../Button';
|
|
4
5
|
import { DraggableContainer } from '../DraggableContainer';
|
|
6
|
+
import LeftArrowClickIcon from '../PropertySelect/img/ui-arrows/arrow01-left-clicked.png';
|
|
7
|
+
import LeftArrowIcon from '../PropertySelect/img/ui-arrows/arrow01-left.png';
|
|
8
|
+
import RightArrowClickIcon from '../PropertySelect/img/ui-arrows/arrow01-right-clicked.png';
|
|
9
|
+
import RightArrowIcon from '../PropertySelect/img/ui-arrows/arrow01-right.png';
|
|
5
10
|
import { RPGUIContainerTypes } from '../RPGUIContainer';
|
|
6
11
|
import { Column } from '../shared/Column';
|
|
7
|
-
|
|
8
12
|
import thumbnailDefault from './img/default.png';
|
|
9
13
|
|
|
10
14
|
export interface IQuestInfoProps {
|
|
11
|
-
title: string;
|
|
12
|
-
children: React.ReactNode;
|
|
13
15
|
onClose?: () => void;
|
|
14
|
-
button?: Array<
|
|
15
|
-
|
|
16
|
+
button?: Array<IQuestsButtonProps>;
|
|
17
|
+
quests: IQuest[];
|
|
16
18
|
}
|
|
17
19
|
|
|
18
|
-
export interface
|
|
20
|
+
export interface IQuestsButtonProps {
|
|
19
21
|
disabled: boolean;
|
|
20
22
|
title: string;
|
|
21
|
-
onClick: () => void;
|
|
23
|
+
onClick: (QuestId: string, NPCId: string) => void;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
export const QuestInfo: React.FC<IQuestInfoProps> = ({
|
|
25
|
-
|
|
27
|
+
quests,
|
|
26
28
|
onClose,
|
|
27
29
|
button,
|
|
28
|
-
thumbnail,
|
|
29
|
-
children,
|
|
30
30
|
}) => {
|
|
31
|
+
const [currentIndex, setCurrentIndex] = useState(0);
|
|
32
|
+
const questsLength = quests.length - 1;
|
|
33
|
+
|
|
34
|
+
const onLeftClick = () => {
|
|
35
|
+
if (currentIndex === 0) setCurrentIndex(questsLength);
|
|
36
|
+
else setCurrentIndex(index => index - 1);
|
|
37
|
+
};
|
|
38
|
+
const onRightClick = () => {
|
|
39
|
+
if (currentIndex === questsLength) setCurrentIndex(0);
|
|
40
|
+
else setCurrentIndex(index => index + 1);
|
|
41
|
+
};
|
|
42
|
+
|
|
31
43
|
return (
|
|
32
44
|
<QuestDraggableContainer
|
|
33
45
|
type={RPGUIContainerTypes.Framed}
|
|
@@ -37,32 +49,81 @@ export const QuestInfo: React.FC<IQuestInfoProps> = ({
|
|
|
37
49
|
width="730px"
|
|
38
50
|
cancelDrag=".equipment-container-body"
|
|
39
51
|
>
|
|
40
|
-
{
|
|
41
|
-
<
|
|
42
|
-
<
|
|
43
|
-
|
|
44
|
-
{
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
52
|
+
{quests.length >= 2 ? (
|
|
53
|
+
<QuestsContainer>
|
|
54
|
+
{currentIndex !== 0 && <LeftArrow onClick={onLeftClick}></LeftArrow>}
|
|
55
|
+
{currentIndex !== quests.length - 1 && (
|
|
56
|
+
<RightArrow onClick={onRightClick}></RightArrow>
|
|
57
|
+
)}
|
|
58
|
+
|
|
59
|
+
<QuestContainer>
|
|
60
|
+
<TitleContainer className="drag-handler">
|
|
61
|
+
<Title>
|
|
62
|
+
<Thumbnail
|
|
63
|
+
src={quests[currentIndex].thumbnail || thumbnailDefault}
|
|
64
|
+
/>
|
|
65
|
+
{quests[currentIndex].title}
|
|
66
|
+
</Title>
|
|
67
|
+
<QuestSplitDiv>
|
|
68
|
+
<hr className="golden" />
|
|
69
|
+
</QuestSplitDiv>
|
|
70
|
+
</TitleContainer>
|
|
71
|
+
<Content>
|
|
72
|
+
<p>{quests[currentIndex].description}</p>
|
|
73
|
+
</Content>
|
|
74
|
+
<QuestColumn className="dark-background" justifyContent="flex-end">
|
|
75
|
+
{button &&
|
|
76
|
+
button.map((item, index) => (
|
|
77
|
+
<Button
|
|
78
|
+
key={index}
|
|
79
|
+
onClick={() =>
|
|
80
|
+
item.onClick(
|
|
81
|
+
quests[currentIndex]._id,
|
|
82
|
+
quests[currentIndex].npcId
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
disabled={item.disabled}
|
|
86
|
+
buttonType={ButtonTypes.RPGUIButton}
|
|
87
|
+
id={`button-${index}`}
|
|
88
|
+
>
|
|
89
|
+
{item.title}
|
|
90
|
+
</Button>
|
|
91
|
+
))}
|
|
92
|
+
</QuestColumn>
|
|
93
|
+
</QuestContainer>
|
|
94
|
+
</QuestsContainer>
|
|
95
|
+
) : (
|
|
96
|
+
<QuestsContainer>
|
|
97
|
+
<QuestContainer>
|
|
98
|
+
<TitleContainer className="drag-handler">
|
|
99
|
+
<Title>
|
|
100
|
+
<Thumbnail src={quests[0].thumbnail || thumbnailDefault} />
|
|
101
|
+
{quests[0].title}
|
|
102
|
+
</Title>
|
|
103
|
+
<QuestSplitDiv>
|
|
104
|
+
<hr className="golden" />
|
|
105
|
+
</QuestSplitDiv>
|
|
106
|
+
</TitleContainer>
|
|
107
|
+
<Content>
|
|
108
|
+
<p>{quests[0].description}</p>
|
|
109
|
+
</Content>
|
|
110
|
+
<QuestColumn className="dark-background" justifyContent="flex-end">
|
|
111
|
+
{button &&
|
|
112
|
+
button.map((item, index) => (
|
|
113
|
+
<Button
|
|
114
|
+
key={index}
|
|
115
|
+
onClick={() => item.onClick(quests[0]._id, quests[0].npcId)}
|
|
116
|
+
disabled={item.disabled}
|
|
117
|
+
buttonType={ButtonTypes.RPGUIButton}
|
|
118
|
+
id={`button-${index}`}
|
|
119
|
+
>
|
|
120
|
+
{item.title}
|
|
121
|
+
</Button>
|
|
122
|
+
))}
|
|
123
|
+
</QuestColumn>
|
|
124
|
+
</QuestContainer>
|
|
125
|
+
</QuestsContainer>
|
|
50
126
|
)}
|
|
51
|
-
<Content>{children}</Content>
|
|
52
|
-
<QuestColumn className="dark-background" justifyContent="flex-end">
|
|
53
|
-
{button &&
|
|
54
|
-
button.map((item, index) => (
|
|
55
|
-
<Button
|
|
56
|
-
key={index}
|
|
57
|
-
onClick={item.onClick}
|
|
58
|
-
disabled={item.disabled}
|
|
59
|
-
buttonType={ButtonTypes.RPGUIButton}
|
|
60
|
-
id={`button-${index}`}
|
|
61
|
-
>
|
|
62
|
-
{item.title}
|
|
63
|
-
</Button>
|
|
64
|
-
))}
|
|
65
|
-
</QuestColumn>
|
|
66
127
|
</QuestDraggableContainer>
|
|
67
128
|
);
|
|
68
129
|
};
|
|
@@ -71,7 +132,6 @@ const QuestDraggableContainer = styled(DraggableContainer)`
|
|
|
71
132
|
border: 1px solid black;
|
|
72
133
|
width: 600px;
|
|
73
134
|
height: 500px;
|
|
74
|
-
overflow-y: scroll;
|
|
75
135
|
padding: 0 0 0 0 !important;
|
|
76
136
|
.DraggableContainer__TitleContainer-sc-184mpyl-2 {
|
|
77
137
|
height: auto;
|
|
@@ -79,7 +139,7 @@ const QuestDraggableContainer = styled(DraggableContainer)`
|
|
|
79
139
|
.container-close {
|
|
80
140
|
position: sticky;
|
|
81
141
|
margin-left: auto;
|
|
82
|
-
top:
|
|
142
|
+
top: 20px;
|
|
83
143
|
padding-right: 5px;
|
|
84
144
|
}
|
|
85
145
|
img {
|
|
@@ -89,6 +149,16 @@ const QuestDraggableContainer = styled(DraggableContainer)`
|
|
|
89
149
|
}
|
|
90
150
|
`;
|
|
91
151
|
|
|
152
|
+
const QuestContainer = styled.div`
|
|
153
|
+
margin-right: 40px;
|
|
154
|
+
margin-left: 40px;
|
|
155
|
+
`;
|
|
156
|
+
|
|
157
|
+
const QuestsContainer = styled.div`
|
|
158
|
+
display: flex;
|
|
159
|
+
align-items: center;
|
|
160
|
+
`;
|
|
161
|
+
|
|
92
162
|
const Content = styled.div`
|
|
93
163
|
padding: 18px;
|
|
94
164
|
h1 {
|
|
@@ -113,14 +183,13 @@ const QuestSplitDiv = styled.div`
|
|
|
113
183
|
const QuestColumn = styled(Column)`
|
|
114
184
|
background: #4e4a4e;
|
|
115
185
|
padding-top: 5px;
|
|
116
|
-
|
|
117
|
-
|
|
186
|
+
margin-bottom: 20px;
|
|
187
|
+
display: flex;
|
|
188
|
+
justify-content: space-evenly;
|
|
118
189
|
`;
|
|
119
190
|
|
|
120
191
|
const TitleContainer = styled.div`
|
|
121
192
|
background: #4e4a4e;
|
|
122
|
-
position: sticky;
|
|
123
|
-
top: 0;
|
|
124
193
|
width: 100%;
|
|
125
194
|
display: flex;
|
|
126
195
|
flex-wrap: wrap;
|
|
@@ -141,3 +210,27 @@ const Thumbnail = styled.img`
|
|
|
141
210
|
width: 64px;
|
|
142
211
|
margin-right: 0.5rem;
|
|
143
212
|
`;
|
|
213
|
+
|
|
214
|
+
const LeftArrow = styled.div`
|
|
215
|
+
background-image: url(${LeftArrowIcon});
|
|
216
|
+
background-size: 100% 100%;
|
|
217
|
+
left: 0;
|
|
218
|
+
position: absolute;
|
|
219
|
+
width: 40px;
|
|
220
|
+
height: 42px;
|
|
221
|
+
:active {
|
|
222
|
+
background-image: url(${LeftArrowClickIcon});
|
|
223
|
+
}
|
|
224
|
+
`;
|
|
225
|
+
|
|
226
|
+
const RightArrow = styled.div`
|
|
227
|
+
background-image: url(${RightArrowIcon});
|
|
228
|
+
right: 0;
|
|
229
|
+
position: absolute;
|
|
230
|
+
width: 40px;
|
|
231
|
+
background-size: 100% 100%;
|
|
232
|
+
height: 42px;
|
|
233
|
+
:active {
|
|
234
|
+
background-image: url(${RightArrowClickIcon});
|
|
235
|
+
}
|
|
236
|
+
`;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import React, { useLayoutEffect, useState } from 'react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
import { DraggableContainer } from './DraggableContainer';
|
|
4
|
+
import { ProgressBar } from './ProgressBar';
|
|
5
|
+
import { RPGUIContainerTypes } from './RPGUIContainer';
|
|
6
|
+
|
|
7
|
+
export interface IQuestListProps {
|
|
8
|
+
title: string;
|
|
9
|
+
description: string;
|
|
10
|
+
quests: { title: string; description: string; completed: boolean }[];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const QuestList: React.FC<IQuestListProps> = ({ quests }) => {
|
|
14
|
+
const [completedQuestsPercentage, setCompletedQuestsPercentage] = useState(0);
|
|
15
|
+
|
|
16
|
+
useLayoutEffect(() => {
|
|
17
|
+
const totalQuests = quests.length;
|
|
18
|
+
const completedQuests = quests.filter(({ completed }) => completed).length;
|
|
19
|
+
|
|
20
|
+
const percentage = Math.floor((completedQuests / totalQuests) * 100);
|
|
21
|
+
|
|
22
|
+
setCompletedQuestsPercentage(percentage);
|
|
23
|
+
}, []);
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<QuestDraggableContainer
|
|
27
|
+
type={RPGUIContainerTypes.Framed}
|
|
28
|
+
onCloseButton={() => {}}
|
|
29
|
+
width="520px"
|
|
30
|
+
>
|
|
31
|
+
<div style={{ width: '100%' }}>
|
|
32
|
+
<Title>Quests</Title>
|
|
33
|
+
<hr className="golden" />
|
|
34
|
+
|
|
35
|
+
<QuestListContainer>
|
|
36
|
+
{quests.map(({ title, description, completed }, i) => (
|
|
37
|
+
<div className="quest-item" key={i}>
|
|
38
|
+
<span className={`quest-number ${completed ? 'completed' : ''}`}>
|
|
39
|
+
{i + 1}
|
|
40
|
+
</span>
|
|
41
|
+
<div className="quest-detail">
|
|
42
|
+
<p className="quest-detail__title">{title}</p>
|
|
43
|
+
<p className="quest-detail__description">{description}</p>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
))}
|
|
47
|
+
</QuestListContainer>
|
|
48
|
+
|
|
49
|
+
<ProgressBar max={100} value={completedQuestsPercentage} color="blue" />
|
|
50
|
+
</div>
|
|
51
|
+
</QuestDraggableContainer>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const QuestDraggableContainer = styled(DraggableContainer)`
|
|
56
|
+
.container-close {
|
|
57
|
+
top: 10px;
|
|
58
|
+
right: 10px;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.quest-title {
|
|
62
|
+
text-align: left;
|
|
63
|
+
margin-left: 44px;
|
|
64
|
+
margin-top: 20px;
|
|
65
|
+
color: yellow;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.quest-desc {
|
|
69
|
+
margin-top: 12px;
|
|
70
|
+
margin-left: 44px;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.rpgui-progress {
|
|
74
|
+
min-width: 80%;
|
|
75
|
+
margin: 0 auto;
|
|
76
|
+
}
|
|
77
|
+
`;
|
|
78
|
+
|
|
79
|
+
const Title = styled.h1`
|
|
80
|
+
z-index: 22;
|
|
81
|
+
font-size: 0.6rem;
|
|
82
|
+
color: yellow !important;
|
|
83
|
+
`;
|
|
84
|
+
|
|
85
|
+
const QuestListContainer = styled.div`
|
|
86
|
+
margin-top: 20px;
|
|
87
|
+
margin-bottom: 40px;
|
|
88
|
+
overflow-y: auto;
|
|
89
|
+
max-height: 400px;
|
|
90
|
+
|
|
91
|
+
.quest-item {
|
|
92
|
+
display: flex;
|
|
93
|
+
align-items: flex-start;
|
|
94
|
+
margin-bottom: 12px;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.quest-number {
|
|
98
|
+
border-radius: 50%;
|
|
99
|
+
width: 28px;
|
|
100
|
+
height: 28px;
|
|
101
|
+
display: flex;
|
|
102
|
+
align-items: center;
|
|
103
|
+
justify-content: center;
|
|
104
|
+
margin-right: 16px;
|
|
105
|
+
background-color: brown;
|
|
106
|
+
flex-shrink: 0;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.quest-number.completed {
|
|
110
|
+
background-color: yellow;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
p {
|
|
114
|
+
margin: 0;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.quest-detail__title {
|
|
118
|
+
color: yellow;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.quest-detail__description {
|
|
122
|
+
margin-top: 5px;
|
|
123
|
+
}
|
|
124
|
+
`;
|
|
@@ -78,7 +78,7 @@ export const items: any = {
|
|
|
78
78
|
isEquipable: false,
|
|
79
79
|
isStackable: false,
|
|
80
80
|
maxStackSize: 99,
|
|
81
|
-
|
|
81
|
+
|
|
82
82
|
isUsable: true,
|
|
83
83
|
isStorable: true,
|
|
84
84
|
layer: 1,
|
|
@@ -140,7 +140,6 @@ export const items: any = {
|
|
|
140
140
|
isEquipable: false,
|
|
141
141
|
isStackable: false,
|
|
142
142
|
maxStackSize: 999,
|
|
143
|
-
stackQty: 171,
|
|
144
143
|
isUsable: true,
|
|
145
144
|
isStorable: true,
|
|
146
145
|
layer: 1,
|
|
@@ -171,7 +170,7 @@ export const items: any = {
|
|
|
171
170
|
isEquipable: false,
|
|
172
171
|
isStackable: false,
|
|
173
172
|
maxStackSize: 999,
|
|
174
|
-
|
|
173
|
+
|
|
175
174
|
isUsable: false,
|
|
176
175
|
isStorable: true,
|
|
177
176
|
layer: 1,
|
|
@@ -202,7 +201,7 @@ export const items: any = {
|
|
|
202
201
|
isEquipable: false,
|
|
203
202
|
isStackable: false,
|
|
204
203
|
maxStackSize: 999,
|
|
205
|
-
|
|
204
|
+
|
|
206
205
|
isUsable: false,
|
|
207
206
|
isStorable: true,
|
|
208
207
|
layer: 1,
|
|
@@ -233,7 +232,7 @@ export const items: any = {
|
|
|
233
232
|
isEquipable: false,
|
|
234
233
|
isStackable: false,
|
|
235
234
|
maxStackSize: 999,
|
|
236
|
-
|
|
235
|
+
|
|
237
236
|
isUsable: false,
|
|
238
237
|
isStorable: true,
|
|
239
238
|
layer: 1,
|
|
@@ -264,7 +263,6 @@ export const items: any = {
|
|
|
264
263
|
isEquipable: false,
|
|
265
264
|
isStackable: false,
|
|
266
265
|
maxStackSize: 999,
|
|
267
|
-
stackQty: 171,
|
|
268
266
|
isUsable: true,
|
|
269
267
|
isStorable: true,
|
|
270
268
|
layer: 1,
|