+6
-5
apps/flyff-exporter/src/scripts/skill-tree.ts
+6
-5
apps/flyff-exporter/src/scripts/skill-tree.ts
···
22
22
// remove vagrant since we don't care about that
23
23
.filter((job) => job.id !== 9686);
24
24
25
-
const skillsWithJobId = skills.map((skill) => ({
25
+
const skillTreeWithoutJobs = skills.map((skill) => ({
26
26
id: skill.id,
27
27
name: skill.name,
28
28
icon: skill.icon,
···
40
40
41
41
// here we should build the tree with just second and third jobs BUT
42
42
// the skills array should contain skills from the 1st, 2nd and 3rd job
43
-
const tree = refinedJobs
43
+
const finalTree = refinedJobs
44
44
.map((job) => ({
45
45
...job,
46
46
skills: [
47
47
// we also get the skills for the parent, which should be the 1st job
48
-
...skillsWithJobId.filter((skill) => skill.job === job.parent),
48
+
...skillTreeWithoutJobs.filter((skill) => skill.job === job.parent),
49
49
// filter for the skills that belong to the job
50
-
...skillsWithJobId.filter((skill) => skill.job === job.id),
50
+
...skillTreeWithoutJobs.filter((skill) => skill.job === job.id),
51
51
],
52
52
}))
53
+
// remove the 1st jobs after combining skills
53
54
.filter((job) => job.parent !== 9686);
54
55
55
56
await Bun.write(
56
57
"./src/exports/skill-tree.json",
57
-
JSON.stringify(tree, null, 2),
58
+
JSON.stringify(finalTree, null, 2),
58
59
);
59
60
}
60
61
+9
-9
apps/skillulator/src/main.tsx
+9
-9
apps/skillulator/src/main.tsx
···
9
9
const router = createRouter({ routeTree });
10
10
11
11
declare module "@tanstack/react-router" {
12
-
interface Register {
13
-
router: typeof router;
14
-
}
12
+
interface Register {
13
+
router: typeof router;
14
+
}
15
15
}
16
16
17
17
const rootElement = document.getElementById("root")!;
18
18
if (!rootElement.innerHTML) {
19
-
const root = ReactDOM.createRoot(rootElement);
20
-
root.render(
21
-
<React.StrictMode>
22
-
<RouterProvider router={router} />
23
-
</React.StrictMode>,
24
-
);
19
+
const root = ReactDOM.createRoot(rootElement);
20
+
root.render(
21
+
<React.StrictMode>
22
+
<RouterProvider router={router} />
23
+
</React.StrictMode>,
24
+
);
25
25
}
+4
-4
apps/skillulator/src/routes/c.$class.tsx
+4
-4
apps/skillulator/src/routes/c.$class.tsx
···
24
24
const createPreloadedSkillTree = useTreeStore(
25
25
(state) => state.createPreloadedSkillTree,
26
26
);
27
-
const setSkillPoints = useTreeStore((state) => state.setSkillPoints);
27
+
const initSkillPoints = useTreeStore((state) => state.initSkillPoints);
28
28
const skillPoints = useTreeStore((state) => state.skillPoints);
29
29
const resetSkillTree = useTreeStore((state) => state.resetSkillTree);
30
30
···
42
42
43
43
const handleLevelChange = useCallback(
44
44
(event: ChangeEvent<HTMLInputElement>) => {
45
-
setSkillPoints(jobId!, +event.target.value);
45
+
initSkillPoints(jobId!, +event.target.value);
46
46
setLevel(+event.target.value);
47
47
},
48
48
[],
···
71
71
useEffect(() => {
72
72
const code = new URLSearchParams(window.location.search).get("tree") ?? "";
73
73
if (!code) {
74
-
setSkillPoints(jobId!, level);
74
+
initSkillPoints(jobId!, level);
75
75
return;
76
76
}
77
77
···
86
86
87
87
createPreloadedSkillTree(jobId!, untangledSkillMap);
88
88
89
-
setSkillPoints(jobId!, +characterLevel!);
89
+
initSkillPoints(jobId!, +characterLevel!);
90
90
}, []);
91
91
92
92
const { i18n } = useTranslation();
+208
-208
apps/skillulator/src/utils/index.ts
+208
-208
apps/skillulator/src/utils/index.ts
···
1
-
import { State } from "../zustand/treeStore";
1
+
import type { State } from "../zustand/treeStore";
2
2
3
3
export function getJobById(jobId: number, jobs: State["jobTree"]) {
4
-
return jobs.find((job) => job.id === jobId);
4
+
return jobs.filter((job) => job.id === jobId).at(0);
5
5
}
6
6
7
7
export function getSkillById(
8
-
skillId: number,
9
-
skills: State["jobTree"][number]["skills"],
8
+
skillId: number,
9
+
skills: State["jobTree"][number]["skills"],
10
10
) {
11
-
return skills.find((skill) => skill.id === skillId);
11
+
return skills.find((skill) => skill.id === skillId);
12
12
}
13
13
14
14
export function getJobByName(jobName: string, jobs: State["jobTree"]) {
15
-
return jobs.find(
16
-
(job) => job.name.en.toLowerCase() === jobName.toLowerCase(),
17
-
);
15
+
return jobs.find(
16
+
(job) => job.name.en.toLowerCase() === jobName.toLowerCase(),
17
+
);
18
18
}
19
19
20
20
export function encodeTree(
21
-
skills: State["jobTree"][number]["skills"],
22
-
characterLevel: number,
21
+
skills: State["jobTree"][number]["skills"],
22
+
characterLevel: number,
23
23
) {
24
-
return (
25
-
skills?.map((skill) => `${skill.id}:${skill.skillLevel}`).join(",") +
26
-
`#${characterLevel}`
27
-
);
24
+
return (
25
+
skills?.map((skill) => `${skill.id}:${skill.skillLevel}`).join(",") +
26
+
`#${characterLevel}`
27
+
);
28
28
}
29
29
30
30
export function decodeTree(encodedSkills: string) {
31
-
const characterLevel = encodedSkills.split("#").at(1);
32
-
const decodedTree = encodedSkills.split("#").at(0);
33
-
return {
34
-
untangledSkillMap: decodedTree!
35
-
.split(",")
36
-
.map((skill) => skill.split(":"))
37
-
.map((s) => ({ skill: +s[0], level: +s[1] })),
38
-
characterLevel,
39
-
};
31
+
const characterLevel = encodedSkills.split("#").at(1);
32
+
const decodedTree = encodedSkills.split("#").at(0);
33
+
return {
34
+
untangledSkillMap: decodedTree!
35
+
.split(",")
36
+
.map((skill) => skill.split(":"))
37
+
.map((s) => ({ skill: +s[0], level: +s[1] })),
38
+
characterLevel,
39
+
};
40
40
}
41
41
42
42
export function getSkillPointsForLevel(characterLevel: number) {
43
-
switch (true) {
44
-
case characterLevel >= 15 && characterLevel <= 20:
45
-
return characterLevel * 2;
46
-
case characterLevel > 20 && characterLevel <= 40:
47
-
return (characterLevel - 20) * 3 + 20 * 2;
48
-
case characterLevel > 40 && characterLevel <= 60:
49
-
return (characterLevel - 40) * 4 + 20 * 3 + 20 * 2;
50
-
case characterLevel > 60 && characterLevel <= 80:
51
-
return (characterLevel - 60) * 5 + 20 * 4 + 20 * 3 + 20 * 2;
52
-
case characterLevel > 80 && characterLevel <= 100:
53
-
return (characterLevel - 80) * 6 + 20 * 5 + 20 * 4 + 20 * 3 + 20 * 2;
54
-
case characterLevel > 100 && characterLevel <= 120:
55
-
return (
56
-
(characterLevel - 100) * 7 + 20 * 6 + 20 * 5 + 20 * 4 + 20 * 3 + 20 * 2
57
-
);
58
-
case characterLevel > 120 && characterLevel <= 140:
59
-
return (
60
-
(characterLevel - 120) * 8 +
61
-
20 * 7 +
62
-
20 * 6 +
63
-
20 * 5 +
64
-
20 * 4 +
65
-
20 * 3 +
66
-
20 * 2
67
-
);
68
-
case characterLevel > 140 && characterLevel <= 150:
69
-
return (
70
-
(characterLevel - 140) * 1 +
71
-
20 * 8 +
72
-
20 * 7 +
73
-
20 * 6 +
74
-
20 * 5 +
75
-
20 * 4 +
76
-
20 * 3 +
77
-
20 * 2
78
-
);
79
-
case characterLevel > 150 && characterLevel <= 160:
80
-
return (
81
-
(characterLevel - 150) * 2 +
82
-
20 * 1 +
83
-
20 * 8 +
84
-
20 * 7 +
85
-
20 * 6 +
86
-
20 * 5 +
87
-
20 * 4 +
88
-
20 * 3 +
89
-
20 * 2
90
-
);
91
-
case characterLevel > 160 && characterLevel <= 165:
92
-
return (
93
-
(characterLevel - 160) * 2 +
94
-
20 * 1 +
95
-
20 * 8 +
96
-
20 * 7 +
97
-
20 * 6 +
98
-
20 * 5 +
99
-
20 * 4 +
100
-
20 * 3 +
101
-
20 * 2 +
102
-
20 * 2
103
-
);
104
-
default:
105
-
return 0;
106
-
}
43
+
switch (true) {
44
+
case characterLevel >= 15 && characterLevel <= 20:
45
+
return characterLevel * 2;
46
+
case characterLevel > 20 && characterLevel <= 40:
47
+
return (characterLevel - 20) * 3 + 20 * 2;
48
+
case characterLevel > 40 && characterLevel <= 60:
49
+
return (characterLevel - 40) * 4 + 20 * 3 + 20 * 2;
50
+
case characterLevel > 60 && characterLevel <= 80:
51
+
return (characterLevel - 60) * 5 + 20 * 4 + 20 * 3 + 20 * 2;
52
+
case characterLevel > 80 && characterLevel <= 100:
53
+
return (characterLevel - 80) * 6 + 20 * 5 + 20 * 4 + 20 * 3 + 20 * 2;
54
+
case characterLevel > 100 && characterLevel <= 120:
55
+
return (
56
+
(characterLevel - 100) * 7 + 20 * 6 + 20 * 5 + 20 * 4 + 20 * 3 + 20 * 2
57
+
);
58
+
case characterLevel > 120 && characterLevel <= 140:
59
+
return (
60
+
(characterLevel - 120) * 8 +
61
+
20 * 7 +
62
+
20 * 6 +
63
+
20 * 5 +
64
+
20 * 4 +
65
+
20 * 3 +
66
+
20 * 2
67
+
);
68
+
case characterLevel > 140 && characterLevel <= 150:
69
+
return (
70
+
(characterLevel - 140) * 1 +
71
+
20 * 8 +
72
+
20 * 7 +
73
+
20 * 6 +
74
+
20 * 5 +
75
+
20 * 4 +
76
+
20 * 3 +
77
+
20 * 2
78
+
);
79
+
case characterLevel > 150 && characterLevel <= 160:
80
+
return (
81
+
(characterLevel - 150) * 2 +
82
+
20 * 1 +
83
+
20 * 8 +
84
+
20 * 7 +
85
+
20 * 6 +
86
+
20 * 5 +
87
+
20 * 4 +
88
+
20 * 3 +
89
+
20 * 2
90
+
);
91
+
case characterLevel > 160 && characterLevel <= 165:
92
+
return (
93
+
(characterLevel - 160) * 2 +
94
+
20 * 1 +
95
+
20 * 8 +
96
+
20 * 7 +
97
+
20 * 6 +
98
+
20 * 5 +
99
+
20 * 4 +
100
+
20 * 3 +
101
+
20 * 2 +
102
+
20 * 2
103
+
);
104
+
default:
105
+
return 0;
106
+
}
107
107
}
108
108
109
109
// eh this could be named better lol
110
110
export const classSkillPoints = {
111
-
// elementor
112
-
9150: {
113
-
firstJobSP: 90,
114
-
secondJobSP: 300,
115
-
},
116
-
//psykeeper
117
-
5709: {
118
-
firstJobSP: 90,
119
-
secondJobSP: 90,
120
-
},
121
-
// blade
122
-
2246: {
123
-
firstJobSP: 60,
124
-
secondJobSP: 80,
125
-
},
126
-
// knight
127
-
5330: {
128
-
firstJobSP: 60,
129
-
secondJobSP: 80,
130
-
},
131
-
// billposter
132
-
7424: {
133
-
firstJobSP: 60,
134
-
secondJobSP: 120,
135
-
},
136
-
// ringmaster
137
-
9389: {
138
-
firstJobSP: 60,
139
-
secondJobSP: 100,
140
-
},
141
-
// ranger
142
-
9295: {
143
-
firstJobSP: 50,
144
-
secondJobSP: 100,
145
-
},
146
-
// jester
147
-
3545: {
148
-
firstJobSP: 50,
149
-
secondJobSP: 100,
150
-
},
111
+
// elementor
112
+
9150: {
113
+
firstJobSP: 90,
114
+
secondJobSP: 300,
115
+
},
116
+
//psykeeper
117
+
5709: {
118
+
firstJobSP: 90,
119
+
secondJobSP: 90,
120
+
},
121
+
// blade
122
+
2246: {
123
+
firstJobSP: 60,
124
+
secondJobSP: 80,
125
+
},
126
+
// knight
127
+
5330: {
128
+
firstJobSP: 60,
129
+
secondJobSP: 80,
130
+
},
131
+
// billposter
132
+
7424: {
133
+
firstJobSP: 60,
134
+
secondJobSP: 120,
135
+
},
136
+
// ringmaster
137
+
9389: {
138
+
firstJobSP: 60,
139
+
secondJobSP: 100,
140
+
},
141
+
// ranger
142
+
9295: {
143
+
firstJobSP: 50,
144
+
secondJobSP: 100,
145
+
},
146
+
// jester
147
+
3545: {
148
+
firstJobSP: 50,
149
+
secondJobSP: 100,
150
+
},
151
151
};
152
152
153
153
export function getJobTotalSkillPoints(
154
-
jobMap: typeof classSkillPoints,
155
-
jobId: number,
156
-
characterLevel: number,
154
+
jobMap: typeof classSkillPoints,
155
+
jobId: number,
156
+
characterLevel: number,
157
157
) {
158
-
if (characterLevel >= 60) {
159
-
return (
160
-
getSkillPointsForLevel(characterLevel) +
161
-
jobMap[jobId].firstJobSP +
162
-
jobMap[jobId].secondJobSP
163
-
);
164
-
}
158
+
if (characterLevel >= 60) {
159
+
return (
160
+
getSkillPointsForLevel(characterLevel) +
161
+
jobMap[jobId].firstJobSP +
162
+
jobMap[jobId].secondJobSP
163
+
);
164
+
}
165
165
166
-
return getSkillPointsForLevel(characterLevel) + jobMap[jobId].firstJobSP;
166
+
return getSkillPointsForLevel(characterLevel) + jobMap[jobId].firstJobSP;
167
167
}
168
168
169
169
export const languages = [
170
-
{
171
-
label: "en",
172
-
value: "en",
173
-
language: "English",
174
-
},
175
-
{
176
-
label: "pt-BR",
177
-
value: "br",
178
-
locale: "pt-BR",
179
-
language: "Português",
180
-
},
181
-
{
182
-
label: "zh",
183
-
value: "cns",
184
-
locale: "zh-CN",
185
-
language: "Chinese",
186
-
},
187
-
{
188
-
label: "ja",
189
-
value: "jp",
190
-
language: "Japanese",
191
-
},
192
-
{
193
-
label: "ko",
194
-
value: "kr",
195
-
language: "Korean",
196
-
},
197
-
{
198
-
label: "es",
199
-
value: "sp",
200
-
language: "Spanish",
201
-
},
202
-
{
203
-
label: "ru",
204
-
value: "ru",
205
-
language: "Russian",
206
-
},
207
-
{
208
-
label: "de",
209
-
value: "de",
210
-
language: "German",
211
-
},
212
-
{
213
-
label: "fi",
214
-
value: "fi",
215
-
language: "Finnish",
216
-
},
217
-
{
218
-
label: "id",
219
-
value: "id",
220
-
language: "Indonesian",
221
-
},
222
-
{
223
-
label: "it",
224
-
value: "it",
225
-
language: "Italian",
226
-
},
227
-
{
228
-
label: "nl",
229
-
value: "nl",
230
-
language: "Dutch",
231
-
},
232
-
{
233
-
label: "pl",
234
-
value: "pl",
235
-
language: "Polish",
236
-
},
170
+
{
171
+
label: "en",
172
+
value: "en",
173
+
language: "English",
174
+
},
175
+
{
176
+
label: "pt-BR",
177
+
value: "br",
178
+
locale: "pt-BR",
179
+
language: "Português",
180
+
},
181
+
{
182
+
label: "zh",
183
+
value: "cns",
184
+
locale: "zh-CN",
185
+
language: "Chinese",
186
+
},
187
+
{
188
+
label: "ja",
189
+
value: "jp",
190
+
language: "Japanese",
191
+
},
192
+
{
193
+
label: "ko",
194
+
value: "kr",
195
+
language: "Korean",
196
+
},
197
+
{
198
+
label: "es",
199
+
value: "sp",
200
+
language: "Spanish",
201
+
},
202
+
{
203
+
label: "ru",
204
+
value: "ru",
205
+
language: "Russian",
206
+
},
207
+
{
208
+
label: "de",
209
+
value: "de",
210
+
language: "German",
211
+
},
212
+
{
213
+
label: "fi",
214
+
value: "fi",
215
+
language: "Finnish",
216
+
},
217
+
{
218
+
label: "id",
219
+
value: "id",
220
+
language: "Indonesian",
221
+
},
222
+
{
223
+
label: "it",
224
+
value: "it",
225
+
language: "Italian",
226
+
},
227
+
{
228
+
label: "nl",
229
+
value: "nl",
230
+
language: "Dutch",
231
+
},
232
+
{
233
+
label: "pl",
234
+
value: "pl",
235
+
language: "Polish",
236
+
},
237
237
];
238
238
239
239
export function getLanguageForSkill(
240
-
langs: typeof languages,
241
-
appLanguage: string,
240
+
langs: typeof languages,
241
+
appLanguage: string,
242
242
) {
243
-
return langs.find((lang) => lang.label === appLanguage)?.value;
243
+
return langs.find((lang) => lang.label === appLanguage)?.value;
244
244
}
+117
-94
apps/skillulator/src/zustand/treeStore.ts
+117
-94
apps/skillulator/src/zustand/treeStore.ts
···
18
18
increaseSkillPoint: (jobId: number, skillId: number) => void;
19
19
increaseSkillToMax: (jobId: number, skillId: number) => void;
20
20
decreaseSkillPoint: (jobId: number, skillId: number) => void;
21
-
setSkillPoints: (jobId: number, characterLevel: number) => void;
21
+
initSkillPoints: (jobId: number, characterLevel: number) => void;
22
22
23
23
createPreloadedSkillTree: (
24
24
jobId: number,
25
-
skills: Array<Record<string, unknown>>,
25
+
skills: Array<Record<string, number>>,
26
26
) => void;
27
27
resetSkillTree: (jobId: number) => void;
28
28
};
···
33
33
skillPoints: 0,
34
34
};
35
35
36
-
export const useTreeStore = create<State & Actions>()((set, get) => ({
36
+
export const useTreeStore = create<State & Actions>()((set, _) => ({
37
37
jobTree,
38
38
classSkillPoints,
39
39
skillPoints: 0,
40
-
setSkillPoints: (jobId: number, characterLevel: number) =>
40
+
initSkillPoints: (jobId: number, characterLevel: number) =>
41
41
set(
42
42
produce((state: State) => {
43
43
// need to figure out how many skill points are already spent and subtract it
44
-
let skillPoints = getJobTotalSkillPoints(
44
+
const skillPoints = getJobTotalSkillPoints(
45
45
state.classSkillPoints,
46
46
jobId,
47
47
characterLevel,
···
49
49
50
50
let skillPointsToSubtract = 0;
51
51
const job = getJobById(jobId, state.jobTree);
52
-
console.log(get(job));
53
-
job?.skills.forEach((s) => {
54
-
skillPointsToSubtract += s.skillLevel * s.points;
55
-
});
56
-
let remainingSkillPoints = skillPoints - skillPointsToSubtract;
52
+
53
+
if (job) {
54
+
for (const skill of job.skills) {
55
+
skillPointsToSubtract += skill.skillLevel * skill.points;
56
+
}
57
+
}
58
+
59
+
const remainingSkillPoints = skillPoints - skillPointsToSubtract;
57
60
58
61
state.skillPoints = remainingSkillPoints;
59
62
return state;
···
62
65
increaseSkillPoint: (jobId: number, skillId: number) =>
63
66
set(
64
67
produce((state: State) => {
65
-
// find the job
66
68
const job = getJobById(jobId, state.jobTree);
67
-
// find skill
68
-
const skill = getSkillById(skillId, job?.skills!);
69
-
if (skill!.skillLevel === skill!.levels) return state;
70
-
if (skill!.points > state.skillPoints) return state;
71
-
skill!.skillLevel += 1;
72
-
state.skillPoints -= skill!.points;
69
+
if (job) {
70
+
const skill = getSkillById(skillId, job?.skills);
71
+
if (skill) {
72
+
if (skill.skillLevel === skill.levels) return state;
73
+
if (skill.points > state.skillPoints) return state;
74
+
skill.skillLevel += 1;
75
+
state.skillPoints -= skill.points;
76
+
}
73
77
74
-
// find all required skills
75
-
// if it's the min level, switch hasMinLevel to true
76
-
job?.skills.forEach((s) => {
77
-
const foundSkill = s.requirements.find((sz) => sz.skill === skillId);
78
-
const skillIndex = s.requirements.findIndex(
79
-
(sx) => sx.skill === skillId,
80
-
);
81
-
if (
82
-
typeof foundSkill !== "undefined" &&
83
-
foundSkill.level === skill!.skillLevel
84
-
) {
85
-
s.requirements[skillIndex].hasMinLevel = true;
78
+
// find all required skills
79
+
// if it's the min level, switch hasMinLevel to true
80
+
for (const skill of job.skills) {
81
+
const requiredSkill = skill.requirements.find(
82
+
(required) => required.skill === skillId,
83
+
);
84
+
const requiredSkillIndex = skill.requirements.findIndex(
85
+
(required) => required.skill === skillId,
86
+
);
87
+
if (
88
+
typeof requiredSkill !== "undefined" &&
89
+
requiredSkill.level === skill.skillLevel
90
+
) {
91
+
skill.requirements[requiredSkillIndex].hasMinLevel = true;
92
+
}
86
93
}
87
-
});
94
+
}
95
+
88
96
return state;
89
97
}),
90
98
),
91
99
decreaseSkillPoint: (jobId: number, skillId: number) =>
92
100
set(
93
101
produce((state: State) => {
94
-
// find the job
95
102
const job = getJobById(jobId, state.jobTree);
96
-
// find skill
97
-
const skill = getSkillById(skillId, job?.skills!);
98
-
if (skill?.skillLevel === 0) return state;
99
-
skill!.skillLevel -= 1;
100
-
state.skillPoints += skill!.points;
101
-
// find all required skills
102
-
// if the skillLevel is less than the required skills required level switch to false
103
-
job?.skills.forEach((s) => {
104
-
const foundSkill = s.requirements.find((sz) => sz.skill === skillId);
105
-
const skillIndex = s.requirements.findIndex(
106
-
(sx) => sx.skill === skillId,
107
-
);
108
-
if (
109
-
typeof foundSkill !== "undefined" &&
110
-
skill!.skillLevel < foundSkill.level
111
-
) {
112
-
s.requirements[skillIndex].hasMinLevel = false;
103
+
if (job) {
104
+
const skill = getSkillById(skillId, job.skills);
105
+
if (skill) {
106
+
if (skill.skillLevel === 0) return state;
107
+
skill.skillLevel -= 1;
108
+
state.skillPoints += skill.points;
109
+
}
110
+
111
+
// find all required skills
112
+
// if the skillLevel is less than the required skills required level switch to false
113
+
for (const skill of job.skills) {
114
+
const requiredSkill = skill.requirements.find(
115
+
(required) => required.skill === skillId,
116
+
);
117
+
const requiredSkillIndex = skill.requirements.findIndex(
118
+
(required) => required.skill === skillId,
119
+
);
120
+
if (
121
+
typeof requiredSkill !== "undefined" &&
122
+
skill.skillLevel < requiredSkill.level
123
+
) {
124
+
skill.requirements[requiredSkillIndex].hasMinLevel = false;
125
+
}
113
126
}
114
-
});
127
+
}
115
128
}),
116
129
),
117
130
createPreloadedSkillTree: (
118
131
jobId: number,
119
-
predefinedSkills: Array<Record<string, unknown>>,
132
+
predefinedSkills: Array<Record<string, number>>,
120
133
) =>
121
134
set(
122
135
produce((state: State) => {
···
124
137
// we check the skill id and level and update the skillLevel accordingly
125
138
// we also need to do the check to see if the skill is the min level
126
139
const job = getJobById(jobId, state.jobTree);
127
-
job?.skills.forEach((originalTreeSkill) => {
128
-
predefinedSkills.forEach((predefinedTreeSkill) => {
129
-
if (originalTreeSkill.id === predefinedTreeSkill.skill) {
130
-
originalTreeSkill.skillLevel = predefinedTreeSkill.level;
140
+
if (job) {
141
+
for (const originalTreeSkill of job.skills) {
142
+
for (const preloadedSkill of predefinedSkills) {
143
+
if (originalTreeSkill.id === preloadedSkill.skill) {
144
+
originalTreeSkill.skillLevel = preloadedSkill.level;
145
+
}
131
146
}
132
-
});
147
+
const skill = getSkillById(originalTreeSkill.id, job.skills);
133
148
134
-
const skill = getSkillById(originalTreeSkill.id, job?.skills!);
135
-
136
-
job?.skills.forEach((s) => {
137
-
const foundSkill = s.requirements.find(
138
-
(sz) => sz.skill === originalTreeSkill.id,
139
-
);
140
-
const skillIndex = s.requirements.findIndex(
141
-
(sx) => sx.skill === originalTreeSkill.id,
142
-
);
143
-
if (
144
-
typeof foundSkill !== "undefined" &&
145
-
foundSkill.level <= skill!.skillLevel
146
-
) {
147
-
s.requirements[skillIndex].hasMinLevel = true;
149
+
if (skill) {
150
+
for (const s of job.skills) {
151
+
const requiredSkill = s.requirements.find(
152
+
(required) => required.skill === originalTreeSkill.id,
153
+
);
154
+
const requiredSkillIndex = s.requirements.findIndex(
155
+
(required) => required.skill === originalTreeSkill.id,
156
+
);
157
+
if (
158
+
typeof requiredSkill !== "undefined" &&
159
+
requiredSkill.level <= skill.skillLevel
160
+
) {
161
+
s.requirements[requiredSkillIndex].hasMinLevel = true;
162
+
}
163
+
}
148
164
}
149
-
});
150
-
});
165
+
}
166
+
}
151
167
}),
152
168
),
153
169
increaseSkillToMax: (skillId: number, jobId: number) =>
154
170
set(
155
171
produce((state: State) => {
156
172
const job = getJobById(jobId, state.jobTree);
157
-
const skill = getSkillById(skillId, job?.skills!);
158
-
if (skill!.levels === skill!.skillLevel) return state;
159
-
if (skill!.levels * skill!.skillLevel < state.skillPoints) {
160
-
skill!.skillLevel =
161
-
state.skillPoints / skill!.points > skill!.levels
162
-
? skill!.levels
163
-
: Math.floor(+(state.skillPoints / skill!.points));
164
-
state.skillPoints -= skill!.skillLevel * skill!.points;
165
-
}
173
+
if (job) {
174
+
const skill = getSkillById(skillId, job.skills);
166
175
167
-
// refactor this block of code
168
-
job?.skills.forEach((s) => {
169
-
const foundSkill = s.requirements.find((sz) => sz.skill === skillId);
170
-
const skillIndex = s.requirements.findIndex(
171
-
(sx) => sx.skill === skillId,
172
-
);
173
-
if (
174
-
typeof foundSkill !== "undefined" &&
175
-
(foundSkill.level < skill!.skillLevel ||
176
-
foundSkill.level === skill!.skillLevel)
177
-
) {
178
-
s.requirements[skillIndex].hasMinLevel = true;
176
+
if (skill) {
177
+
if (skill.levels === skill.skillLevel) return state;
178
+
if (skill.levels * skill.skillLevel < state.skillPoints) {
179
+
skill.skillLevel =
180
+
state.skillPoints / skill.points > skill.levels
181
+
? skill.levels
182
+
: Math.floor(+(state.skillPoints / skill.points));
183
+
state.skillPoints -= skill.skillLevel * skill.points;
184
+
}
179
185
}
180
-
});
186
+
187
+
// refactor this block of code
188
+
for (const s of job.skills) {
189
+
const requiredSkill = s.requirements.find(
190
+
(required) => required.skill === skillId,
191
+
);
192
+
const requiredSkillIndex = s.requirements.findIndex(
193
+
(required) => required.skill === skillId,
194
+
);
195
+
if (
196
+
typeof requiredSkill !== "undefined" &&
197
+
(requiredSkill.level < s.skillLevel ||
198
+
requiredSkill.level === s.skillLevel)
199
+
) {
200
+
s.requirements[requiredSkillIndex].hasMinLevel = true;
201
+
}
202
+
}
203
+
}
181
204
}),
182
205
),
183
206
resetSkillTree: (jobId: number) =>
184
207
set((state: State) => {
185
-
let skillPoints = getJobTotalSkillPoints(
208
+
const skillPoints = getJobTotalSkillPoints(
186
209
state.classSkillPoints,
187
210
jobId,
188
211
15,