BLADEBURNER: Change skill.canUpgrade and Skills UI (#1744)

This commit is contained in:
catloversg 2024-11-04 14:08:19 +07:00 committed by GitHub
parent 5786d7adcb
commit bc02d4f92f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 28 additions and 20 deletions

@ -153,21 +153,17 @@ export class Bladeburner implements OperationTeam {
/** Attempts to perform a skill upgrade, gives a message on both success and failure */ /** Attempts to perform a skill upgrade, gives a message on both success and failure */
upgradeSkill(skillName: BladeburnerSkillName, count = 1): Attempt<{ message: string }> { upgradeSkill(skillName: BladeburnerSkillName, count = 1): Attempt<{ message: string }> {
const currentSkillLevel = this.skills[skillName] ?? 0; const currentSkillLevel = this.skills[skillName] ?? 0;
const actualCount = currentSkillLevel + count - currentSkillLevel; const availability = Skills[skillName].canUpgrade(this, count);
if (actualCount === 0) {
return {
message: `Cannot upgrade ${skillName}: Due to floating-point inaccuracy and the small value of specified "count", your skill cannot be upgraded.`,
};
}
const availability = Skills[skillName].canUpgrade(this, actualCount);
if (!availability.available) { if (!availability.available) {
return { message: `Cannot upgrade ${skillName}: ${availability.error}` }; return { message: `Cannot upgrade ${skillName}: ${availability.error}` };
} }
this.skillPoints -= availability.cost; this.skillPoints -= availability.cost;
this.setSkillLevel(skillName, currentSkillLevel + actualCount); this.setSkillLevel(skillName, currentSkillLevel + availability.actualCount);
return { return {
success: true, success: true,
message: `Upgraded skill ${skillName} by ${actualCount} level${actualCount > 1 ? "s" : ""}`, message: `Upgraded skill ${skillName} by ${availability.actualCount} level${
availability.actualCount > 1 ? "s" : ""
}`,
}; };
} }

@ -135,19 +135,25 @@ export class Skill {
return result - 1; return result - 1;
} }
canUpgrade(bladeburner: Bladeburner, count = 1): Availability<{ cost: number }> { canUpgrade(bladeburner: Bladeburner, count = 1): Availability<{ actualCount: number; cost: number }> {
const currentLevel = bladeburner.skills[this.name] ?? 0; const currentLevel = bladeburner.skills[this.name] ?? 0;
if (!isPositiveInteger(count)) { const actualCount = currentLevel + count - currentLevel;
return { error: `Invalid upgrade count ${count}` }; if (actualCount === 0) {
return {
error: `Cannot upgrade ${this.name}: Due to floating-point inaccuracy and the small value of specified "count", your skill cannot be upgraded.`,
};
} }
if (currentLevel + count > this.maxLvl) { if (!isPositiveInteger(actualCount)) {
return { error: `Upgraded level ${currentLevel + count} exceeds max` }; return { error: `Invalid upgrade count ${actualCount}` };
} }
const cost = this.calculateCost(currentLevel, count); if (currentLevel + actualCount > this.maxLvl) {
return { error: `Upgraded level ${currentLevel + actualCount} exceeds max` };
}
const cost = this.calculateCost(currentLevel, actualCount);
if (cost > bladeburner.skillPoints) { if (cost > bladeburner.skillPoints) {
return { error: `Insufficient skill points for upgrade` }; return { error: `Insufficient skill points for upgrade` };
} }
return { available: true, cost }; return { available: true, actualCount, cost };
} }
getMultiplier(name: BladeburnerMultName): number { getMultiplier(name: BladeburnerMultName): number {

@ -18,8 +18,14 @@ export function SkillElem({ skill, bladeburner, onUpgrade }: SkillElemProps): Re
const skillName = skill.name; const skillName = skill.name;
const skillLevel = bladeburner.getSkillLevel(skillName); const skillLevel = bladeburner.getSkillLevel(skillName);
const pointCost = useMemo(() => skill.calculateCost(skillLevel), [skill, skillLevel]); const pointCost = useMemo(() => skill.calculateCost(skillLevel), [skill, skillLevel]);
// No need to support "+1" button when the skill level reaches Number.MAX_SAFE_INTEGER.
const canLevel = bladeburner.skillPoints >= pointCost; const isSupported = skillLevel < Number.MAX_SAFE_INTEGER;
// Use skill.canUpgrade() instead of reimplementing all conditional checks.
const canLevel = isSupported ? skill.canUpgrade(bladeburner, 1).available ?? false : false;
/**
* maxLvl is only useful when we check if we should show "MAX LEVEL". For the check of the icon button, we don't need
* it. This condition is checked in skill.canUpgrade().
*/
const maxLvl = skill.maxLvl ? skillLevel >= skill.maxLvl : false; const maxLvl = skill.maxLvl ? skillLevel >= skill.maxLvl : false;
function onClick(): void { function onClick(): void {
@ -31,7 +37,7 @@ export function SkillElem({ skill, bladeburner, onUpgrade }: SkillElemProps): Re
<Paper sx={{ my: 1, p: 1 }}> <Paper sx={{ my: 1, p: 1 }}>
<Box display="flex" flexDirection="row" alignItems="center"> <Box display="flex" flexDirection="row" alignItems="center">
<CopyableText variant="h6" color="primary" value={skillName} /> <CopyableText variant="h6" color="primary" value={skillName} />
{!canLevel || maxLvl ? ( {!canLevel ? (
<IconButton disabled> <IconButton disabled>
<CloseIcon /> <CloseIcon />
</IconButton> </IconButton>
@ -45,7 +51,7 @@ export function SkillElem({ skill, bladeburner, onUpgrade }: SkillElemProps): Re
{maxLvl ? ( {maxLvl ? (
<Typography>MAX LEVEL</Typography> <Typography>MAX LEVEL</Typography>
) : ( ) : (
<Typography>Skill Points required: {formatBigNumber(pointCost)}</Typography> <Typography>Skill Points required: {isSupported ? formatBigNumber(pointCost) : "N/A"}</Typography>
)} )}
<Typography>{skill.desc}</Typography> <Typography>{skill.desc}</Typography>
</Paper> </Paper>