@rpg-engine/long-bow 0.8.81 → 0.8.83
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/SkillProgressBar.d.ts +3 -1
- package/dist/components/SkillsContainer.d.ts +2 -2
- package/dist/long-bow.cjs.development.js +79 -41
- 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 +80 -42
- package/dist/long-bow.esm.js.map +1 -1
- package/package.json +2 -2
- package/src/components/SkillProgressBar.tsx +52 -18
- package/src/components/SkillsContainer.tsx +14 -13
- package/src/mocks/skills.mocks.ts +21 -9
- package/src/stories/Character/skills/SkillsContainer.stories.tsx +3 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rpg-engine/long-bow",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.83",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"typings": "dist/index.d.ts",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"dependencies": {
|
|
85
85
|
"@capacitor/core": "^6.1.0",
|
|
86
86
|
"@rollup/plugin-image": "^2.1.1",
|
|
87
|
-
"@rpg-engine/shared": "0.10.32",
|
|
87
|
+
"@rpg-engine/shared": "^0.10.32",
|
|
88
88
|
"dayjs": "^1.11.2",
|
|
89
89
|
"font-awesome": "^4.7.0",
|
|
90
90
|
"fs-extra": "^10.1.0",
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CharacterClass,
|
|
3
|
+
getLevelFromSP,
|
|
4
|
+
getSPForLevel,
|
|
5
|
+
getSPForLevelExponential,
|
|
6
|
+
getSkillConstants,
|
|
7
|
+
} from '@rpg-engine/shared';
|
|
1
8
|
import React from 'react';
|
|
2
9
|
import styled from 'styled-components';
|
|
3
10
|
import { uiColors } from '../constants/uiColors';
|
|
@@ -8,13 +15,14 @@ import { Tooltip } from './Tooltip/Tooltip';
|
|
|
8
15
|
|
|
9
16
|
export interface ISkillProgressBarProps {
|
|
10
17
|
skillName: string;
|
|
18
|
+
skillKey?: string;
|
|
19
|
+
characterClass?: CharacterClass;
|
|
11
20
|
bgColor: string;
|
|
12
21
|
level: number;
|
|
13
22
|
skillPoints: number;
|
|
14
23
|
texturePath: string;
|
|
15
24
|
showSkillPoints?: boolean;
|
|
16
25
|
skillPointsToNextLevel: number;
|
|
17
|
-
skillPointsForCurrentLevel: number;
|
|
18
26
|
atlasJSON: any;
|
|
19
27
|
atlasIMG: any;
|
|
20
28
|
buffAndDebuff?: number;
|
|
@@ -23,10 +31,11 @@ export interface ISkillProgressBarProps {
|
|
|
23
31
|
export const SkillProgressBar: React.FC<ISkillProgressBarProps> = ({
|
|
24
32
|
bgColor,
|
|
25
33
|
skillName,
|
|
34
|
+
skillKey,
|
|
35
|
+
characterClass,
|
|
26
36
|
level,
|
|
27
37
|
skillPoints: currentSkillPoints,
|
|
28
|
-
|
|
29
|
-
skillPointsForCurrentLevel,
|
|
38
|
+
|
|
30
39
|
texturePath,
|
|
31
40
|
showSkillPoints = true,
|
|
32
41
|
atlasIMG,
|
|
@@ -34,19 +43,44 @@ export const SkillProgressBar: React.FC<ISkillProgressBarProps> = ({
|
|
|
34
43
|
|
|
35
44
|
buffAndDebuff,
|
|
36
45
|
}) => {
|
|
37
|
-
//
|
|
38
|
-
const
|
|
46
|
+
// Use CharacterClass.None as default if skillKey is provided but characterClass is not
|
|
47
|
+
const effectiveClass = characterClass ?? CharacterClass.None;
|
|
48
|
+
|
|
49
|
+
// Calculate the effective level based on actual SP (handles data inconsistencies)
|
|
50
|
+
const calculateEffectiveLevel = (): number => {
|
|
51
|
+
if (!skillKey) {
|
|
52
|
+
return level; // Fallback to stored level for general "Level" display
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const { A, b, c } = getSkillConstants(skillKey, effectiveClass);
|
|
56
|
+
const actualLevel = Math.floor(getLevelFromSP(currentSkillPoints, A, b, c));
|
|
57
|
+
return Math.max(c, actualLevel); // At least starting level
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const effectiveLevel = calculateEffectiveLevel();
|
|
61
|
+
|
|
62
|
+
// Calculate progress based on actual SP position
|
|
39
63
|
const calculateProgress = (): number => {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
);
|
|
64
|
+
if (!skillKey) {
|
|
65
|
+
// Fallback for general "Level" display: simple ratio of current SP to next level
|
|
66
|
+
const spForCurrentLevel = getSPForLevel(level);
|
|
67
|
+
const spForNextLevel = getSPForLevel(level + 1);
|
|
68
|
+
const range = spForNextLevel - spForCurrentLevel;
|
|
69
|
+
const progress = currentSkillPoints - spForCurrentLevel;
|
|
70
|
+
return Math.min(100, Math.max(0, (progress / range) * 100));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const { A, b, c } = getSkillConstants(skillKey, effectiveClass);
|
|
74
|
+
|
|
75
|
+
// Calculate SP thresholds for current effective level
|
|
76
|
+
const spForEffectiveLevel = getSPForLevelExponential(effectiveLevel, A, b, c);
|
|
77
|
+
const spForNextLevel = getSPForLevelExponential(effectiveLevel + 1, A, b, c);
|
|
78
|
+
|
|
79
|
+
// Progress within current effective level
|
|
80
|
+
const range = spForNextLevel - spForEffectiveLevel;
|
|
81
|
+
const progressInLevel = currentSkillPoints - spForEffectiveLevel;
|
|
82
|
+
|
|
83
|
+
return Math.min(100, Math.max(0, (progressInLevel / Math.max(1, range)) * 100));
|
|
50
84
|
};
|
|
51
85
|
|
|
52
86
|
const progress = calculateProgress();
|
|
@@ -70,7 +104,7 @@ export const SkillProgressBar: React.FC<ISkillProgressBarProps> = ({
|
|
|
70
104
|
<TitleNameContainer>
|
|
71
105
|
<TitleNameBuff>{skillName}</TitleNameBuff>
|
|
72
106
|
<TitleNameBuff>
|
|
73
|
-
lv {
|
|
107
|
+
lv {effectiveLevel} ({skillsBuffsCalc(effectiveLevel, buffAndDebuff)})
|
|
74
108
|
</TitleNameBuff>
|
|
75
109
|
</TitleNameContainer>
|
|
76
110
|
<TitleNameBuffContainer>
|
|
@@ -84,7 +118,7 @@ export const SkillProgressBar: React.FC<ISkillProgressBarProps> = ({
|
|
|
84
118
|
<TitleNameContainer>
|
|
85
119
|
<TitleNameDebuff>{skillName}</TitleNameDebuff>
|
|
86
120
|
<TitleNameDebuff>
|
|
87
|
-
lv {
|
|
121
|
+
lv {effectiveLevel} ({skillsBuffsCalc(effectiveLevel, buffAndDebuff)})
|
|
88
122
|
</TitleNameDebuff>
|
|
89
123
|
</TitleNameContainer>
|
|
90
124
|
<div>
|
|
@@ -101,7 +135,7 @@ export const SkillProgressBar: React.FC<ISkillProgressBarProps> = ({
|
|
|
101
135
|
{!buffAndDebuff && (
|
|
102
136
|
<TitleNameContainer>
|
|
103
137
|
<TitleName>{skillName}</TitleName>
|
|
104
|
-
<ValueDisplay>lv {
|
|
138
|
+
<ValueDisplay>lv {effectiveLevel}</ValueDisplay>
|
|
105
139
|
</TitleNameContainer>
|
|
106
140
|
)}
|
|
107
141
|
</ProgressTitle>
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
|
-
CharacterClass,
|
|
3
2
|
ISkill,
|
|
4
3
|
ISkillDetails,
|
|
4
|
+
getSPForLevel,
|
|
5
5
|
getSPForLevelExponential,
|
|
6
6
|
getSkillConstants,
|
|
7
|
+
CharacterClass,
|
|
7
8
|
getXPForLevel,
|
|
8
9
|
} from '@rpg-engine/shared';
|
|
9
10
|
import React from 'react';
|
|
@@ -14,7 +15,7 @@ import { SkillProgressBar } from './SkillProgressBar';
|
|
|
14
15
|
|
|
15
16
|
export interface ISkillContainerProps {
|
|
16
17
|
skill: ISkill;
|
|
17
|
-
characterClass
|
|
18
|
+
characterClass?: CharacterClass;
|
|
18
19
|
onCloseButton: () => void;
|
|
19
20
|
atlasJSON: any;
|
|
20
21
|
atlasIMG: any;
|
|
@@ -114,22 +115,25 @@ export const SkillsContainer: React.FC<ISkillContainerProps> = ({
|
|
|
114
115
|
continue;
|
|
115
116
|
}
|
|
116
117
|
|
|
117
|
-
//
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
118
|
+
// Calculate skillPointsToNextLevel using exponential formula if characterClass available
|
|
119
|
+
const calcSkillPointsToNextLevel = (): number => {
|
|
120
|
+
if (characterClass) {
|
|
121
|
+
const { A, b, c } = getSkillConstants(key, characterClass);
|
|
122
|
+
return Math.round(getSPForLevelExponential(skillDetails.level + 1, A, b, c));
|
|
123
|
+
}
|
|
124
|
+
return Math.round(getSPForLevel(skillDetails.level + 1));
|
|
125
|
+
};
|
|
123
126
|
|
|
124
127
|
output.push(
|
|
125
128
|
<SkillProgressBar
|
|
126
129
|
key={key}
|
|
127
130
|
skillName={skillNameMap[key]}
|
|
131
|
+
skillKey={key}
|
|
132
|
+
characterClass={characterClass}
|
|
128
133
|
bgColor={skillCategoryColor}
|
|
129
134
|
level={skillDetails.level || 0}
|
|
130
135
|
skillPoints={Math.round(skillDetails.skillPoints) || 0}
|
|
131
|
-
skillPointsToNextLevel={
|
|
132
|
-
skillPointsForCurrentLevel={skillPointsForCurrentLevel}
|
|
136
|
+
skillPointsToNextLevel={calcSkillPointsToNextLevel()}
|
|
133
137
|
texturePath={value}
|
|
134
138
|
atlasIMG={atlasIMG}
|
|
135
139
|
atlasJSON={atlasJSON}
|
|
@@ -164,9 +168,6 @@ export const SkillsContainer: React.FC<ISkillContainerProps> = ({
|
|
|
164
168
|
skillPointsToNextLevel={
|
|
165
169
|
Math.round(getXPForLevel(skill.level + 1)) || 0
|
|
166
170
|
}
|
|
167
|
-
skillPointsForCurrentLevel={
|
|
168
|
-
Math.round(getXPForLevel(skill.level)) || 0
|
|
169
|
-
}
|
|
170
171
|
texturePath={'swords/broad-sword.png'}
|
|
171
172
|
atlasIMG={atlasIMG}
|
|
172
173
|
atlasJSON={atlasJSON}
|
|
@@ -2,16 +2,28 @@ import {
|
|
|
2
2
|
ISkill,
|
|
3
3
|
SkillType,
|
|
4
4
|
getSPForLevel,
|
|
5
|
+
getSPForLevelExponential,
|
|
6
|
+
getSkillConstants,
|
|
7
|
+
CharacterClass,
|
|
5
8
|
getXPForLevel,
|
|
6
9
|
} from '@rpg-engine/shared';
|
|
7
10
|
|
|
11
|
+
// Use Warrior as default character class for mock data
|
|
12
|
+
const mockCharacterClass = CharacterClass.Warrior;
|
|
13
|
+
|
|
14
|
+
// Helper function to get SP for next level using exponential formula
|
|
15
|
+
const getMockSPForNextLevel = (skillKey: string, level: number): number => {
|
|
16
|
+
const { A, b, c } = getSkillConstants(skillKey, mockCharacterClass);
|
|
17
|
+
return Math.round(getSPForLevelExponential(level, A, b, c));
|
|
18
|
+
};
|
|
19
|
+
|
|
8
20
|
export const skillMock = {
|
|
9
21
|
_id: '62aebda8785a9f0089a4f757',
|
|
10
22
|
stamina: {
|
|
11
23
|
type: SkillType.BasicAttributes,
|
|
12
24
|
level: 1,
|
|
13
25
|
skillPoints: 10,
|
|
14
|
-
skillPointsToNextLevel:
|
|
26
|
+
skillPointsToNextLevel: getMockSPForNextLevel('stamina', 2),
|
|
15
27
|
},
|
|
16
28
|
magic: {
|
|
17
29
|
type: SkillType.BasicAttributes,
|
|
@@ -43,49 +55,49 @@ export const skillMock = {
|
|
|
43
55
|
type: SkillType.BasicAttributes,
|
|
44
56
|
level: 2,
|
|
45
57
|
skillPoints: 70,
|
|
46
|
-
skillPointsToNextLevel:
|
|
58
|
+
skillPointsToNextLevel: getMockSPForNextLevel('dexterity', 3),
|
|
47
59
|
},
|
|
48
60
|
first: {
|
|
49
61
|
type: SkillType.Combat,
|
|
50
62
|
level: 1,
|
|
51
63
|
skillPoints: 22,
|
|
52
|
-
skillPointsToNextLevel:
|
|
64
|
+
skillPointsToNextLevel: getMockSPForNextLevel('first', 2),
|
|
53
65
|
},
|
|
54
66
|
club: {
|
|
55
67
|
type: SkillType.Combat,
|
|
56
68
|
level: 2,
|
|
57
69
|
skillPoints: 22,
|
|
58
|
-
skillPointsToNextLevel:
|
|
70
|
+
skillPointsToNextLevel: getMockSPForNextLevel('club', 3),
|
|
59
71
|
},
|
|
60
72
|
sword: {
|
|
61
73
|
type: SkillType.Combat,
|
|
62
74
|
level: 4,
|
|
63
75
|
skillPoints: 273,
|
|
64
|
-
skillPointsToNextLevel:
|
|
76
|
+
skillPointsToNextLevel: getMockSPForNextLevel('sword', 5),
|
|
65
77
|
},
|
|
66
78
|
dagger: {
|
|
67
79
|
type: SkillType.Combat,
|
|
68
80
|
level: 4,
|
|
69
81
|
skillPoints: 300,
|
|
70
|
-
skillPointsToNextLevel:
|
|
82
|
+
skillPointsToNextLevel: getMockSPForNextLevel('dagger', 5),
|
|
71
83
|
},
|
|
72
84
|
axe: {
|
|
73
85
|
type: SkillType.Combat,
|
|
74
86
|
level: 5,
|
|
75
87
|
skillPoints: 400,
|
|
76
|
-
skillPointsToNextLevel:
|
|
88
|
+
skillPointsToNextLevel: getMockSPForNextLevel('axe', 6),
|
|
77
89
|
},
|
|
78
90
|
distance: {
|
|
79
91
|
type: SkillType.Combat,
|
|
80
92
|
level: 4,
|
|
81
93
|
skillPoints: 76,
|
|
82
|
-
skillPointsToNextLevel:
|
|
94
|
+
skillPointsToNextLevel: getMockSPForNextLevel('distance', 5),
|
|
83
95
|
},
|
|
84
96
|
shielding: {
|
|
85
97
|
type: SkillType.Combat,
|
|
86
98
|
level: 3,
|
|
87
99
|
skillPoints: 120,
|
|
88
|
-
skillPointsToNextLevel:
|
|
100
|
+
skillPointsToNextLevel: getMockSPForNextLevel('shielding', 4),
|
|
89
101
|
},
|
|
90
102
|
fishing: {
|
|
91
103
|
type: SkillType.Gathering,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CharacterClass } from '@rpg-engine/shared';
|
|
1
2
|
import { Meta, Story } from '@storybook/react';
|
|
2
3
|
import React from 'react';
|
|
3
4
|
import { RPGUIRoot } from '../../../components/RPGUI/RPGUIRoot';
|
|
@@ -21,6 +22,7 @@ const Template: Story<ISkillContainerProps> = args => (
|
|
|
21
22
|
<SkillsContainer
|
|
22
23
|
{...args}
|
|
23
24
|
skill={skillMock}
|
|
25
|
+
characterClass={CharacterClass.Warrior}
|
|
24
26
|
onCloseButton={() => console.log('close skill container')}
|
|
25
27
|
atlasIMG={atlasIMG}
|
|
26
28
|
atlasJSON={atlasJSON}
|
|
@@ -32,4 +34,5 @@ export const Default = Template.bind([]);
|
|
|
32
34
|
|
|
33
35
|
Default.args = {
|
|
34
36
|
skill: skillMock,
|
|
37
|
+
characterClass: CharacterClass.Warrior,
|
|
35
38
|
};
|