mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2025-01-03 11:57:34 +01:00
Almost done converting blade to react.
This commit is contained in:
parent
cc8de58cff
commit
4865563f26
@ -89,6 +89,32 @@ import {
|
|||||||
completeAction,
|
completeAction,
|
||||||
processAction,
|
processAction,
|
||||||
startAction,
|
startAction,
|
||||||
|
calculateStaminaGainPerSecond,
|
||||||
|
calculateMaxStamina,
|
||||||
|
create,
|
||||||
|
prestige,
|
||||||
|
storeCycles,
|
||||||
|
getCurrentCity,
|
||||||
|
upgradeSkill,
|
||||||
|
postToConsole,
|
||||||
|
log,
|
||||||
|
calculateStaminaPenalty,
|
||||||
|
getTypeAndNameFromActionId,
|
||||||
|
getContractNamesNetscriptFn,
|
||||||
|
getOperationNamesNetscriptFn,
|
||||||
|
getBlackOpNamesNetscriptFn,
|
||||||
|
getGeneralActionNamesNetscriptFn,
|
||||||
|
getSkillNamesNetscriptFn,
|
||||||
|
startActionNetscriptFn,
|
||||||
|
getActionTimeNetscriptFn,
|
||||||
|
getActionEstimatedSuccessChanceNetscriptFn,
|
||||||
|
getActionCountRemainingNetscriptFn,
|
||||||
|
getSkillLevelNetscriptFn,
|
||||||
|
getSkillUpgradeCostNetscriptFn,
|
||||||
|
upgradeSkillNetscriptFn,
|
||||||
|
getTeamSizeNetscriptFn,
|
||||||
|
setTeamSizeNetscriptFn,
|
||||||
|
joinBladeburnerFactionNetscriptFn,
|
||||||
} from "./Bladeburner/Bladeburner";
|
} from "./Bladeburner/Bladeburner";
|
||||||
|
|
||||||
function Bladeburner(params={}) {
|
function Bladeburner(params={}) {
|
||||||
@ -130,7 +156,7 @@ function Bladeburner(params={}) {
|
|||||||
// Max Stamina is based on stats and Bladeburner-specific bonuses
|
// Max Stamina is based on stats and Bladeburner-specific bonuses
|
||||||
this.staminaBonus = 0; // Gained from training
|
this.staminaBonus = 0; // Gained from training
|
||||||
this.maxStamina = 0;
|
this.maxStamina = 0;
|
||||||
this.calculateMaxStamina();
|
calculateMaxStamina(this, Player);
|
||||||
this.stamina = this.maxStamina;
|
this.stamina = this.maxStamina;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -168,622 +194,40 @@ function Bladeburner(params={}) {
|
|||||||
];
|
];
|
||||||
|
|
||||||
// Initialization
|
// Initialization
|
||||||
if (params.new) {this.create();}
|
if (params.new) create(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Bladeburner.prototype.prestige = function() {
|
Bladeburner.prototype.prestige = function() { prestige(this); }
|
||||||
resetAction(this);
|
Bladeburner.prototype.storeCycles = function(numCycles=1) { storeCycles(this, numCycles); }
|
||||||
var bladeburnerFac = Factions["Bladeburners"];
|
Bladeburner.prototype.calculateStaminaPenalty = function() { return calculateStaminaPenalty(this); }
|
||||||
if (this.rank >= BladeburnerConstants.RankNeededForFaction) {
|
Bladeburner.prototype.getCurrentCity = function() { return getCurrentCity(this); }
|
||||||
joinFaction(bladeburnerFac);
|
Bladeburner.prototype.upgradeSkill = function(skill) { upgradeSkill(this, skill); }
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.create = function() {
|
|
||||||
this.contracts["Tracking"] = new Contract({
|
|
||||||
name:"Tracking",
|
|
||||||
desc:"Identify and locate Synthoids. This contract involves reconnaissance " +
|
|
||||||
"and information-gathering ONLY. Do NOT engage. Stealth is of the utmost importance.<br><br>" +
|
|
||||||
"Successfully completing Tracking contracts will slightly improve your Synthoid population estimate for " +
|
|
||||||
"whatever city you are currently in.",
|
|
||||||
baseDifficulty:125,difficultyFac:1.02,rewardFac:1.041,
|
|
||||||
rankGain:0.3, hpLoss:0.5,
|
|
||||||
count:getRandomInt(25, 150), countGrowth:getRandomInt(5, 75)/10,
|
|
||||||
weights:{hack:0,str:0.05,def:0.05,dex:0.35,agi:0.35,cha:0.1, int:0.05},
|
|
||||||
decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.9, int:1},
|
|
||||||
isStealth:true,
|
|
||||||
});
|
|
||||||
this.contracts["Bounty Hunter"] = new Contract({
|
|
||||||
name:"Bounty Hunter",
|
|
||||||
desc:"Hunt down and capture fugitive Synthoids. These Synthoids are wanted alive.<br><br>" +
|
|
||||||
"Successfully completing a Bounty Hunter contract will lower the population in your " +
|
|
||||||
"current city, and will also increase its chaos level.",
|
|
||||||
baseDifficulty:250, difficultyFac:1.04,rewardFac:1.085,
|
|
||||||
rankGain:0.9, hpLoss:1,
|
|
||||||
count:getRandomInt(5, 150), countGrowth:getRandomInt(5, 75)/10,
|
|
||||||
weights:{hack:0,str:0.15,def:0.15,dex:0.25,agi:0.25,cha:0.1, int:0.1},
|
|
||||||
decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.8, int:0.9},
|
|
||||||
isKill:true,
|
|
||||||
});
|
|
||||||
this.contracts["Retirement"] = new Contract({
|
|
||||||
name:"Retirement",
|
|
||||||
desc:"Hunt down and retire (kill) rogue Synthoids.<br><br>" +
|
|
||||||
"Successfully completing a Retirement contract will lower the population in your current " +
|
|
||||||
"city, and will also increase its chaos level.",
|
|
||||||
baseDifficulty:200, difficultyFac:1.03, rewardFac:1.065,
|
|
||||||
rankGain:0.6, hpLoss:1,
|
|
||||||
count:getRandomInt(5, 150), countGrowth:getRandomInt(5, 75)/10,
|
|
||||||
weights:{hack:0,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0.1, int:0.1},
|
|
||||||
decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.8, int:0.9},
|
|
||||||
isKill:true,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.operations["Investigation"] = new Operation({
|
|
||||||
name:"Investigation",
|
|
||||||
desc:"As a field agent, investigate and identify Synthoid " +
|
|
||||||
"populations, movements, and operations.<br><br>Successful " +
|
|
||||||
"Investigation ops will increase the accuracy of your " +
|
|
||||||
"synthoid data.<br><br>" +
|
|
||||||
"You will NOT lose HP from failed Investigation ops.",
|
|
||||||
baseDifficulty:400, difficultyFac:1.03,rewardFac:1.07,reqdRank:25,
|
|
||||||
rankGain:2.2, rankLoss:0.2,
|
|
||||||
count:getRandomInt(1, 100), countGrowth:getRandomInt(10, 40)/10,
|
|
||||||
weights:{hack:0.25,str:0.05,def:0.05,dex:0.2,agi:0.1,cha:0.25, int:0.1},
|
|
||||||
decays:{hack:0.85,str:0.9,def:0.9,dex:0.9,agi:0.9,cha:0.7, int:0.9},
|
|
||||||
isStealth:true,
|
|
||||||
});
|
|
||||||
this.operations["Undercover Operation"] = new Operation({
|
|
||||||
name:"Undercover Operation",
|
|
||||||
desc:"Conduct undercover operations to identify hidden " +
|
|
||||||
"and underground Synthoid communities and organizations.<br><br>" +
|
|
||||||
"Successful Undercover ops will increase the accuracy of your synthoid " +
|
|
||||||
"data.",
|
|
||||||
baseDifficulty:500, difficultyFac:1.04, rewardFac:1.09, reqdRank:100,
|
|
||||||
rankGain:4.4, rankLoss:0.4, hpLoss:2,
|
|
||||||
count:getRandomInt(1, 100), countGrowth:getRandomInt(10, 40)/10,
|
|
||||||
weights:{hack:0.2,str:0.05,def:0.05,dex:0.2,agi:0.2,cha:0.2, int:0.1},
|
|
||||||
decays:{hack:0.8,str:0.9,def:0.9,dex:0.9,agi:0.9,cha:0.7, int:0.9},
|
|
||||||
isStealth:true,
|
|
||||||
});
|
|
||||||
this.operations["Sting Operation"] = new Operation({
|
|
||||||
name:"Sting Operation",
|
|
||||||
desc:"Conduct a sting operation to bait and capture particularly " +
|
|
||||||
"notorious Synthoid criminals.",
|
|
||||||
baseDifficulty:650, difficultyFac:1.04, rewardFac:1.095, reqdRank:500,
|
|
||||||
rankGain:5.5, rankLoss:0.5, hpLoss:2.5,
|
|
||||||
count:getRandomInt(1, 150), countGrowth:getRandomInt(3, 40)/10,
|
|
||||||
weights:{hack:0.25,str:0.05,def:0.05,dex:0.25,agi:0.1,cha:0.2, int:0.1},
|
|
||||||
decays:{hack:0.8,str:0.85,def:0.85,dex:0.85,agi:0.85,cha:0.7, int:0.9},
|
|
||||||
isStealth:true,
|
|
||||||
});
|
|
||||||
this.operations["Raid"] = new Operation({
|
|
||||||
name:"Raid",
|
|
||||||
desc:"Lead an assault on a known Synthoid community. Note that " +
|
|
||||||
"there must be an existing Synthoid community in your current city " +
|
|
||||||
"in order for this Operation to be successful.",
|
|
||||||
baseDifficulty:800, difficultyFac:1.045, rewardFac:1.1, reqdRank:3000,
|
|
||||||
rankGain:55,rankLoss:2.5,hpLoss:50,
|
|
||||||
count:getRandomInt(1, 150), countGrowth:getRandomInt(2, 40)/10,
|
|
||||||
weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1},
|
|
||||||
decays:{hack:0.7,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.9},
|
|
||||||
isKill:true,
|
|
||||||
});
|
|
||||||
this.operations["Stealth Retirement Operation"] = new Operation({
|
|
||||||
name:"Stealth Retirement Operation",
|
|
||||||
desc:"Lead a covert operation to retire Synthoids. The " +
|
|
||||||
"objective is to complete the task without " +
|
|
||||||
"drawing any attention. Stealth and discretion are key.",
|
|
||||||
baseDifficulty:1000, difficultyFac:1.05, rewardFac:1.11, reqdRank:20e3,
|
|
||||||
rankGain:22, rankLoss:2, hpLoss:10,
|
|
||||||
count:getRandomInt(1, 150), countGrowth:getRandomInt(1, 20)/10,
|
|
||||||
weights:{hack:0.1,str:0.1,def:0.1,dex:0.3,agi:0.3,cha:0, int:0.1},
|
|
||||||
decays:{hack:0.7,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.9},
|
|
||||||
isStealth:true, isKill:true,
|
|
||||||
});
|
|
||||||
this.operations["Assassination"] = new Operation({
|
|
||||||
name:"Assassination",
|
|
||||||
desc:"Assassinate Synthoids that have been identified as " +
|
|
||||||
"important, high-profile social and political leaders " +
|
|
||||||
"in the Synthoid communities.",
|
|
||||||
baseDifficulty:1500, difficultyFac:1.06, rewardFac:1.14, reqdRank:50e3,
|
|
||||||
rankGain:44, rankLoss:4, hpLoss:5,
|
|
||||||
count:getRandomInt(1, 150), countGrowth:getRandomInt(1, 20)/10,
|
|
||||||
weights:{hack:0.1,str:0.1,def:0.1,dex:0.3,agi:0.3,cha:0, int:0.1},
|
|
||||||
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.8},
|
|
||||||
isStealth:true, isKill:true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.storeCycles = function(numCycles=1) {
|
|
||||||
this.storedCycles += numCycles;
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.process = function() {
|
|
||||||
// Edge case condition...if Operation Daedalus is complete trigger the BitNode
|
|
||||||
if (redPillFlag === false && this.blackops.hasOwnProperty("Operation Daedalus")) {
|
|
||||||
return hackWorldDaemon(Player.bitNodeN);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the Player starts doing some other actions, set action to idle and alert
|
|
||||||
if (Augmentations[AugmentationNames.BladesSimulacrum].owned === false && Player.isWorking) {
|
|
||||||
if (this.action.type !== ActionTypes["Idle"]) {
|
|
||||||
let msg = "Your Bladeburner action was cancelled because you started doing something else.";
|
|
||||||
if (this.automateEnabled) {
|
|
||||||
msg += `<br><br>Your automation was disabled as well. You will have to re-enable it through the Bladeburner console`
|
|
||||||
this.automateEnabled = false;
|
|
||||||
}
|
|
||||||
if (!Settings.SuppressBladeburnerPopup) {
|
|
||||||
dialogBoxCreate(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resetAction(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the Player has no Stamina, set action to idle
|
|
||||||
if (this.stamina <= 0) {
|
|
||||||
this.log("Your Bladeburner action was cancelled because your stamina hit 0");
|
|
||||||
resetAction(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// A 'tick' for this mechanic is one second (= 5 game cycles)
|
|
||||||
if (this.storedCycles >= BladeburnerConstants.CyclesPerSecond) {
|
|
||||||
var seconds = Math.floor(this.storedCycles / BladeburnerConstants.CyclesPerSecond);
|
|
||||||
seconds = Math.min(seconds, 5); // Max of 5 'ticks'
|
|
||||||
this.storedCycles -= seconds * BladeburnerConstants.CyclesPerSecond;
|
|
||||||
|
|
||||||
// Stamina
|
|
||||||
this.calculateMaxStamina();
|
|
||||||
this.stamina += (this.calculateStaminaGainPerSecond() * seconds);
|
|
||||||
this.stamina = Math.min(this.maxStamina, this.stamina);
|
|
||||||
|
|
||||||
// Count increase for contracts/operations
|
|
||||||
for (let contract of Object.values(this.contracts)) {
|
|
||||||
contract.count += (seconds * contract.countGrowth/BladeburnerConstants.ActionCountGrowthPeriod);
|
|
||||||
}
|
|
||||||
for (let op of Object.values(this.operations)) {
|
|
||||||
op.count += (seconds * op.countGrowth/BladeburnerConstants.ActionCountGrowthPeriod);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chaos goes down very slowly
|
|
||||||
for (let cityName of BladeburnerConstants.CityNames) {
|
|
||||||
var city = this.cities[cityName];
|
|
||||||
if (!(city instanceof City)) {throw new Error("Invalid City object when processing passive chaos reduction in Bladeburner.process");}
|
|
||||||
city.chaos -= (0.0001 * seconds);
|
|
||||||
city.chaos = Math.max(0, city.chaos);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Random Events
|
|
||||||
this.randomEventCounter -= seconds;
|
|
||||||
if (this.randomEventCounter <= 0) {
|
|
||||||
randomEvent(this);
|
|
||||||
// Add instead of setting because we might have gone over the required time for the event
|
|
||||||
this.randomEventCounter += getRandomInt(240, 600);
|
|
||||||
}
|
|
||||||
|
|
||||||
processAction(this, Player, seconds);
|
|
||||||
|
|
||||||
// Automation
|
|
||||||
if (this.automateEnabled) {
|
|
||||||
// Note: Do NOT set this.action = this.automateActionHigh/Low since it creates a reference
|
|
||||||
if (this.stamina <= this.automateThreshLow) {
|
|
||||||
if (this.action.name !== this.automateActionLow.name || this.action.type !== this.automateActionLow.type) {
|
|
||||||
this.action = new ActionIdentifier({type: this.automateActionLow.type, name: this.automateActionLow.name});
|
|
||||||
startAction(this, Player, this.action);
|
|
||||||
}
|
|
||||||
} else if (this.stamina >= this.automateThreshHigh) {
|
|
||||||
if (this.action.name !== this.automateActionHigh.name || this.action.type !== this.automateActionHigh.type) {
|
|
||||||
this.action = new ActionIdentifier({type: this.automateActionHigh.type, name: this.automateActionHigh.name});
|
|
||||||
startAction(this, Player, this.action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.calculateMaxStamina = function() {
|
|
||||||
const effAgility = Player.agility * this.skillMultipliers.effAgi;
|
|
||||||
let maxStamina = (Math.pow(effAgility, 0.8) + this.staminaBonus) *
|
|
||||||
this.skillMultipliers.stamina *
|
|
||||||
Player.bladeburner_max_stamina_mult;
|
|
||||||
if (this.maxStamina !== maxStamina) {
|
|
||||||
const oldMax = this.maxStamina;
|
|
||||||
this.maxStamina = maxStamina;
|
|
||||||
this.stamina = this.maxStamina * this.stamina / oldMax;
|
|
||||||
}
|
|
||||||
if (isNaN(maxStamina)) {throw new Error("Max Stamina calculated to be NaN in Bladeburner.calculateMaxStamina()");}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.calculateStaminaGainPerSecond = function() {
|
|
||||||
var effAgility = Player.agility * this.skillMultipliers.effAgi;
|
|
||||||
var maxStaminaBonus = this.maxStamina / BladeburnerConstants.MaxStaminaToGainFactor;
|
|
||||||
var gain = (BladeburnerConstants.StaminaGainPerSecond + maxStaminaBonus) * Math.pow(effAgility, 0.17);
|
|
||||||
return gain * (this.skillMultipliers.stamina * Player.bladeburner_stamina_gain_mult);
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.calculateStaminaPenalty = function() {
|
|
||||||
return Math.min(1, this.stamina / (0.5 * this.maxStamina));
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.getCurrentCity = function() {
|
|
||||||
var city = this.cities[this.city];
|
|
||||||
if (!(city instanceof City)) {
|
|
||||||
throw new Error("Bladeburner.getCurrentCity() did not properly return a City object");
|
|
||||||
}
|
|
||||||
return city;
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.upgradeSkill = function(skill) {
|
|
||||||
// This does NOT handle deduction of skill points
|
|
||||||
var skillName = skill.name;
|
|
||||||
if (this.skills[skillName]) {
|
|
||||||
++this.skills[skillName];
|
|
||||||
} else {
|
|
||||||
this.skills[skillName] = 1;
|
|
||||||
}
|
|
||||||
if (isNaN(this.skills[skillName]) || this.skills[skillName] < 0) {
|
|
||||||
throw new Error("Level of Skill " + skillName + " is invalid: " + this.skills[skillName]);
|
|
||||||
}
|
|
||||||
updateSkillMultipliers(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets the player to the "IDLE" action
|
|
||||||
Bladeburner.prototype.resetAction = function() {
|
|
||||||
this.action = new ActionIdentifier({type:ActionTypes.Idle});
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//////////////////////////// Unconvertable for now /////////////////////////////
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Bladeburner Console Window
|
// Bladeburner Console Window
|
||||||
Bladeburner.prototype.postToConsole = function(input, saveToLogs=true) {
|
Bladeburner.prototype.postToConsole = function(input, saveToLogs=true) { postToConsole(this, input, saveToLogs); }
|
||||||
const MaxConsoleEntries = 100;
|
Bladeburner.prototype.log = function(input) { log(this, input); }
|
||||||
if (saveToLogs) {
|
|
||||||
this.consoleLogs.push(input);
|
|
||||||
if (this.consoleLogs.length > MaxConsoleEntries) {
|
|
||||||
this.consoleLogs.shift();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.log = function(input) {
|
|
||||||
// Adds a timestamp and then just calls postToConsole
|
|
||||||
this.postToConsole(`[${getTimestamp()}] ${input}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handles a potential series of commands (comm1; comm2; comm3;)
|
// Handles a potential series of commands (comm1; comm2; comm3;)
|
||||||
Bladeburner.prototype.executeConsoleCommands = function(commands) {
|
Bladeburner.prototype.executeConsoleCommands = function(commands) { executeConsoleCommands(this, Player, commands); }
|
||||||
executeConsoleCommands(this, commands);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//////////////////////////////// Netscript Fns /////////////////////////////////
|
//////////////////////////////// Netscript Fns /////////////////////////////////
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Bladeburner.prototype.getTypeAndNameFromActionId = function(actionId) {
|
Bladeburner.prototype.getTypeAndNameFromActionId = function(actionId) { getTypeAndNameFromActionId(this, actionId); }
|
||||||
var res = {};
|
Bladeburner.prototype.getContractNamesNetscriptFn = function() { getContractNamesNetscriptFn(this); }
|
||||||
let types = Object.keys(ActionTypes);
|
Bladeburner.prototype.getOperationNamesNetscriptFn = function() { getOperationNamesNetscriptFn(this); }
|
||||||
for (let i = 0; i < types.length; ++i) {
|
Bladeburner.prototype.getBlackOpNamesNetscriptFn = function() { getBlackOpNamesNetscriptFn(this); }
|
||||||
if (actionId.type === ActionTypes[types[i]]) {
|
Bladeburner.prototype.getGeneralActionNamesNetscriptFn = function() { getGeneralActionNamesNetscriptFn(this); }
|
||||||
res.type = types[i];
|
Bladeburner.prototype.getSkillNamesNetscriptFn = function() { getSkillNamesNetscriptFn(this); }
|
||||||
break;
|
Bladeburner.prototype.startActionNetscriptFn = function(type, name, workerScript) { startActionNetscriptFn(this, Player, type, name, workerScript); }
|
||||||
}
|
Bladeburner.prototype.getActionTimeNetscriptFn = function(type, name, workerScript) { getActionTimeNetscriptFn(this, Player, type, name, workerScript); }
|
||||||
}
|
Bladeburner.prototype.getActionEstimatedSuccessChanceNetscriptFn = function(type, name, workerScript) { getActionEstimatedSuccessChanceNetscriptFn(this, Player, type, name, workerScript); }
|
||||||
if (res.type == null) {res.type = "Idle";}
|
Bladeburner.prototype.getActionCountRemainingNetscriptFn = function(type, name, workerScript) { getActionCountRemainingNetscriptFn(this, Player, type, name, workerScript); }
|
||||||
|
Bladeburner.prototype.getSkillLevelNetscriptFn = function(skillName, workerScript) { getSkillLevelNetscriptFn(this, skillName, workerScript); }
|
||||||
res.name = actionId.name != null ? actionId.name : "Idle";
|
Bladeburner.prototype.getSkillUpgradeCostNetscriptFn = function(skillName, workerScript) { getSkillUpgradeCostNetscriptFn(this, skillName, workerScript); }
|
||||||
return res;
|
Bladeburner.prototype.upgradeSkillNetscriptFn = function(skillName, workerScript) { upgradeSkillNetscriptFn(this, skillName, workerScript); }
|
||||||
}
|
Bladeburner.prototype.getTeamSizeNetscriptFn = function(type, name, workerScript) { getTeamSizeNetscriptFn(this, type, name, workerScript); }
|
||||||
|
Bladeburner.prototype.setTeamSizeNetscriptFn = function(type, name, size, workerScript) { setTeamSizeNetscriptFn(this, type, name, size, workerScript); }
|
||||||
Bladeburner.prototype.getContractNamesNetscriptFn = function() {
|
Bladeburner.prototype.joinBladeburnerFactionNetscriptFn = function(workerScript) { joinBladeburnerFactionNetscriptFn(this, workerScript); }
|
||||||
return Object.keys(this.contracts);
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.getOperationNamesNetscriptFn = function() {
|
|
||||||
return Object.keys(this.operations);
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.getBlackOpNamesNetscriptFn = function() {
|
|
||||||
return Object.keys(BlackOperations);
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.getGeneralActionNamesNetscriptFn = function() {
|
|
||||||
return Object.keys(GeneralActions);
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.getSkillNamesNetscriptFn = function() {
|
|
||||||
return Object.keys(Skills);
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.startActionNetscriptFn = function(type, name, workerScript) {
|
|
||||||
const errorLogText = `Invalid action: type='${type}' name='${name}'`;
|
|
||||||
const actionId = getActionIdFromTypeAndName(this, type, name);
|
|
||||||
if (actionId == null) {
|
|
||||||
workerScript.log("bladeburner.startAction", errorLogText);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special logic for Black Ops
|
|
||||||
if (actionId.type === ActionTypes["BlackOp"]) {
|
|
||||||
// Can't start a BlackOp if you don't have the required rank
|
|
||||||
let action = getActionObject(this, actionId);
|
|
||||||
if (action.reqdRank > this.rank) {
|
|
||||||
workerScript.log("bladeburner.startAction", `Insufficient rank to start Black Op '${actionId.name}'.`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can't start a BlackOp if its already been done
|
|
||||||
if (this.blackops[actionId.name] != null) {
|
|
||||||
workerScript.log("bladeburner.startAction", `Black Op ${actionId.name} has already been completed.`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can't start a BlackOp if you haven't done the one before it
|
|
||||||
var blackops = [];
|
|
||||||
for (const nm in BlackOperations) {
|
|
||||||
if (BlackOperations.hasOwnProperty(nm)) {
|
|
||||||
blackops.push(nm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
blackops.sort(function(a, b) {
|
|
||||||
return (BlackOperations[a].reqdRank - BlackOperations[b].reqdRank); // Sort black ops in intended order
|
|
||||||
});
|
|
||||||
|
|
||||||
let i = blackops.indexOf(actionId.name);
|
|
||||||
if (i === -1) {
|
|
||||||
workerScript.log("bladeburner.startAction", `Invalid Black Op: '${name}'`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i > 0 && this.blackops[blackops[i-1]] == null) {
|
|
||||||
workerScript.log("bladeburner.startAction", `Preceding Black Op must be completed before starting '${actionId.name}'.`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
startAction(this, Player, actionId);
|
|
||||||
workerScript.log("bladeburner.startAction", `Starting bladeburner action with type '${type}' and name ${name}"`);
|
|
||||||
return true;
|
|
||||||
} catch(e) {
|
|
||||||
resetAction(this);
|
|
||||||
workerScript.log("bladeburner.startAction", errorLogText);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.getActionTimeNetscriptFn = function(type, name, workerScript) {
|
|
||||||
const errorLogText = `Invalid action: type='${type}' name='${name}'`
|
|
||||||
const actionId = getActionIdFromTypeAndName(this, type, name);
|
|
||||||
if (actionId == null) {
|
|
||||||
workerScript.log("bladeburner.getActionTime", errorLogText);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const actionObj = getActionObject(this, actionId);
|
|
||||||
if (actionObj == null) {
|
|
||||||
workerScript.log("bladeburner.getActionTime", errorLogText);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (actionId.type) {
|
|
||||||
case ActionTypes["Contract"]:
|
|
||||||
case ActionTypes["Operation"]:
|
|
||||||
case ActionTypes["BlackOp"]:
|
|
||||||
case ActionTypes["BlackOperation"]:
|
|
||||||
return actionObj.getActionTime(this);
|
|
||||||
case ActionTypes["Training"]:
|
|
||||||
case ActionTypes["Field Analysis"]:
|
|
||||||
case ActionTypes["FieldAnalysis"]:
|
|
||||||
return 30;
|
|
||||||
case ActionTypes["Recruitment"]:
|
|
||||||
return getRecruitmentTime(this, Player);
|
|
||||||
case ActionTypes["Diplomacy"]:
|
|
||||||
case ActionTypes["Hyperbolic Regeneration Chamber"]:
|
|
||||||
return 60;
|
|
||||||
default:
|
|
||||||
workerScript.log("bladeburner.getActionTime", errorLogText);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.getActionEstimatedSuccessChanceNetscriptFn = function(type, name, workerScript) {
|
|
||||||
const errorLogText = `Invalid action: type='${type}' name='${name}'`
|
|
||||||
const actionId = getActionIdFromTypeAndName(this, type, name);
|
|
||||||
if (actionId == null) {
|
|
||||||
workerScript.log("bladeburner.getActionEstimatedSuccessChance", errorLogText);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const actionObj = getActionObject(this, actionId);
|
|
||||||
if (actionObj == null) {
|
|
||||||
workerScript.log("bladeburner.getActionEstimatedSuccessChance", errorLogText);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (actionId.type) {
|
|
||||||
case ActionTypes["Contract"]:
|
|
||||||
case ActionTypes["Operation"]:
|
|
||||||
case ActionTypes["BlackOp"]:
|
|
||||||
case ActionTypes["BlackOperation"]:
|
|
||||||
return actionObj.getSuccessChance(this, {est:true});
|
|
||||||
case ActionTypes["Training"]:
|
|
||||||
case ActionTypes["Field Analysis"]:
|
|
||||||
case ActionTypes["FieldAnalysis"]:
|
|
||||||
return 1;
|
|
||||||
case ActionTypes["Recruitment"]:
|
|
||||||
return getRecruitmentSuccessChance(this, Player);
|
|
||||||
default:
|
|
||||||
workerScript.log("bladeburner.getActionEstimatedSuccessChance", errorLogText);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.getActionCountRemainingNetscriptFn = function(type, name, workerScript) {
|
|
||||||
const errorLogText = `Invalid action: type='${type}' name='${name}'`;
|
|
||||||
const actionId = getActionIdFromTypeAndName(this, type, name);
|
|
||||||
if (actionId == null) {
|
|
||||||
workerScript.log("bladeburner.getActionCountRemaining", errorLogText);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const actionObj = getActionObject(this, actionId);
|
|
||||||
if (actionObj == null) {
|
|
||||||
workerScript.log("bladeburner.getActionCountRemaining", errorLogText);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (actionId.type) {
|
|
||||||
case ActionTypes["Contract"]:
|
|
||||||
case ActionTypes["Operation"]:
|
|
||||||
return Math.floor( actionObj.count );
|
|
||||||
case ActionTypes["BlackOp"]:
|
|
||||||
case ActionTypes["BlackOperation"]:
|
|
||||||
if (this.blackops[name] != null) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
case ActionTypes["Training"]:
|
|
||||||
case ActionTypes["Field Analysis"]:
|
|
||||||
case ActionTypes["FieldAnalysis"]:
|
|
||||||
return Infinity;
|
|
||||||
default:
|
|
||||||
workerScript.log("bladeburner.getActionCountRemaining", errorLogText);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.getSkillLevelNetscriptFn = function(skillName, workerScript) {
|
|
||||||
if (skillName === "" || !Skills.hasOwnProperty(skillName)) {
|
|
||||||
workerScript.log("bladeburner.getSkillLevel", `Invalid skill: '${skillName}'`);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.skills[skillName] == null) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return this.skills[skillName];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.getSkillUpgradeCostNetscriptFn = function(skillName, workerScript) {
|
|
||||||
if (skillName === "" || !Skills.hasOwnProperty(skillName)) {
|
|
||||||
workerScript.log("bladeburner.getSkillUpgradeCost", `Invalid skill: '${skillName}'`);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const skill = Skills[skillName];
|
|
||||||
if (this.skills[skillName] == null) {
|
|
||||||
return skill.calculateCost(0);
|
|
||||||
} else {
|
|
||||||
return skill.calculateCost(this.skills[skillName]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.upgradeSkillNetscriptFn = function(skillName, workerScript) {
|
|
||||||
const errorLogText = `Invalid skill: '${skillName}'`;
|
|
||||||
if (!Skills.hasOwnProperty(skillName)) {
|
|
||||||
workerScript.log("bladeburner.upgradeSkill", errorLogText);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const skill = Skills[skillName];
|
|
||||||
let currentLevel = 0;
|
|
||||||
if (this.skills[skillName] && !isNaN(this.skills[skillName])) {
|
|
||||||
currentLevel = this.skills[skillName];
|
|
||||||
}
|
|
||||||
const cost = skill.calculateCost(currentLevel);
|
|
||||||
|
|
||||||
if(skill.maxLvl && currentLevel >= skill.maxLvl) {
|
|
||||||
workerScript.log("bladeburner.upgradeSkill", `Skill '${skillName}' is already maxed.`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.skillPoints < cost) {
|
|
||||||
workerScript.log("bladeburner.upgradeSkill", `You do not have enough skill points to upgrade ${skillName} (You have ${this.skillPoints}, you need ${cost})`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.skillPoints -= cost;
|
|
||||||
this.upgradeSkill(skill);
|
|
||||||
workerScript.log("bladeburner.upgradeSkill", `'${skillName}' upgraded to level ${this.skills[skillName]}`);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.getTeamSizeNetscriptFn = function(type, name, workerScript) {
|
|
||||||
if (type === "" && name === "") {
|
|
||||||
return this.teamSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
const errorLogText = `Invalid action: type='${type}' name='${name}'`;
|
|
||||||
const actionId = getActionIdFromTypeAndName(this, type, name);
|
|
||||||
if (actionId == null) {
|
|
||||||
workerScript.log("bladeburner.getTeamSize", errorLogText);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const actionObj = getActionObject(this, actionId);
|
|
||||||
if (actionObj == null) {
|
|
||||||
workerScript.log("bladeburner.getTeamSize", errorLogText);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actionId.type === ActionTypes["Operation"] ||
|
|
||||||
actionId.type === ActionTypes["BlackOp"] ||
|
|
||||||
actionId.type === ActionTypes["BlackOperation"]) {
|
|
||||||
return actionObj.teamCount;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.setTeamSizeNetscriptFn = function(type, name, size, workerScript) {
|
|
||||||
const errorLogText = `Invalid action: type='${type}' name='${name}'`;
|
|
||||||
const actionId = getActionIdFromTypeAndName(this, type, name);
|
|
||||||
if (actionId == null) {
|
|
||||||
workerScript.log("bladeburner.setTeamSize", errorLogText);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actionId.type !== ActionTypes["Operation"] &&
|
|
||||||
actionId.type !== ActionTypes["BlackOp"] &&
|
|
||||||
actionId.type !== ActionTypes["BlackOperation"]) {
|
|
||||||
workerScript.log("bladeburner.setTeamSize", "Only valid for 'Operations' and 'BlackOps'");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const actionObj = getActionObject(this, actionId);
|
|
||||||
if (actionObj == null) {
|
|
||||||
workerScript.log("bladeburner.setTeamSize", errorLogText);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
let sanitizedSize = Math.round(size);
|
|
||||||
if (isNaN(sanitizedSize) || sanitizedSize < 0) {
|
|
||||||
workerScript.log("bladeburner.setTeamSize", `Invalid size: ${size}`);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (this.teamSize < sanitizedSize) {sanitizedSize = this.teamSize;}
|
|
||||||
actionObj.teamCount = sanitizedSize;
|
|
||||||
workerScript.log("bladeburner.setTeamSize", `Team size for '${name}' set to ${sanitizedSize}.`);
|
|
||||||
return sanitizedSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.joinBladeburnerFactionNetscriptFn = function(workerScript) {
|
|
||||||
var bladeburnerFac = Factions["Bladeburners"];
|
|
||||||
if (bladeburnerFac.isMember) {
|
|
||||||
return true;
|
|
||||||
} else if (this.rank >= BladeburnerConstants.RankNeededForFaction) {
|
|
||||||
joinFaction(bladeburnerFac);
|
|
||||||
workerScript.log("bladeburner.joinBladeburnerFaction", "Joined Bladeburners faction.");
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
workerScript.log("bladeburner.joinBladeburnerFaction", `You do not have the required rank (${this.rank}/${BladeburnerConstants.RankNeededForFaction}).`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.toJSON = function() {
|
Bladeburner.prototype.toJSON = function() {
|
||||||
return Generic_toJSON("Bladeburner", this);
|
return Generic_toJSON("Bladeburner", this);
|
||||||
|
@ -8,6 +8,8 @@ import { ActionIdentifier } from "./ActionIdentifier";
|
|||||||
import { ActionTypes } from "./data/ActionTypes";
|
import { ActionTypes } from "./data/ActionTypes";
|
||||||
import { BlackOperations } from "./BlackOperations";
|
import { BlackOperations } from "./BlackOperations";
|
||||||
import { BlackOperation } from "./BlackOperation";
|
import { BlackOperation } from "./BlackOperation";
|
||||||
|
import { Operation } from "./Operation";
|
||||||
|
import { Contract } from "./Contract";
|
||||||
import { GeneralActions } from "./GeneralActions";
|
import { GeneralActions } from "./GeneralActions";
|
||||||
import { formatNumber } from "../../utils/StringHelperFunctions";
|
import { formatNumber } from "../../utils/StringHelperFunctions";
|
||||||
import { Skills } from "./Skills";
|
import { Skills } from "./Skills";
|
||||||
@ -25,7 +27,14 @@ import { addOffset } from "../../utils/helpers/addOffset";
|
|||||||
import { Faction } from "../Faction/Faction";
|
import { Faction } from "../Faction/Faction";
|
||||||
import { Factions, factionExists } from "../Faction/Factions";
|
import { Factions, factionExists } from "../Faction/Factions";
|
||||||
import { calculateHospitalizationCost } from "../Hospital/Hospital";
|
import { calculateHospitalizationCost } from "../Hospital/Hospital";
|
||||||
import { hackWorldDaemon } from "../RedPill";
|
import { hackWorldDaemon, redPillFlag } from "../RedPill";
|
||||||
|
import { dialogBoxCreate } from "../../utils/DialogBox";
|
||||||
|
import { Settings } from "../Settings/Settings";
|
||||||
|
import { Augmentations } from "../Augmentation/Augmentations";
|
||||||
|
import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
|
||||||
|
import { getTimestamp } from "../../utils/helpers/getTimestamp";
|
||||||
|
import { joinFaction } from "../Faction/FactionHelpers";
|
||||||
|
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||||
|
|
||||||
export function getActionIdFromTypeAndName(bladeburner: IBladeburner, type: string = "", name: string = ""): IActionIdentifier | null {
|
export function getActionIdFromTypeAndName(bladeburner: IBladeburner, type: string = "", name: string = ""): IActionIdentifier | null {
|
||||||
if (type === "" || name === "") {return null;}
|
if (type === "" || name === "") {return null;}
|
||||||
@ -548,7 +557,7 @@ export function executeConsoleCommand(bladeburner: IBladeburner, player: IPlayer
|
|||||||
executeStartConsoleCommand(bladeburner, player, args);
|
executeStartConsoleCommand(bladeburner, player, args);
|
||||||
break;
|
break;
|
||||||
case "stop":
|
case "stop":
|
||||||
bladeburner.resetAction();
|
resetAction(bladeburner);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
bladeburner.postToConsole("Invalid console command");
|
bladeburner.postToConsole("Invalid console command");
|
||||||
@ -1310,4 +1319,597 @@ export function startAction(bladeburner: IBladeburner, player: IPlayer, actionId
|
|||||||
throw new Error("Invalid Action Type in startAction(Bladeburner,player, ): " + actionId.type);
|
throw new Error("Invalid Action Type in startAction(Bladeburner,player, ): " + actionId.type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function calculateStaminaPenalty(bladeburner: IBladeburner): number {
|
||||||
|
return Math.min(1, bladeburner.stamina / (0.5 * bladeburner.maxStamina));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function calculateStaminaGainPerSecond(bladeburner: IBladeburner, player: IPlayer): number {
|
||||||
|
const effAgility = player.agility * bladeburner.skillMultipliers.effAgi;
|
||||||
|
const maxStaminaBonus = bladeburner.maxStamina / BladeburnerConstants.MaxStaminaToGainFactor;
|
||||||
|
const gain = (BladeburnerConstants.StaminaGainPerSecond + maxStaminaBonus) * Math.pow(effAgility, 0.17);
|
||||||
|
return gain * (bladeburner.skillMultipliers.stamina * player.bladeburner_stamina_gain_mult);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function calculateMaxStamina(bladeburner: IBladeburner, player: IPlayer) {
|
||||||
|
const effAgility = player.agility * bladeburner.skillMultipliers.effAgi;
|
||||||
|
let maxStamina = (Math.pow(effAgility, 0.8) + bladeburner.staminaBonus) *
|
||||||
|
bladeburner.skillMultipliers.stamina *
|
||||||
|
player.bladeburner_max_stamina_mult;
|
||||||
|
if (bladeburner.maxStamina !== maxStamina) {
|
||||||
|
const oldMax = bladeburner.maxStamina;
|
||||||
|
bladeburner.maxStamina = maxStamina;
|
||||||
|
bladeburner.stamina = bladeburner.maxStamina * bladeburner.stamina / oldMax;
|
||||||
|
}
|
||||||
|
if (isNaN(maxStamina)) {throw new Error("Max Stamina calculated to be NaN in Bladeburner.calculateMaxStamina()");}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function create(bladeburner: IBladeburner): void {
|
||||||
|
bladeburner.contracts["Tracking"] = new Contract({
|
||||||
|
name:"Tracking",
|
||||||
|
desc:"Identify and locate Synthoids. This contract involves reconnaissance " +
|
||||||
|
"and information-gathering ONLY. Do NOT engage. Stealth is of the utmost importance.<br><br>" +
|
||||||
|
"Successfully completing Tracking contracts will slightly improve your Synthoid population estimate for " +
|
||||||
|
"whatever city you are currently in.",
|
||||||
|
baseDifficulty:125,difficultyFac:1.02,rewardFac:1.041,
|
||||||
|
rankGain:0.3, hpLoss:0.5,
|
||||||
|
count:getRandomInt(25, 150), countGrowth:getRandomInt(5, 75)/10,
|
||||||
|
weights:{hack:0,str:0.05,def:0.05,dex:0.35,agi:0.35,cha:0.1, int:0.05},
|
||||||
|
decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.9, int:1},
|
||||||
|
isStealth:true,
|
||||||
|
});
|
||||||
|
bladeburner.contracts["Bounty Hunter"] = new Contract({
|
||||||
|
name:"Bounty Hunter",
|
||||||
|
desc:"Hunt down and capture fugitive Synthoids. These Synthoids are wanted alive.<br><br>" +
|
||||||
|
"Successfully completing a Bounty Hunter contract will lower the population in your " +
|
||||||
|
"current city, and will also increase its chaos level.",
|
||||||
|
baseDifficulty:250, difficultyFac:1.04,rewardFac:1.085,
|
||||||
|
rankGain:0.9, hpLoss:1,
|
||||||
|
count:getRandomInt(5, 150), countGrowth:getRandomInt(5, 75)/10,
|
||||||
|
weights:{hack:0,str:0.15,def:0.15,dex:0.25,agi:0.25,cha:0.1, int:0.1},
|
||||||
|
decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.8, int:0.9},
|
||||||
|
isKill:true,
|
||||||
|
});
|
||||||
|
bladeburner.contracts["Retirement"] = new Contract({
|
||||||
|
name:"Retirement",
|
||||||
|
desc:"Hunt down and retire (kill) rogue Synthoids.<br><br>" +
|
||||||
|
"Successfully completing a Retirement contract will lower the population in your current " +
|
||||||
|
"city, and will also increase its chaos level.",
|
||||||
|
baseDifficulty:200, difficultyFac:1.03, rewardFac:1.065,
|
||||||
|
rankGain:0.6, hpLoss:1,
|
||||||
|
count:getRandomInt(5, 150), countGrowth:getRandomInt(5, 75)/10,
|
||||||
|
weights:{hack:0,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0.1, int:0.1},
|
||||||
|
decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.8, int:0.9},
|
||||||
|
isKill:true,
|
||||||
|
});
|
||||||
|
|
||||||
|
bladeburner.operations["Investigation"] = new Operation({
|
||||||
|
name:"Investigation",
|
||||||
|
desc:"As a field agent, investigate and identify Synthoid " +
|
||||||
|
"populations, movements, and operations.<br><br>Successful " +
|
||||||
|
"Investigation ops will increase the accuracy of your " +
|
||||||
|
"synthoid data.<br><br>" +
|
||||||
|
"You will NOT lose HP from failed Investigation ops.",
|
||||||
|
baseDifficulty:400, difficultyFac:1.03,rewardFac:1.07,reqdRank:25,
|
||||||
|
rankGain:2.2, rankLoss:0.2,
|
||||||
|
count:getRandomInt(1, 100), countGrowth:getRandomInt(10, 40)/10,
|
||||||
|
weights:{hack:0.25,str:0.05,def:0.05,dex:0.2,agi:0.1,cha:0.25, int:0.1},
|
||||||
|
decays:{hack:0.85,str:0.9,def:0.9,dex:0.9,agi:0.9,cha:0.7, int:0.9},
|
||||||
|
isStealth:true,
|
||||||
|
});
|
||||||
|
bladeburner.operations["Undercover Operation"] = new Operation({
|
||||||
|
name:"Undercover Operation",
|
||||||
|
desc:"Conduct undercover operations to identify hidden " +
|
||||||
|
"and underground Synthoid communities and organizations.<br><br>" +
|
||||||
|
"Successful Undercover ops will increase the accuracy of your synthoid " +
|
||||||
|
"data.",
|
||||||
|
baseDifficulty:500, difficultyFac:1.04, rewardFac:1.09, reqdRank:100,
|
||||||
|
rankGain:4.4, rankLoss:0.4, hpLoss:2,
|
||||||
|
count:getRandomInt(1, 100), countGrowth:getRandomInt(10, 40)/10,
|
||||||
|
weights:{hack:0.2,str:0.05,def:0.05,dex:0.2,agi:0.2,cha:0.2, int:0.1},
|
||||||
|
decays:{hack:0.8,str:0.9,def:0.9,dex:0.9,agi:0.9,cha:0.7, int:0.9},
|
||||||
|
isStealth:true,
|
||||||
|
});
|
||||||
|
bladeburner.operations["Sting Operation"] = new Operation({
|
||||||
|
name:"Sting Operation",
|
||||||
|
desc:"Conduct a sting operation to bait and capture particularly " +
|
||||||
|
"notorious Synthoid criminals.",
|
||||||
|
baseDifficulty:650, difficultyFac:1.04, rewardFac:1.095, reqdRank:500,
|
||||||
|
rankGain:5.5, rankLoss:0.5, hpLoss:2.5,
|
||||||
|
count:getRandomInt(1, 150), countGrowth:getRandomInt(3, 40)/10,
|
||||||
|
weights:{hack:0.25,str:0.05,def:0.05,dex:0.25,agi:0.1,cha:0.2, int:0.1},
|
||||||
|
decays:{hack:0.8,str:0.85,def:0.85,dex:0.85,agi:0.85,cha:0.7, int:0.9},
|
||||||
|
isStealth:true,
|
||||||
|
});
|
||||||
|
bladeburner.operations["Raid"] = new Operation({
|
||||||
|
name:"Raid",
|
||||||
|
desc:"Lead an assault on a known Synthoid community. Note that " +
|
||||||
|
"there must be an existing Synthoid community in your current city " +
|
||||||
|
"in order for this Operation to be successful.",
|
||||||
|
baseDifficulty:800, difficultyFac:1.045, rewardFac:1.1, reqdRank:3000,
|
||||||
|
rankGain:55,rankLoss:2.5,hpLoss:50,
|
||||||
|
count:getRandomInt(1, 150), countGrowth:getRandomInt(2, 40)/10,
|
||||||
|
weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1},
|
||||||
|
decays:{hack:0.7,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.9},
|
||||||
|
isKill:true,
|
||||||
|
});
|
||||||
|
bladeburner.operations["Stealth Retirement Operation"] = new Operation({
|
||||||
|
name:"Stealth Retirement Operation",
|
||||||
|
desc:"Lead a covert operation to retire Synthoids. The " +
|
||||||
|
"objective is to complete the task without " +
|
||||||
|
"drawing any attention. Stealth and discretion are key.",
|
||||||
|
baseDifficulty:1000, difficultyFac:1.05, rewardFac:1.11, reqdRank:20e3,
|
||||||
|
rankGain:22, rankLoss:2, hpLoss:10,
|
||||||
|
count:getRandomInt(1, 150), countGrowth:getRandomInt(1, 20)/10,
|
||||||
|
weights:{hack:0.1,str:0.1,def:0.1,dex:0.3,agi:0.3,cha:0, int:0.1},
|
||||||
|
decays:{hack:0.7,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.9},
|
||||||
|
isStealth:true, isKill:true,
|
||||||
|
});
|
||||||
|
bladeburner.operations["Assassination"] = new Operation({
|
||||||
|
name:"Assassination",
|
||||||
|
desc:"Assassinate Synthoids that have been identified as " +
|
||||||
|
"important, high-profile social and political leaders " +
|
||||||
|
"in the Synthoid communities.",
|
||||||
|
baseDifficulty:1500, difficultyFac:1.06, rewardFac:1.14, reqdRank:50e3,
|
||||||
|
rankGain:44, rankLoss:4, hpLoss:5,
|
||||||
|
count:getRandomInt(1, 150), countGrowth:getRandomInt(1, 20)/10,
|
||||||
|
weights:{hack:0.1,str:0.1,def:0.1,dex:0.3,agi:0.3,cha:0, int:0.1},
|
||||||
|
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.8},
|
||||||
|
isStealth:true, isKill:true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function process(bladeburner: IBladeburner, player: IPlayer): void {
|
||||||
|
// Edge case condition...if Operation Daedalus is complete trigger the BitNode
|
||||||
|
if (redPillFlag === false && bladeburner.blackops.hasOwnProperty("Operation Daedalus")) {
|
||||||
|
return hackWorldDaemon(player.bitNodeN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the Player starts doing some other actions, set action to idle and alert
|
||||||
|
if (Augmentations[AugmentationNames.BladesSimulacrum].owned === false && player.isWorking) {
|
||||||
|
if (bladeburner.action.type !== ActionTypes["Idle"]) {
|
||||||
|
let msg = "Your Bladeburner action was cancelled because you started doing something else.";
|
||||||
|
if (bladeburner.automateEnabled) {
|
||||||
|
msg += `<br><br>Your automation was disabled as well. You will have to re-enable it through the Bladeburner console`
|
||||||
|
bladeburner.automateEnabled = false;
|
||||||
|
}
|
||||||
|
if (!Settings.SuppressBladeburnerPopup) {
|
||||||
|
dialogBoxCreate(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resetAction(bladeburner);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the Player has no Stamina, set action to idle
|
||||||
|
if (bladeburner.stamina <= 0) {
|
||||||
|
bladeburner.log("Your Bladeburner action was cancelled because your stamina hit 0");
|
||||||
|
resetAction(bladeburner);
|
||||||
|
}
|
||||||
|
|
||||||
|
// A 'tick' for this mechanic is one second (= 5 game cycles)
|
||||||
|
if (bladeburner.storedCycles >= BladeburnerConstants.CyclesPerSecond) {
|
||||||
|
let seconds = Math.floor(bladeburner.storedCycles / BladeburnerConstants.CyclesPerSecond);
|
||||||
|
seconds = Math.min(seconds, 5); // Max of 5 'ticks'
|
||||||
|
bladeburner.storedCycles -= seconds * BladeburnerConstants.CyclesPerSecond;
|
||||||
|
|
||||||
|
// Stamina
|
||||||
|
calculateMaxStamina(bladeburner, player);
|
||||||
|
bladeburner.stamina += (calculateStaminaGainPerSecond(bladeburner, player) * seconds);
|
||||||
|
bladeburner.stamina = Math.min(bladeburner.maxStamina, bladeburner.stamina);
|
||||||
|
|
||||||
|
// Count increase for contracts/operations
|
||||||
|
for (const contract of (Object.values(bladeburner.contracts) as Contract[])) {
|
||||||
|
contract.count += (seconds * contract.countGrowth/BladeburnerConstants.ActionCountGrowthPeriod);
|
||||||
|
}
|
||||||
|
for (const op of (Object.values(bladeburner.operations) as Operation[])) {
|
||||||
|
op.count += (seconds * op.countGrowth/BladeburnerConstants.ActionCountGrowthPeriod);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chaos goes down very slowly
|
||||||
|
for (const cityName of BladeburnerConstants.CityNames) {
|
||||||
|
const city = bladeburner.cities[cityName];
|
||||||
|
if (!(city instanceof City)) {throw new Error("Invalid City object when processing passive chaos reduction in Bladeburner.process");}
|
||||||
|
city.chaos -= (0.0001 * seconds);
|
||||||
|
city.chaos = Math.max(0, city.chaos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Random Events
|
||||||
|
bladeburner.randomEventCounter -= seconds;
|
||||||
|
if (bladeburner.randomEventCounter <= 0) {
|
||||||
|
randomEvent(bladeburner);
|
||||||
|
// Add instead of setting because we might have gone over the required time for the event
|
||||||
|
bladeburner.randomEventCounter += getRandomInt(240, 600);
|
||||||
|
}
|
||||||
|
|
||||||
|
processAction(bladeburner, player, seconds);
|
||||||
|
|
||||||
|
// Automation
|
||||||
|
if (bladeburner.automateEnabled) {
|
||||||
|
// Note: Do NOT set bladeburner.action = bladeburner.automateActionHigh/Low since it creates a reference
|
||||||
|
if (bladeburner.stamina <= bladeburner.automateThreshLow) {
|
||||||
|
if (bladeburner.action.name !== bladeburner.automateActionLow.name || bladeburner.action.type !== bladeburner.automateActionLow.type) {
|
||||||
|
bladeburner.action = new ActionIdentifier({type: bladeburner.automateActionLow.type, name: bladeburner.automateActionLow.name});
|
||||||
|
startAction(bladeburner, player, bladeburner.action);
|
||||||
|
}
|
||||||
|
} else if (bladeburner.stamina >= bladeburner.automateThreshHigh) {
|
||||||
|
if (bladeburner.action.name !== bladeburner.automateActionHigh.name || bladeburner.action.type !== bladeburner.automateActionHigh.type) {
|
||||||
|
bladeburner.action = new ActionIdentifier({type: bladeburner.automateActionHigh.type, name: bladeburner.automateActionHigh.name});
|
||||||
|
startAction(bladeburner, player, bladeburner.action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export function prestige(bladeburner: IBladeburner): void {
|
||||||
|
resetAction(bladeburner);
|
||||||
|
const bladeburnerFac = Factions["Bladeburners"];
|
||||||
|
if (bladeburner.rank >= BladeburnerConstants.RankNeededForFaction) {
|
||||||
|
joinFaction(bladeburnerFac);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function storeCycles(bladeburner: IBladeburner, numCycles: number = 1): void {
|
||||||
|
bladeburner.storedCycles += numCycles;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCurrentCity(bladeburner: IBladeburner): City {
|
||||||
|
const city = bladeburner.cities[bladeburner.city];
|
||||||
|
if (!(city instanceof City)) {
|
||||||
|
throw new Error("Bladeburner.getCurrentCity() did not properly return a City object");
|
||||||
|
}
|
||||||
|
return city;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function upgradeSkill(bladeburner: IBladeburner, skill: Skill) {
|
||||||
|
// This does NOT handle deduction of skill points
|
||||||
|
const skillName = skill.name;
|
||||||
|
if (bladeburner.skills[skillName]) {
|
||||||
|
++bladeburner.skills[skillName];
|
||||||
|
} else {
|
||||||
|
bladeburner.skills[skillName] = 1;
|
||||||
|
}
|
||||||
|
if (isNaN(bladeburner.skills[skillName]) || bladeburner.skills[skillName] < 0) {
|
||||||
|
throw new Error("Level of Skill " + skillName + " is invalid: " + bladeburner.skills[skillName]);
|
||||||
|
}
|
||||||
|
updateSkillMultipliers(bladeburner);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bladeburner Console Window
|
||||||
|
export function postToConsole(bladeburner: IBladeburner, input: string, saveToLogs: boolean = true) {
|
||||||
|
const MaxConsoleEntries = 100;
|
||||||
|
if (saveToLogs) {
|
||||||
|
bladeburner.consoleLogs.push(input);
|
||||||
|
if (bladeburner.consoleLogs.length > MaxConsoleEntries) {
|
||||||
|
bladeburner.consoleLogs.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function log(bladeburner: IBladeburner, input: string) {
|
||||||
|
// Adds a timestamp and then just calls postToConsole
|
||||||
|
bladeburner.postToConsole(`[${getTimestamp()}] ${input}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//////////////////////////////// Netscript Fns /////////////////////////////////
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
export function getTypeAndNameFromActionId(bladeburner: IBladeburner, actionId: IActionIdentifier) {
|
||||||
|
const res = {type: '', name: ''};
|
||||||
|
const types = Object.keys(ActionTypes);
|
||||||
|
for (let i = 0; i < types.length; ++i) {
|
||||||
|
if (actionId.type === ActionTypes[types[i]]) {
|
||||||
|
res.type = types[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (res.type == null) {res.type = "Idle";}
|
||||||
|
|
||||||
|
res.name = actionId.name != null ? actionId.name : "Idle";
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
export function getContractNamesNetscriptFn(bladeburner: IBladeburner) {
|
||||||
|
return Object.keys(bladeburner.contracts);
|
||||||
|
}
|
||||||
|
export function getOperationNamesNetscriptFn(bladeburner: IBladeburner) {
|
||||||
|
return Object.keys(bladeburner.operations);
|
||||||
|
}
|
||||||
|
export function getBlackOpNamesNetscriptFn(bladeburner: IBladeburner) {
|
||||||
|
return Object.keys(BlackOperations);
|
||||||
|
}
|
||||||
|
export function getGeneralActionNamesNetscriptFn(bladeburner: IBladeburner) {
|
||||||
|
return Object.keys(GeneralActions);
|
||||||
|
}
|
||||||
|
export function getSkillNamesNetscriptFn(bladeburner: IBladeburner) {
|
||||||
|
return Object.keys(Skills);
|
||||||
|
}
|
||||||
|
export function startActionNetscriptFn(bladeburner: IBladeburner, player: IPlayer, type: string, name: string, workerScript: WorkerScript) {
|
||||||
|
const errorLogText = `Invalid action: type='${type}' name='${name}'`;
|
||||||
|
const actionId = getActionIdFromTypeAndName(bladeburner, type, name);
|
||||||
|
if (actionId == null) {
|
||||||
|
workerScript.log("bladeburner.startAction", errorLogText);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special logic for Black Ops
|
||||||
|
if (actionId.type === ActionTypes["BlackOp"]) {
|
||||||
|
// Can't start a BlackOp if you don't have the required rank
|
||||||
|
const action = getActionObject(bladeburner, actionId);
|
||||||
|
if(action == null) throw new Error('Action not found ${actionId.type}, ${actionId.name}');
|
||||||
|
if(!(action instanceof BlackOperation)) throw new Error(`Action should be BlackOperation but isn't`);
|
||||||
|
const blackOp = (action as BlackOperation);
|
||||||
|
if (action.reqdRank > bladeburner.rank) {
|
||||||
|
workerScript.log("bladeburner.startAction", `Insufficient rank to start Black Op '${actionId.name}'.`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can't start a BlackOp if its already been done
|
||||||
|
if (bladeburner.blackops[actionId.name] != null) {
|
||||||
|
workerScript.log("bladeburner.startAction", `Black Op ${actionId.name} has already been completed.`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can't start a BlackOp if you haven't done the one before it
|
||||||
|
var blackops = [];
|
||||||
|
for (const nm in BlackOperations) {
|
||||||
|
if (BlackOperations.hasOwnProperty(nm)) {
|
||||||
|
blackops.push(nm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
blackops.sort(function(a, b) {
|
||||||
|
return (BlackOperations[a].reqdRank - BlackOperations[b].reqdRank); // Sort black ops in intended order
|
||||||
|
});
|
||||||
|
|
||||||
|
let i = blackops.indexOf(actionId.name);
|
||||||
|
if (i === -1) {
|
||||||
|
workerScript.log("bladeburner.startAction", `Invalid Black Op: '${name}'`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > 0 && bladeburner.blackops[blackops[i-1]] == null) {
|
||||||
|
workerScript.log("bladeburner.startAction", `Preceding Black Op must be completed before starting '${actionId.name}'.`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
startAction(bladeburner, player, actionId);
|
||||||
|
workerScript.log("bladeburner.startAction", `Starting bladeburner action with type '${type}' and name ${name}"`);
|
||||||
|
return true;
|
||||||
|
} catch(e) {
|
||||||
|
resetAction(bladeburner);
|
||||||
|
workerScript.log("bladeburner.startAction", errorLogText);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function getActionTimeNetscriptFn(bladeburner: IBladeburner, player: IPlayer, type: string, name: string, workerScript: WorkerScript) {
|
||||||
|
const errorLogText = `Invalid action: type='${type}' name='${name}'`
|
||||||
|
const actionId = getActionIdFromTypeAndName(bladeburner, type, name);
|
||||||
|
if (actionId == null) {
|
||||||
|
workerScript.log("bladeburner.getActionTime", errorLogText);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const actionObj = getActionObject(bladeburner, actionId);
|
||||||
|
if (actionObj == null) {
|
||||||
|
workerScript.log("bladeburner.getActionTime", errorLogText);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (actionId.type) {
|
||||||
|
case ActionTypes["Contract"]:
|
||||||
|
case ActionTypes["Operation"]:
|
||||||
|
case ActionTypes["BlackOp"]:
|
||||||
|
case ActionTypes["BlackOperation"]:
|
||||||
|
return actionObj.getActionTime(bladeburner);
|
||||||
|
case ActionTypes["Training"]:
|
||||||
|
case ActionTypes["Field Analysis"]:
|
||||||
|
case ActionTypes["FieldAnalysis"]:
|
||||||
|
return 30;
|
||||||
|
case ActionTypes["Recruitment"]:
|
||||||
|
return getRecruitmentTime(bladeburner, player);
|
||||||
|
case ActionTypes["Diplomacy"]:
|
||||||
|
case ActionTypes["Hyperbolic Regeneration Chamber"]:
|
||||||
|
return 60;
|
||||||
|
default:
|
||||||
|
workerScript.log("bladeburner.getActionTime", errorLogText);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function getActionEstimatedSuccessChanceNetscriptFn(bladeburner: IBladeburner, player: IPlayer, type: string, name: string, workerScript: WorkerScript) {
|
||||||
|
const errorLogText = `Invalid action: type='${type}' name='${name}'`
|
||||||
|
const actionId = getActionIdFromTypeAndName(bladeburner, type, name);
|
||||||
|
if (actionId == null) {
|
||||||
|
workerScript.log("bladeburner.getActionEstimatedSuccessChance", errorLogText);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const actionObj = getActionObject(bladeburner, actionId);
|
||||||
|
if (actionObj == null) {
|
||||||
|
workerScript.log("bladeburner.getActionEstimatedSuccessChance", errorLogText);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (actionId.type) {
|
||||||
|
case ActionTypes["Contract"]:
|
||||||
|
case ActionTypes["Operation"]:
|
||||||
|
case ActionTypes["BlackOp"]:
|
||||||
|
case ActionTypes["BlackOperation"]:
|
||||||
|
return actionObj.getSuccessChance(bladeburner, {est:true});
|
||||||
|
case ActionTypes["Training"]:
|
||||||
|
case ActionTypes["Field Analysis"]:
|
||||||
|
case ActionTypes["FieldAnalysis"]:
|
||||||
|
return 1;
|
||||||
|
case ActionTypes["Recruitment"]:
|
||||||
|
return getRecruitmentSuccessChance(bladeburner, player);
|
||||||
|
default:
|
||||||
|
workerScript.log("bladeburner.getActionEstimatedSuccessChance", errorLogText);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function getActionCountRemainingNetscriptFn(bladeburner: IBladeburner, type: string, name: string, workerScript: WorkerScript) {
|
||||||
|
const errorLogText = `Invalid action: type='${type}' name='${name}'`;
|
||||||
|
const actionId = getActionIdFromTypeAndName(bladeburner, type, name);
|
||||||
|
if (actionId == null) {
|
||||||
|
workerScript.log("bladeburner.getActionCountRemaining", errorLogText);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const actionObj = getActionObject(bladeburner, actionId);
|
||||||
|
if (actionObj == null) {
|
||||||
|
workerScript.log("bladeburner.getActionCountRemaining", errorLogText);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (actionId.type) {
|
||||||
|
case ActionTypes["Contract"]:
|
||||||
|
case ActionTypes["Operation"]:
|
||||||
|
return Math.floor( actionObj.count );
|
||||||
|
case ActionTypes["BlackOp"]:
|
||||||
|
case ActionTypes["BlackOperation"]:
|
||||||
|
if (bladeburner.blackops[name] != null) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
case ActionTypes["Training"]:
|
||||||
|
case ActionTypes["Field Analysis"]:
|
||||||
|
case ActionTypes["FieldAnalysis"]:
|
||||||
|
return Infinity;
|
||||||
|
default:
|
||||||
|
workerScript.log("bladeburner.getActionCountRemaining", errorLogText);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function getSkillLevelNetscriptFn(bladeburner: IBladeburner, skillName: string, workerScript: WorkerScript) {
|
||||||
|
if (skillName === "" || !Skills.hasOwnProperty(skillName)) {
|
||||||
|
workerScript.log("bladeburner.getSkillLevel", `Invalid skill: '${skillName}'`);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bladeburner.skills[skillName] == null) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return bladeburner.skills[skillName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function getSkillUpgradeCostNetscriptFn(bladeburner: IBladeburner, skillName: string, workerScript: WorkerScript) {
|
||||||
|
if (skillName === "" || !Skills.hasOwnProperty(skillName)) {
|
||||||
|
workerScript.log("bladeburner.getSkillUpgradeCost", `Invalid skill: '${skillName}'`);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const skill = Skills[skillName];
|
||||||
|
if (bladeburner.skills[skillName] == null) {
|
||||||
|
return skill.calculateCost(0);
|
||||||
|
} else {
|
||||||
|
return skill.calculateCost(bladeburner.skills[skillName]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function upgradeSkillNetscriptFn(bladeburner: IBladeburner, skillName: string, workerScript: WorkerScript) {
|
||||||
|
const errorLogText = `Invalid skill: '${skillName}'`;
|
||||||
|
if (!Skills.hasOwnProperty(skillName)) {
|
||||||
|
workerScript.log("bladeburner.upgradeSkill", errorLogText);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const skill = Skills[skillName];
|
||||||
|
let currentLevel = 0;
|
||||||
|
if (bladeburner.skills[skillName] && !isNaN(bladeburner.skills[skillName])) {
|
||||||
|
currentLevel = bladeburner.skills[skillName];
|
||||||
|
}
|
||||||
|
const cost = skill.calculateCost(currentLevel);
|
||||||
|
|
||||||
|
if(skill.maxLvl && currentLevel >= skill.maxLvl) {
|
||||||
|
workerScript.log("bladeburner.upgradeSkill", `Skill '${skillName}' is already maxed.`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bladeburner.skillPoints < cost) {
|
||||||
|
workerScript.log("bladeburner.upgradeSkill", `You do not have enough skill points to upgrade ${skillName} (You have ${bladeburner.skillPoints}, you need ${cost})`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bladeburner.skillPoints -= cost;
|
||||||
|
bladeburner.upgradeSkill(skill);
|
||||||
|
workerScript.log("bladeburner.upgradeSkill", `'${skillName}' upgraded to level ${bladeburner.skills[skillName]}`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
export function getTeamSizeNetscriptFn(bladeburner: IBladeburner, type: string, name: string, workerScript: WorkerScript): number {
|
||||||
|
if (type === "" && name === "") {
|
||||||
|
return bladeburner.teamSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
const errorLogText = `Invalid action: type='${type}' name='${name}'`;
|
||||||
|
const actionId = getActionIdFromTypeAndName(bladeburner, type, name);
|
||||||
|
if (actionId == null) {
|
||||||
|
workerScript.log("bladeburner.getTeamSize", errorLogText);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const actionObj = getActionObject(bladeburner, actionId);
|
||||||
|
if (actionObj == null) {
|
||||||
|
workerScript.log("bladeburner.getTeamSize", errorLogText);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actionId.type === ActionTypes["Operation"] ||
|
||||||
|
actionId.type === ActionTypes["BlackOp"] ||
|
||||||
|
actionId.type === ActionTypes["BlackOperation"]) {
|
||||||
|
return actionObj.teamCount;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function setTeamSizeNetscriptFn(bladeburner: IBladeburner, type: string, name: string, size: number, workerScript: WorkerScript): number {
|
||||||
|
const errorLogText = `Invalid action: type='${type}' name='${name}'`;
|
||||||
|
const actionId = getActionIdFromTypeAndName(bladeburner, type, name);
|
||||||
|
if (actionId == null) {
|
||||||
|
workerScript.log("bladeburner.setTeamSize", errorLogText);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actionId.type !== ActionTypes["Operation"] &&
|
||||||
|
actionId.type !== ActionTypes["BlackOp"] &&
|
||||||
|
actionId.type !== ActionTypes["BlackOperation"]) {
|
||||||
|
workerScript.log("bladeburner.setTeamSize", "Only valid for 'Operations' and 'BlackOps'");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const actionObj = getActionObject(bladeburner, actionId);
|
||||||
|
if (actionObj == null) {
|
||||||
|
workerScript.log("bladeburner.setTeamSize", errorLogText);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let sanitizedSize = Math.round(size);
|
||||||
|
if (isNaN(sanitizedSize) || sanitizedSize < 0) {
|
||||||
|
workerScript.log("bladeburner.setTeamSize", `Invalid size: ${size}`);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (bladeburner.teamSize < sanitizedSize) {sanitizedSize = bladeburner.teamSize;}
|
||||||
|
actionObj.teamCount = sanitizedSize;
|
||||||
|
workerScript.log("bladeburner.setTeamSize", `Team size for '${name}' set to ${sanitizedSize}.`);
|
||||||
|
return sanitizedSize;
|
||||||
|
}
|
||||||
|
export function joinBladeburnerFactionNetscriptFn(bladeburner: IBladeburner, workerScript: WorkerScript): boolean {
|
||||||
|
var bladeburnerFac = Factions["Bladeburners"];
|
||||||
|
if (bladeburnerFac.isMember) {
|
||||||
|
return true;
|
||||||
|
} else if (bladeburner.rank >= BladeburnerConstants.RankNeededForFaction) {
|
||||||
|
joinFaction(bladeburnerFac);
|
||||||
|
workerScript.log("bladeburner.joinBladeburnerFaction", "Joined Bladeburners faction.");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
workerScript.log("bladeburner.joinBladeburnerFaction", `You do not have the required rank (${bladeburner.rank}/${BladeburnerConstants.RankNeededForFaction}).`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -43,6 +43,7 @@ export interface IPlayer {
|
|||||||
homeComputer: string;
|
homeComputer: string;
|
||||||
hp: number;
|
hp: number;
|
||||||
jobs: IMap<string>;
|
jobs: IMap<string>;
|
||||||
|
isWorking: boolean;
|
||||||
karma: number;
|
karma: number;
|
||||||
location: LocationName;
|
location: LocationName;
|
||||||
max_hp: number;
|
max_hp: number;
|
||||||
|
1
src/RedPill.d.ts
vendored
1
src/RedPill.d.ts
vendored
@ -1 +1,2 @@
|
|||||||
|
export declare let redPillFlag: boolean;
|
||||||
export declare function hackWorldDaemon(currentNodeNumber: number, flume: boolean = false, quick: boolean = false): void;
|
export declare function hackWorldDaemon(currentNodeNumber: number, flume: boolean = false, quick: boolean = false): void;
|
@ -18,6 +18,7 @@ import {
|
|||||||
initBitNodeMultipliers,
|
initBitNodeMultipliers,
|
||||||
} from "./BitNode/BitNode";
|
} from "./BitNode/BitNode";
|
||||||
import { Bladeburner } from "./Bladeburner";
|
import { Bladeburner } from "./Bladeburner";
|
||||||
|
import { process as ProcessBladeburner } from "./Bladeburner/Bladeburner";
|
||||||
import { CharacterOverviewComponent } from "./ui/React/CharacterOverview";
|
import { CharacterOverviewComponent } from "./ui/React/CharacterOverview";
|
||||||
import { cinematicTextFlag } from "./CinematicText";
|
import { cinematicTextFlag } from "./CinematicText";
|
||||||
import { generateRandomContract } from "./CodingContractGenerator";
|
import { generateRandomContract } from "./CodingContractGenerator";
|
||||||
@ -883,7 +884,7 @@ const Engine = {
|
|||||||
}
|
}
|
||||||
if (Player.bladeburner instanceof Bladeburner) {
|
if (Player.bladeburner instanceof Bladeburner) {
|
||||||
try {
|
try {
|
||||||
Player.bladeburner.process();
|
ProcessBladeburner(Player.bladeburner, Player);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
exceptionAlert("Exception caught in Bladeburner.process(): " + e);
|
exceptionAlert("Exception caught in Bladeburner.process(): " + e);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user