mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-26 17:43:48 +01:00
Merge pull request #3810 from Undeemiss/multi-hash-sell
BLADEBURNER: Add batch functionality to NS spendHashes API
This commit is contained in:
commit
0d95533470
@ -467,7 +467,7 @@ export function updateHashManagerCapacity(player: IPlayer): void {
|
|||||||
player.hashManager.updateCapacity(total);
|
player.hashManager.updateCapacity(total);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget: string): boolean {
|
export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget: string, count = 1): boolean {
|
||||||
if (!(player.hashManager instanceof HashManager)) {
|
if (!(player.hashManager instanceof HashManager)) {
|
||||||
console.error(`Player does not have a HashManager`);
|
console.error(`Player does not have a HashManager`);
|
||||||
return false;
|
return false;
|
||||||
@ -475,21 +475,21 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
|||||||
|
|
||||||
// HashManager handles the transaction. This just needs to actually implement
|
// HashManager handles the transaction. This just needs to actually implement
|
||||||
// the effects of the upgrade
|
// the effects of the upgrade
|
||||||
if (player.hashManager.upgrade(upgName)) {
|
if (player.hashManager.upgrade(upgName, count)) {
|
||||||
const upg = HashUpgrades[upgName];
|
const upg = HashUpgrades[upgName];
|
||||||
|
|
||||||
switch (upgName) {
|
switch (upgName) {
|
||||||
case "Sell for Money": {
|
case "Sell for Money": {
|
||||||
player.gainMoney(upg.value, "hacknet");
|
player.gainMoney(upg.value * count, "hacknet");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "Sell for Corporation Funds": {
|
case "Sell for Corporation Funds": {
|
||||||
const corp = player.corporation;
|
const corp = player.corporation;
|
||||||
if (corp === null) {
|
if (corp === null) {
|
||||||
player.hashManager.refundUpgrade(upgName);
|
player.hashManager.refundUpgrade(upgName, count);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
corp.funds = corp.funds + upg.value;
|
corp.funds = corp.funds + upg.value * count;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "Reduce Minimum Security": {
|
case "Reduce Minimum Security": {
|
||||||
@ -497,13 +497,13 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
|||||||
const target = GetServer(upgTarget);
|
const target = GetServer(upgTarget);
|
||||||
if (target == null) {
|
if (target == null) {
|
||||||
console.error(`Invalid target specified in purchaseHashUpgrade(): ${upgTarget}`);
|
console.error(`Invalid target specified in purchaseHashUpgrade(): ${upgTarget}`);
|
||||||
return false;
|
throw new Error(`'${upgTarget}' is not a server.`);
|
||||||
}
|
}
|
||||||
if (!(target instanceof Server)) throw new Error(`'${upgTarget}' is not a normal server.`);
|
if (!(target instanceof Server)) throw new Error(`'${upgTarget}' is not a normal server.`);
|
||||||
|
|
||||||
target.changeMinimumSecurity(upg.value, true);
|
target.changeMinimumSecurity(upg.value ** count, true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
player.hashManager.refundUpgrade(upgName);
|
player.hashManager.refundUpgrade(upgName, count);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -513,13 +513,16 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
|||||||
const target = GetServer(upgTarget);
|
const target = GetServer(upgTarget);
|
||||||
if (target == null) {
|
if (target == null) {
|
||||||
console.error(`Invalid target specified in purchaseHashUpgrade(): ${upgTarget}`);
|
console.error(`Invalid target specified in purchaseHashUpgrade(): ${upgTarget}`);
|
||||||
return false;
|
throw new Error(`'${upgTarget}' is not a server.`);
|
||||||
}
|
}
|
||||||
if (!(target instanceof Server)) throw new Error(`'${upgTarget}' is not a normal server.`);
|
if (!(target instanceof Server)) throw new Error(`'${upgTarget}' is not a normal server.`);
|
||||||
|
|
||||||
|
//Manually loop the change so as to properly handle the softcap
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
target.changeMaximumMoney(upg.value);
|
target.changeMaximumMoney(upg.value);
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
player.hashManager.refundUpgrade(upgName);
|
player.hashManager.refundUpgrade(upgName, count);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -536,11 +539,11 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
|||||||
// This will throw if player doesn't have a corporation
|
// This will throw if player doesn't have a corporation
|
||||||
const corp = player.corporation;
|
const corp = player.corporation;
|
||||||
if (corp === null) {
|
if (corp === null) {
|
||||||
player.hashManager.refundUpgrade(upgName);
|
player.hashManager.refundUpgrade(upgName, count);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (const division of corp.divisions) {
|
for (const division of corp.divisions) {
|
||||||
division.sciResearch.qty += upg.value;
|
division.sciResearch.qty += upg.value * count;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -548,30 +551,31 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
|||||||
// This will throw if player isnt in Bladeburner
|
// This will throw if player isnt in Bladeburner
|
||||||
const bladeburner = player.bladeburner;
|
const bladeburner = player.bladeburner;
|
||||||
if (bladeburner === null) {
|
if (bladeburner === null) {
|
||||||
player.hashManager.refundUpgrade(upgName);
|
player.hashManager.refundUpgrade(upgName, count);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bladeburner.changeRank(player, upg.value);
|
bladeburner.changeRank(player, upg.value * count);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "Exchange for Bladeburner SP": {
|
case "Exchange for Bladeburner SP": {
|
||||||
// This will throw if player isnt in Bladeburner
|
// This will throw if player isnt in Bladeburner
|
||||||
const bladeburner = player.bladeburner;
|
const bladeburner = player.bladeburner;
|
||||||
if (bladeburner === null) {
|
if (bladeburner === null) {
|
||||||
player.hashManager.refundUpgrade(upgName);
|
player.hashManager.refundUpgrade(upgName, count);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bladeburner.skillPoints += upg.value;
|
bladeburner.skillPoints += upg.value * count;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "Generate Coding Contract": {
|
case "Generate Coding Contract": {
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
generateRandomContract();
|
generateRandomContract();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
console.warn(`Unrecognized upgrade name ${upgName}. Upgrade has no effect`);
|
console.warn(`Unrecognized upgrade name ${upgName}. Upgrade has no effect`);
|
||||||
player.hashManager.refundUpgrade(upgName);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ export class HashManager {
|
|||||||
/**
|
/**
|
||||||
* Get the cost (in hashes) of an upgrade
|
* Get the cost (in hashes) of an upgrade
|
||||||
*/
|
*/
|
||||||
getUpgradeCost(upgName: string): number {
|
getUpgradeCost(upgName: string, count = 1): number {
|
||||||
const upg = this.getUpgrade(upgName);
|
const upg = this.getUpgrade(upgName);
|
||||||
const currLevel = this.upgrades[upgName];
|
const currLevel = this.upgrades[upgName];
|
||||||
if (upg == null || currLevel == null) {
|
if (upg == null || currLevel == null) {
|
||||||
@ -81,7 +81,7 @@ export class HashManager {
|
|||||||
return Infinity;
|
return Infinity;
|
||||||
}
|
}
|
||||||
|
|
||||||
return upg.getCost(currLevel);
|
return upg.getCost(currLevel, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
prestige(): void {
|
prestige(): void {
|
||||||
@ -97,11 +97,11 @@ export class HashManager {
|
|||||||
/**
|
/**
|
||||||
* Reverts an upgrade and refunds the hashes used to buy it
|
* Reverts an upgrade and refunds the hashes used to buy it
|
||||||
*/
|
*/
|
||||||
refundUpgrade(upgName: string): void {
|
refundUpgrade(upgName: string, count = 1): void {
|
||||||
const upg = HashUpgrades[upgName];
|
const upg = HashUpgrades[upgName];
|
||||||
|
|
||||||
// Reduce the level first, so we get the right cost
|
// Reduce the level first, so we get the right cost
|
||||||
--this.upgrades[upgName];
|
this.upgrades[upgName] -= count;
|
||||||
|
|
||||||
const currLevel = this.upgrades[upgName];
|
const currLevel = this.upgrades[upgName];
|
||||||
if (upg == null || currLevel == null || currLevel < 0) {
|
if (upg == null || currLevel == null || currLevel < 0) {
|
||||||
@ -109,7 +109,7 @@ export class HashManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cost = upg.getCost(currLevel);
|
const cost = upg.getCost(currLevel, count);
|
||||||
this.hashes += cost;
|
this.hashes += cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,21 +137,21 @@ export class HashManager {
|
|||||||
* Returns boolean indicating whether or not the upgrade was successfully purchased
|
* Returns boolean indicating whether or not the upgrade was successfully purchased
|
||||||
* Note that this does NOT actually implement the effect
|
* Note that this does NOT actually implement the effect
|
||||||
*/
|
*/
|
||||||
upgrade(upgName: string): boolean {
|
upgrade(upgName: string, count = 1): boolean {
|
||||||
const upg = HashUpgrades[upgName];
|
const upg = HashUpgrades[upgName];
|
||||||
if (upg == null) {
|
if (upg == null) {
|
||||||
console.error(`Invalid Upgrade Name given to HashManager.upgrade(): ${upgName}`);
|
console.error(`Invalid Upgrade Name given to HashManager.upgrade(): ${upgName}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cost = this.getUpgradeCost(upgName);
|
const cost = this.getUpgradeCost(upgName, count);
|
||||||
|
|
||||||
if (this.hashes < cost) {
|
if (this.hashes < cost) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.hashes -= cost;
|
this.hashes -= cost;
|
||||||
++this.upgrades[upgName];
|
this.upgrades[upgName] += count;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -62,11 +62,15 @@ export class HashUpgrade {
|
|||||||
// Functions that returns the UI element to display the effect of this upgrade.
|
// Functions that returns the UI element to display the effect of this upgrade.
|
||||||
effectText: (level: number) => JSX.Element | null = () => null;
|
effectText: (level: number) => JSX.Element | null = () => null;
|
||||||
|
|
||||||
getCost(levels: number): number {
|
getCost(currentLevel: number, count = 1): number {
|
||||||
if (typeof this.cost === "number") {
|
if (typeof this.cost === "number") {
|
||||||
return this.cost;
|
return this.cost * count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Math.round((levels + 1) * this.costPerLevel);
|
//This formula is equivalent to
|
||||||
|
//(currentLevel + 1) * this.costPerLevel
|
||||||
|
//being performed repeatedly
|
||||||
|
const collapsedSum = 0.5 * count * (count + 2 * currentLevel + 1);
|
||||||
|
return this.costPerLevel * collapsedSum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,23 +188,25 @@ export function NetscriptHacknet(player: IPlayer, workerScript: WorkerScript): I
|
|||||||
},
|
},
|
||||||
hashCost:
|
hashCost:
|
||||||
(ctx: NetscriptContext) =>
|
(ctx: NetscriptContext) =>
|
||||||
(_upgName: unknown): number => {
|
(_upgName: unknown, _count: unknown = 1): number => {
|
||||||
const upgName = ctx.helper.string("upgName", _upgName);
|
const upgName = ctx.helper.string("upgName", _upgName);
|
||||||
|
const count = ctx.helper.number("count", _count);
|
||||||
if (!hasHacknetServers(player)) {
|
if (!hasHacknetServers(player)) {
|
||||||
return Infinity;
|
return Infinity;
|
||||||
}
|
}
|
||||||
|
|
||||||
return player.hashManager.getUpgradeCost(upgName);
|
return player.hashManager.getUpgradeCost(upgName, count);
|
||||||
},
|
},
|
||||||
spendHashes:
|
spendHashes:
|
||||||
(ctx: NetscriptContext) =>
|
(ctx: NetscriptContext) =>
|
||||||
(_upgName: unknown, _upgTarget: unknown = ""): boolean => {
|
(_upgName: unknown, _upgTarget: unknown = "", _count: unknown = 1): boolean => {
|
||||||
const upgName = ctx.helper.string("upgName", _upgName);
|
const upgName = ctx.helper.string("upgName", _upgName);
|
||||||
const upgTarget = ctx.helper.string("upgTarget", _upgTarget);
|
const upgTarget = ctx.helper.string("upgTarget", _upgTarget);
|
||||||
|
const count = ctx.helper.number("count", _count);
|
||||||
if (!hasHacknetServers(player)) {
|
if (!hasHacknetServers(player)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return purchaseHashUpgrade(player, upgName, upgTarget);
|
return purchaseHashUpgrade(player, upgName, upgTarget, count);
|
||||||
},
|
},
|
||||||
getHashUpgrades: () => (): string[] => {
|
getHashUpgrades: () => (): string[] => {
|
||||||
if (!hasHacknetServers(player)) {
|
if (!hasHacknetServers(player)) {
|
||||||
|
7
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
7
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
@ -2675,9 +2675,10 @@ export interface Hacknet {
|
|||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
* @param upgName - Name of the upgrade of Hacknet Node.
|
* @param upgName - Name of the upgrade of Hacknet Node.
|
||||||
|
* @param count - Number of upgrades to buy at once. Defaults to 1 if not specified.
|
||||||
* @returns Number of hashes required for the specified upgrade.
|
* @returns Number of hashes required for the specified upgrade.
|
||||||
*/
|
*/
|
||||||
hashCost(upgName: string): number;
|
hashCost(upgName: string, count?: number): number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Purchase a hash upgrade.
|
* Purchase a hash upgrade.
|
||||||
@ -2707,9 +2708,11 @@ export interface Hacknet {
|
|||||||
* ```
|
* ```
|
||||||
* @param upgName - Name of the upgrade of Hacknet Node.
|
* @param upgName - Name of the upgrade of Hacknet Node.
|
||||||
* @param upgTarget - Object to which upgrade applies. Required for certain upgrades.
|
* @param upgTarget - Object to which upgrade applies. Required for certain upgrades.
|
||||||
|
* @param count - Number of upgrades to buy at once. Defaults to 1 if not specified.
|
||||||
|
* For compatability reasons, upgTarget must be specified, even if it is not used, in order to specify count.
|
||||||
* @returns True if the upgrade is successfully purchased, and false otherwise..
|
* @returns True if the upgrade is successfully purchased, and false otherwise..
|
||||||
*/
|
*/
|
||||||
spendHashes(upgName: string, upgTarget?: string): boolean;
|
spendHashes(upgName: string, upgTarget?: string, count?: number): boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the list of hash upgrades
|
* Get the list of hash upgrades
|
||||||
|
Loading…
Reference in New Issue
Block a user