Address review

Add ns function setToBladeburnerAction
Formatting updates
fix sleeves using player stamina
Correct supporting sleeve causing error
This commit is contained in:
rderfler 2022-04-30 15:25:36 -04:00
parent 47ce4f4927
commit 7cf21629a7
9 changed files with 97 additions and 23 deletions

@ -1264,7 +1264,7 @@ export class Bladeburner implements IBladeburner {
} }
} }
completeAction(player: IPlayer, person: IPerson, actionIdent: IActionIdentifier): ITaskTracker { completeAction(player: IPlayer, person: IPerson, actionIdent: IActionIdentifier, isPlayer = true): ITaskTracker {
let retValue = createTaskTracker(); let retValue = createTaskTracker();
switch (actionIdent.type) { switch (actionIdent.type) {
case ActionTypes["Contract"]: case ActionTypes["Contract"]:
@ -1281,10 +1281,12 @@ export class Bladeburner implements IBladeburner {
difficulty / BladeburnerConstants.DiffMultLinearFactor; difficulty / BladeburnerConstants.DiffMultLinearFactor;
const rewardMultiplier = Math.pow(action.rewardFac, action.level - 1); const rewardMultiplier = Math.pow(action.rewardFac, action.level - 1);
// Stamina loss is based on difficulty if (isPlayer) {
this.stamina -= BladeburnerConstants.BaseStaminaLoss * difficultyMultiplier; // Stamina loss is based on difficulty
if (this.stamina < 0) { this.stamina -= BladeburnerConstants.BaseStaminaLoss * difficultyMultiplier;
this.stamina = 0; if (this.stamina < 0) {
this.stamina = 0;
}
} }
// Process Contract/Operation success/failure // Process Contract/Operation success/failure

@ -100,7 +100,7 @@ export interface IBladeburner {
completeOperation(success: boolean, player: IPlayer): void; completeOperation(success: boolean, player: IPlayer): void;
getActionObject(actionId: IActionIdentifier): IAction | null; getActionObject(actionId: IActionIdentifier): IAction | null;
completeContract(success: boolean, actionIdent: IActionIdentifier): void; completeContract(success: boolean, actionIdent: IActionIdentifier): void;
completeAction(player: IPlayer, person: IPerson, actionIdent: IActionIdentifier): ITaskTracker; completeAction(player: IPlayer, person: IPerson, actionIdent: IActionIdentifier, isPlayer?: boolean): ITaskTracker;
infiltrateSynthoidCommunities(): void; infiltrateSynthoidCommunities(): void;
changeRank(player: IPlayer, change: number): void; changeRank(player: IPlayer, change: number): void;
processAction(router: IRouter, player: IPlayer, seconds: number): void; processAction(router: IRouter, player: IPlayer, seconds: number): void;

@ -282,6 +282,7 @@ const sleeve: IMap<any> = {
getSleeveAugmentations: RamCostConstants.ScriptSleeveBaseRamCost, getSleeveAugmentations: RamCostConstants.ScriptSleeveBaseRamCost,
getSleevePurchasableAugs: RamCostConstants.ScriptSleeveBaseRamCost, getSleevePurchasableAugs: RamCostConstants.ScriptSleeveBaseRamCost,
purchaseSleeveAug: RamCostConstants.ScriptSleeveBaseRamCost, purchaseSleeveAug: RamCostConstants.ScriptSleeveBaseRamCost,
setToBladeburnerAction: RamCostConstants.ScriptSleeveBaseRamCost,
}; };
// Stanek API // Stanek API

@ -310,5 +310,36 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
return player.sleeves[sleeveNumber].tryBuyAugmentation(player, aug); return player.sleeves[sleeveNumber].tryBuyAugmentation(player, aug);
}, },
setToBladeburnerAction: function (_sleeveNumber: unknown, _action: unknown, _contract?: unknown): boolean {
updateRam("setToBladeburnerAction");
const sleeveNumber = helper.number("setToBladeburnerAction", "sleeveNumber", _sleeveNumber);
const action = helper.string("setToBladeburnerAction", "action", _action);
let contract: string;
if (typeof _contract === "undefined") {
contract = "------";
} else {
contract = helper.string("setToBladeburnerAction", "contract", _contract);
}
checkSleeveAPIAccess("setToBladeburnerAction");
checkSleeveNumber("setToBladeburnerAction", sleeveNumber);
// Cannot Take on Contracts if another sleeve is performing that action
if (action === "Take on contracts") {
for (let i = 0; i < player.sleeves.length; ++i) {
if (i === sleeveNumber) {
continue;
}
const other = player.sleeves[i];
if (other.currentTask === SleeveTaskType.Bladeburner && other.bbAction === action) {
throw helper.makeRuntimeErrorMsg(
"sleeve.setToBladeburnerAction",
`Sleeve ${sleeveNumber} cannot take of contracts because Sleeve ${i} is already performing that action.`,
);
}
}
}
return player.sleeves[sleeveNumber].bladeburner(player, action, contract);
},
}; };
} }

