Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,7 @@ Anyway?`,
<a href="/achievement{location.search}">{t("Achievements")}</a> /
<a href="/conduct{location.search}">{t("Conducts")}</a>
</li>
<li><a href="/skill{location.search}">{t("Skills")}</a></li>
<li><a href="/proficiency{location.search}">{t("Proficiencies")}</a></li>
</ul>

Expand Down
116 changes: 116 additions & 0 deletions src/types/Skill.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,102 @@ const itemsUsingSkill = data
) as SupportedTypesWithMapped["GUN"][];
itemsUsingSkill.sort(byName);

const craftingRecipes = data
.byType("recipe")
.filter(
(r) =>
r.skill_used === item.id &&
r.result &&
data.byIdMaybe("item", r.result) &&
!r.never_learn
);

const recipesByLevel = new Map<number, typeof craftingRecipes>();
for (const recipe of craftingRecipes) {
const level = recipe.difficulty ?? 0;
if (!recipesByLevel.has(level)) recipesByLevel.set(level, []);
recipesByLevel.get(level)!.push(recipe);
}
const recipesByLevelList = [...recipesByLevel.entries()].sort(
(a, b) => a[0] - b[0]
);
recipesByLevelList.forEach(([, recipes]) => {
recipes.sort((a, b) => {
const itemA = data.byId("item", a.result!);
const itemB = data.byId("item", b.result!);
if (!itemA || !itemB) return 0; // If either item doesn't exist, consider them equal
return singularName(itemA).localeCompare(singularName(itemB));
});
});

function getRecipeLearningInfo(recipe: any, recipeLevel: number): string {
const parts = [];

// Check for autolearn
if (recipe.autolearn) {
if (Array.isArray(recipe.autolearn)) {
// Multiple skills for autolearn - check if it's just current skill at current level
if (
recipe.autolearn.length === 1 &&
recipe.autolearn[0][0] === item.id &&
recipe.autolearn[0][1] === recipeLevel
) {
parts.push("Autolearn");
} else {
const autolearns = recipe.autolearn.map(
([skill, level]: [string, number]) => {
const skillData = data.byIdMaybe("skill", skill);
const skillName = skillData ? singularName(skillData) : skill;
return `${skillName} ${level}`;
}
);
parts.push(`Autolearn ${autolearns.join(", ")}`);
}
} else {
// Single skill autolearn based on recipe difficulty
if (recipe.skill_used) {
const recipeDifficulty = recipe.difficulty ?? 0;
// If autolearn skill matches current skill and level matches the group level, just say "Autolearn"
if (recipe.skill_used === item.id && recipeDifficulty === recipeLevel) {
parts.push("Autolearn");
} else {
const skillData = data.byIdMaybe("skill", recipe.skill_used);
const skillName = skillData
? singularName(skillData)
: recipe.skill_used;
parts.push(`Autolearn ${skillName} ${recipeDifficulty}`);
}
}
}
}

// Check for book learning
const writtenIn = Array.isArray(recipe.book_learn)
? [...recipe.book_learn]
: [...Object.entries((recipe.book_learn ?? {}) as Record<string, any>)].map(
([k, v]) => [k, v.skill_level ?? v]
);

if (writtenIn.length > 0) {
if (writtenIn.length >= 3) {
parts.push(`Written in ${writtenIn.length} books`);
} else {
const bookNames = writtenIn.map(([bookId, level]) => {
const book = data.byIdMaybe("item", bookId);
const bookName = book ? singularName(book) : bookId;
return level ? `${bookName} (${level})` : bookName;
});
if (writtenIn.length === 2) {
parts.push(`Written in ${bookNames.join(" and ")}`);
} else {
parts.push(`Written in ${bookNames[0]}`);
}
}
}

return parts.length > 0 ? ` (${parts.join("; ")})` : "";
}

const practiceRecipes = data
.byType("practice")
.filter((r) => r.skill_used === item.id);
Expand Down Expand Up @@ -91,6 +187,26 @@ practiceRecipes.sort(
</section>
{/if}

{#if craftingRecipes.length}
<section>
<h1>{t("Crafting Recipes", { _context: "Skill" })}</h1>
<dl>
{#each recipesByLevelList as [level, recipes]}
<dt style="font-variant: tabular-nums">Level {level}</dt>
<dd>
<LimitedList items={recipes} let:item limit={5}>
{#if item.result}
<ThingLink id={item.result} type="item" /><span
style="color: var(--cata-color-gray)"
>{getRecipeLearningInfo(item, level)}</span>
{/if}
</LimitedList>
</dd>
{/each}
</dl>
</section>
{/if}

{#if practiceRecipes.length}
<h1>{t("Practice Recipes", { _context: "Skill" })}</h1>
{#each practiceRecipes as recipe}
Expand Down