mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-23 06:32:26 +01:00
More converting blade to react.
This commit is contained in:
parent
58ada6d128
commit
cc8de58cff
@ -80,6 +80,15 @@ import {
|
|||||||
getDiplomacyEffectiveness,
|
getDiplomacyEffectiveness,
|
||||||
getRecruitmentSuccessChance,
|
getRecruitmentSuccessChance,
|
||||||
getRecruitmentTime,
|
getRecruitmentTime,
|
||||||
|
resetSkillMultipliers,
|
||||||
|
updateSkillMultipliers,
|
||||||
|
resetAction,
|
||||||
|
getActionObject,
|
||||||
|
completeOperation,
|
||||||
|
completeContract,
|
||||||
|
completeAction,
|
||||||
|
processAction,
|
||||||
|
startAction,
|
||||||
} from "./Bladeburner/Bladeburner";
|
} from "./Bladeburner/Bladeburner";
|
||||||
|
|
||||||
function Bladeburner(params={}) {
|
function Bladeburner(params={}) {
|
||||||
@ -116,7 +125,7 @@ function Bladeburner(params={}) {
|
|||||||
// Map of SkillNames -> level
|
// Map of SkillNames -> level
|
||||||
this.skills = {};
|
this.skills = {};
|
||||||
this.skillMultipliers = {};
|
this.skillMultipliers = {};
|
||||||
this.updateSkillMultipliers(); // Calls resetSkillMultipliers()
|
updateSkillMultipliers(this); // Calls resetSkillMultipliers()
|
||||||
|
|
||||||
// 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
|
||||||
@ -163,7 +172,7 @@ function Bladeburner(params={}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Bladeburner.prototype.prestige = function() {
|
Bladeburner.prototype.prestige = function() {
|
||||||
this.resetAction();
|
resetAction(this);
|
||||||
var bladeburnerFac = Factions["Bladeburners"];
|
var bladeburnerFac = Factions["Bladeburners"];
|
||||||
if (this.rank >= BladeburnerConstants.RankNeededForFaction) {
|
if (this.rank >= BladeburnerConstants.RankNeededForFaction) {
|
||||||
joinFaction(bladeburnerFac);
|
joinFaction(bladeburnerFac);
|
||||||
@ -289,7 +298,6 @@ Bladeburner.prototype.storeCycles = function(numCycles=1) {
|
|||||||
this.storedCycles += numCycles;
|
this.storedCycles += numCycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Bladeburner.prototype.process = function() {
|
Bladeburner.prototype.process = function() {
|
||||||
// Edge case condition...if Operation Daedalus is complete trigger the BitNode
|
// Edge case condition...if Operation Daedalus is complete trigger the BitNode
|
||||||
if (redPillFlag === false && this.blackops.hasOwnProperty("Operation Daedalus")) {
|
if (redPillFlag === false && this.blackops.hasOwnProperty("Operation Daedalus")) {
|
||||||
@ -308,13 +316,13 @@ Bladeburner.prototype.process = function() {
|
|||||||
dialogBoxCreate(msg);
|
dialogBoxCreate(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.resetAction();
|
resetAction(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the Player has no Stamina, set action to idle
|
// If the Player has no Stamina, set action to idle
|
||||||
if (this.stamina <= 0) {
|
if (this.stamina <= 0) {
|
||||||
this.log("Your Bladeburner action was cancelled because your stamina hit 0");
|
this.log("Your Bladeburner action was cancelled because your stamina hit 0");
|
||||||
this.resetAction();
|
resetAction(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A 'tick' for this mechanic is one second (= 5 game cycles)
|
// A 'tick' for this mechanic is one second (= 5 game cycles)
|
||||||
@ -352,7 +360,7 @@ Bladeburner.prototype.process = function() {
|
|||||||
this.randomEventCounter += getRandomInt(240, 600);
|
this.randomEventCounter += getRandomInt(240, 600);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.processAction(seconds);
|
processAction(this, Player, seconds);
|
||||||
|
|
||||||
// Automation
|
// Automation
|
||||||
if (this.automateEnabled) {
|
if (this.automateEnabled) {
|
||||||
@ -360,12 +368,12 @@ Bladeburner.prototype.process = function() {
|
|||||||
if (this.stamina <= this.automateThreshLow) {
|
if (this.stamina <= this.automateThreshLow) {
|
||||||
if (this.action.name !== this.automateActionLow.name || this.action.type !== this.automateActionLow.type) {
|
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});
|
this.action = new ActionIdentifier({type: this.automateActionLow.type, name: this.automateActionLow.name});
|
||||||
this.startAction(this.action);
|
startAction(this, Player, this.action);
|
||||||
}
|
}
|
||||||
} else if (this.stamina >= this.automateThreshHigh) {
|
} else if (this.stamina >= this.automateThreshHigh) {
|
||||||
if (this.action.name !== this.automateActionHigh.name || this.action.type !== this.automateActionHigh.type) {
|
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});
|
this.action = new ActionIdentifier({type: this.automateActionHigh.type, name: this.automateActionHigh.name});
|
||||||
this.startAction(this.action);
|
startAction(this, Player, this.action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -397,34 +405,6 @@ Bladeburner.prototype.calculateStaminaPenalty = function() {
|
|||||||
return Math.min(1, this.stamina / (0.5 * this.maxStamina));
|
return Math.min(1, this.stamina / (0.5 * this.maxStamina));
|
||||||
}
|
}
|
||||||
|
|
||||||
Bladeburner.prototype.changeRank = function(change) {
|
|
||||||
if (isNaN(change)) {throw new Error("NaN passed into Bladeburner.changeRank()");}
|
|
||||||
this.rank += change;
|
|
||||||
if (this.rank < 0) {this.rank = 0;}
|
|
||||||
this.maxRank = Math.max(this.rank, this.maxRank);
|
|
||||||
|
|
||||||
var bladeburnersFactionName = "Bladeburners";
|
|
||||||
if (factionExists(bladeburnersFactionName)) {
|
|
||||||
var bladeburnerFac = Factions[bladeburnersFactionName];
|
|
||||||
if (!(bladeburnerFac instanceof Faction)) {
|
|
||||||
throw new Error("Could not properly get Bladeburner Faction object in Bladeburner UI Overview Faction button");
|
|
||||||
}
|
|
||||||
if (bladeburnerFac.isMember) {
|
|
||||||
var favorBonus = 1 + (bladeburnerFac.favor / 100);
|
|
||||||
bladeburnerFac.playerReputation += (BladeburnerConstants.RankToFactionRepFactor * change * Player.faction_rep_mult * favorBonus);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gain skill points
|
|
||||||
var rankNeededForSp = (this.totalSkillPoints+1) * BladeburnerConstants.RanksPerSkillPoint;
|
|
||||||
if (this.maxRank >= rankNeededForSp) {
|
|
||||||
// Calculate how many skill points to gain
|
|
||||||
var gainedSkillPoints = Math.floor((this.maxRank - rankNeededForSp) / BladeburnerConstants.RanksPerSkillPoint + 1);
|
|
||||||
this.skillPoints += gainedSkillPoints;
|
|
||||||
this.totalSkillPoints += gainedSkillPoints;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.getCurrentCity = function() {
|
Bladeburner.prototype.getCurrentCity = function() {
|
||||||
var city = this.cities[this.city];
|
var city = this.cities[this.city];
|
||||||
if (!(city instanceof City)) {
|
if (!(city instanceof City)) {
|
||||||
@ -433,55 +413,6 @@ Bladeburner.prototype.getCurrentCity = function() {
|
|||||||
return city;
|
return city;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bladeburner.prototype.resetSkillMultipliers = function() {
|
|
||||||
this.skillMultipliers = {
|
|
||||||
successChanceAll: 1,
|
|
||||||
successChanceStealth: 1,
|
|
||||||
successChanceKill: 1,
|
|
||||||
successChanceContract: 1,
|
|
||||||
successChanceOperation: 1,
|
|
||||||
successChanceEstimate: 1,
|
|
||||||
actionTime: 1,
|
|
||||||
effHack: 1,
|
|
||||||
effStr: 1,
|
|
||||||
effDef: 1,
|
|
||||||
effDex: 1,
|
|
||||||
effAgi: 1,
|
|
||||||
effCha: 1,
|
|
||||||
effInt: 1,
|
|
||||||
stamina: 1,
|
|
||||||
money: 1,
|
|
||||||
expGain: 1,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.updateSkillMultipliers = function() {
|
|
||||||
this.resetSkillMultipliers();
|
|
||||||
for (var skillName in this.skills) {
|
|
||||||
if (this.skills.hasOwnProperty(skillName)) {
|
|
||||||
var skill = Skills[skillName];
|
|
||||||
if (skill == null) {
|
|
||||||
throw new Error("Could not find Skill Object for: " + skillName);
|
|
||||||
}
|
|
||||||
var level = this.skills[skillName];
|
|
||||||
if (level == null || level <= 0) {continue;} //Not upgraded
|
|
||||||
|
|
||||||
var multiplierNames = Object.keys(this.skillMultipliers);
|
|
||||||
for (var i = 0; i < multiplierNames.length; ++i) {
|
|
||||||
var multiplierName = multiplierNames[i];
|
|
||||||
if (skill[multiplierName] != null && !isNaN(skill[multiplierName])) {
|
|
||||||
var value = skill[multiplierName] * level;
|
|
||||||
var multiplierValue = 1 + (value / 100);
|
|
||||||
if (multiplierName === "actionTime") {
|
|
||||||
multiplierValue = 1 - (value / 100);
|
|
||||||
}
|
|
||||||
this.skillMultipliers[multiplierName] *= multiplierValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.upgradeSkill = function(skill) {
|
Bladeburner.prototype.upgradeSkill = function(skill) {
|
||||||
// This does NOT handle deduction of skill points
|
// This does NOT handle deduction of skill points
|
||||||
var skillName = skill.name;
|
var skillName = skill.name;
|
||||||
@ -493,35 +424,7 @@ Bladeburner.prototype.upgradeSkill = function(skill) {
|
|||||||
if (isNaN(this.skills[skillName]) || this.skills[skillName] < 0) {
|
if (isNaN(this.skills[skillName]) || this.skills[skillName] < 0) {
|
||||||
throw new Error("Level of Skill " + skillName + " is invalid: " + this.skills[skillName]);
|
throw new Error("Level of Skill " + skillName + " is invalid: " + this.skills[skillName]);
|
||||||
}
|
}
|
||||||
this.updateSkillMultipliers();
|
updateSkillMultipliers(this);
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.getActionObject = function(actionId) {
|
|
||||||
/**
|
|
||||||
* Given an ActionIdentifier object, returns the corresponding
|
|
||||||
* GeneralAction, Contract, Operation, or BlackOperation object
|
|
||||||
*/
|
|
||||||
switch (actionId.type) {
|
|
||||||
case ActionTypes["Contract"]:
|
|
||||||
return this.contracts[actionId.name];
|
|
||||||
case ActionTypes["Operation"]:
|
|
||||||
return this.operations[actionId.name];
|
|
||||||
case ActionTypes["BlackOp"]:
|
|
||||||
case ActionTypes["BlackOperation"]:
|
|
||||||
return BlackOperations[actionId.name];
|
|
||||||
case ActionTypes["Training"]:
|
|
||||||
return GeneralActions["Training"];
|
|
||||||
case ActionTypes["Field Analysis"]:
|
|
||||||
return GeneralActions["Field Analysis"];
|
|
||||||
case ActionTypes["Recruitment"]:
|
|
||||||
return GeneralActions["Recruitment"];
|
|
||||||
case ActionTypes["Diplomacy"]:
|
|
||||||
return GeneralActions["Diplomacy"];
|
|
||||||
case ActionTypes["Hyperbolic Regeneration Chamber"]:
|
|
||||||
return GeneralActions["Hyperbolic Regeneration Chamber"];
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the player to the "IDLE" action
|
// Sets the player to the "IDLE" action
|
||||||
@ -529,448 +432,8 @@ Bladeburner.prototype.resetAction = function() {
|
|||||||
this.action = new ActionIdentifier({type:ActionTypes.Idle});
|
this.action = new ActionIdentifier({type:ActionTypes.Idle});
|
||||||
}
|
}
|
||||||
|
|
||||||
Bladeburner.prototype.startAction = function(actionId) {
|
|
||||||
if (actionId == null) {return;}
|
|
||||||
this.action = actionId;
|
|
||||||
this.actionTimeCurrent = 0;
|
|
||||||
switch (actionId.type) {
|
|
||||||
case ActionTypes["Idle"]:
|
|
||||||
this.actionTimeToComplete = 0;
|
|
||||||
break;
|
|
||||||
case ActionTypes["Contract"]:
|
|
||||||
try {
|
|
||||||
var action = this.getActionObject(actionId);
|
|
||||||
if (action == null) {
|
|
||||||
throw new Error("Failed to get Contract Object for: " + actionId.name);
|
|
||||||
}
|
|
||||||
if (action.count < 1) {return this.resetAction();}
|
|
||||||
this.actionTimeToComplete = action.getActionTime(this);
|
|
||||||
} catch(e) {
|
|
||||||
exceptionAlert(e);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ActionTypes["Operation"]:
|
|
||||||
try {
|
|
||||||
var action = this.getActionObject(actionId);
|
|
||||||
if (action == null) {
|
|
||||||
throw new Error ("Failed to get Operation Object for: " + actionId.name);
|
|
||||||
}
|
|
||||||
if (action.count < 1) {return this.resetAction();}
|
|
||||||
if (actionId.name === "Raid" && this.getCurrentCity().commsEst === 0) {return this.resetAction();}
|
|
||||||
this.actionTimeToComplete = action.getActionTime(this);
|
|
||||||
} catch(e) {
|
|
||||||
exceptionAlert(e);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ActionTypes["BlackOp"]:
|
|
||||||
case ActionTypes["BlackOperation"]:
|
|
||||||
try {
|
|
||||||
// Safety measure - don't repeat BlackOps that are already done
|
|
||||||
if (this.blackops[actionId.name] != null) {
|
|
||||||
this.resetAction();
|
|
||||||
this.log("Error: Tried to start a Black Operation that had already been completed");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
var action = this.getActionObject(actionId);
|
|
||||||
if (action == null) {
|
|
||||||
throw new Error("Failed to get BlackOperation object for: " + actionId.name);
|
|
||||||
}
|
|
||||||
this.actionTimeToComplete = action.getActionTime(this);
|
|
||||||
} catch(e) {
|
|
||||||
exceptionAlert(e);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ActionTypes["Recruitment"]:
|
|
||||||
this.actionTimeToComplete = getRecruitmentTime(this, Player);
|
|
||||||
break;
|
|
||||||
case ActionTypes["Training"]:
|
|
||||||
case ActionTypes["FieldAnalysis"]:
|
|
||||||
case ActionTypes["Field Analysis"]:
|
|
||||||
this.actionTimeToComplete = 30;
|
|
||||||
break;
|
|
||||||
case ActionTypes["Diplomacy"]:
|
|
||||||
case ActionTypes["Hyperbolic Regeneration Chamber"]:
|
|
||||||
this.actionTimeToComplete = 60;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Error("Invalid Action Type in Bladeburner.startAction(): " + actionId.type);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.processAction = function(seconds) {
|
|
||||||
if (this.action.type === ActionTypes["Idle"]) {return;}
|
|
||||||
if (this.actionTimeToComplete <= 0) {
|
|
||||||
throw new Error(`Invalid actionTimeToComplete value: ${this.actionTimeToComplete}, type; ${this.action.type}`);
|
|
||||||
}
|
|
||||||
if (!(this.action instanceof ActionIdentifier)) {
|
|
||||||
throw new Error("Bladeburner.action is not an ActionIdentifier Object");
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the previous action went past its completion time, add to the next action
|
|
||||||
// This is not added inmediatly in case the automation changes the action
|
|
||||||
this.actionTimeCurrent += seconds + this.actionTimeOverflow;
|
|
||||||
this.actionTimeOverflow = 0;
|
|
||||||
if (this.actionTimeCurrent >= this.actionTimeToComplete) {
|
|
||||||
this.actionTimeOverflow = this.actionTimeCurrent - this.actionTimeToComplete;
|
|
||||||
return this.completeAction();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.completeAction = function() {
|
|
||||||
switch (this.action.type) {
|
|
||||||
case ActionTypes["Contract"]:
|
|
||||||
case ActionTypes["Operation"]:
|
|
||||||
try {
|
|
||||||
var isOperation = (this.action.type === ActionTypes["Operation"]);
|
|
||||||
var action = this.getActionObject(this.action);
|
|
||||||
if (action == null) {
|
|
||||||
throw new Error("Failed to get Contract/Operation Object for: " + this.action.name);
|
|
||||||
}
|
|
||||||
var difficulty = action.getDifficulty();
|
|
||||||
var difficultyMultiplier = Math.pow(difficulty, BladeburnerConstants.DiffMultExponentialFactor) + difficulty / BladeburnerConstants.DiffMultLinearFactor;
|
|
||||||
var rewardMultiplier = Math.pow(action.rewardFac, action.level-1);
|
|
||||||
|
|
||||||
// Stamina loss is based on difficulty
|
|
||||||
this.stamina -= (BladeburnerConstants.BaseStaminaLoss * difficultyMultiplier);
|
|
||||||
if (this.stamina < 0) {this.stamina = 0;}
|
|
||||||
|
|
||||||
// Process Contract/Operation success/failure
|
|
||||||
if (action.attempt(this)) {
|
|
||||||
gainActionStats(this, Player, action, true);
|
|
||||||
++action.successes;
|
|
||||||
--action.count;
|
|
||||||
|
|
||||||
// Earn money for contracts
|
|
||||||
var moneyGain = 0;
|
|
||||||
if (!isOperation) {
|
|
||||||
moneyGain = BladeburnerConstants.ContractBaseMoneyGain * rewardMultiplier * this.skillMultipliers.money;
|
|
||||||
Player.gainMoney(moneyGain);
|
|
||||||
Player.recordMoneySource(moneyGain, "bladeburner");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isOperation) {
|
|
||||||
action.setMaxLevel(BladeburnerConstants.OperationSuccessesPerLevel);
|
|
||||||
} else {
|
|
||||||
action.setMaxLevel(BladeburnerConstants.ContractSuccessesPerLevel);
|
|
||||||
}
|
|
||||||
if (action.rankGain) {
|
|
||||||
var gain = addOffset(action.rankGain * rewardMultiplier * BitNodeMultipliers.BladeburnerRank, 10);
|
|
||||||
this.changeRank(gain);
|
|
||||||
if (isOperation && this.logging.ops) {
|
|
||||||
this.log(action.name + " successfully completed! Gained " + formatNumber(gain, 3) + " rank");
|
|
||||||
} else if (!isOperation && this.logging.contracts) {
|
|
||||||
this.log(action.name + " contract successfully completed! Gained " + formatNumber(gain, 3) + " rank and " + numeralWrapper.formatMoney(moneyGain));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
isOperation ? this.completeOperation(true) : this.completeContract(true);
|
|
||||||
} else {
|
|
||||||
gainActionStats(this, Player, action, false);
|
|
||||||
++action.failures;
|
|
||||||
var loss = 0, damage = 0;
|
|
||||||
if (action.rankLoss) {
|
|
||||||
loss = addOffset(action.rankLoss * rewardMultiplier, 10);
|
|
||||||
this.changeRank(-1 * loss);
|
|
||||||
}
|
|
||||||
if (action.hpLoss) {
|
|
||||||
damage = action.hpLoss * difficultyMultiplier;
|
|
||||||
damage = Math.ceil(addOffset(damage, 10));
|
|
||||||
this.hpLost += damage;
|
|
||||||
const cost = calculateHospitalizationCost(Player, damage);
|
|
||||||
if (Player.takeDamage(damage)) {
|
|
||||||
++this.numHosp;
|
|
||||||
this.moneyLost += cost;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var logLossText = "";
|
|
||||||
if (loss > 0) {logLossText += "Lost " + formatNumber(loss, 3) + " rank. ";}
|
|
||||||
if (damage > 0) {logLossText += "Took " + formatNumber(damage, 0) + " damage.";}
|
|
||||||
if (isOperation && this.logging.ops) {
|
|
||||||
this.log(action.name + " failed! " + logLossText);
|
|
||||||
} else if (!isOperation && this.logging.contracts) {
|
|
||||||
this.log(action.name + " contract failed! " + logLossText);
|
|
||||||
}
|
|
||||||
isOperation ? this.completeOperation(false) : this.completeContract(false);
|
|
||||||
}
|
|
||||||
if (action.autoLevel) {action.level = action.maxLevel;} // Autolevel
|
|
||||||
this.startAction(this.action); // Repeat action
|
|
||||||
} catch(e) {
|
|
||||||
exceptionAlert(e);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ActionTypes["BlackOp"]:
|
|
||||||
case ActionTypes["BlackOperation"]:
|
|
||||||
try {
|
|
||||||
var action = this.getActionObject(this.action);
|
|
||||||
if (action == null || !(action instanceof BlackOperation)) {
|
|
||||||
throw new Error("Failed to get BlackOperation Object for: " + this.action.name);
|
|
||||||
}
|
|
||||||
var difficulty = action.getDifficulty();
|
|
||||||
var difficultyMultiplier = Math.pow(difficulty, BladeburnerConstants.DiffMultExponentialFactor) + difficulty / BladeburnerConstants.DiffMultLinearFactor;
|
|
||||||
|
|
||||||
// Stamina loss is based on difficulty
|
|
||||||
this.stamina -= (BladeburnerConstants.BaseStaminaLoss * difficultyMultiplier);
|
|
||||||
if (this.stamina < 0) {this.stamina = 0;}
|
|
||||||
|
|
||||||
// Team loss variables
|
|
||||||
var teamCount = action.teamCount, teamLossMax;
|
|
||||||
|
|
||||||
if (action.attempt(this)) {
|
|
||||||
gainActionStats(this, Player, action, true);
|
|
||||||
action.count = 0;
|
|
||||||
this.blackops[action.name] = true;
|
|
||||||
var rankGain = 0;
|
|
||||||
if (action.rankGain) {
|
|
||||||
rankGain = addOffset(action.rankGain * BitNodeMultipliers.BladeburnerRank, 10);
|
|
||||||
this.changeRank(rankGain);
|
|
||||||
}
|
|
||||||
teamLossMax = Math.ceil(teamCount/2);
|
|
||||||
|
|
||||||
// Operation Daedalus
|
|
||||||
if (action.name === "Operation Daedalus") {
|
|
||||||
this.resetAction();
|
|
||||||
return hackWorldDaemon(Player.bitNodeN);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.logging.blackops) {
|
|
||||||
this.log(action.name + " successful! Gained " + formatNumber(rankGain, 1) + " rank");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gainActionStats(this, Player, action, false);
|
|
||||||
var rankLoss = 0, damage = 0;
|
|
||||||
if (action.rankLoss) {
|
|
||||||
rankLoss = addOffset(action.rankLoss, 10);
|
|
||||||
this.changeRank(-1 * rankLoss);
|
|
||||||
}
|
|
||||||
if (action.hpLoss) {
|
|
||||||
damage = action.hpLoss * difficultyMultiplier;
|
|
||||||
damage = Math.ceil(addOffset(damage, 10));
|
|
||||||
const cost = calculateHospitalizationCost(Player, damage);
|
|
||||||
if (Player.takeDamage(damage)) {
|
|
||||||
++this.numHosp;
|
|
||||||
this.moneyLost += cost;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
teamLossMax = Math.floor(teamCount);
|
|
||||||
|
|
||||||
if (this.logging.blackops) {
|
|
||||||
this.log(action.name + " failed! Lost " + formatNumber(rankLoss, 1) + " rank and took " + formatNumber(damage, 0) + " damage");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.resetAction(); // Stop regardless of success or fail
|
|
||||||
|
|
||||||
// Calculate team lossses
|
|
||||||
if (teamCount >= 1) {
|
|
||||||
var losses = getRandomInt(1, teamLossMax);
|
|
||||||
this.teamSize -= losses;
|
|
||||||
this.teamLost += losses;
|
|
||||||
if (this.logging.blackops) {
|
|
||||||
this.log("You lost " + formatNumber(losses, 0) + " team members during " + action.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch(e) {
|
|
||||||
exceptionAlert(e);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ActionTypes["Training"]:
|
|
||||||
this.stamina -= (0.5 * BladeburnerConstants.BaseStaminaLoss);
|
|
||||||
var strExpGain = 30 * Player.strength_exp_mult,
|
|
||||||
defExpGain = 30 * Player.defense_exp_mult,
|
|
||||||
dexExpGain = 30 * Player.dexterity_exp_mult,
|
|
||||||
agiExpGain = 30 * Player.agility_exp_mult,
|
|
||||||
staminaGain = 0.04 * this.skillMultipliers.stamina;
|
|
||||||
Player.gainStrengthExp(strExpGain);
|
|
||||||
Player.gainDefenseExp(defExpGain);
|
|
||||||
Player.gainDexterityExp(dexExpGain);
|
|
||||||
Player.gainAgilityExp(agiExpGain);
|
|
||||||
this.staminaBonus += (staminaGain);
|
|
||||||
if (this.logging.general) {
|
|
||||||
this.log("Training completed. Gained: " +
|
|
||||||
formatNumber(strExpGain, 1) + " str exp, " +
|
|
||||||
formatNumber(defExpGain, 1) + " def exp, " +
|
|
||||||
formatNumber(dexExpGain, 1) + " dex exp, " +
|
|
||||||
formatNumber(agiExpGain, 1) + " agi exp, " +
|
|
||||||
formatNumber(staminaGain, 3) + " max stamina");
|
|
||||||
}
|
|
||||||
this.startAction(this.action); // Repeat action
|
|
||||||
break;
|
|
||||||
case ActionTypes["FieldAnalysis"]:
|
|
||||||
case ActionTypes["Field Analysis"]:
|
|
||||||
// Does not use stamina. Effectiveness depends on hacking, int, and cha
|
|
||||||
var eff = 0.04 * Math.pow(Player.hacking_skill, 0.3) +
|
|
||||||
0.04 * Math.pow(Player.intelligence, 0.9) +
|
|
||||||
0.02 * Math.pow(Player.charisma, 0.3);
|
|
||||||
eff *= Player.bladeburner_analysis_mult;
|
|
||||||
if (isNaN(eff) || eff < 0) {
|
|
||||||
throw new Error("Field Analysis Effectiveness calculated to be NaN or negative");
|
|
||||||
}
|
|
||||||
var hackingExpGain = 20 * Player.hacking_exp_mult,
|
|
||||||
charismaExpGain = 20 * Player.charisma_exp_mult;
|
|
||||||
Player.gainHackingExp(hackingExpGain);
|
|
||||||
Player.gainIntelligenceExp(BladeburnerConstants.BaseIntGain);
|
|
||||||
Player.gainCharismaExp(charismaExpGain);
|
|
||||||
this.changeRank(0.1 * BitNodeMultipliers.BladeburnerRank);
|
|
||||||
this.getCurrentCity().improvePopulationEstimateByPercentage(eff * this.skillMultipliers.successChanceEstimate);
|
|
||||||
if (this.logging.general) {
|
|
||||||
this.log("Field analysis completed. Gained 0.1 rank, " + formatNumber(hackingExpGain, 1) + " hacking exp, and " + formatNumber(charismaExpGain, 1) + " charisma exp");
|
|
||||||
}
|
|
||||||
this.startAction(this.action); // Repeat action
|
|
||||||
break;
|
|
||||||
case ActionTypes["Recruitment"]:
|
|
||||||
var successChance = getRecruitmentSuccessChance(this, Player);
|
|
||||||
if (Math.random() < successChance) {
|
|
||||||
var expGain = 2 * BladeburnerConstants.BaseStatGain * this.actionTimeToComplete;
|
|
||||||
Player.gainCharismaExp(expGain);
|
|
||||||
++this.teamSize;
|
|
||||||
if (this.logging.general) {
|
|
||||||
this.log("Successfully recruited a team member! Gained " + formatNumber(expGain, 1) + " charisma exp");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var expGain = BladeburnerConstants.BaseStatGain * this.actionTimeToComplete;
|
|
||||||
Player.gainCharismaExp(expGain);
|
|
||||||
if (this.logging.general) {
|
|
||||||
this.log("Failed to recruit a team member. Gained " + formatNumber(expGain, 1) + " charisma exp");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.startAction(this.action); // Repeat action
|
|
||||||
break;
|
|
||||||
case ActionTypes["Diplomacy"]:
|
|
||||||
var eff = getDiplomacyEffectiveness(this, Player);
|
|
||||||
this.getCurrentCity().chaos *= eff;
|
|
||||||
if (this.getCurrentCity().chaos < 0) { this.getCurrentCity().chaos = 0; }
|
|
||||||
if (this.logging.general) {
|
|
||||||
this.log(`Diplomacy completed. Chaos levels in the current city fell by ${numeralWrapper.formatPercentage(1 - eff)}`);
|
|
||||||
}
|
|
||||||
this.startAction(this.action); // Repeat Action
|
|
||||||
break;
|
|
||||||
case ActionTypes["Hyperbolic Regeneration Chamber"]: {
|
|
||||||
Player.regenerateHp(BladeburnerConstants.HrcHpGain);
|
|
||||||
|
|
||||||
const staminaGain = this.maxStamina * (BladeburnerConstants.HrcStaminaGain / 100);
|
|
||||||
this.stamina = Math.min(this.maxStamina, this.stamina + staminaGain);
|
|
||||||
this.startAction(this.action);
|
|
||||||
if (this.logging.general) {
|
|
||||||
this.log(`Rested in Hyperbolic Regeneration Chamber. Restored ${BladeburnerConstants.HrcHpGain} HP and gained ${numeralWrapper.formatStamina(staminaGain)} stamina`);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
console.error(`Bladeburner.completeAction() called for invalid action: ${this.action.type}`);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.completeContract = function(success) {
|
|
||||||
if (this.action.type !== ActionTypes.Contract) {
|
|
||||||
throw new Error("completeContract() called even though current action is not a Contract");
|
|
||||||
}
|
|
||||||
var city = this.getCurrentCity();
|
|
||||||
if (success) {
|
|
||||||
switch (this.action.name) {
|
|
||||||
case "Tracking":
|
|
||||||
// Increase estimate accuracy by a relatively small amount
|
|
||||||
city.improvePopulationEstimateByCount(getRandomInt(100, 1e3));
|
|
||||||
break;
|
|
||||||
case "Bounty Hunter":
|
|
||||||
city.changePopulationByCount(-1, {estChange:-1});
|
|
||||||
city.changeChaosByCount(0.02);
|
|
||||||
break;
|
|
||||||
case "Retirement":
|
|
||||||
city.changePopulationByCount(-1, {estChange:-1});
|
|
||||||
city.changeChaosByCount(0.04);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Error("Invalid Action name in completeContract: " + this.action.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bladeburner.prototype.completeOperation = function(success) {
|
|
||||||
if (this.action.type !== ActionTypes.Operation) {
|
|
||||||
throw new Error("completeOperation() called even though current action is not an Operation");
|
|
||||||
}
|
|
||||||
var action = this.getActionObject(this.action);
|
|
||||||
if (action == null) {
|
|
||||||
throw new Error("Failed to get Contract/Operation Object for: " + this.action.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate team losses
|
|
||||||
var teamCount = action.teamCount, max;
|
|
||||||
if (teamCount >= 1) {
|
|
||||||
if (success) {
|
|
||||||
max = Math.ceil(teamCount/2);
|
|
||||||
} else {
|
|
||||||
max = Math.floor(teamCount)
|
|
||||||
}
|
|
||||||
var losses = getRandomInt(0, max);
|
|
||||||
this.teamSize -= losses;
|
|
||||||
this.teamLost += losses;
|
|
||||||
if (this.logging.ops && losses > 0) {
|
|
||||||
this.log("Lost " + formatNumber(losses, 0) + " team members during this " + action.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var city = this.getCurrentCity();
|
|
||||||
switch (action.name) {
|
|
||||||
case "Investigation":
|
|
||||||
if (success) {
|
|
||||||
city.improvePopulationEstimateByPercentage(0.4 * this.skillMultipliers.successChanceEstimate);
|
|
||||||
if (Math.random() < (0.02 * this.skillMultipliers.successChanceEstimate)) {
|
|
||||||
city.improveCommunityEstimate(1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
triggerPotentialMigration(this, this.city, 0.1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "Undercover Operation":
|
|
||||||
if (success) {
|
|
||||||
city.improvePopulationEstimateByPercentage(0.8 * this.skillMultipliers.successChanceEstimate);
|
|
||||||
if (Math.random() < (0.02 * this.skillMultipliers.successChanceEstimate)) {
|
|
||||||
city.improveCommunityEstimate(1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
triggerPotentialMigration(this, this.city, 0.15);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "Sting Operation":
|
|
||||||
if (success) {
|
|
||||||
city.changePopulationByPercentage(-0.1, {changeEstEqually:true, nonZero:true});
|
|
||||||
}
|
|
||||||
city.changeChaosByCount(0.1);
|
|
||||||
break;
|
|
||||||
case "Raid":
|
|
||||||
if (success) {
|
|
||||||
city.changePopulationByPercentage(-1, {changeEstEqually:true, nonZero:true});
|
|
||||||
--city.comms;
|
|
||||||
--city.commsEst;
|
|
||||||
} else {
|
|
||||||
var change = getRandomInt(-10, -5) / 10;
|
|
||||||
city.changePopulationByPercentage(change, {nonZero:true});
|
|
||||||
}
|
|
||||||
city.changeChaosByPercentage(getRandomInt(1, 5));
|
|
||||||
break;
|
|
||||||
case "Stealth Retirement Operation":
|
|
||||||
if (success) {
|
|
||||||
city.changePopulationByPercentage(-0.5, {changeEstEqually:true,nonZero:true});
|
|
||||||
}
|
|
||||||
city.changeChaosByPercentage(getRandomInt(-3, -1));
|
|
||||||
break;
|
|
||||||
case "Assassination":
|
|
||||||
if (success) {
|
|
||||||
city.changePopulationByCount(-1, {estChange:-1});
|
|
||||||
}
|
|
||||||
city.changeChaosByPercentage(getRandomInt(-5, 5));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Error("Invalid Action name in completeOperation: " + this.action.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/////////////////////////////Unconvertable for now//////////////////////////////
|
//////////////////////////// Unconvertable for now /////////////////////////////
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Bladeburner Console Window
|
// Bladeburner Console Window
|
||||||
@ -995,7 +458,7 @@ Bladeburner.prototype.executeConsoleCommands = function(commands) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/////////////////////////////////Netscript Fns//////////////////////////////////
|
//////////////////////////////// Netscript Fns /////////////////////////////////
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Bladeburner.prototype.getTypeAndNameFromActionId = function(actionId) {
|
Bladeburner.prototype.getTypeAndNameFromActionId = function(actionId) {
|
||||||
@ -1044,7 +507,7 @@ Bladeburner.prototype.startActionNetscriptFn = function(type, name, workerScript
|
|||||||
// Special logic for Black Ops
|
// Special logic for Black Ops
|
||||||
if (actionId.type === ActionTypes["BlackOp"]) {
|
if (actionId.type === ActionTypes["BlackOp"]) {
|
||||||
// Can't start a BlackOp if you don't have the required rank
|
// Can't start a BlackOp if you don't have the required rank
|
||||||
let action = this.getActionObject(actionId);
|
let action = getActionObject(this, actionId);
|
||||||
if (action.reqdRank > this.rank) {
|
if (action.reqdRank > this.rank) {
|
||||||
workerScript.log("bladeburner.startAction", `Insufficient rank to start Black Op '${actionId.name}'.`);
|
workerScript.log("bladeburner.startAction", `Insufficient rank to start Black Op '${actionId.name}'.`);
|
||||||
return false;
|
return false;
|
||||||
@ -1080,11 +543,11 @@ Bladeburner.prototype.startActionNetscriptFn = function(type, name, workerScript
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.startAction(actionId);
|
startAction(this, Player, actionId);
|
||||||
workerScript.log("bladeburner.startAction", `Starting bladeburner action with type '${type}' and name ${name}"`);
|
workerScript.log("bladeburner.startAction", `Starting bladeburner action with type '${type}' and name ${name}"`);
|
||||||
return true;
|
return true;
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
this.resetAction();
|
resetAction(this);
|
||||||
workerScript.log("bladeburner.startAction", errorLogText);
|
workerScript.log("bladeburner.startAction", errorLogText);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1098,7 +561,7 @@ Bladeburner.prototype.getActionTimeNetscriptFn = function(type, name, workerScri
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const actionObj = this.getActionObject(actionId);
|
const actionObj = getActionObject(this, actionId);
|
||||||
if (actionObj == null) {
|
if (actionObj == null) {
|
||||||
workerScript.log("bladeburner.getActionTime", errorLogText);
|
workerScript.log("bladeburner.getActionTime", errorLogText);
|
||||||
return -1;
|
return -1;
|
||||||
@ -1133,7 +596,7 @@ Bladeburner.prototype.getActionEstimatedSuccessChanceNetscriptFn = function(type
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const actionObj = this.getActionObject(actionId);
|
const actionObj = getActionObject(this, actionId);
|
||||||
if (actionObj == null) {
|
if (actionObj == null) {
|
||||||
workerScript.log("bladeburner.getActionEstimatedSuccessChance", errorLogText);
|
workerScript.log("bladeburner.getActionEstimatedSuccessChance", errorLogText);
|
||||||
return -1;
|
return -1;
|
||||||
@ -1165,7 +628,7 @@ Bladeburner.prototype.getActionCountRemainingNetscriptFn = function(type, name,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const actionObj = this.getActionObject(actionId);
|
const actionObj = getActionObject(this, actionId);
|
||||||
if (actionObj == null) {
|
if (actionObj == null) {
|
||||||
workerScript.log("bladeburner.getActionCountRemaining", errorLogText);
|
workerScript.log("bladeburner.getActionCountRemaining", errorLogText);
|
||||||
return -1;
|
return -1;
|
||||||
@ -1261,7 +724,7 @@ Bladeburner.prototype.getTeamSizeNetscriptFn = function(type, name, workerScript
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const actionObj = this.getActionObject(actionId);
|
const actionObj = getActionObject(this, actionId);
|
||||||
if (actionObj == null) {
|
if (actionObj == null) {
|
||||||
workerScript.log("bladeburner.getTeamSize", errorLogText);
|
workerScript.log("bladeburner.getTeamSize", errorLogText);
|
||||||
return -1;
|
return -1;
|
||||||
@ -1291,7 +754,7 @@ Bladeburner.prototype.setTeamSizeNetscriptFn = function(type, name, size, worker
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const actionObj = this.getActionObject(actionId);
|
const actionObj = getActionObject(this, actionId);
|
||||||
if (actionObj == null) {
|
if (actionObj == null) {
|
||||||
workerScript.log("bladeburner.setTeamSize", errorLogText);
|
workerScript.log("bladeburner.setTeamSize", errorLogText);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -7,6 +7,7 @@ import { IActionIdentifier } from "./IActionIdentifier";
|
|||||||
import { ActionIdentifier } from "./ActionIdentifier";
|
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 { 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";
|
||||||
@ -18,6 +19,13 @@ import { ConsoleHelpText } from "./data/Help";
|
|||||||
import { exceptionAlert } from "../../utils/helpers/exceptionAlert";
|
import { exceptionAlert } from "../../utils/helpers/exceptionAlert";
|
||||||
import { getRandomInt } from "../../utils/helpers/getRandomInt";
|
import { getRandomInt } from "../../utils/helpers/getRandomInt";
|
||||||
import { BladeburnerConstants } from "./data/Constants";
|
import { BladeburnerConstants } from "./data/Constants";
|
||||||
|
import { numeralWrapper } from "../ui/numeralFormat";
|
||||||
|
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||||
|
import { addOffset } from "../../utils/helpers/addOffset";
|
||||||
|
import { Faction } from "../Faction/Faction";
|
||||||
|
import { Factions, factionExists } from "../Faction/Factions";
|
||||||
|
import { calculateHospitalizationCost } from "../Hospital/Hospital";
|
||||||
|
import { hackWorldDaemon } from "../RedPill";
|
||||||
|
|
||||||
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;}
|
||||||
@ -104,7 +112,7 @@ export function getActionIdFromTypeAndName(bladeburner: IBladeburner, type: stri
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function executeStartConsoleCommand(bladeburner: IBladeburner, args: string[]): void {
|
export function executeStartConsoleCommand(bladeburner: IBladeburner, player: IPlayer, args: string[]): void {
|
||||||
if (args.length !== 3) {
|
if (args.length !== 3) {
|
||||||
bladeburner.postToConsole("Invalid usage of 'start' console command: start [type] [name]");
|
bladeburner.postToConsole("Invalid usage of 'start' console command: start [type] [name]");
|
||||||
bladeburner.postToConsole("Use 'help start' for more info");
|
bladeburner.postToConsole("Use 'help start' for more info");
|
||||||
@ -117,7 +125,7 @@ export function executeStartConsoleCommand(bladeburner: IBladeburner, args: stri
|
|||||||
if (GeneralActions[name] != null) {
|
if (GeneralActions[name] != null) {
|
||||||
bladeburner.action.type = ActionTypes[name];
|
bladeburner.action.type = ActionTypes[name];
|
||||||
bladeburner.action.name = name;
|
bladeburner.action.name = name;
|
||||||
bladeburner.startAction(bladeburner.action);
|
startAction(bladeburner,player, bladeburner.action);
|
||||||
} else {
|
} else {
|
||||||
bladeburner.postToConsole("Invalid action name specified: " + args[2]);
|
bladeburner.postToConsole("Invalid action name specified: " + args[2]);
|
||||||
}
|
}
|
||||||
@ -127,7 +135,7 @@ export function executeStartConsoleCommand(bladeburner: IBladeburner, args: stri
|
|||||||
if (bladeburner.contracts[name] != null) {
|
if (bladeburner.contracts[name] != null) {
|
||||||
bladeburner.action.type = ActionTypes.Contract;
|
bladeburner.action.type = ActionTypes.Contract;
|
||||||
bladeburner.action.name = name;
|
bladeburner.action.name = name;
|
||||||
bladeburner.startAction(bladeburner.action);
|
startAction(bladeburner,player, bladeburner.action);
|
||||||
} else {
|
} else {
|
||||||
bladeburner.postToConsole("Invalid contract name specified: " + args[2]);
|
bladeburner.postToConsole("Invalid contract name specified: " + args[2]);
|
||||||
}
|
}
|
||||||
@ -139,7 +147,7 @@ export function executeStartConsoleCommand(bladeburner: IBladeburner, args: stri
|
|||||||
if (bladeburner.operations[name] != null) {
|
if (bladeburner.operations[name] != null) {
|
||||||
bladeburner.action.type = ActionTypes.Operation;
|
bladeburner.action.type = ActionTypes.Operation;
|
||||||
bladeburner.action.name = name;
|
bladeburner.action.name = name;
|
||||||
bladeburner.startAction(bladeburner.action);
|
startAction(bladeburner,player, bladeburner.action);
|
||||||
} else {
|
} else {
|
||||||
bladeburner.postToConsole("Invalid Operation name specified: " + args[2]);
|
bladeburner.postToConsole("Invalid Operation name specified: " + args[2]);
|
||||||
}
|
}
|
||||||
@ -151,7 +159,7 @@ export function executeStartConsoleCommand(bladeburner: IBladeburner, args: stri
|
|||||||
if (BlackOperations[name] != null) {
|
if (BlackOperations[name] != null) {
|
||||||
bladeburner.action.type = ActionTypes.BlackOperation;
|
bladeburner.action.type = ActionTypes.BlackOperation;
|
||||||
bladeburner.action.name = name;
|
bladeburner.action.name = name;
|
||||||
bladeburner.startAction(bladeburner.action);
|
startAction(bladeburner,player, bladeburner.action);
|
||||||
} else {
|
} else {
|
||||||
bladeburner.postToConsole("Invalid BlackOp name specified: " + args[2]);
|
bladeburner.postToConsole("Invalid BlackOp name specified: " + args[2]);
|
||||||
}
|
}
|
||||||
@ -512,7 +520,7 @@ export function parseCommandArguments(command: string): string[] {
|
|||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function executeConsoleCommand(bladeburner: IBladeburner, command: string) {
|
export function executeConsoleCommand(bladeburner: IBladeburner, player: IPlayer, command: string) {
|
||||||
command = command.trim();
|
command = command.trim();
|
||||||
command = command.replace(/\s\s+/g, ' '); // Replace all whitespace w/ a single space
|
command = command.replace(/\s\s+/g, ' '); // Replace all whitespace w/ a single space
|
||||||
|
|
||||||
@ -537,7 +545,7 @@ export function executeConsoleCommand(bladeburner: IBladeburner, command: string
|
|||||||
executeSkillConsoleCommand(bladeburner, args);
|
executeSkillConsoleCommand(bladeburner, args);
|
||||||
break;
|
break;
|
||||||
case "start":
|
case "start":
|
||||||
executeStartConsoleCommand(bladeburner, args);
|
executeStartConsoleCommand(bladeburner, player, args);
|
||||||
break;
|
break;
|
||||||
case "stop":
|
case "stop":
|
||||||
bladeburner.resetAction();
|
bladeburner.resetAction();
|
||||||
@ -549,7 +557,7 @@ export function executeConsoleCommand(bladeburner: IBladeburner, command: string
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handles a potential series of commands (comm1; comm2; comm3;)
|
// Handles a potential series of commands (comm1; comm2; comm3;)
|
||||||
export function executeConsoleCommands(bladeburner: IBladeburner, commands: string): void {
|
export function executeConsoleCommands(bladeburner: IBladeburner, player: IPlayer, commands: string): void {
|
||||||
try {
|
try {
|
||||||
// Console History
|
// Console History
|
||||||
if (bladeburner.consoleHistory[bladeburner.consoleHistory.length-1] != commands) {
|
if (bladeburner.consoleHistory[bladeburner.consoleHistory.length-1] != commands) {
|
||||||
@ -561,7 +569,7 @@ export function executeConsoleCommands(bladeburner: IBladeburner, commands: stri
|
|||||||
|
|
||||||
const arrayOfCommands = commands.split(";");
|
const arrayOfCommands = commands.split(";");
|
||||||
for (let i = 0; i < arrayOfCommands.length; ++i) {
|
for (let i = 0; i < arrayOfCommands.length; ++i) {
|
||||||
executeConsoleCommand(bladeburner, arrayOfCommands[i]);
|
executeConsoleCommand(bladeburner, player, arrayOfCommands[i]);
|
||||||
}
|
}
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
exceptionAlert(e);
|
exceptionAlert(e);
|
||||||
@ -742,3 +750,564 @@ export function getRecruitmentTime(bladeburner: IBladeburner, player: IPlayer):
|
|||||||
const charismaFactor = Math.pow(effCharisma, 0.81) + effCharisma / 90;
|
const charismaFactor = Math.pow(effCharisma, 0.81) + effCharisma / 90;
|
||||||
return Math.max(10, Math.round(BladeburnerConstants.BaseRecruitmentTimeNeeded - charismaFactor));
|
return Math.max(10, Math.round(BladeburnerConstants.BaseRecruitmentTimeNeeded - charismaFactor));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function resetSkillMultipliers(bladeburner: IBladeburner): void {
|
||||||
|
bladeburner.skillMultipliers = {
|
||||||
|
successChanceAll: 1,
|
||||||
|
successChanceStealth: 1,
|
||||||
|
successChanceKill: 1,
|
||||||
|
successChanceContract: 1,
|
||||||
|
successChanceOperation: 1,
|
||||||
|
successChanceEstimate: 1,
|
||||||
|
actionTime: 1,
|
||||||
|
effHack: 1,
|
||||||
|
effStr: 1,
|
||||||
|
effDef: 1,
|
||||||
|
effDex: 1,
|
||||||
|
effAgi: 1,
|
||||||
|
effCha: 1,
|
||||||
|
effInt: 1,
|
||||||
|
stamina: 1,
|
||||||
|
money: 1,
|
||||||
|
expGain: 1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateSkillMultipliers(bladeburner: IBladeburner): void {
|
||||||
|
resetSkillMultipliers(bladeburner);
|
||||||
|
for (const skillName in bladeburner.skills) {
|
||||||
|
if (bladeburner.skills.hasOwnProperty(skillName)) {
|
||||||
|
const skill = Skills[skillName];
|
||||||
|
if (skill == null) {
|
||||||
|
throw new Error("Could not find Skill Object for: " + skillName);
|
||||||
|
}
|
||||||
|
const level = bladeburner.skills[skillName];
|
||||||
|
if (level == null || level <= 0) {continue;} //Not upgraded
|
||||||
|
|
||||||
|
const multiplierNames = Object.keys(bladeburner.skillMultipliers);
|
||||||
|
for (let i = 0; i < multiplierNames.length; ++i) {
|
||||||
|
const multiplierName = multiplierNames[i];
|
||||||
|
if (skill.getMultiplier(multiplierName) != null && !isNaN(skill.getMultiplier(multiplierName))) {
|
||||||
|
const value = skill.getMultiplier(multiplierName) * level;
|
||||||
|
let multiplierValue = 1 + (value / 100);
|
||||||
|
if (multiplierName === "actionTime") {
|
||||||
|
multiplierValue = 1 - (value / 100);
|
||||||
|
}
|
||||||
|
bladeburner.skillMultipliers[multiplierName] *= multiplierValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Sets the player to the "IDLE" action
|
||||||
|
export function resetAction(bladeburner: IBladeburner): void {
|
||||||
|
bladeburner.action = new ActionIdentifier({type:ActionTypes.Idle});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function completeOperation(bladeburner: IBladeburner, success: boolean): void {
|
||||||
|
if (bladeburner.action.type !== ActionTypes.Operation) {
|
||||||
|
throw new Error("completeOperation() called even though current action is not an Operation");
|
||||||
|
}
|
||||||
|
const action = getActionObject(bladeburner, bladeburner.action);
|
||||||
|
if (action == null) {
|
||||||
|
throw new Error("Failed to get Contract/Operation Object for: " + bladeburner.action.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate team losses
|
||||||
|
const teamCount = action.teamCount;
|
||||||
|
if (teamCount >= 1) {
|
||||||
|
let max;
|
||||||
|
if (success) {
|
||||||
|
max = Math.ceil(teamCount/2);
|
||||||
|
} else {
|
||||||
|
max = Math.floor(teamCount)
|
||||||
|
}
|
||||||
|
const losses = getRandomInt(0, max);
|
||||||
|
bladeburner.teamSize -= losses;
|
||||||
|
bladeburner.teamLost += losses;
|
||||||
|
if (bladeburner.logging.ops && losses > 0) {
|
||||||
|
bladeburner.log("Lost " + formatNumber(losses, 0) + " team members during this " + action.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const city = bladeburner.getCurrentCity();
|
||||||
|
switch (action.name) {
|
||||||
|
case "Investigation":
|
||||||
|
if (success) {
|
||||||
|
city.improvePopulationEstimateByPercentage(0.4 * bladeburner.skillMultipliers.successChanceEstimate);
|
||||||
|
if (Math.random() < (0.02 * bladeburner.skillMultipliers.successChanceEstimate)) {
|
||||||
|
city.improveCommunityEstimate(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
triggerPotentialMigration(bladeburner, bladeburner.city, 0.1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "Undercover Operation":
|
||||||
|
if (success) {
|
||||||
|
city.improvePopulationEstimateByPercentage(0.8 * bladeburner.skillMultipliers.successChanceEstimate);
|
||||||
|
if (Math.random() < (0.02 * bladeburner.skillMultipliers.successChanceEstimate)) {
|
||||||
|
city.improveCommunityEstimate(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
triggerPotentialMigration(bladeburner, bladeburner.city, 0.15);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "Sting Operation":
|
||||||
|
if (success) {
|
||||||
|
city.changePopulationByPercentage(-0.1, {changeEstEqually:true, nonZero:true});
|
||||||
|
}
|
||||||
|
city.changeChaosByCount(0.1);
|
||||||
|
break;
|
||||||
|
case "Raid":
|
||||||
|
if (success) {
|
||||||
|
city.changePopulationByPercentage(-1, {changeEstEqually:true, nonZero:true});
|
||||||
|
--city.comms;
|
||||||
|
--city.commsEst;
|
||||||
|
} else {
|
||||||
|
const change = getRandomInt(-10, -5) / 10;
|
||||||
|
city.changePopulationByPercentage(change, {nonZero:true, changeEstEqually:false});
|
||||||
|
}
|
||||||
|
city.changeChaosByPercentage(getRandomInt(1, 5));
|
||||||
|
break;
|
||||||
|
case "Stealth Retirement Operation":
|
||||||
|
if (success) {
|
||||||
|
city.changePopulationByPercentage(-0.5, {changeEstEqually:true,nonZero:true});
|
||||||
|
}
|
||||||
|
city.changeChaosByPercentage(getRandomInt(-3, -1));
|
||||||
|
break;
|
||||||
|
case "Assassination":
|
||||||
|
if (success) {
|
||||||
|
city.changePopulationByCount(-1, {estChange:-1, estOffset: 0});
|
||||||
|
}
|
||||||
|
city.changeChaosByPercentage(getRandomInt(-5, 5));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error("Invalid Action name in completeOperation: " + bladeburner.action.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getActionObject(bladeburner: IBladeburner, actionId: IActionIdentifier): IAction | null {
|
||||||
|
/**
|
||||||
|
* Given an ActionIdentifier object, returns the corresponding
|
||||||
|
* GeneralAction, Contract, Operation, or BlackOperation object
|
||||||
|
*/
|
||||||
|
switch (actionId.type) {
|
||||||
|
case ActionTypes["Contract"]:
|
||||||
|
return bladeburner.contracts[actionId.name];
|
||||||
|
case ActionTypes["Operation"]:
|
||||||
|
return bladeburner.operations[actionId.name];
|
||||||
|
case ActionTypes["BlackOp"]:
|
||||||
|
case ActionTypes["BlackOperation"]:
|
||||||
|
return BlackOperations[actionId.name];
|
||||||
|
case ActionTypes["Training"]:
|
||||||
|
return GeneralActions["Training"];
|
||||||
|
case ActionTypes["Field Analysis"]:
|
||||||
|
return GeneralActions["Field Analysis"];
|
||||||
|
case ActionTypes["Recruitment"]:
|
||||||
|
return GeneralActions["Recruitment"];
|
||||||
|
case ActionTypes["Diplomacy"]:
|
||||||
|
return GeneralActions["Diplomacy"];
|
||||||
|
case ActionTypes["Hyperbolic Regeneration Chamber"]:
|
||||||
|
return GeneralActions["Hyperbolic Regeneration Chamber"];
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function completeContract(bladeburner: IBladeburner, success: boolean): void {
|
||||||
|
if (bladeburner.action.type !== ActionTypes.Contract) {
|
||||||
|
throw new Error("completeContract() called even though current action is not a Contract");
|
||||||
|
}
|
||||||
|
var city = bladeburner.getCurrentCity();
|
||||||
|
if (success) {
|
||||||
|
switch (bladeburner.action.name) {
|
||||||
|
case "Tracking":
|
||||||
|
// Increase estimate accuracy by a relatively small amount
|
||||||
|
city.improvePopulationEstimateByCount(getRandomInt(100, 1e3));
|
||||||
|
break;
|
||||||
|
case "Bounty Hunter":
|
||||||
|
city.changePopulationByCount(-1, {estChange:-1, estOffset: 0});
|
||||||
|
city.changeChaosByCount(0.02);
|
||||||
|
break;
|
||||||
|
case "Retirement":
|
||||||
|
city.changePopulationByCount(-1, {estChange:-1, estOffset: 0});
|
||||||
|
city.changeChaosByCount(0.04);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error("Invalid Action name in completeContract: " + bladeburner.action.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function completeAction(bladeburner: IBladeburner, player: IPlayer): void {
|
||||||
|
switch (bladeburner.action.type) {
|
||||||
|
case ActionTypes["Contract"]:
|
||||||
|
case ActionTypes["Operation"]: {
|
||||||
|
try {
|
||||||
|
const isOperation = (bladeburner.action.type === ActionTypes["Operation"]);
|
||||||
|
const action = getActionObject(bladeburner, bladeburner.action);
|
||||||
|
if (action == null) {
|
||||||
|
throw new Error("Failed to get Contract/Operation Object for: " + bladeburner.action.name);
|
||||||
|
}
|
||||||
|
const difficulty = action.getDifficulty();
|
||||||
|
const difficultyMultiplier = Math.pow(difficulty, BladeburnerConstants.DiffMultExponentialFactor) + difficulty / BladeburnerConstants.DiffMultLinearFactor;
|
||||||
|
const rewardMultiplier = Math.pow(action.rewardFac, action.level-1);
|
||||||
|
|
||||||
|
// Stamina loss is based on difficulty
|
||||||
|
bladeburner.stamina -= (BladeburnerConstants.BaseStaminaLoss * difficultyMultiplier);
|
||||||
|
if (bladeburner.stamina < 0) {bladeburner.stamina = 0;}
|
||||||
|
|
||||||
|
// Process Contract/Operation success/failure
|
||||||
|
if (action.attempt(bladeburner)) {
|
||||||
|
gainActionStats(bladeburner, player, action, true);
|
||||||
|
++action.successes;
|
||||||
|
--action.count;
|
||||||
|
|
||||||
|
// Earn money for contracts
|
||||||
|
let moneyGain = 0;
|
||||||
|
if (!isOperation) {
|
||||||
|
moneyGain = BladeburnerConstants.ContractBaseMoneyGain * rewardMultiplier * bladeburner.skillMultipliers.money;
|
||||||
|
player.gainMoney(moneyGain);
|
||||||
|
player.recordMoneySource(moneyGain, "bladeburner");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isOperation) {
|
||||||
|
action.setMaxLevel(BladeburnerConstants.OperationSuccessesPerLevel);
|
||||||
|
} else {
|
||||||
|
action.setMaxLevel(BladeburnerConstants.ContractSuccessesPerLevel);
|
||||||
|
}
|
||||||
|
if (action.rankGain) {
|
||||||
|
const gain = addOffset(action.rankGain * rewardMultiplier * BitNodeMultipliers.BladeburnerRank, 10);
|
||||||
|
changeRank(bladeburner, player, gain);
|
||||||
|
if (isOperation && bladeburner.logging.ops) {
|
||||||
|
bladeburner.log(action.name + " successfully completed! Gained " + formatNumber(gain, 3) + " rank");
|
||||||
|
} else if (!isOperation && bladeburner.logging.contracts) {
|
||||||
|
bladeburner.log(action.name + " contract successfully completed! Gained " + formatNumber(gain, 3) + " rank and " + numeralWrapper.formatMoney(moneyGain));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isOperation ? completeOperation(bladeburner, true) : completeContract(bladeburner, true);
|
||||||
|
} else {
|
||||||
|
gainActionStats(bladeburner, player, action, false);
|
||||||
|
++action.failures;
|
||||||
|
let loss = 0, damage = 0;
|
||||||
|
if (action.rankLoss) {
|
||||||
|
loss = addOffset(action.rankLoss * rewardMultiplier, 10);
|
||||||
|
changeRank(bladeburner, player, -1 * loss);
|
||||||
|
}
|
||||||
|
if (action.hpLoss) {
|
||||||
|
damage = action.hpLoss * difficultyMultiplier;
|
||||||
|
damage = Math.ceil(addOffset(damage, 10));
|
||||||
|
bladeburner.hpLost += damage;
|
||||||
|
const cost = calculateHospitalizationCost(player, damage);
|
||||||
|
if (player.takeDamage(damage)) {
|
||||||
|
++bladeburner.numHosp;
|
||||||
|
bladeburner.moneyLost += cost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let logLossText = "";
|
||||||
|
if (loss > 0) {logLossText += "Lost " + formatNumber(loss, 3) + " rank. ";}
|
||||||
|
if (damage > 0) {logLossText += "Took " + formatNumber(damage, 0) + " damage.";}
|
||||||
|
if (isOperation && bladeburner.logging.ops) {
|
||||||
|
bladeburner.log(action.name + " failed! " + logLossText);
|
||||||
|
} else if (!isOperation && bladeburner.logging.contracts) {
|
||||||
|
bladeburner.log(action.name + " contract failed! " + logLossText);
|
||||||
|
}
|
||||||
|
isOperation ? completeOperation(bladeburner, false) : completeContract(bladeburner, false);
|
||||||
|
}
|
||||||
|
if (action.autoLevel) {action.level = action.maxLevel;} // Autolevel
|
||||||
|
startAction(bladeburner,player, bladeburner.action); // Repeat action
|
||||||
|
} catch(e) {
|
||||||
|
exceptionAlert(e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ActionTypes["BlackOp"]:
|
||||||
|
case ActionTypes["BlackOperation"]: {
|
||||||
|
try {
|
||||||
|
const action = getActionObject(bladeburner, bladeburner.action);
|
||||||
|
if (action == null || !(action instanceof BlackOperation)) {
|
||||||
|
throw new Error("Failed to get BlackOperation Object for: " + bladeburner.action.name);
|
||||||
|
}
|
||||||
|
const difficulty = action.getDifficulty();
|
||||||
|
const difficultyMultiplier = Math.pow(difficulty, BladeburnerConstants.DiffMultExponentialFactor) + difficulty / BladeburnerConstants.DiffMultLinearFactor;
|
||||||
|
|
||||||
|
// Stamina loss is based on difficulty
|
||||||
|
bladeburner.stamina -= (BladeburnerConstants.BaseStaminaLoss * difficultyMultiplier);
|
||||||
|
if (bladeburner.stamina < 0) {bladeburner.stamina = 0;}
|
||||||
|
|
||||||
|
// Team loss variables
|
||||||
|
const teamCount = action.teamCount;
|
||||||
|
let teamLossMax;
|
||||||
|
|
||||||
|
if (action.attempt(bladeburner)) {
|
||||||
|
gainActionStats(bladeburner, player, action, true);
|
||||||
|
action.count = 0;
|
||||||
|
bladeburner.blackops[action.name] = true;
|
||||||
|
let rankGain = 0;
|
||||||
|
if (action.rankGain) {
|
||||||
|
rankGain = addOffset(action.rankGain * BitNodeMultipliers.BladeburnerRank, 10);
|
||||||
|
changeRank(bladeburner, player, rankGain);
|
||||||
|
}
|
||||||
|
teamLossMax = Math.ceil(teamCount/2);
|
||||||
|
|
||||||
|
// Operation Daedalus
|
||||||
|
if (action.name === "Operation Daedalus") {
|
||||||
|
resetAction(bladeburner);
|
||||||
|
return hackWorldDaemon(player.bitNodeN);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bladeburner.logging.blackops) {
|
||||||
|
bladeburner.log(action.name + " successful! Gained " + formatNumber(rankGain, 1) + " rank");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gainActionStats(bladeburner, player, action, false);
|
||||||
|
let rankLoss = 0;
|
||||||
|
let damage = 0;
|
||||||
|
if (action.rankLoss) {
|
||||||
|
rankLoss = addOffset(action.rankLoss, 10);
|
||||||
|
changeRank(bladeburner, player, -1 * rankLoss);
|
||||||
|
}
|
||||||
|
if (action.hpLoss) {
|
||||||
|
damage = action.hpLoss * difficultyMultiplier;
|
||||||
|
damage = Math.ceil(addOffset(damage, 10));
|
||||||
|
const cost = calculateHospitalizationCost(player, damage);
|
||||||
|
if (player.takeDamage(damage)) {
|
||||||
|
++bladeburner.numHosp;
|
||||||
|
bladeburner.moneyLost += cost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
teamLossMax = Math.floor(teamCount);
|
||||||
|
|
||||||
|
if (bladeburner.logging.blackops) {
|
||||||
|
bladeburner.log(action.name + " failed! Lost " + formatNumber(rankLoss, 1) + " rank and took " + formatNumber(damage, 0) + " damage");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resetAction(bladeburner); // Stop regardless of success or fail
|
||||||
|
|
||||||
|
// Calculate team lossses
|
||||||
|
if (teamCount >= 1) {
|
||||||
|
const losses = getRandomInt(1, teamLossMax);
|
||||||
|
bladeburner.teamSize -= losses;
|
||||||
|
bladeburner.teamLost += losses;
|
||||||
|
if (bladeburner.logging.blackops) {
|
||||||
|
bladeburner.log("You lost " + formatNumber(losses, 0) + " team members during " + action.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
exceptionAlert(e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ActionTypes["Training"]: {
|
||||||
|
bladeburner.stamina -= (0.5 * BladeburnerConstants.BaseStaminaLoss);
|
||||||
|
const strExpGain = 30 * player.strength_exp_mult,
|
||||||
|
defExpGain = 30 * player.defense_exp_mult,
|
||||||
|
dexExpGain = 30 * player.dexterity_exp_mult,
|
||||||
|
agiExpGain = 30 * player.agility_exp_mult,
|
||||||
|
staminaGain = 0.04 * bladeburner.skillMultipliers.stamina;
|
||||||
|
player.gainStrengthExp(strExpGain);
|
||||||
|
player.gainDefenseExp(defExpGain);
|
||||||
|
player.gainDexterityExp(dexExpGain);
|
||||||
|
player.gainAgilityExp(agiExpGain);
|
||||||
|
bladeburner.staminaBonus += (staminaGain);
|
||||||
|
if (bladeburner.logging.general) {
|
||||||
|
bladeburner.log("Training completed. Gained: " +
|
||||||
|
formatNumber(strExpGain, 1) + " str exp, " +
|
||||||
|
formatNumber(defExpGain, 1) + " def exp, " +
|
||||||
|
formatNumber(dexExpGain, 1) + " dex exp, " +
|
||||||
|
formatNumber(agiExpGain, 1) + " agi exp, " +
|
||||||
|
formatNumber(staminaGain, 3) + " max stamina");
|
||||||
|
}
|
||||||
|
startAction(bladeburner,player, bladeburner.action); // Repeat action
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ActionTypes["FieldAnalysis"]:
|
||||||
|
case ActionTypes["Field Analysis"]: {
|
||||||
|
// Does not use stamina. Effectiveness depends on hacking, int, and cha
|
||||||
|
let eff = 0.04 * Math.pow(player.hacking_skill, 0.3) +
|
||||||
|
0.04 * Math.pow(player.intelligence, 0.9) +
|
||||||
|
0.02 * Math.pow(player.charisma, 0.3);
|
||||||
|
eff *= player.bladeburner_analysis_mult;
|
||||||
|
if (isNaN(eff) || eff < 0) {
|
||||||
|
throw new Error("Field Analysis Effectiveness calculated to be NaN or negative");
|
||||||
|
}
|
||||||
|
const hackingExpGain = 20 * player.hacking_exp_mult,
|
||||||
|
charismaExpGain = 20 * player.charisma_exp_mult;
|
||||||
|
player.gainHackingExp(hackingExpGain);
|
||||||
|
player.gainIntelligenceExp(BladeburnerConstants.BaseIntGain);
|
||||||
|
player.gainCharismaExp(charismaExpGain);
|
||||||
|
changeRank(bladeburner, player, 0.1 * BitNodeMultipliers.BladeburnerRank);
|
||||||
|
bladeburner.getCurrentCity().improvePopulationEstimateByPercentage(eff * bladeburner.skillMultipliers.successChanceEstimate);
|
||||||
|
if (bladeburner.logging.general) {
|
||||||
|
bladeburner.log("Field analysis completed. Gained 0.1 rank, " + formatNumber(hackingExpGain, 1) + " hacking exp, and " + formatNumber(charismaExpGain, 1) + " charisma exp");
|
||||||
|
}
|
||||||
|
startAction(bladeburner,player, bladeburner.action); // Repeat action
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ActionTypes["Recruitment"]: {
|
||||||
|
const successChance = getRecruitmentSuccessChance(bladeburner, player);
|
||||||
|
if (Math.random() < successChance) {
|
||||||
|
const expGain = 2 * BladeburnerConstants.BaseStatGain * bladeburner.actionTimeToComplete;
|
||||||
|
player.gainCharismaExp(expGain);
|
||||||
|
++bladeburner.teamSize;
|
||||||
|
if (bladeburner.logging.general) {
|
||||||
|
bladeburner.log("Successfully recruited a team member! Gained " + formatNumber(expGain, 1) + " charisma exp");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const expGain = BladeburnerConstants.BaseStatGain * bladeburner.actionTimeToComplete;
|
||||||
|
player.gainCharismaExp(expGain);
|
||||||
|
if (bladeburner.logging.general) {
|
||||||
|
bladeburner.log("Failed to recruit a team member. Gained " + formatNumber(expGain, 1) + " charisma exp");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
startAction(bladeburner,player, bladeburner.action); // Repeat action
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ActionTypes["Diplomacy"]: {
|
||||||
|
let eff = getDiplomacyEffectiveness(bladeburner, player);
|
||||||
|
bladeburner.getCurrentCity().chaos *= eff;
|
||||||
|
if (bladeburner.getCurrentCity().chaos < 0) { bladeburner.getCurrentCity().chaos = 0; }
|
||||||
|
if (bladeburner.logging.general) {
|
||||||
|
bladeburner.log(`Diplomacy completed. Chaos levels in the current city fell by ${numeralWrapper.formatPercentage(1 - eff)}`);
|
||||||
|
}
|
||||||
|
startAction(bladeburner,player, bladeburner.action); // Repeat Action
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ActionTypes["Hyperbolic Regeneration Chamber"]: {
|
||||||
|
player.regenerateHp(BladeburnerConstants.HrcHpGain);
|
||||||
|
|
||||||
|
const staminaGain = bladeburner.maxStamina * (BladeburnerConstants.HrcStaminaGain / 100);
|
||||||
|
bladeburner.stamina = Math.min(bladeburner.maxStamina, bladeburner.stamina + staminaGain);
|
||||||
|
startAction(bladeburner,player, bladeburner.action);
|
||||||
|
if (bladeburner.logging.general) {
|
||||||
|
bladeburner.log(`Rested in Hyperbolic Regeneration Chamber. Restored ${BladeburnerConstants.HrcHpGain} HP and gained ${numeralWrapper.formatStamina(staminaGain)} stamina`);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
console.error(`Bladeburner.completeAction() called for invalid action: ${bladeburner.action.type}`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function changeRank(bladeburner: IBladeburner, player: IPlayer, change: number): void {
|
||||||
|
if (isNaN(change)) {throw new Error("NaN passed into Bladeburner.changeRank()");}
|
||||||
|
bladeburner.rank += change;
|
||||||
|
if (bladeburner.rank < 0) {bladeburner.rank = 0;}
|
||||||
|
bladeburner.maxRank = Math.max(bladeburner.rank, bladeburner.maxRank);
|
||||||
|
|
||||||
|
var bladeburnersFactionName = "Bladeburners";
|
||||||
|
if (factionExists(bladeburnersFactionName)) {
|
||||||
|
var bladeburnerFac = Factions[bladeburnersFactionName];
|
||||||
|
if (!(bladeburnerFac instanceof Faction)) {
|
||||||
|
throw new Error("Could not properly get Bladeburner Faction object in Bladeburner UI Overview Faction button");
|
||||||
|
}
|
||||||
|
if (bladeburnerFac.isMember) {
|
||||||
|
var favorBonus = 1 + (bladeburnerFac.favor / 100);
|
||||||
|
bladeburnerFac.playerReputation += (BladeburnerConstants.RankToFactionRepFactor * change * player.faction_rep_mult * favorBonus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gain skill points
|
||||||
|
var rankNeededForSp = (bladeburner.totalSkillPoints+1) * BladeburnerConstants.RanksPerSkillPoint;
|
||||||
|
if (bladeburner.maxRank >= rankNeededForSp) {
|
||||||
|
// Calculate how many skill points to gain
|
||||||
|
var gainedSkillPoints = Math.floor((bladeburner.maxRank - rankNeededForSp) / BladeburnerConstants.RanksPerSkillPoint + 1);
|
||||||
|
bladeburner.skillPoints += gainedSkillPoints;
|
||||||
|
bladeburner.totalSkillPoints += gainedSkillPoints;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function processAction(bladeburner: IBladeburner, player: IPlayer, seconds: number): void {
|
||||||
|
if (bladeburner.action.type === ActionTypes["Idle"]) return;
|
||||||
|
if (bladeburner.actionTimeToComplete <= 0) {
|
||||||
|
throw new Error(`Invalid actionTimeToComplete value: ${bladeburner.actionTimeToComplete}, type; ${bladeburner.action.type}`);
|
||||||
|
}
|
||||||
|
if (!(bladeburner.action instanceof ActionIdentifier)) {
|
||||||
|
throw new Error("Bladeburner.action is not an ActionIdentifier Object");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the previous action went past its completion time, add to the next action
|
||||||
|
// This is not added inmediatly in case the automation changes the action
|
||||||
|
bladeburner.actionTimeCurrent += seconds + bladeburner.actionTimeOverflow;
|
||||||
|
bladeburner.actionTimeOverflow = 0;
|
||||||
|
if (bladeburner.actionTimeCurrent >= bladeburner.actionTimeToComplete) {
|
||||||
|
bladeburner.actionTimeOverflow = bladeburner.actionTimeCurrent - bladeburner.actionTimeToComplete;
|
||||||
|
return completeAction(bladeburner, player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function startAction(bladeburner: IBladeburner, player: IPlayer, actionId: IActionIdentifier): void {
|
||||||
|
if (actionId == null) return;
|
||||||
|
bladeburner.action = actionId;
|
||||||
|
bladeburner.actionTimeCurrent = 0;
|
||||||
|
switch (actionId.type) {
|
||||||
|
case ActionTypes["Idle"]:
|
||||||
|
bladeburner.actionTimeToComplete = 0;
|
||||||
|
break;
|
||||||
|
case ActionTypes["Contract"]:
|
||||||
|
try {
|
||||||
|
const action = getActionObject(bladeburner, actionId);
|
||||||
|
if (action == null) {
|
||||||
|
throw new Error("Failed to get Contract Object for: " + actionId.name);
|
||||||
|
}
|
||||||
|
if (action.count < 1) {return resetAction(bladeburner);}
|
||||||
|
bladeburner.actionTimeToComplete = action.getActionTime(bladeburner);
|
||||||
|
} catch(e) {
|
||||||
|
exceptionAlert(e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ActionTypes["Operation"]: {
|
||||||
|
try {
|
||||||
|
const action = getActionObject(bladeburner, actionId);
|
||||||
|
if (action == null) {
|
||||||
|
throw new Error ("Failed to get Operation Object for: " + actionId.name);
|
||||||
|
}
|
||||||
|
if (action.count < 1) {return resetAction(bladeburner);}
|
||||||
|
if (actionId.name === "Raid" && bladeburner.getCurrentCity().commsEst === 0) {return resetAction(bladeburner);}
|
||||||
|
bladeburner.actionTimeToComplete = action.getActionTime(bladeburner);
|
||||||
|
} catch(e) {
|
||||||
|
exceptionAlert(e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ActionTypes["BlackOp"]:
|
||||||
|
case ActionTypes["BlackOperation"]: {
|
||||||
|
try {
|
||||||
|
// Safety measure - don't repeat BlackOps that are already done
|
||||||
|
if (bladeburner.blackops[actionId.name] != null) {
|
||||||
|
resetAction(bladeburner);
|
||||||
|
bladeburner.log("Error: Tried to start a Black Operation that had already been completed");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const action = getActionObject(bladeburner, actionId);
|
||||||
|
if (action == null) {
|
||||||
|
throw new Error("Failed to get BlackOperation object for: " + actionId.name);
|
||||||
|
}
|
||||||
|
bladeburner.actionTimeToComplete = action.getActionTime(bladeburner);
|
||||||
|
} catch(e) {
|
||||||
|
exceptionAlert(e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ActionTypes["Recruitment"]:
|
||||||
|
bladeburner.actionTimeToComplete = getRecruitmentTime(bladeburner, player);
|
||||||
|
break;
|
||||||
|
case ActionTypes["Training"]:
|
||||||
|
case ActionTypes["FieldAnalysis"]:
|
||||||
|
case ActionTypes["Field Analysis"]:
|
||||||
|
bladeburner.actionTimeToComplete = 30;
|
||||||
|
break;
|
||||||
|
case ActionTypes["Diplomacy"]:
|
||||||
|
case ActionTypes["Hyperbolic Regeneration Chamber"]:
|
||||||
|
bladeburner.actionTimeToComplete = 60;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error("Invalid Action Type in startAction(Bladeburner,player, ): " + actionId.type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
@ -4,14 +4,14 @@ import { getRandomInt } from "../../utils/helpers/getRandomInt";
|
|||||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
|
||||||
import { addOffset } from "../../utils/helpers/addOffset";
|
import { addOffset } from "../../utils/helpers/addOffset";
|
||||||
|
|
||||||
export class ChangePopulationByCountParams {
|
interface IChangePopulationByCountParams {
|
||||||
estChange = 0;
|
estChange: number;
|
||||||
estOffset = 0;
|
estOffset: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ChangePopulationByPercentageParams {
|
interface IChangePopulationByPercentageParams {
|
||||||
nonZero = false;
|
nonZero: boolean;
|
||||||
changeEstEqually = false;
|
changeEstEqually: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class City {
|
export class City {
|
||||||
@ -113,7 +113,7 @@ export class City {
|
|||||||
* estChange(int): How much the estimate should change by
|
* estChange(int): How much the estimate should change by
|
||||||
* estOffset(int): Add offset to estimate (offset by percentage)
|
* estOffset(int): Add offset to estimate (offset by percentage)
|
||||||
*/
|
*/
|
||||||
changePopulationByCount(n: number, params: ChangePopulationByCountParams=new ChangePopulationByCountParams()): void {
|
changePopulationByCount(n: number, params: IChangePopulationByCountParams = {estChange: 0, estOffset: 0}): void {
|
||||||
if (isNaN(n)) {throw new Error("NaN passed into City.changePopulationByCount()");}
|
if (isNaN(n)) {throw new Error("NaN passed into City.changePopulationByCount()");}
|
||||||
this.pop += n;
|
this.pop += n;
|
||||||
if (params.estChange && !isNaN(params.estChange)) {this.popEst += params.estChange;}
|
if (params.estChange && !isNaN(params.estChange)) {this.popEst += params.estChange;}
|
||||||
@ -129,7 +129,7 @@ export class City {
|
|||||||
* changeEstEqually(bool) - Change the population estimate by an equal amount
|
* changeEstEqually(bool) - Change the population estimate by an equal amount
|
||||||
* nonZero (bool) - Set to true to ensure that population always changes by at least 1
|
* nonZero (bool) - Set to true to ensure that population always changes by at least 1
|
||||||
*/
|
*/
|
||||||
changePopulationByPercentage(p: number, params: ChangePopulationByPercentageParams=new ChangePopulationByPercentageParams()): number {
|
changePopulationByPercentage(p: number, params: IChangePopulationByPercentageParams={nonZero: false, changeEstEqually: false}): number {
|
||||||
if (isNaN(p)) {throw new Error("NaN passed into City.changePopulationByPercentage()");}
|
if (isNaN(p)) {throw new Error("NaN passed into City.changePopulationByPercentage()");}
|
||||||
if (p === 0) {return 0;}
|
if (p === 0) {return 0;}
|
||||||
let change = Math.round(this.pop * (p/100));
|
let change = Math.round(this.pop * (p/100));
|
||||||
|
@ -11,6 +11,7 @@ export interface IBladeburner {
|
|||||||
totalSkillPoints: number;
|
totalSkillPoints: number;
|
||||||
teamSize: number;
|
teamSize: number;
|
||||||
teamLost: number;
|
teamLost: number;
|
||||||
|
hpLost: number;
|
||||||
storedCycles: number;
|
storedCycles: number;
|
||||||
randomEventCounter: number;
|
randomEventCounter: number;
|
||||||
actionTimeToComplete: number;
|
actionTimeToComplete: number;
|
||||||
|
@ -103,5 +103,28 @@ export class Skill {
|
|||||||
calculateCost(currentLevel: number): number {
|
calculateCost(currentLevel: number): number {
|
||||||
return Math.floor((this.baseCost + (currentLevel * this.costInc)) * BitNodeMultipliers.BladeburnerSkillCost);
|
return Math.floor((this.baseCost + (currentLevel * this.costInc)) * BitNodeMultipliers.BladeburnerSkillCost);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getMultiplier(name: string): number {
|
||||||
|
if(name === "successChanceAll") return this.successChanceAll;
|
||||||
|
if(name === "successChanceStealth") return this.successChanceStealth;
|
||||||
|
if(name === "successChanceKill") return this.successChanceKill;
|
||||||
|
if(name === "successChanceContract") return this.successChanceContract;
|
||||||
|
if(name === "successChanceOperation") return this.successChanceOperation;
|
||||||
|
if(name === "successChanceEstimate") return this.successChanceEstimate;
|
||||||
|
|
||||||
|
if(name === "actionTime") return this.actionTime;
|
||||||
|
|
||||||
|
if(name === "effHack") return this.effHack;
|
||||||
|
if(name === "effStr") return this.effStr;
|
||||||
|
if(name === "effDef") return this.effDef;
|
||||||
|
if(name === "effDex") return this.effDex;
|
||||||
|
if(name === "effAgi") return this.effAgi;
|
||||||
|
if(name === "effCha") return this.effCha;
|
||||||
|
|
||||||
|
if(name === "stamina") return this.stamina;
|
||||||
|
if(name === "money") return this.money;
|
||||||
|
if(name === "expGain") return this.expGain;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,9 +6,11 @@ import { BlackOpPage } from "./BlackOpPage";
|
|||||||
import { SkillPage } from "./SkillPage";
|
import { SkillPage } from "./SkillPage";
|
||||||
import { stealthIcon, killIcon } from "../data/Icons";
|
import { stealthIcon, killIcon } from "../data/Icons";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { IBladeburner } from "../IBladeburner";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: IBladeburner;
|
||||||
|
player: IPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AllPages(props: IProps): React.ReactElement {
|
export function AllPages(props: IProps): React.ReactElement {
|
||||||
@ -36,10 +38,10 @@ export function AllPages(props: IProps): React.ReactElement {
|
|||||||
<Header name={'BlackOps'} />
|
<Header name={'BlackOps'} />
|
||||||
<Header name={'Skills'} />
|
<Header name={'Skills'} />
|
||||||
<div style={{display:"block", margin:"4px", padding:"4px"}}>
|
<div style={{display:"block", margin:"4px", padding:"4px"}}>
|
||||||
{page === 'General' && <GeneralActionPage bladeburner={props.bladeburner} />}
|
{page === 'General' && <GeneralActionPage bladeburner={props.bladeburner} player={props.player} />}
|
||||||
{page === 'Contracts' && <ContractPage bladeburner={props.bladeburner} />}
|
{page === 'Contracts' && <ContractPage bladeburner={props.bladeburner} player={props.player} />}
|
||||||
{page === 'Operations' && <OperationPage bladeburner={props.bladeburner} />}
|
{page === 'Operations' && <OperationPage bladeburner={props.bladeburner} player={props.player} />}
|
||||||
{page === 'BlackOps' && <BlackOpPage bladeburner={props.bladeburner} />}
|
{page === 'BlackOps' && <BlackOpPage bladeburner={props.bladeburner} player={props.player} />}
|
||||||
{page === 'Skills' && <SkillPage bladeburner={props.bladeburner} />}
|
{page === 'Skills' && <SkillPage bladeburner={props.bladeburner} />}
|
||||||
</div>
|
</div>
|
||||||
<span className="text">{stealthIcon}= This action requires stealth, {killIcon} = This action involves retirement</span>
|
<span className="text">{stealthIcon}= This action requires stealth, {killIcon} = This action involves retirement</span>
|
||||||
|
@ -9,9 +9,12 @@ import { stealthIcon, killIcon } from "../data/Icons";
|
|||||||
import { createPopup } from "../../ui/React/createPopup";
|
import { createPopup } from "../../ui/React/createPopup";
|
||||||
import { TeamSizePopup } from "./TeamSizePopup";
|
import { TeamSizePopup } from "./TeamSizePopup";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { IBladeburner } from "../IBladeburner";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { startAction } from "../Bladeburner";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: IBladeburner;
|
||||||
|
player: IPlayer;
|
||||||
action: any;
|
action: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +35,7 @@ export function BlackOpElem(props: IProps): React.ReactElement {
|
|||||||
function onStart() {
|
function onStart() {
|
||||||
props.bladeburner.action.type = ActionTypes.BlackOperation;
|
props.bladeburner.action.type = ActionTypes.BlackOperation;
|
||||||
props.bladeburner.action.name = props.action.name;
|
props.bladeburner.action.name = props.action.name;
|
||||||
props.bladeburner.startAction(props.bladeburner.action);
|
startAction(props.bladeburner, props.player, props.bladeburner.action);
|
||||||
setRerender(old => !old);
|
setRerender(old => !old);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,9 +10,11 @@ import { BlackOperations } from "../BlackOperations";
|
|||||||
import { BlackOperation } from "../BlackOperation";
|
import { BlackOperation } from "../BlackOperation";
|
||||||
import { BlackOpElem } from "./BlackOpElem";
|
import { BlackOpElem } from "./BlackOpElem";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { IBladeburner } from "../IBladeburner";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: IBladeburner;
|
||||||
|
player: IPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BlackOpList(props: IProps): React.ReactElement {
|
export function BlackOpList(props: IProps): React.ReactElement {
|
||||||
@ -34,7 +36,7 @@ export function BlackOpList(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
return (<>
|
return (<>
|
||||||
{blackops.map((blackop: BlackOperation) => <li key={blackop.name} className="bladeburner-action">
|
{blackops.map((blackop: BlackOperation) => <li key={blackop.name} className="bladeburner-action">
|
||||||
<BlackOpElem bladeburner={props.bladeburner} action={blackop} />
|
<BlackOpElem bladeburner={props.bladeburner} action={blackop} player={props.player} />
|
||||||
</li>,
|
</li>,
|
||||||
)}
|
)}
|
||||||
</>);
|
</>);
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { BlackOpList } from "./BlackOpList";
|
import { BlackOpList } from "./BlackOpList";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { IBladeburner } from "../IBladeburner";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: IBladeburner;
|
||||||
|
player: IPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BlackOpPage(props: IProps): React.ReactElement {
|
export function BlackOpPage(props: IProps): React.ReactElement {
|
||||||
@ -21,6 +23,6 @@ export function BlackOpPage(props: IProps): React.ReactElement {
|
|||||||
Like normal operations, you may use a team for Black Ops. Failing
|
Like normal operations, you may use a team for Black Ops. Failing
|
||||||
a black op will incur heavy HP and rank losses.
|
a black op will incur heavy HP and rank losses.
|
||||||
</p>
|
</p>
|
||||||
<BlackOpList bladeburner={props.bladeburner} />
|
<BlackOpList bladeburner={props.bladeburner} player={props.player} />
|
||||||
</>);
|
</>);
|
||||||
}
|
}
|
@ -1,6 +1,8 @@
|
|||||||
import React, { useState, useRef, useEffect } from "react";
|
import React, { useState, useRef, useEffect } from "react";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { IBladeburner } from "../IBladeburner";
|
||||||
|
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
|
||||||
interface ILineProps {
|
interface ILineProps {
|
||||||
content: any;
|
content: any;
|
||||||
}
|
}
|
||||||
@ -13,6 +15,7 @@ function Line(props: ILineProps): React.ReactElement {
|
|||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: IBladeburner;
|
||||||
|
player: IPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Console(props: IProps): React.ReactElement {
|
export function Console(props: IProps): React.ReactElement {
|
||||||
|
@ -8,9 +8,12 @@ import {
|
|||||||
import { stealthIcon, killIcon } from "../data/Icons";
|
import { stealthIcon, killIcon } from "../data/Icons";
|
||||||
import { BladeburnerConstants } from "../data/Constants";
|
import { BladeburnerConstants } from "../data/Constants";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { IBladeburner } from "../IBladeburner";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { startAction } from "../Bladeburner";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: IBladeburner;
|
||||||
|
player: IPlayer;
|
||||||
action: any;
|
action: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,19 +29,19 @@ export function ContractElem(props: IProps): React.ReactElement {
|
|||||||
function onStart() {
|
function onStart() {
|
||||||
props.bladeburner.action.type = ActionTypes.Contract;
|
props.bladeburner.action.type = ActionTypes.Contract;
|
||||||
props.bladeburner.action.name = props.action.name;
|
props.bladeburner.action.name = props.action.name;
|
||||||
props.bladeburner.startAction(props.bladeburner.action);
|
startAction(props.bladeburner, props.player, props.bladeburner.action);
|
||||||
setRerender(old => !old);
|
setRerender(old => !old);
|
||||||
}
|
}
|
||||||
|
|
||||||
function increaseLevel() {
|
function increaseLevel() {
|
||||||
++props.action.level;
|
++props.action.level;
|
||||||
if (isActive) props.bladeburner.startAction(props.bladeburner.action);
|
if (isActive) startAction(props.bladeburner, props.player, props.bladeburner.action);
|
||||||
setRerender(old => !old);
|
setRerender(old => !old);
|
||||||
}
|
}
|
||||||
|
|
||||||
function decreaseLevel() {
|
function decreaseLevel() {
|
||||||
--props.action.level;
|
--props.action.level;
|
||||||
if (isActive) props.bladeburner.startAction(props.bladeburner.action);
|
if (isActive) startAction(props.bladeburner, props.player, props.bladeburner.action);
|
||||||
setRerender(old => !old);
|
setRerender(old => !old);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,9 +6,11 @@ import {
|
|||||||
import { ContractElem } from "./ContractElem";
|
import { ContractElem } from "./ContractElem";
|
||||||
import { Contract } from "../Contract";
|
import { Contract } from "../Contract";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { IBladeburner } from "../IBladeburner";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: IBladeburner;
|
||||||
|
player: IPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ContractList(props: IProps): React.ReactElement {
|
export function ContractList(props: IProps): React.ReactElement {
|
||||||
@ -16,7 +18,7 @@ export function ContractList(props: IProps): React.ReactElement {
|
|||||||
const contracts = props.bladeburner.contracts;
|
const contracts = props.bladeburner.contracts;
|
||||||
return (<>
|
return (<>
|
||||||
{names.map((name: string) => <li key={name} className="bladeburner-action">
|
{names.map((name: string) => <li key={name} className="bladeburner-action">
|
||||||
<ContractElem bladeburner={props.bladeburner} action={contracts[name]} />
|
<ContractElem bladeburner={props.bladeburner} action={contracts[name]} player={props.player} />
|
||||||
</li>,
|
</li>,
|
||||||
)}
|
)}
|
||||||
</>);
|
</>);
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { ContractList } from "./ContractList";
|
import { ContractList } from "./ContractList";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { IBladeburner } from "../IBladeburner";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: IBladeburner;
|
||||||
|
player: IPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ContractPage(props: IProps): React.ReactElement {
|
export function ContractPage(props: IProps): React.ReactElement {
|
||||||
@ -16,6 +18,6 @@ export function ContractPage(props: IProps): React.ReactElement {
|
|||||||
You can unlock higher-level contracts by successfully completing them.
|
You can unlock higher-level contracts by successfully completing them.
|
||||||
Higher-level contracts are more difficult, but grant more rank, experience, and money.
|
Higher-level contracts are more difficult, but grant more rank, experience, and money.
|
||||||
</p>
|
</p>
|
||||||
<ContractList bladeburner={props.bladeburner} />
|
<ContractList bladeburner={props.bladeburner} player={props.player} />
|
||||||
</>);
|
</>);
|
||||||
}
|
}
|
@ -8,9 +8,13 @@ import {
|
|||||||
import { stealthIcon, killIcon } from "../data/Icons";
|
import { stealthIcon, killIcon } from "../data/Icons";
|
||||||
import { BladeburnerConstants } from "../data/Constants";
|
import { BladeburnerConstants } from "../data/Constants";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { IBladeburner } from "../IBladeburner";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
|
||||||
|
import { startAction } from "../Bladeburner";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: IBladeburner;
|
||||||
|
player: IPlayer;
|
||||||
action: any;
|
action: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,7 +26,7 @@ export function GeneralActionElem(props: IProps): React.ReactElement {
|
|||||||
function onStart() {
|
function onStart() {
|
||||||
props.bladeburner.action.type = ActionTypes[(props.action.name as string)];
|
props.bladeburner.action.type = ActionTypes[(props.action.name as string)];
|
||||||
props.bladeburner.action.name = props.action.name;
|
props.bladeburner.action.name = props.action.name;
|
||||||
props.bladeburner.startAction(props.bladeburner.action);
|
startAction(props.bladeburner, props.player, props.bladeburner.action);
|
||||||
setRerender(old => !old);
|
setRerender(old => !old);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,9 +7,11 @@ import { GeneralActionElem } from "./GeneralActionElem";
|
|||||||
import { Action } from "../Action";
|
import { Action } from "../Action";
|
||||||
import { GeneralActions } from "../GeneralActions";
|
import { GeneralActions } from "../GeneralActions";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { IBladeburner } from "../IBladeburner";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: IBladeburner;
|
||||||
|
player: IPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function GeneralActionList(props: IProps): React.ReactElement {
|
export function GeneralActionList(props: IProps): React.ReactElement {
|
||||||
@ -21,7 +23,7 @@ export function GeneralActionList(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
return (<>
|
return (<>
|
||||||
{actions.map((action: Action) => <li key={action.name} className="bladeburner-action">
|
{actions.map((action: Action) => <li key={action.name} className="bladeburner-action">
|
||||||
<GeneralActionElem bladeburner={props.bladeburner} action={action} />
|
<GeneralActionElem bladeburner={props.bladeburner} action={action} player={props.player} />
|
||||||
</li>,
|
</li>,
|
||||||
)}
|
)}
|
||||||
</>);
|
</>);
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { GeneralActionList } from "./GeneralActionList";
|
import { GeneralActionList } from "./GeneralActionList";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { IBladeburner } from "../IBladeburner";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: IBladeburner;
|
||||||
|
player: IPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function GeneralActionPage(props: IProps): React.ReactElement {
|
export function GeneralActionPage(props: IProps): React.ReactElement {
|
||||||
@ -12,6 +14,6 @@ export function GeneralActionPage(props: IProps): React.ReactElement {
|
|||||||
These are generic actions that will assist you in your Bladeburner
|
These are generic actions that will assist you in your Bladeburner
|
||||||
duties. They will not affect your Bladeburner rank in any way.
|
duties. They will not affect your Bladeburner rank in any way.
|
||||||
</p>
|
</p>
|
||||||
<GeneralActionList bladeburner={props.bladeburner} />
|
<GeneralActionList bladeburner={props.bladeburner} player={props.player} />
|
||||||
</>);
|
</>);
|
||||||
}
|
}
|
@ -10,9 +10,12 @@ import { BladeburnerConstants } from "../data/Constants";
|
|||||||
import { createPopup } from "../../ui/React/createPopup";
|
import { createPopup } from "../../ui/React/createPopup";
|
||||||
import { TeamSizePopup } from "./TeamSizePopup";
|
import { TeamSizePopup } from "./TeamSizePopup";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { IBladeburner } from "../IBladeburner";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
import { startAction } from "../Bladeburner";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: IBladeburner;
|
||||||
|
player: IPlayer;
|
||||||
action: any;
|
action: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,7 +31,7 @@ export function OperationElem(props: IProps): React.ReactElement {
|
|||||||
function onStart() {
|
function onStart() {
|
||||||
props.bladeburner.action.type = ActionTypes.Operation;
|
props.bladeburner.action.type = ActionTypes.Operation;
|
||||||
props.bladeburner.action.name = props.action.name;
|
props.bladeburner.action.name = props.action.name;
|
||||||
props.bladeburner.startAction(props.bladeburner.action);
|
startAction(props.bladeburner, props.player, props.bladeburner.action);
|
||||||
setRerender(old => !old);
|
setRerender(old => !old);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,13 +46,13 @@ export function OperationElem(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
function increaseLevel() {
|
function increaseLevel() {
|
||||||
++props.action.level;
|
++props.action.level;
|
||||||
if (isActive) props.bladeburner.startAction(props.bladeburner.action);
|
if (isActive) startAction(props.bladeburner, props.player, props.bladeburner.action);
|
||||||
setRerender(old => !old);
|
setRerender(old => !old);
|
||||||
}
|
}
|
||||||
|
|
||||||
function decreaseLevel() {
|
function decreaseLevel() {
|
||||||
--props.action.level;
|
--props.action.level;
|
||||||
if (isActive) props.bladeburner.startAction(props.bladeburner.action);
|
if (isActive) startAction(props.bladeburner, props.player, props.bladeburner.action);
|
||||||
setRerender(old => !old);
|
setRerender(old => !old);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,9 +6,11 @@ import {
|
|||||||
import { OperationElem } from "./OperationElem";
|
import { OperationElem } from "./OperationElem";
|
||||||
import { Operation } from "../Operation";
|
import { Operation } from "../Operation";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { IBladeburner } from "../IBladeburner";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: IBladeburner;
|
||||||
|
player: IPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function OperationList(props: IProps): React.ReactElement {
|
export function OperationList(props: IProps): React.ReactElement {
|
||||||
@ -16,7 +18,7 @@ export function OperationList(props: IProps): React.ReactElement {
|
|||||||
const operations = props.bladeburner.operations;
|
const operations = props.bladeburner.operations;
|
||||||
return (<>
|
return (<>
|
||||||
{names.map((name: string) => <li key={name} className="bladeburner-action">
|
{names.map((name: string) => <li key={name} className="bladeburner-action">
|
||||||
<OperationElem bladeburner={props.bladeburner} action={operations[name]} />
|
<OperationElem bladeburner={props.bladeburner} action={operations[name]} player={props.player} />
|
||||||
</li>,
|
</li>,
|
||||||
)}
|
)}
|
||||||
</>);
|
</>);
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { OperationList } from "./OperationList";
|
import { OperationList } from "./OperationList";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { IBladeburner } from "../IBladeburner";
|
||||||
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: IBladeburner;
|
||||||
|
player: IPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function OperationPage(props: IProps): React.ReactElement {
|
export function OperationPage(props: IProps): React.ReactElement {
|
||||||
@ -27,6 +29,6 @@ export function OperationPage(props: IProps): React.ReactElement {
|
|||||||
You can unlock higher-level operations by successfully completing them.
|
You can unlock higher-level operations by successfully completing them.
|
||||||
Higher-level operations are more difficult, but grant more rank and experience.
|
Higher-level operations are more difficult, but grant more rank and experience.
|
||||||
</p>
|
</p>
|
||||||
<OperationList bladeburner={props.bladeburner} />
|
<OperationList bladeburner={props.bladeburner} player={props.player} />
|
||||||
</>);
|
</>);
|
||||||
}
|
}
|
@ -19,10 +19,10 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
<div style={{height: '100%', width:"30%", display:"inline-block", border:"1px solid white"}}>
|
<div style={{height: '100%', width:"30%", display:"inline-block", border:"1px solid white"}}>
|
||||||
<Stats bladeburner={props.bladeburner} player={props.player} engine={props.engine} />
|
<Stats bladeburner={props.bladeburner} player={props.player} engine={props.engine} />
|
||||||
</div>
|
</div>
|
||||||
<Console bladeburner={props.bladeburner} />
|
<Console bladeburner={props.bladeburner} player={props.player} />
|
||||||
</div>
|
</div>
|
||||||
<div style={{width:"70%", display:"block", border:"1px solid white", marginTop:"6px", padding: "6px", position:"relative"}}>
|
<div style={{width:"70%", display:"block", border:"1px solid white", marginTop:"6px", padding: "6px", position:"relative"}}>
|
||||||
<AllPages bladeburner={props.bladeburner} />
|
<AllPages bladeburner={props.bladeburner} player={props.player} />
|
||||||
</div>
|
</div>
|
||||||
</div>);
|
</div>);
|
||||||
}
|
}
|
1
src/RedPill.d.ts
vendored
Normal file
1
src/RedPill.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
export declare function hackWorldDaemon(currentNodeNumber: number, flume: boolean = false, quick: boolean = false): void;
|
Loading…
Reference in New Issue
Block a user