@ -35,6 +35,8 @@ import { LocationName } from "../../Locations/data/LocationNames";
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver"; import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
import { BladeburnerConstants } from "../../Bladeburner/data/Constants"; import { BladeburnerConstants } from "../../Bladeburner/data/Constants";
import { numeralWrapper } from "../../ui/numeralFormat";
import { capitalizeFirstLetter, capitalizeEachWord } from "../../utils/StringHelperFunctions";
export class Sleeve extends Person { export class Sleeve extends Person {
/** /**
@ -221,6 +223,10 @@ export class Sleeve extends Person {
return retValue; return retValue;
} }
} else if (this.currentTask === SleeveTaskType.Bladeburner) { } else if (this.currentTask === SleeveTaskType.Bladeburner) {
if (this.currentTaskMaxTime === 0) {
this.currentTaskTime = 0;
return retValue;
}
// For bladeburner, all experience and money is gained at the end // For bladeburner, all experience and money is gained at the end
const bb = p.bladeburner; const bb = p.bladeburner;
if (bb === null) { if (bb === null) {
@ -236,10 +242,9 @@ export class Sleeve extends Person {
this.currentTaskTime = 0; this.currentTaskTime = 0;
return retValue; return retValue;
} }
let type: string; let type: string;
let name: string; let name: string;
if (this.bbAction === "Take on Contracts") { if (this.bbAction === "Take on contracts") {
type = "Contracts"; type = "Contracts";
name = this.bbContract; name = this.bbContract;
} else { } else {
@ -257,7 +262,7 @@ export class Sleeve extends Person {
const action = bb.getActionObject(actionIdent); const action = bb.getActionObject(actionIdent);
if ((action?.count ?? 0) > 0) { if ((action?.count ?? 0) > 0) {
const bbRetValue = bb.completeAction(p, this, actionIdent); const bbRetValue = bb.completeAction(p, this, actionIdent, false);
if (bbRetValue) { if (bbRetValue) {
retValue = this.gainExperience(p, bbRetValue); retValue = this.gainExperience(p, bbRetValue);
this.gainMoney(p, bbRetValue); this.gainMoney(p, bbRetValue);
@ -647,7 +652,8 @@ export class Sleeve extends Person {
if (this.currentTask == SleeveTaskType.Class) { if (this.currentTask == SleeveTaskType.Class) {
const retVal = createTaskTracker(); const retVal = createTaskTracker();
retVal.int = CONSTANTS.IntelligenceClassBaseExpGain * Math.round(this.currentTaskTime / 1000); retVal.int = CONSTANTS.IntelligenceClassBaseExpGain * Math.round(this.currentTaskTime / 1000);
this.gainExperience(p, retVal); //Wont be shared with other sleeves const r = this.gainExperience(p, retVal);
p.sleeves.filter((s) => s != this).forEach((s) => s.gainExperience(p, r, 1, true));
} }
this.earningsForTask = createTaskTracker(); this.earningsForTask = createTaskTracker();
this.gainRatesForTask = createTaskTracker(); this.gainRatesForTask = createTaskTracker();
@ -660,7 +666,7 @@ export class Sleeve extends Person {
this.gymStatType = ""; this.gymStatType = "";
this.className = ""; this.className = "";
this.bbAction = ""; this.bbAction = "";
this.bbContract = ""; this.bbContract = "------";
} }
shockRecovery(p: IPlayer): boolean { shockRecovery(p: IPlayer): boolean {
@ -1091,8 +1097,10 @@ export class Sleeve extends Person {
this.currentTaskLocation = ""; this.currentTaskLocation = "";
let time = 0; let time = 0;
this.bbContract = "------";
switch (action) { switch (action) {
case "Field Analysis": case "Field analysis":
time = this.getBladeburnerActionTime(p, "General", action); time = this.getBladeburnerActionTime(p, "General", action);
this.gainRatesForTask.hack = 20 * this.hacking_exp_mult; this.gainRatesForTask.hack = 20 * this.hacking_exp_mult;
this.gainRatesForTask.cha = 20 * this.charisma_exp_mult; this.gainRatesForTask.cha = 20 * this.charisma_exp_mult;
@ -1101,7 +1109,9 @@ export class Sleeve extends Person {
time = this.getBladeburnerActionTime(p, "General", action); time = this.getBladeburnerActionTime(p, "General", action);
this.gainRatesForTask.cha = this.gainRatesForTask.cha =
2 * BladeburnerConstants.BaseStatGain * (p.bladeburner?.getRecruitmentTime(this) ?? 0) * 1000; 2 * BladeburnerConstants.BaseStatGain * (p.bladeburner?.getRecruitmentTime(this) ?? 0) * 1000;
this.currentTaskLocation = (p.bladeburner?.getRecruitmentSuccessChance(this) ?? 0).toString() + "%"; this.currentTaskLocation = `(Success Rate: ${numeralWrapper.formatPercentage(
this.recrutmentSuccessChance(p),
)})`;
break; break;
case "Diplomacy": case "Diplomacy":
time = this.getBladeburnerActionTime(p, "General", action); time = this.getBladeburnerActionTime(p, "General", action);
@ -1114,20 +1124,24 @@ export class Sleeve extends Person {
p.bladeburner?.sleeveSupport(true); p.bladeburner?.sleeveSupport(true);
time = 0; time = 0;
break; break;
case "Take on Contracts": case "Take on contracts":
time = this.getBladeburnerActionTime(p, "Contracts", contract); time = this.getBladeburnerActionTime(p, "Contracts", contract);
this.contractGainRates(p, "Contracts", contract); this.contractGainRates(p, "Contracts", contract);
this.currentTaskLocation = this.contractSuccessChance(p, "Contracts", contract); this.currentTaskLocation = this.contractSuccessChance(p, "Contracts", contract);
this.bbContract = capitalizeEachWord(contract.toLowerCase());
break; break;
} }
this.bbAction = action; this.bbAction = capitalizeFirstLetter(action.toLowerCase());
this.bbContract = contract;
this.currentTaskMaxTime = time; this.currentTaskMaxTime = time;
this.currentTask = SleeveTaskType.Bladeburner; this.currentTask = SleeveTaskType.Bladeburner;
return true; return true;
} }
recrutmentSuccessChance(p: IPlayer): number {
return Math.max(0, Math.min(1, p.bladeburner?.getRecruitmentSuccessChance(this) ?? 0));
}
contractSuccessChance(p: IPlayer, type: string, name: string): string { contractSuccessChance(p: IPlayer, type: string, name: string): string {
const bb = p.bladeburner; const bb = p.bladeburner;
if (bb === null) { if (bb === null) {
@ -1143,7 +1157,7 @@ export class Sleeve extends Person {
if (chances[0] >= 1) { if (chances[0] >= 1) {
return "100%"; return "100%";
} else { } else {
return `${chances[0] * 100}% - ${chances[1] * 100}%`; return `${numeralWrapper.formatPercentage(chances[0])} - ${numeralWrapper.formatPercentage(chances[1])}`;
} }
} }

@ -122,8 +122,7 @@ export function SleeveElem(props: IProps): React.ReactElement {
} }
desc = ( desc = (
<> <>
This sleeve is currently attempting to {props.sleeve.bbAction} This sleeve is currently attempting to {props.sleeve.bbAction}. {message}
{message}
</> </>
); );
break; break;

@ -23,12 +23,12 @@ const universitySelectorOptions: string[] = [
const gymSelectorOptions: string[] = ["Train Strength", "Train Defense", "Train Dexterity", "Train Agility"]; const gymSelectorOptions: string[] = ["Train Strength", "Train Defense", "Train Dexterity", "Train Agility"];
const bladeburnerSelectorOptions: string[] = [ const bladeburnerSelectorOptions: string[] = [
"Field Analysis", "Field analysis",
"Recruitment", "Recruitment",
"Diplomacy", "Diplomacy",
"Infiltrate synthoids", "Infiltrate synthoids",
"Support main sleeve", "Support main sleeve",
"Take on Contracts", "Take on contracts",
]; ];
interface IProps { interface IProps {
@ -101,7 +101,7 @@ function possibleContracts(player: IPlayer, sleeve: Sleeve): string[] {
if (sleeve === otherSleeve) { if (sleeve === otherSleeve) {
continue; continue;
} }
if (otherSleeve.currentTask === SleeveTaskType.Bladeburner && otherSleeve.bbAction == "Take on Contracts") { if (otherSleeve.currentTask === SleeveTaskType.Bladeburner && otherSleeve.bbAction == "Take on contracts") {
contracts = contracts.filter((x) => x != otherSleeve.bbContract); contracts = contracts.filter((x) => x != otherSleeve.bbContract);
} }
} }
@ -202,7 +202,7 @@ const tasks: {
return { return {
first: bladeburnerSelectorOptions, first: bladeburnerSelectorOptions,
second: (s1: string) => { second: (s1: string) => {
if (s1 === "Take on Contracts") { if (s1 === "Take on contracts") {
return possibleContracts(player, sleeve); return possibleContracts(player, sleeve);
} else { } else {
return ["------"]; return ["------"];

@ -3777,6 +3777,20 @@ export interface Sleeve {
* @returns True if the aug was purchased and installed on the sleeve, false otherwise. * @returns True if the aug was purchased and installed on the sleeve, false otherwise.
*/ */
purchaseSleeveAug(sleeveNumber: number, augName: string): boolean; purchaseSleeveAug(sleeveNumber: number, augName: string): boolean;
/**
* Set a sleeve to perform bladeburner actions.
* @remarks
* RAM cost: 4 GB
*
* Return a boolean indicating whether or not the sleeve started working out.
*
* @param sleeveNumber - Index of the sleeve to workout at the gym.
* @param action - Name of the action to be performed.
* @param contract - Name of the contract if applicable.
* @returns True if the sleeve started working out, false otherwise.
*/
setToBladeburnerAction(sleeveNumber: number, action: string, contract?: string): boolean;
} }
/** /**

@ -117,6 +117,17 @@ function cyrb53(str: string, seed = 0): string {
return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(16); return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(16);
} }
function capitalizeFirstLetter(s: string): string {
return s.charAt(0).toUpperCase() + s.slice(1);
}
function capitalizeEachWord(s: string): string {
return s
.split(" ")
.map((word) => capitalizeFirstLetter(word))
.join(" ");
}
export { export {
convertTimeMsToTimeElapsedString, convertTimeMsToTimeElapsedString,
longestCommonStart, longestCommonStart,
@ -124,4 +135,6 @@ export {
formatNumber, formatNumber,
generateRandomString, generateRandomString,
cyrb53, cyrb53,
capitalizeFirstLetter,
capitalizeEachWord,
}; };