Finished location code refactor. Has not yet been tested

This commit is contained in:
danielyxie 2019-04-01 02:23:25 -07:00
parent 3f8b9e4a32
commit 4b95ba9ed1
46 changed files with 2100 additions and 3083 deletions

@ -6,7 +6,6 @@ import { Engine } from "./engine";
import { Faction } from "./Faction/Faction";
import { Factions, factionExists } from "./Faction/Factions";
import { joinFaction, displayFactionContent } from "./Faction/FactionHelpers";
import { Locations } from "./Locations";
import { Player } from "./Player";
import { hackWorldDaemon, redPillFlag } from "./RedPill";
import { numeralWrapper } from "./ui/numeralFormat";
@ -218,7 +217,7 @@ $(document).keydown(function(event) {
});
function City(params={}) {
this.name = params.name ? params.name : Locations.Sector12;
this.name = params.name ? params.name : CityNames[2]; // Sector-12
//Synthoid population and estimate
this.pop = params.pop ? params.pop : getRandomInt(PopulationThreshold, 1.5 * PopulationThreshold);
@ -690,7 +689,7 @@ function Bladeburner(params={}) {
for (var i = 0; i < CityNames.length; ++i) {
this.cities[CityNames[i]] = new City({name:CityNames[i]});
}
this.city = Locations.Sector12;
this.city = CityNames[2]; // Sector-12
//Map of SkillNames -> level
this.skills = {};

@ -1,5 +1,5 @@
import { CONSTANTS } from "../Constants";
import * as names from "./data/CompanyPositionNames";
import * as names from "./data/companypositionnames";
/* tslint:disable:completed-docs */

@ -1,7 +1,8 @@
import { IConstructorParams } from "../Company";
import { Locations } from "../../Locations";
import * as posNames from "./CompanyPositionNames";
import { IMap } from "../../types";
import * as posNames from "./companypositionnames";
import { IConstructorParams } from "../Company";
import { IMap } from "../../types";
import { LocationName } from "../../Locations/data/LocationNames";
// Create Objects containing Company Positions by category
// Will help in metadata construction later
@ -89,7 +90,7 @@ CEOOnly[posNames.BusinessCompanyPositions[5]] = true;
// Metadata
export const companiesMetadata: IConstructorParams[] = [
{
name: Locations.AevumECorp,
name: LocationName.AevumECorp,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -101,7 +102,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 249,
},
{
name: Locations.Sector12MegaCorp,
name: LocationName.Sector12MegaCorp,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -113,7 +114,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 249,
},
{
name: Locations.AevumBachmanAndAssociates,
name: LocationName.AevumBachmanAndAssociates,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -125,7 +126,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 224,
},
{
name: Locations.Sector12BladeIndustries,
name: LocationName.Sector12BladeIndustries,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -137,7 +138,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 224,
},
{
name: Locations.VolhavenNWO,
name: LocationName.VolhavenNWO,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -149,7 +150,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 249,
},
{
name: Locations.AevumClarkeIncorporated,
name: LocationName.AevumClarkeIncorporated,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -161,7 +162,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 224,
},
{
name: Locations.VolhavenOmniTekIncorporated,
name: LocationName.VolhavenOmniTekIncorporated,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -173,7 +174,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 224,
},
{
name: Locations.Sector12FourSigma,
name: LocationName.Sector12FourSigma,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -185,7 +186,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 224,
},
{
name: Locations.ChongqingKuaiGongInternational,
name: LocationName.ChongqingKuaiGongInternational,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -197,7 +198,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 224,
},
{
name: Locations.AevumFulcrumTechnologies,
name: LocationName.AevumFulcrumTechnologies,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -208,7 +209,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 224,
},
{
name: Locations.IshimaStormTechnologies,
name: LocationName.IshimaStormTechnologies,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -220,7 +221,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 199,
},
{
name: Locations.NewTokyoDefComm,
name: LocationName.NewTokyoDefComm,
info: "",
companyPositions: Object.assign({},
CEOOnly,
@ -232,7 +233,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 199,
},
{
name: Locations.VolhavenHeliosLabs,
name: LocationName.VolhavenHeliosLabs,
info: "",
companyPositions: Object.assign({},
CEOOnly,
@ -244,7 +245,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 199,
},
{
name: Locations.NewTokyoVitaLife,
name: LocationName.NewTokyoVitaLife,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -256,7 +257,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 199,
},
{
name: Locations.Sector12IcarusMicrosystems,
name: LocationName.Sector12IcarusMicrosystems,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -268,7 +269,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 199,
},
{
name: Locations.Sector12UniversalEnergy,
name: LocationName.Sector12UniversalEnergy,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -280,7 +281,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 199,
},
{
name: Locations.AevumGalacticCybersystems,
name: LocationName.AevumGalacticCybersystems,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -292,7 +293,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 199,
},
{
name: Locations.AevumAeroCorp,
name: LocationName.AevumAeroCorp,
info: "",
companyPositions: Object.assign({},
CEOOnly,
@ -305,7 +306,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 199,
},
{
name: Locations.VolhavenOmniaCybersystems,
name: LocationName.VolhavenOmniaCybersystems,
info: "",
companyPositions: Object.assign({},
CEOOnly,
@ -318,7 +319,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 199,
},
{
name: Locations.ChongqingSolarisSpaceSystems,
name: LocationName.ChongqingSolarisSpaceSystems,
info: "",
companyPositions: Object.assign({},
CEOOnly,
@ -331,7 +332,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 199,
},
{
name: Locations.Sector12DeltaOne,
name: LocationName.Sector12DeltaOne,
info: "",
companyPositions: Object.assign({},
CEOOnly,
@ -344,7 +345,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 199,
},
{
name: Locations.NewTokyoGlobalPharmaceuticals,
name: LocationName.NewTokyoGlobalPharmaceuticals,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -357,7 +358,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 224,
},
{
name: Locations.IshimaNovaMedical,
name: LocationName.IshimaNovaMedical,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -370,7 +371,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 199,
},
{
name: Locations.Sector12CIA,
name: LocationName.Sector12CIA,
info: "",
companyPositions: Object.assign({},
SoftwarePositionsUpToHeadOfEngineering,
@ -385,7 +386,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 149,
},
{
name: Locations.Sector12NSA,
name: LocationName.Sector12NSA,
info: "",
companyPositions: Object.assign({},
SoftwarePositionsUpToHeadOfEngineering,
@ -400,7 +401,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 149,
},
{
name: Locations.AevumWatchdogSecurity,
name: LocationName.AevumWatchdogSecurity,
info: "",
companyPositions: Object.assign({},
SoftwarePositionsUpToHeadOfEngineering,
@ -415,7 +416,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 124,
},
{
name: Locations.VolhavenLexoCorp,
name: LocationName.VolhavenLexoCorp,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -428,7 +429,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 99,
},
{
name: Locations.AevumRhoConstruction,
name: LocationName.AevumRhoConstruction,
info: "",
companyPositions: Object.assign({},
SoftwarePositionsUpToLeadDeveloper,
@ -439,7 +440,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 49,
},
{
name: Locations.Sector12AlphaEnterprises,
name: LocationName.Sector12AlphaEnterprises,
info: "",
companyPositions: Object.assign({},
SoftwarePositionsUpToLeadDeveloper,
@ -451,7 +452,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 99,
},
{
name: Locations.AevumPolice,
name: LocationName.AevumPolice,
info: "",
companyPositions: Object.assign({},
AllSecurityPositions,
@ -462,7 +463,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 99,
},
{
name: Locations.VolhavenSysCoreSecurities,
name: LocationName.VolhavenSysCoreSecurities,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions
@ -472,7 +473,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 124,
},
{
name: Locations.VolhavenCompuTek,
name: LocationName.VolhavenCompuTek,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions
@ -482,7 +483,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 74,
},
{
name: Locations.AevumNetLinkTechnologies,
name: LocationName.AevumNetLinkTechnologies,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions
@ -492,7 +493,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 99,
},
{
name: Locations.Sector12CarmichaelSecurity,
name: LocationName.Sector12CarmichaelSecurity,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -505,7 +506,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 74,
},
{
name: Locations.Sector12FoodNStuff,
name: LocationName.Sector12FoodNStuff,
info: "",
companyPositions: Object.assign({},
EmployeeOnly, PartTimeEmployeeOnly
@ -515,7 +516,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 0,
},
{
name: Locations.Sector12JoesGuns,
name: LocationName.Sector12JoesGuns,
info: "",
companyPositions: Object.assign({},
EmployeeOnly, PartTimeEmployeeOnly
@ -525,7 +526,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 0,
},
{
name: Locations.IshimaOmegaSoftware,
name: LocationName.IshimaOmegaSoftware,
info: "",
companyPositions: Object.assign({},
AllSoftwarePositions,
@ -537,7 +538,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 49,
},
{
name: Locations.NewTokyoNoodleBar,
name: LocationName.NewTokyoNoodleBar,
info: "",
companyPositions: Object.assign({},
WaiterOnly, PartTimeWaiterOnly

@ -1,6 +1,6 @@
// Metadata used for constructing Company Positions
import { IConstructorParams } from "../CompanyPosition";
import * as posNames from "./CompanyPositionNames";
import * as posNames from "./companypositionnames";
export const companyPositionMetadata: IConstructorParams[] = [
{

@ -18,8 +18,8 @@ import { BitNodeMultipliers } from "../BitNode/BitNode
import { CONSTANTS } from "../Constants";
import { Factions } from "../Faction/Factions";
import { showLiterature } from "../Literature";
import { Locations } from "../Locations";
import { createCityMap } from "../Locations/Cities";
import { CityName } from "../Locations/data/CityNames";
import { Player } from "../Player";
import { numeralWrapper } from "../ui/numeralFormat";
@ -113,15 +113,15 @@ $(document).mousedown(function(event) {
var empManualAssignmentModeActive = false;
function Industry(params={}) {
this.offices = { //Maps locations to offices. 0 if no office at that location
[Locations.Aevum]: 0,
[Locations.Chongqing]: 0,
[Locations.Sector12]: new OfficeSpace({
loc:Locations.Sector12,
[CityName.Aevum]: 0,
[CityName.Chongqing]: 0,
[CityName.Sector12]: new OfficeSpace({
loc:CityName.Sector12,
size:OfficeInitialSize,
}),
[Locations.NewTokyo]: 0,
[Locations.Ishima]: 0,
[Locations.Volhaven]: 0
[CityName.NewTokyo]: 0,
[CityName.Ishima]: 0,
[CityName.Volhaven]: 0
};
this.name = params.name ? params.name : 0;
@ -172,17 +172,17 @@ function Industry(params={}) {
this.newInd = true;
this.warehouses = { //Maps locations to warehouses. 0 if no warehouse at that location
[Locations.Aevum]: 0,
[Locations.Chonqing]: 0,
[Locations.Sector12]: new Warehouse({
[CityName.Aevum]: 0,
[CityName.Chonqing]: 0,
[CityName.Sector12]: new Warehouse({
corp: params.corp,
industry: this,
loc: Locations.Sector12,
loc: CityName.Sector12,
size: WarehouseInitialSize,
}),
[Locations.NewTokyo]: 0,
[Locations.Ishima]: 0,
[Locations.Volhaven]: 0
[CityName.NewTokyo]: 0,
[CityName.Ishima]: 0,
[CityName.Volhaven]: 0
};
this.init();
@ -571,7 +571,7 @@ Industry.prototype.processProductMarket = function(marketCycles=1) {
const product = this.products[name];
let change = getRandomInt(0, 3) * 0.0004;
if (change === 0) { continue; }
if (this.type === Industries.Pharmaceutical || this.type === Industries.Software ||
this.type === Industries.Robotics) {
change *= 3;

@ -11,7 +11,7 @@ import { overviewPage } from "./Routing";
import { OfficeSpace } from "../Corporation";
import { CityName } from "../../Locations/data/Cities";
import { CityName } from "../../Locations/data/CityNames";
export class MainPanel extends BaseReactComponent {
constructor(props) {

@ -7,7 +7,6 @@ import { Engine } from "../engine";
import { Faction } from "./Faction";
import { Factions } from "./Factions";
import { FactionInfos } from "./FactionInfo";
import { Locations} from "../Location";
import { HackingMission, setInMission } from "../Missions";
import { Player } from "../Player";
import { PurchaseAugmentationsOrderSetting } from "../Settings/SettingEnums";

10
src/IEngine.ts Normal file

@ -0,0 +1,10 @@
/**
* TypeScript interface for the game engine (engine.js), which can't be converted
* to TypeScript at the moment
*/
export interface IEngine {
loadBladeburnerContent: () => void;
loadInfiltrationContent: () => void;
loadResleevingContent: () => void;
loadStockMarketContent: () => void;
}

7
src/Infiltration.d.ts vendored Normal file

@ -0,0 +1,7 @@
import { LocationName } from "./Locations/data/LocationNames";
export declare function beginInfiltration(companyName: LocationName,
startLevel: number,
rewardVal: number,
maxClearance: number,
diff: number): void;

@ -382,13 +382,13 @@ function iTutorialEvaluateStep() {
//Flash 'City' menu and set its tutorial click handler
cityMainMenu.setAttribute("class", "flashing-button");
cityMainMenu.addEventListener("click", function() {
Engine.loadWorldContent();
Engine.loadLocationContent();
iTutorialNextStep();
return false;
});
break;
case iTutorialSteps.WorldDescription:
Engine.loadWorldContent();
Engine.loadLocationContent();
iTutorialSetText("This page lists all of the different locations you can currently " +
"travel to. Each location has something that you can do. " +
"There's a lot of content out in the world, make sure " +

File diff suppressed because it is too large Load Diff

@ -5,8 +5,18 @@ import { CityName } from "./data/CityNames";
import { LocationName } from "./data/LocationNames";
import { LocationType } from "./LocationTypeEnum";
interface IInfiltrationMetadata {
baseRewardValue: number;
difficulty: number;
maxClearanceLevel: number;
startingSecurityLevel: number;
}
export interface IConstructorParams {
city?: CityName | null;
costMult?: number;
expMult?: number;
infiltrationData?: IInfiltrationMetadata;
name?: LocationName;
types?: LocationType[];
techVendorMaxRam?: number;
@ -20,6 +30,22 @@ export class Location {
*/
city: CityName | null = null;
/**
* Cost multiplier that influences how expensive a gym/university is
*/
costMult: number = 0;
/**
* Exp multiplier that influences how effective a gym/university is
*/
expMult: number = 0;
/**
* Companies can be infiltrated. This contains the data required for that
* infiltration event
*/
infiltrationData?: IInfiltrationMetadata;
/**
* Identifier for location
*/
@ -45,6 +71,9 @@ export class Location {
constructor(p: IConstructorParams) {
if (p.city) { this.city = p.city; }
if (p.costMult) { this.costMult = p.costMult; }
if (p.expMult) { this.expMult = p.expMult; }
if (p.infiltrationData) { this.infiltrationData = p.infiltrationData; }
if (p.name) { this.name = p.name; }
if (p.types) { this.types = p.types; }
if (p.techVendorMaxRam) { this.techVendorMaxRam = p.techVendorMaxRam; }

@ -1,9 +0,0 @@
/**
* Location and traveling-related helper functions.
* Mostly used for UI
*/
import { Player } from "../Player";
import { Company } from "../Company/Company";
import { getJobRequirementText } from "../Company/GetJobRequirementText";
import * as posNames from "../Company/data/companypositionnames";

@ -0,0 +1,281 @@
/**
* Location and traveling-related helper functions.
* Mostly used for UI
*/
import { CONSTANTS } from "../Constants";
import { CityName } from "./data/CityNames";
import { IPlayer } from "../PersonObjects/IPlayer";
import { AllServers,
AddToAllServers } from "../Server/AllServers";
import { Server } from "../Server/Server";
import { getPurchaseServerCost,
purchaseRamForHomeComputer,
purchaseServer } from "../Server/ServerPurchases";
import { SpecialServerIps } from "../Server/SpecialServerIps";
import { Settings } from "../Settings/Settings";
import { numeralWrapper } from "../ui/numeralFormat";
import { dialogBoxCreate } from "../../utils/DialogBox";
import { createRandomIp } from "../../utils/IPAddress";
import { yesNoBoxGetYesButton,
yesNoBoxGetNoButton,
yesNoBoxClose,
yesNoBoxCreate,
yesNoTxtInpBoxGetYesButton,
yesNoTxtInpBoxGetNoButton,
yesNoTxtInpBoxClose,
yesNoTxtInpBoxCreate } from "../../utils/YesNoBox";
import { createElement } from "../../utils/uiHelpers/createElement";
import { createPopup } from "../../utils/uiHelpers/createPopup";
import { createPopupCloseButton } from "../../utils/uiHelpers/createPopupCloseButton";
import { removeElementById } from "../../utils/uiHelpers/removeElementById";
/**
* Create a pop-up box that lets the player confirm traveling to a different city
* If settings are configured to suppress this popup, just instantly travel
* The actual "Travel" implementation is implemented in the UI, and is passed in
* as an argument
*/
type TravelFunction = (to: CityName) => void;
export function createTravelPopup(destination: CityName, travelFn: TravelFunction) {
const cost = CONSTANTS.TravelCost;
if (Settings.SuppressTravelConfirmation) {
travelFn(destination);
return;
}
const yesBtn = yesNoBoxGetYesButton();
const noBtn = yesNoBoxGetNoButton();
if (yesBtn == null || noBtn == null) {
console.warn(`Could nto find YesNo pop-up box buttons`);
return;
}
yesBtn.innerHTML = "Yes";
yesBtn.addEventListener("click", () => {
yesNoBoxClose();
travelFn(destination);
return false;
});
noBtn.innerHTML = "No";
noBtn.addEventListener("click", () => {
yesNoBoxClose();
return false;
});
yesNoBoxCreate(`Would you like to travel to ${destination}? The trip will ` +
`cost ${numeralWrapper.formatMoney(cost)}`);
}
/**
* Create a pop-up box that lets the player purchase a server.
* @param ram - Amount of RAM (GB) on server
* @param p - Player object
*/
export function createPurchaseServerPopup(ram: number, p: IPlayer) {
const cost = getPurchaseServerCost(ram);
if (cost === Infinity) {
dialogBoxCreate("Something went wrong when trying to purchase this server. Please contact developer");
return;
}
var yesBtn = yesNoTxtInpBoxGetYesButton();
var noBtn = yesNoTxtInpBoxGetNoButton();
if (yesBtn == null || noBtn == null) { return; }
yesBtn.innerHTML = "Purchase Server";
noBtn.innerHTML = "Cancel";
yesBtn.addEventListener("click", function() {
purchaseServer(ram, p);
yesNoTxtInpBoxClose();
});
noBtn.addEventListener("click", function() {
yesNoTxtInpBoxClose();
});
yesNoTxtInpBoxCreate("Would you like to purchase a new server with " + ram +
"GB of RAM for $" + numeralWrapper.formatMoney(cost) + "?<br><br>" +
"Please enter the server hostname below:<br>");
}
/**
* Create a popup that lets the player start a Corporation
*/
export function createStartCorporationPopup(p: IPlayer) {
if (p.hasCorporation) { return; }
const popupId = "create-corporation-popup";
const txt = createElement("p", {
innerHTML: "Would you like to start a corporation? This will require $150b for registration " +
"and initial funding. This $150b can either be self-funded, or you can obtain " +
"the seed money from the government in exchange for 500 million shares<br><br>" +
"If you would like to start one, please enter a name for your corporation below:",
});
const nameInput = createElement("input", {
placeholder: "Corporation Name",
}) as HTMLInputElement;
const selfFundedButton = createElement("button", {
class: "popup-box-button",
innerText: "Self-Fund",
clickListener: () => {
if (!p.canAfford(150e9)) {
dialogBoxCreate("You don't have enough money to create a corporation! You need $150b");
return false;
}
p.loseMoney(150e9);
const companyName = nameInput.value;
if (companyName == null || companyName == "") {
dialogBoxCreate("Invalid company name!");
return false;
}
p.startCorporation(companyName);
const worldHeader = document.getElementById("world-menu-header");
if (worldHeader instanceof HTMLElement) {
worldHeader.click(); worldHeader.click();
}
dialogBoxCreate("Congratulations! You just self-funded your own corporation. You can visit " +
"and manage your company in the City");
removeElementById(popupId);
return false;
}
});
const seedMoneyButton = createElement("button", {
class: "popup-box-button",
innerText: "Use Seed Money",
clickListener: () => {
const companyName = nameInput.value;
if (companyName == null || companyName == "") {
dialogBoxCreate("Invalid company name!");
return false;
}
p.startCorporation(companyName, 500e6);
const worldHeader = document.getElementById("world-menu-header");
if (worldHeader instanceof HTMLElement) {
worldHeader.click(); worldHeader.click();
}
dialogBoxCreate("Congratulations! You just started your own corporation with government seed money. " +
"You can visit and manage your company in the City");
removeElementById(popupId);
return false;
}
})
const cancelBtn = createPopupCloseButton(popupId, { class: "popup-box-button" });
createPopup(popupId, [txt, nameInput, cancelBtn, selfFundedButton, seedMoneyButton]);
nameInput.focus();
}
/**
* Create a popup that lets the player upgrade the cores on his/her home computer
* @param p - Player object
*/
export function createUpgradeHomeCoresPopup(p: IPlayer) {
const currentCores = p.getHomeComputer().cpuCores;
if (currentCores >= 8) { return; } // Max of 8 cores
//Cost of purchasing another cost is found by indexing this array with number of current cores
const allCosts = [0,
10e9, // 1->2 Cores - 10 bn
250e9, // 2->3 Cores - 250 bn
5e12, // 3->4 Cores - 5 trillion
100e12, // 4->5 Cores - 100 trillion
1e15, // 5->6 Cores - 1 quadrillion
20e15, // 6->7 Cores - 20 quadrillion
200e15]; // 7->8 Cores - 200 quadrillion
const cost: number = allCosts[currentCores];
const yesBtn = yesNoBoxGetYesButton();
const noBtn = yesNoBoxGetNoButton();
if (yesBtn == null || noBtn == null) { return; }
yesBtn.innerHTML = "Purchase";
yesBtn.addEventListener("click", ()=>{
if (!p.canAfford(cost)) {
dialogBoxCreate("You do not have enough money to purchase an additional CPU Core for your home computer!");
} else {
p.loseMoney(cost);
p.getHomeComputer().cpuCores++;
dialogBoxCreate("You purchased an additional CPU Core for your home computer! It now has " +
p.getHomeComputer().cpuCores + " cores.");
}
yesNoBoxClose();
});
noBtn.innerHTML = "Cancel";
noBtn.addEventListener("click", ()=>{
yesNoBoxClose();
});
yesNoBoxCreate("Would you like to purchase an additional CPU Core for your home computer? Each CPU Core " +
"lets you start with an additional Core Node in Hacking Missions.<br><br>" +
"Purchasing an additional core (for a total of " + (p.getHomeComputer().cpuCores + 1) + ") will " +
"cost " + numeralWrapper.formatMoney(cost));
}
/**
* Create a popup that lets the player upgrade the RAM on his/her home computer
* @param p - Player object
*/
export function createUpgradeHomeRamPopup(p: IPlayer) {
const cost: number = p.getUpgradeHomeRamCost();
const ram: number = p.getHomeComputer().maxRam;
const yesBtn = yesNoBoxGetYesButton();
const noBtn = yesNoBoxGetNoButton();
if (yesBtn == null || noBtn == null) { return; }
yesBtn.innerText = "Purchase";
yesBtn.addEventListener("click", ()=>{
purchaseRamForHomeComputer(cost, p);
yesNoBoxClose();
});
noBtn.innerText = "Cancel";
noBtn.addEventListener("click", ()=>{
yesNoBoxClose();
});
yesNoBoxCreate("Would you like to purchase additional RAM for your home computer? <br><br>" +
"This will upgrade your RAM from " + ram + "GB to " + ram*2 + "GB. <br><br>" +
"This will cost " + numeralWrapper.format(cost, '$0.000a'));
}
/**
* Attempt to purchase a TOR router
* @param p - Player object
*/
export function purchaseTorRouter(p: IPlayer) {
if (!p.canAfford(CONSTANTS.TorRouterCost)) {
dialogBoxCreate("You cannot afford to purchase the Tor router");
return;
}
p.loseMoney(CONSTANTS.TorRouterCost);
const darkweb = new Server({
ip: createRandomIp(), hostname:"darkweb", organizationName:"",
isConnectedTo:false, adminRights:false, purchasedByPlayer:false, maxRam:1
});
AddToAllServers(darkweb);
SpecialServerIps.addIp("Darkweb Server", darkweb.ip);
p.getHomeComputer().serversOnNetwork.push(darkweb.ip);
darkweb.serversOnNetwork.push(p.getHomeComputer().ip);
dialogBoxCreate("You have purchased a Tor router!<br>" +
"You now have access to the dark web from your home computer<br>" +
"Use the scan/scan-analyze commands to search for the dark web connection.");
}

@ -21,17 +21,13 @@ export enum LocationName {
AevumNetLinkTechnologies = "NetLink Technologies",
AevumPolice = "Aevum Police Headquarters",
AevumRhoConstruction = "Rho Construction",
AevumSlums = "Aevum Slums", // TODO Delete this and other Slums locations
AevumSnapFitnessGym = "Snap Fitness Gym",
AevumSummitUniversity = "Summit University",
AevumTravelAgency = "Aevum Travel Agency", // TODO Delete this and other travel agency locations
AevumWatchdogSecurity = "Watchdog Security",
// Chongqing locations
ChongqingKuaiGongInternational = "KuaiGong International",
ChongqingSlums = "Chongqing Slums",
ChongqingSolarisSpaceSystems = "Solaris Space Systems",
ChongqingTravelAgency = "Chongqing Travel Agency",
// Sector 12
Sector12AlphaEnterprises = "Alpha Enterprises",
@ -49,24 +45,18 @@ export enum LocationName {
Sector12NSA = "National Security Agency",
Sector12PowerhouseGym = "Powerhouse Gym",
Sector12RothmanUniversity = "Rothman University",
Sector12Slums = "Sector-12 Slums",
Sector12TravelAgency = "Sector-12 Travel Agency",
Sector12UniversalEnergy = "Universal Energy",
// New Tokyo
NewTokyoDefComm = "DefComm",
NewTokyoGlobalPharmaceuticals = "Global Pharmaceuticals",
NewTokyoNoodleBar = "Noodle Bar",
NewTokyoSlums = "New Tokyo Slums",
NewTokyoTravelAgency = "New Tokyo Travel Agency",
NewTokyoVitaLife = "VitaLife",
// Ishima
IshimaNovaMedical = "Nova Medical",
IshimaOmegaSoftware = "Omega Software",
IshimaSlums = "Ishima Slums",
IshimaStormTechnologies = "Storm Technologies",
IshimaTravelAgency = "Ishima Travel Agency",
// Volhaven
VolhavenCompuTek = "CompuTek",
@ -76,9 +66,7 @@ export enum LocationName {
VolhavenNWO = "NWO",
VolhavenOmniTekIncorporated = "OmniTek Incorporated",
VolhavenOmniaCybersystems = "Omnia Cybersystems",
VolhavenSlums = "Volhaven Slums",
VolhavenSysCoreSecurities = "SysCore Securities",
VolhavenTravelAgency = "Volhaven Travel Agency",
VolhavenZBInstituteOfTechnology = "ZB Institute of Technology",
// Generic locations

@ -10,26 +10,52 @@ import { LocationType } from "../LocationTypeEnum";
export const LocationsMetadata: IConstructorParams[] = [
{
city: CityName.Aevum,
infiltrationData: {
baseRewardValue: 32,
difficulty: 4.4,
maxClearanceLevel: 50,
startingSecurityLevel: 1350,
},
name: LocationName.AevumAeroCorp,
types: [LocationType.Company],
},
{
city: CityName.Aevum,
infiltrationData: {
baseRewardValue: 42,
difficulty: 4.1,
maxClearanceLevel: 60,
startingSecurityLevel: 1350,
},
name: LocationName.AevumBachmanAndAssociates,
types: [LocationType.Company],
},
{
city: CityName.Aevum,
infiltrationData: {
baseRewardValue: 34,
difficulty: 3.6,
maxClearanceLevel: 75,
startingSecurityLevel: 1800,
},
name: LocationName.AevumClarkeIncorporated,
types: [LocationType.Company],
},
{
city: CityName.Aevum,
costMult: 3,
expMult: 2,
name: LocationName.AevumCrushFitnessGym,
types: [LocationType.Gym],
},
{
city: CityName.Aevum,
infiltrationData: {
baseRewardValue: 116,
difficulty: 6,
maxClearanceLevel: 150,
startingSecurityLevel: 4800,
},
name: LocationName.AevumECorp,
types: [LocationType.Company, LocationType.TechVendor],
techVendorMaxRam: 512,
@ -37,6 +63,12 @@ export const LocationsMetadata: IConstructorParams[] = [
},
{
city: CityName.Aevum,
infiltrationData: {
baseRewardValue: 96,
difficulty: 6.2,
maxClearanceLevel: 100,
startingSecurityLevel: 4140,
},
name: LocationName.AevumFulcrumTechnologies,
types: [LocationType.Company, LocationType.TechVendor],
techVendorMaxRam: 1024,
@ -44,11 +76,23 @@ export const LocationsMetadata: IConstructorParams[] = [
},
{
city: CityName.Aevum,
infiltrationData: {
baseRewardValue: 30,
difficulty: 3.95,
maxClearanceLevel: 50,
startingSecurityLevel: 1260,
},
name: LocationName.AevumGalacticCybersystems,
types: [LocationType.Company],
},
{
city: CityName.Aevum,
infiltrationData: {
baseRewardValue: 10,
difficulty: 1.4,
maxClearanceLevel: 25,
startingSecurityLevel: 144,
},
name: LocationName.AevumNetLinkTechnologies,
types: [LocationType.Company, LocationType.TechVendor],
techVendorMaxRam: 64,
@ -56,46 +100,92 @@ export const LocationsMetadata: IConstructorParams[] = [
},
{
city: CityName.Aevum,
infiltrationData: {
baseRewardValue: 18,
difficulty: 2.2,
maxClearanceLevel: 25,
startingSecurityLevel: 565,
},
name: LocationName.AevumPolice,
types: [LocationType.Company],
},
{
city: CityName.Aevum,
infiltrationData: {
baseRewardValue: 16,
difficulty: 1.9,
maxClearanceLevel: 20,
startingSecurityLevel: 485,
},
name: LocationName.AevumRhoConstruction,
types: [LocationType.Company],
},
{
city: CityName.Aevum,
costMult: 10,
expMult: 5,
name: LocationName.AevumSnapFitnessGym,
types: [LocationType.Gym],
},
{
city: CityName.Aevum,
costMult: 4,
expMult: 3,
name: LocationName.AevumSummitUniversity,
types: [LocationType.University],
},
{
city: CityName.Aevum,
infiltrationData: {
baseRewardValue: 20,
difficulty: 3,
maxClearanceLevel: 30,
startingSecurityLevel: 690,
},
name: LocationName.AevumWatchdogSecurity,
types: [LocationType.Company],
},
{
city: CityName.Chongqing,
infiltrationData: {
baseRewardValue: 100,
difficulty: 6.1,
maxClearanceLevel: 100,
startingSecurityLevel: 4450,
},
name: LocationName.ChongqingKuaiGongInternational,
types: [LocationType.Company],
},
{
city: CityName.Chongqing,
infiltrationData: {
baseRewardValue: 52,
difficulty: 6,
maxClearanceLevel: 75,
startingSecurityLevel: 2915,
},
name: LocationName.ChongqingSolarisSpaceSystems,
types: [LocationType.Company],
},
{
city: CityName.Ishima,
infiltrationData: {
baseRewardValue: 20,
difficulty: 3.2,
maxClearanceLevel: 50,
startingSecurityLevel: 485,
},
name: LocationName.IshimaNovaMedical,
types: [LocationType.Company],
},
{
city: CityName.Ishima,
infiltrationData: {
baseRewardValue: 10,
difficulty: 1.6,
maxClearanceLevel: 40,
startingSecurityLevel: 130,
},
name: LocationName.IshimaOmegaSoftware,
types: [LocationType.Company, LocationType.TechVendor],
techVendorMaxRam: 128,
@ -103,6 +193,12 @@ export const LocationsMetadata: IConstructorParams[] = [
},
{
city: CityName.Ishima,
infiltrationData: {
baseRewardValue: 24,
difficulty: 4.1,
maxClearanceLevel: 100,
startingSecurityLevel: 570,
},
name: LocationName.IshimaStormTechnologies,
types: [LocationType.Company, LocationType.TechVendor],
techVendorMaxRam: 512,
@ -110,11 +206,23 @@ export const LocationsMetadata: IConstructorParams[] = [
},
{
city: CityName.NewTokyo,
infiltrationData: {
baseRewardValue: 28,
difficulty: 4,
maxClearanceLevel: 70,
startingSecurityLevel: 1050,
},
name: LocationName.NewTokyoDefComm,
types: [LocationType.Company],
},
{
city: CityName.NewTokyo,
infiltrationData: {
baseRewardValue: 24,
difficulty: 3.8,
maxClearanceLevel: 80,
startingSecurityLevel: 700,
},
name: LocationName.NewTokyoGlobalPharmaceuticals,
types: [LocationType.Company],
},
@ -125,11 +233,23 @@ export const LocationsMetadata: IConstructorParams[] = [
},
{
city: CityName.NewTokyo,
infiltrationData: {
baseRewardValue: 22,
difficulty: 3.5,
maxClearanceLevel: 100,
startingSecurityLevel: 605,
},
name: LocationName.NewTokyoVitaLife,
types: [LocationType.Company, LocationType.Special],
},
{
city: CityName.Sector12,
infiltrationData: {
baseRewardValue: 14,
difficulty: 2.25,
maxClearanceLevel: 40,
startingSecurityLevel: 200,
},
name: LocationName.Sector12AlphaEnterprises,
types: [LocationType.Company, LocationType.TechVendor],
techVendorMaxRam: 8,
@ -137,6 +257,12 @@ export const LocationsMetadata: IConstructorParams[] = [
},
{
city: CityName.Sector12,
infiltrationData: {
baseRewardValue: 46,
difficulty: 4.2,
maxClearanceLevel: 100,
startingSecurityLevel: 2160,
},
name: LocationName.Sector12BladeIndustries,
types: [LocationType.Company],
},
@ -147,6 +273,12 @@ export const LocationsMetadata: IConstructorParams[] = [
},
{
city: CityName.Sector12,
infiltrationData: {
baseRewardValue: 18,
difficulty: 2.5,
maxClearanceLevel: 60,
startingSecurityLevel: 405,
},
name: LocationName.Sector12CarmichaelSecurity,
types: [LocationType.Company],
},
@ -157,6 +289,12 @@ export const LocationsMetadata: IConstructorParams[] = [
},
{
city: CityName.Sector12,
infiltrationData: {
baseRewardValue: 24,
difficulty: 4.3,
maxClearanceLevel: 50,
startingSecurityLevel: 700,
},
name: LocationName.Sector12DeltaOne,
types: [LocationType.Company],
},
@ -167,26 +305,52 @@ export const LocationsMetadata: IConstructorParams[] = [
},
{
city: CityName.Sector12,
infiltrationData: {
baseRewardValue: 58,
difficulty: 7,
maxClearanceLevel: 100,
startingSecurityLevel: 1350,
},
name: LocationName.Sector12FourSigma,
types: [LocationType.Company],
},
{
city: CityName.Sector12,
infiltrationData: {
baseRewardValue: 32,
difficulty: 5.4,
maxClearanceLevel: 70,
startingSecurityLevel: 730,
},
name: LocationName.Sector12IcarusMicrosystems,
types: [LocationType.Company],
},
{
city: CityName.Sector12,
expMult: 1,
costMult: 1,
name: LocationName.Sector12IronGym,
types: [LocationType.Gym],
},
{
city: CityName.Sector12,
infiltrationData: {
baseRewardValue: 8,
difficulty: 1.8,
maxClearanceLevel: 20,
startingSecurityLevel: 120,
},
name: LocationName.Sector12JoesGuns,
types: [LocationType.Company],
},
{
city: CityName.Sector12,
infiltrationData: {
baseRewardValue: 114,
difficulty: 6.75,
maxClearanceLevel: 125,
startingSecurityLevel: 4500,
},
name: LocationName.Sector12MegaCorp,
types: [LocationType.Company],
},
@ -197,21 +361,37 @@ export const LocationsMetadata: IConstructorParams[] = [
},
{
city: CityName.Sector12,
costMult: 20,
expMult: 10,
name: LocationName.Sector12PowerhouseGym,
types: [LocationType.Gym],
},
{
city: CityName.Sector12,
costMult: 3,
expMult: 2,
name: LocationName.Sector12RothmanUniversity,
types: [LocationType.University],
},
{
city: CityName.Sector12,
infiltrationData: {
baseRewardValue: 24,
difficulty: 4.3,
maxClearanceLevel: 50,
startingSecurityLevel: 700,
},
name: LocationName.Sector12UniversalEnergy,
types: [LocationType.Company],
},
{
city: CityName.Volhaven,
infiltrationData: {
baseRewardValue: 12,
difficulty: 2.1,
maxClearanceLevel: 60,
startingSecurityLevel: 195,
},
name: LocationName.VolhavenCompuTek,
types: [LocationType.Company, LocationType.TechVendor],
techVendorMaxRam: 256,
@ -219,26 +399,52 @@ export const LocationsMetadata: IConstructorParams[] = [
},
{
city: CityName.Volhaven,
infiltrationData: {
baseRewardValue: 28,
difficulty: 3,
maxClearanceLevel: 75,
startingSecurityLevel: 1080,
},
name: LocationName.VolhavenHeliosLabs,
types: [LocationType.Company],
},
{
city: CityName.Volhaven,
infiltrationData: {
baseRewardValue: 14,
difficulty: 2,
maxClearanceLevel: 60,
startingSecurityLevel: 340,
},
name: LocationName.VolhavenLexoCorp,
types: [LocationType.Company],
},
{
city: CityName.Volhaven,
costMult: 7,
expMult: 4,
name: LocationName.VolhavenMilleniumFitnessGym,
types: [LocationType.Gym],
},
{
city: CityName.Volhaven,
infiltrationData: {
baseRewardValue: 56,
difficulty: 6.8,
maxClearanceLevel: 200,
startingSecurityLevel: 1460,
},
name: LocationName.VolhavenNWO,
types: [LocationType.Company],
},
{
city: CityName.Volhaven,
infiltrationData: {
baseRewardValue: 44,
difficulty: 4.4,
maxClearanceLevel: 100,
startingSecurityLevel: 1215,
},
name: LocationName.VolhavenOmniTekIncorporated,
types: [LocationType.Company, LocationType.TechVendor],
techVendorMaxRam: 1024,
@ -246,16 +452,30 @@ export const LocationsMetadata: IConstructorParams[] = [
},
{
city: CityName.Volhaven,
infiltrationData: {
baseRewardValue: 28,
difficulty: 4.9,
maxClearanceLevel: 90,
startingSecurityLevel: 725,
},
name: LocationName.VolhavenOmniaCybersystems,
types: [LocationType.Company],
},
{
city: CityName.Volhaven,
infiltrationData: {
baseRewardValue: 18,
difficulty: 2.4,
maxClearanceLevel: 75,
startingSecurityLevel: 430,
},
name: LocationName.VolhavenSysCoreSecurities,
types: [LocationType.Company],
},
{
city: CityName.Volhaven,
costMult: 5,
expMult: 4,
name: LocationName.VolhavenZBInstituteOfTechnology,
types: [LocationType.University],
},

@ -0,0 +1,46 @@
/**
* React Component for a button that's used to apply for a job
*/
import * as React from "react";
import { Company } from "../../Company/Company";
import { CompanyPosition } from "../../Company/CompanyPosition";
import { getJobRequirementText } from "../../Company/GetJobRequirementText";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { StdButton } from "../../ui/React/StdButton";
type IProps = {
company: Company;
entryPosType: CompanyPosition;
onClick: (e: React.MouseEvent<HTMLElement>) => void;
p: IPlayer;
text: string;
}
export class ApplyToJobButton extends React.Component<IProps, any> {
constructor(props: IProps) {
super(props);
this.getJobRequirementTooltip = this.getJobRequirementTooltip.bind(this);
}
getJobRequirementTooltip(): string {
const pos = this.props.p.getNextCompanyPosition(this.props.company, this.props.entryPosType);
if (pos == null) { return "" };
if (!this.props.company.hasPosition(pos)) { return ""; }
return getJobRequirementText(this.props.company, pos, true);
}
render() {
return (
<StdButton
onClick={this.props.onClick}
text={this.props.text}
tooltip={this.getJobRequirementTooltip()}
/>
)
}
}

@ -1,19 +1,29 @@
/**
* React Component for displaying a location's UI, when that location is a company
* React Subcomponent for displaying a location's UI, when that location is a company
*
* This subcomponent renders all of the buttons for applying to jobs at a company
*/
import * as React from "react";
import { LocationName } from "../data/LocationNames";
import { ApplyToJobButton } from "./ApplyToJobButton";
import { Companies } from "../../Company/Companies";
import { Company } from "../../Company/Company";
import { CompanyPosition } from "../../Company/CompanyPosition";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { Location } from "../Location";
import { Locations } from "../Locations";
import { LocationName } from "../data/LocationNames";
import { StdButton } from "../../ui/React/StdButton";
import { StdButtonWithTooltip } from "../../ui/React/StdButtonWithTooltip";
import { IEngine } from "../../IEngine";
import { beginInfiltration } from "../../Infiltration";
import { Companies } from "../../Company/Companies";
import { Company } from "../../Company/Company";
import { CompanyPositions } from "../../Company/CompanyPositions";
import * as posNames from "../../Company/data/companypositionnames";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { StdButton } from "../../ui/React/StdButton";
type IProps = {
engine: IEngine;
locName: LocationName;
p: IPlayer;
}
@ -25,6 +35,11 @@ export class CompanyLocation extends React.Component<IProps, any> {
*/
company: Company;
/**
* Reference to the Location that this component is being rendered for
*/
location: Location;
constructor(props: IProps) {
super(props);
@ -39,6 +54,12 @@ export class CompanyLocation extends React.Component<IProps, any> {
this.applyForSoftwareConsultantJob = this.applyForSoftwareConsultantJob.bind(this);
this.applyForSoftwareJob = this.applyForSoftwareJob.bind(this);
this.applyForWaiterJob = this.applyForWaiterJob.bind(this);
this.startInfiltration = this.startInfiltration.bind(this);
this.location = Locations[props.locName];
if (this.location == null) {
throw new Error(`CompanyLocation component constructed with invalid location: ${props.locName}`);
}
this.company = Companies[props.locName];
if (this.company == null) {
@ -101,24 +122,136 @@ export class CompanyLocation extends React.Component<IProps, any> {
this.props.p.applyForWaiterJob();
}
getJobRequirementTooltip(company: Company, entryPosType: CompanyPosition) {
if (!(company instanceof Company)) { return; }
startInfiltration(e: React.MouseEvent<HTMLElement>) {
if (!e.isTrusted) { return false; }
const loc = this.location;
const pos = this.props.p.getNextCompanyPosition(company, entryPosType);
if (pos == null) { return };
this.props.engine.loadInfiltrationContent();
if (!company.hasPosition(pos)) { return; }
return getJobRequirementText(company, pos, true);
const data = loc.infiltrationData;
if (data == null) { return false; }
beginInfiltration(this.props.locName, data.startingSecurityLevel, data.baseRewardValue, data.maxClearanceLevel, data.difficulty);
}
render() {
return (
<div>
{
this.company.hasAgentPositions() &&
<StdButton onClick={this.applyForAgentJob} text={""}
<ApplyToJobButton
company={this.company}
entryPosType={CompanyPositions[posNames.AgentCompanyPositions[0]]}
onClick={this.applyForAgentJob}
p={this.props.p}
text={"Apply for Agent Job"}
/>
}
{
this.company.hasBusinessConsultantPositions() &&
<ApplyToJobButton
company={this.company}
entryPosType={CompanyPositions[posNames.BusinessConsultantCompanyPositions[0]]}
onClick={this.applyForBusinessConsultantJob}
p={this.props.p}
text={"Apply for Business Consultant Job"}
/>
}
{
this.company.hasBusinessPositions() &&
<ApplyToJobButton
company={this.company}
entryPosType={CompanyPositions[posNames.BusinessCompanyPositions[0]]}
onClick={this.applyForBusinessJob}
p={this.props.p}
text={"Apply for Business Job"}
/>
}
{
this.company.hasEmployeePositions() &&
<ApplyToJobButton
company={this.company}
entryPosType={CompanyPositions[posNames.MiscCompanyPositions[1]]}
onClick={this.applyForEmployeeJob}
p={this.props.p}
text={"Apply to be an Employee"}
/>
}
{
this.company.hasEmployeePositions() &&
<ApplyToJobButton
company={this.company}
entryPosType={CompanyPositions[posNames.PartTimeCompanyPositions[1]]}
onClick={this.applyForPartTimeEmployeeJob}
p={this.props.p}
text={"Apply to be a part-time Employee"}
/>
}
{
this.company.hasITPositions() &&
<ApplyToJobButton
company={this.company}
entryPosType={CompanyPositions[posNames.ITCompanyPositions[0]]}
onClick={this.applyForItJob}
p={this.props.p}
text={"Apply for IT Job"}
/>
}
{
this.company.hasSecurityPositions() &&
<ApplyToJobButton
company={this.company}
entryPosType={CompanyPositions[posNames.SecurityCompanyPositions[2]]}
onClick={this.applyForSecurityJob}
p={this.props.p}
text={"Apply for Security Job"}
/>
}
{
this.company.hasSoftwareConsultantPositions() &&
<ApplyToJobButton
company={this.company}
entryPosType={CompanyPositions[posNames.SoftwareConsultantCompanyPositions[0]]}
onClick={this.applyForSoftwareConsultantJob}
p={this.props.p}
text={"Apply for Software Consultant Job"}
/>
}
{
this.company.hasSoftwarePositions() &&
<ApplyToJobButton
company={this.company}
entryPosType={CompanyPositions[posNames.SoftwareCompanyPositions[0]]}
onClick={this.applyForSoftwareJob}
p={this.props.p}
text={"Apply for Software Job"}
/>
}
{
this.company.hasWaiterPositions() &&
<ApplyToJobButton
company={this.company}
entryPosType={CompanyPositions[posNames.MiscCompanyPositions[0]]}
onClick={this.applyForWaiterJob}
p={this.props.p}
text={"Apply to be a Waiter"}
/>
}
{
this.company.hasWaiterPositions() &&
<ApplyToJobButton
company={this.company}
entryPosType={CompanyPositions[posNames.PartTimeCompanyPositions[0]]}
onClick={this.applyForPartTimeWaiterJob}
p={this.props.p}
text={"Apply to be a part-time Waiter"}
/>
}
{
(this.location.infiltrationData != null) &&
<StdButton
onClick={this.startInfiltration}
text={"Infiltration Company"}
/>
}
</div>
)

@ -6,36 +6,33 @@
*/
import * as React from "react";
import { Location } from "../Location";
import { Locations } from "../Locations";
import { LocationType } from "../LocationTypeEnum";
import { LocationName } from "../data/LocationNames";
import { CompanyLocation } from "./CompanyLocation";
import { GymLocation } from "./GymLocation";
import { HospitalLocation } from "./HospitalLocation";
import { SlumsLocation } from "./SlumsLocation";
import { SpecialLocation } from "./SpecialLocation";
import { TechVendorLocation } from "./TechVendorLocation";
import { TravelAgencyLocation } from "./TravelAgencyLocation";
import { UniversityLocation } from "./UniversityLocation";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { Location } from "../Location";
import { LocationType } from "../LocationTypeEnum";
import { CityName } from "../data/CityNames";
import { StdButton } from "../../ui/React/StdButton";
import { IEngine } from "../../IEngine";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { StdButton } from "../../ui/React/StdButton";
type IProps = {
locName: LocationName;
engine: IEngine;
loc: Location;
p: IPlayer;
returnToCity: () => void;
travel: (to: CityName) => void;
}
export class GenericLocation extends React.Component<IProps, any> {
/**
* Reference to the Location object that is being rendered
*/
loc: Location;
constructor(props: IProps) {
super(props);
this.loc = Locations[props.locName];
if (this.loc == null) {
throw new Error(`Invalid Location being rendered: ${props.locName}`);
}
}
/**
* Determine what needs to be rendered for this location based on the locations
* type. Returns an array of React components that should be rendered
@ -43,41 +40,79 @@ export class GenericLocation extends React.Component<IProps, any> {
getLocationSpecificContent(): React.ReactNode[] {
const content: React.ReactNode[] = [];
if (this.loc.types.includes(LocationType.Company)) {
if (this.props.loc.types.includes(LocationType.Company)) {
content.push(
<CompanyLocation
engine={this.props.engine}
locName={this.props.loc.name}
p={this.props.p}
/>
)
}
if (this.loc.types.includes(LocationType.Gym)) {
if (this.props.loc.types.includes(LocationType.Gym)) {
content.push(
<GymLocation
loc={this.props.loc}
p={this.props.p}
/>
)
}
if (this.loc.types.includes(LocationType.Hospital)) {
if (this.props.loc.types.includes(LocationType.Hospital)) {
content.push(
<HospitalLocation
p={this.props.p}
/>
)
}
if (this.loc.types.includes(LocationType.Slums)) {
if (this.props.loc.types.includes(LocationType.Slums)) {
content.push(
<SlumsLocation
p={this.props.p}
/>
)
}
if (this.loc.types.includes(LocationType.Special)) {
if (this.props.loc.types.includes(LocationType.Special)) {
content.push(
<SpecialLocation
engine={this.props.engine}
loc={this.props.loc}
p={this.props.p}
/>
)
}
if (this.loc.types.includes(LocationType.StockMarket)) {
if (this.props.loc.types.includes(LocationType.TechVendor)) {
content.push(
<TechVendorLocation
loc={this.props.loc}
p={this.props.p}
/>
)
}
if (this.loc.types.includes(LocationType.TechVendor)) {
if (this.props.loc.types.includes(LocationType.TravelAgency)) {
content.push(
<TravelAgencyLocation
p={this.props.p}
travel={this.props.travel}
/>
)
}
if (this.loc.types.includes(LocationType.TravelAgency)) {
if (this.props.loc.types.includes(LocationType.University)) {
content.push(
<UniversityLocation
loc={this.props.loc}
p={this.props.p}
/>
)
}
if (this.loc.types.includes(LocationType.University)) {
}
return content;
}
render() {
@ -87,7 +122,7 @@ export class GenericLocation extends React.Component<IProps, any> {
<div>
<StdButton onClick={this.props.returnToCity} text={"Return to world"} />
<br />
<h1>this.loc.name</h1>
<h1>{this.props.loc.name}</h1>
{locContent}
</div>
)

@ -0,0 +1,78 @@
/**
* React Subcomponent for displaying a location's UI, when that location is a gym
*
* This subcomponent renders all of the buttons for training at the gym
*/
import * as React from "react";
import { Location } from "../Location";
import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { numeralWrapper } from "../../ui/numeralFormat";
import { StdButton } from "../../ui/React/StdButton";
type IProps = {
loc: Location;
p: IPlayer;
}
export class GymLocation extends React.Component<IProps, any> {
constructor(props: IProps) {
super(props);
this.trainStrength = this.trainStrength.bind(this);
this.trainDefense = this.trainDefense.bind(this);
this.trainDexterity = this.trainDexterity.bind(this);
this.trainAgility = this.trainAgility.bind(this);
}
train(stat: string) {
const loc = this.props.loc;
this.props.p.startClass(loc.costMult, loc.expMult, stat);
}
trainStrength() {
return this.train(CONSTANTS.ClassGymStrength);
}
trainDefense() {
return this.train(CONSTANTS.ClassGymDefense);
}
trainDexterity() {
return this.train(CONSTANTS.ClassGymDexterity);
}
trainAgility() {
return this.train(CONSTANTS.ClassGymAgility);
}
render() {
const costMult: number = this.props.loc.costMult;
const cost = CONSTANTS.ClassGymBaseCost * costMult;
return (
<div>
<StdButton
onClick={this.trainStrength}
text={`Train Strength (${numeralWrapper.formatMoney(cost)} / sec)`}
/>
<StdButton
onClick={this.trainDefense}
text={`Train Defense (${numeralWrapper.formatMoney(cost)} / sec)`}
/>
<StdButton
onClick={this.trainDexterity}
text={`Train Dexterity (${numeralWrapper.formatMoney(cost)} / sec)`}
/>
<StdButton
onClick={this.trainAgility}
text={`Train Agility (${numeralWrapper.formatMoney(cost)} / sec)`}
/>
</div>
)
}
}

@ -0,0 +1,55 @@
/**
* React Subcomponent for displaying a location's UI, when that location is a hospital
*
* This subcomponent renders all of the buttons for hospital options
*/
import * as React from "react";
import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { numeralWrapper } from "../../ui/numeralFormat";
import { AutoupdatingStdButton } from "../../ui/React/AutoupdatingStdButton";
import { dialogBoxCreate } from "../../../utils/DialogBox";
type IProps = {
p: IPlayer;
}
export class HospitalLocation extends React.Component<IProps, any> {
constructor(props: IProps) {
super(props);
this.getCost = this.getCost.bind(this);
this.getHealed = this.getHealed.bind(this);
}
getCost(): number {
return (this.props.p.max_hp - this.props.p.hp) * CONSTANTS.HospitalCostPerHp;
}
getHealed(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
if (this.props.p.hp < 0) { this.props.p.hp = 0; }
if (this.props.p.hp >= this.props.p.max_hp) { return; }
const cost = this.getCost();
this.props.p.loseMoney(cost);
this.props.p.hp = this.props.p.max_hp;
dialogBoxCreate(`You were healed to full health! The hospital billed you for ${numeralWrapper.formatMoney(cost)}`);
}
render() {
const cost = this.getCost();
return (
<AutoupdatingStdButton
onClick={this.getHealed}
text={`Get treatment for wounds - ${numeralWrapper.formatMoney(cost)}`}
/>
)
}
}

@ -4,13 +4,23 @@
import * as React from "react";
import { LocationCity } from "./City";
import { GenericLocation } from "./GenericLocation";
import { Cities } from "../Cities";
import { Locations } from "../Locations";
import { LocationType } from "../LocationTypeEnum";
import { CityName } from "../data/CityNames";
import { LocationName } from "../data/LocationNames";
import { CONSTANTS } from "../../Constants";
import { IEngine } from "../../IEngine";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { dialogBoxCreate } from "../../../utils/DialogBox";
type IProps = {
engine: IEngine;
p: IPlayer;
}
@ -30,16 +40,8 @@ export class LocationRoot extends React.Component<IProps, IState> {
location: props.p.location,
}
this.changeCity = this.changeCity.bind(this);
this.returnToCity = this.returnToCity.bind(this);
}
changeCity(to: CityName): void {
if (this.props.p.travel(to)) {
this.setState({
city: to
});
}
this.travel = this.travel.bind(this);
}
enterLocation(to: LocationName): void {
@ -64,10 +66,15 @@ export class LocationRoot extends React.Component<IProps, IState> {
* Render UI for a city
*/
renderCity(): React.ReactNode {
const city = Cities[this.state.city];
if (city == null) {
throw new Error(`Invalid city when rendering UI: ${this.state.city}`);
}
return (
<div>
<h2>{this.state.city}</h2>
<LocationCity city={this.state.city} enterLocation={this.enterLocation} />
<LocationCity city={city} enterLocation={this.enterLocation} />
</div>
)
}
@ -76,11 +83,61 @@ export class LocationRoot extends React.Component<IProps, IState> {
* Render UI for a specific location
*/
renderLocation(): React.ReactNode {
const loc = Locations[this.state.location];
if (loc == null) {
throw new Error(`Invalid location when rendering UI: ${this.state.location}`);
}
if (loc.types.includes(LocationType.StockMarket)) {
this.props.engine.loadStockMarketContent();
}
return (
<GenericLocation />
<GenericLocation
engine={this.props.engine}
loc={loc}
p={this.props.p}
returnToCity={this.returnToCity}
travel={this.travel}
/>
)
}
/**
* Travel to a different city
* @param {CityName} to - Destination city
*/
travel(to: CityName): void {
const p = this.props.p;
const cost = CONSTANTS.TravelCost;
if (!p.canAfford(cost)) {
dialogBoxCreate(`You cannot afford to travel to ${to}`);
return;
}
p.loseMoney(cost);
p.travel(to);
dialogBoxCreate(`You are now in ${to}!`);
// Dynamically update main menu
if (p.firstTimeTraveled === false) {
p.firstTimeTraveled = true;
const travelTab = document.getElementById("travel-tab");
const worldHeader = document.getElementById("world-menu-header");
if (travelTab != null && worldHeader !== null) {
travelTab.style.display = "list-item";
worldHeader.click(); worldHeader.click();
}
}
if (this.props.p.travel(to)) {
this.setState({
city: to
});
}
}
render() {
if (this.state.inCity) {
return this.renderCity();

@ -0,0 +1,187 @@
/**
* React Subcomponent for displaying a location's UI, when that location is a slum
*
* This subcomponent renders all of the buttons for committing crimes
*/
import * as React from "react";
import { Crimes } from "../../Crime/Crimes";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { numeralWrapper } from "../../ui/numeralFormat";
import { AutoupdatingStdButton } from "../../ui/React/AutoupdatingStdButton";
type IProps = {
p: IPlayer;
}
export class SlumsLocation extends React.Component<IProps, any> {
constructor(props: IProps) {
super(props);
this.shoplift = this.shoplift.bind(this);
this.robStore = this.robStore.bind(this);
this.mug = this.mug.bind(this);
this.larceny = this.larceny.bind(this);
this.dealDrugs = this.dealDrugs.bind(this);
this.bondForgery = this.bondForgery.bind(this);
this.traffickArms = this.traffickArms.bind(this);
this.homicide = this.homicide.bind(this);
this.grandTheftAuto = this.grandTheftAuto.bind(this);
this.kidnap = this.kidnap.bind(this);
this.assassinate = this.assassinate.bind(this);
this.heist = this.heist.bind(this);
}
shoplift(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
Crimes.Shoplift.commit(this.props.p);
}
robStore(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
Crimes.RobSTore.commit(this.props.p);
}
mug(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
Crimes.mug.commit(this.props.p);
}
larceny(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
Crimes.Larceny.commit(this.props.p);
}
dealDrugs(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
Crimes.DealDrugs.commit(this.props.p);
}
bondForgery(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
Crimes.BondForgery.commit(this.props.p);
}
traffickArms(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
Crimes.TraffickArms.commit(this.props.p);
}
homicide(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
Crimes.Homicide.commit(this.props.p);
}
grandTheftAuto(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
Crimes.GrandTheftAuto.commit(this.props.p);
}
kidnap(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
Crimes.Kidnap.commit(this.props.p);
}
assassinate(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
Crimes.Assassination.commit(this.props.p);
}
heist(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
Crimes.Heist.commit(this.props.p);
}
render() {
const shopliftChance = Crimes.Shoplift.successRate(this.props.p);
const robStoreChance = Crimes.RobStore.successRate(this.props.p);
const mugChance = Crimes.Mug.successRate(this.props.p);
const larcenyChance = Crimes.Larceny.successRate(this.props.p);
const drugsChance = Crimes.DealDrugs.successRate(this.props.p);
const bondChance = Crimes.BondForgery.successRate(this.props.p);
const armsChance = Crimes.TraffickArms.successRate(this.props.p);
const homicideChance = Crimes.Homicide.successRate(this.props.p);
const gtaChance = Crimes.GrandTheftAuto.successRate(this.props.p);
const kidnapChance = Crimes.Kidnap.successRate(this.props.p);
const assassinateChance = Crimes.Assassination.successRate(this.props.p);
const heistChance = Crimes.Heist.successRate(this.props.p);
return (
<div>
<AutoupdatingStdButton
intervalTime={5e3}
onClick={this.shoplift}
text={`Shoplift (${numeralWrapper.formatPercentage(shopliftChance)} chance of success)`}
tooltip={"Attempt to shoplift from a low-end retailer"}
/>
<AutoupdatingStdButton
intervalTime={5e3}
onClick={this.robStore}
text={`Rob store (${numeralWrapper.formatPercentage(robStoreChance)} chance of success)`}
tooltip={"Attempt to commit armed robbery on a high-end store"}
/>
<AutoupdatingStdButton
intervalTime={5e3}
onClick={this.mug}
text={`Mug someone (${numeralWrapper.formatPercentage(mugChance)} chance of success)`}
tooltip={"Attempt to mug a random person on the street"}
/>
<AutoupdatingStdButton
intervalTime={5e3}
onClick={this.larceny}
text={`Larceny (${numeralWrapper.formatPercentage(larcenyChance)} chance of success)`}
tooltip={"Attempt to rob property from someone's house"}
/>
<AutoupdatingStdButton
intervalTime={5e3}
onClick={this.dealDrugs}
text={`Deal Drugs (${numeralWrapper.formatPercentage(drugsChance)} chance of success)`}
tooltip={"Attempt to deal drugs"}
/>
<AutoupdatingStdButton
intervalTime={5e3}
onClick={this.bondForgery}
text={`Bond Forgery (${numeralWrapper.formatPercentage(bondChance)} chance of success)`}
tooltip={"Attempt to forge corporate bonds"}
/>
<AutoupdatingStdButton
intervalTime={5e3}
onClick={this.traffickArms}
text={`Traffick illegal Arms (${numeralWrapper.formatPercentage(armsChance)} chance of success)`}
tooltip={"Attempt to smuggle illegal arms into the city"}
/>
<AutoupdatingStdButton
intervalTime={5e3}
onClick={this.homicide}
text={`Homicide (${numeralWrapper.formatPercentage(homicideChance)} chance of success)`}
tooltip={"Attempt to murder a random person on the street"}
/>
<AutoupdatingStdButton
intervalTime={5e3}
onClick={this.grandTheftAuto}
text={`Grand theft Auto (${numeralWrapper.formatPercentage(gtaChance)} chance of success)`}
tooltip={"Attempt to commit grand theft auto"}
/>
<AutoupdatingStdButton
intervalTime={5e3}
onClick={this.kidnap}
text={`Kidnap and Ransom (${numeralWrapper.formatPercentage(kidnapChance)} chance of success)`}
tooltip={"Attempt to kidnap and ransom a high-profile-target"}
/>
<AutoupdatingStdButton
intervalTime={5e3}
onClick={this.assassinate}
text={`Assassinate (${numeralWrapper.formatPercentage(assassinateChance)} chance of success)`}
tooltip={"Attempt to assassinate a high-profile target"}
/>
<AutoupdatingStdButton
intervalTime={5e3}
onClick={this.heist}
text={`Heist (${numeralWrapper.formatPercentage(heistChance)} chance of success)`}
tooltip={"Attempt to pull off the ultimate heist"}
/>
</div>
)
}
}

@ -0,0 +1,136 @@
/**
* React Subcomponent for displaying a location's UI, when that location has special
* actions/options/properties
*
* Examples:
* - Bladeburner @ NSA
* - Re-sleeving @ VitaLife
* - Create Corporation @ City Hall
*
* This subcomponent creates all of the buttons for interacting with those special
* properties
*/
import * as React from "react";
import { Location } from "../Location";
import { createStartCorporationPopup } from "../LocationsHelpers";
import { LocationName } from "../data/LocationNames";
import { IEngine } from "../../IEngine";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { AutoupdatingStdButton } from "../../ui/React/AutoupdatingStdButton";
import { StdButton } from "../../ui/React/StdButton";
import { dialogBoxCreate } from "../../../utils/DialogBox";
type IProps = {
engine: IEngine;
loc: Location;
p: IPlayer;
}
type IState = {
inBladeburner: boolean;
}
export class SpecialLocation extends React.Component<IProps, IState> {
constructor(props: IProps) {
super(props);
this.createCorporationPopup = this.createCorporationPopup.bind(this);
this.handleBladeburner = this.handleBladeburner.bind(this);
this.handleResleeving = this.handleResleeving.bind(this);
this.state = {
inBladeburner: this.props.p.inBladeburner(),
}
}
/**
* Click handler for "Create Corporation" button at Sector-12 City Hall
*/
createCorporationPopup() {
createStartCorporationPopup(this.props.p);
}
/**
* Click handler for Bladeburner button at Sector-12 NSA
*/
handleBladeburner() {
const p = this.props.p;
if (p.inBladeburner()) {
// Enter Bladeburner division
this.props.engine.loadBladeburnerContent();
} else {
// Apply for Bladeburner division
if (p.strength >= 100 && p.defense >= 100 && p.dexterity >= 100 && p.agility >= 100) {
p.startBladeburner({ new: true });
dialogBoxCreate("You have been accepted into the Bladeburner division!");
this.setState({
inBladeburner: true,
});
const worldHeader = document.getElementById("world-menu-header");
if (worldHeader instanceof HTMLElement) {
worldHeader.click(); worldHeader.click();
}
} else {
dialogBoxCreate("Rejected! Please apply again when you have 100 of each combat stat (str, def, dex, agi)");
}
}
}
/**
* Click handler for Resleeving button at New Tokyo VitaLife
*/
handleResleeving() {
this.props.engine.loadResleevingContent();
}
renderBladeburner(): React.ReactNode {
const text = this.state.inBladeburner ? "Enter Bladeburner Headquarters" : "Apply to Bladeburner Division";
return (
<StdButton
onClick={this.handleBladeburner}
text={text}
/>
)
}
renderCreateCorporation(): React.ReactNode {
return (
<AutoupdatingStdButton
disabled={this.props.p.hasCorporation()}
onClick={this.createCorporationPopup}
text={"Create a Corporation"}
/>
)
}
renderResleeving(): React.ReactNode {
return (
<StdButton
onClick={this.handleResleeving}
text={"Re-Sleeve"}
/>
)
}
render() {
switch (this.props.loc.name) {
case LocationName.NewTokyoVitaLife: {
return this.renderResleeving();
}
case LocationName.Sector12CityHall: {
return this.renderCreateCorporation();
}
case LocationName.Sector12NSA: {
return this.renderBladeburner();
}
default:
console.error(`Location ${this.props.loc.name} doesn't have any special properties`);
break;
}
}
}

@ -0,0 +1,94 @@
/**
* React Subcomponent for displaying a location's UI, when that location is a tech vendor
*
* This subcomponent renders all of the buttons for purchasing things from tech vendors
*/
import * as React from "react";
import { Location } from "../Location";
import { createPurchaseServerPopup,
createUpgradeHomeCoresPopup,
createUpgradeHomeRamPopup,
purchaseTorRouter } from "../LocationsHelpers";
import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { getPurchaseServerCost } from "../../Server/ServerPurchases";
import { numeralWrapper } from "../../ui/numeralFormat";
import { StdButtonPurchased } from "../../ui/React/StdButtonPurchased";
import { StdButton } from "../../ui/React/StdButton";
type IProps = {
loc: Location;
p: IPlayer;
}
export class TechVendorLocation extends React.Component<IProps, any> {
constructor(props: IProps) {
super(props);
this.state = {
torPurchased: props.p.hasTorRouter(),
}
this.createUpgradeHomeCoresPopup = this.createUpgradeHomeCoresPopup.bind(this);
this.createUpgradeHomeRamPopup = this.createUpgradeHomeRamPopup.bind(this);
this.purchaseTorRouter = this.purchaseTorRouter.bind(this);
}
createUpgradeHomeCoresPopup() {
createUpgradeHomeCoresPopup(this.props.p);
}
createUpgradeHomeRamPopup() {
createUpgradeHomeRamPopup(this.props.p);
}
purchaseTorRouter() {
purchaseTorRouter(this.props.p);
}
render() {
const loc: Location = this.props.loc;
const purchaseServerButtons: React.ReactNode[] = [];
for (let i = loc.techVendorMinRam; i <= loc.techVendorMaxRam; i *= 2) {
const cost = getPurchaseServerCost(i);
purchaseServerButtons.push(
<StdButton
key={i}
onClick={() => createPurchaseServerPopup(i, this.props.p)}
text={`Purchase ${i}GB Server - ${numeralWrapper.formatMoney(cost)}`}
/>
)
}
return (
<div>
{purchaseServerButtons}
{
this.state.torPurchased ? (
<StdButtonPurchased
text={"TOR Router - Purchased"}
/>
) : (
<StdButton
onClick={this.purchaseTorRouter}
text={`Purchase TOR Router - ${numeralWrapper.formatMoney(CONSTANTS.TorRouterCost)}`}
/>
)
}
<StdButton
onClick={this.createUpgradeHomeRamPopup}
text={`Purchase additional RAM for Home computer`}
/>
<StdButton
onClick={this.createUpgradeHomeCoresPopup}
text={`Purchase additional Core for Home computer`}
/>
</div>
)
}
}

@ -0,0 +1,54 @@
/**
* React Subcomponent for displaying a location's UI, when that location is a Travel Agency
*
* This subcomponent renders all of the buttons for traveling to different cities
*/
import * as React from "react";
import { CityName } from "../data/CityNames";
import { createTravelPopup } from "../LocationsHelpers";
import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { numeralWrapper } from "../../ui/numeralFormat";
import { StdButton } from "../../ui/React/StdButton";
type IProps = {
p: IPlayer;
travel: (to: CityName) => void;
}
export class TravelAgencyLocation extends React.Component<IProps, any> {
constructor(props: IProps) {
super(props);
}
render() {
const travelBtns: React.ReactNode[] = [];
for (const key in CityName) {
const city = CityName[key];
// Skip current city
if (city === this.props.p.city) { continue; }
travelBtns.push(
<StdButton
key={city}
onClick={createTravelPopup.bind(null, city, this.props.travel)}
text={`Travel to ${city}`}
/>
)
}
return (
<div>
<p>
From here, you can travel to any other city! A ticket costs
{numeralWrapper.formatMoney(CONSTANTS.TravelCost)}
</p>
{travelBtns}
</div>
)
}
}

@ -0,0 +1,100 @@
/**
* React Subcomponent for displaying a location's UI, when that location is a university
*
* This subcomponent renders all of the buttons for studying/taking courses
*/
import * as React from "react";
import { Location } from "../Location";
import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { numeralWrapper } from "../../ui/numeralFormat";
import { StdButton } from "../../ui/React/StdButton";
type IProps = {
loc: Location;
p: IPlayer;
}
export class UniversityLocation extends React.Component<IProps, any> {
constructor(props: IProps) {
super(props);
this.take = this.take.bind(this);
this.dataStructures = this.dataStructures.bind(this);
this.networks = this.networks.bind(this);
this.algorithms = this.algorithms.bind(this);
this.management = this.management.bind(this);
this.leadership = this.leadership.bind(this);
}
take(stat: string) {
const loc = this.props.loc;
this.props.p.startClass(loc.costMult, loc.expMult, stat);
}
study() {
return this.take(CONSTANTS.ClassStudyComputerScience);
}
dataStructures() {
return this.take(CONSTANTS.ClassDataStructures);
}
networks() {
return this.take(CONSTANTS.ClassNetworks);
}
algorithms() {
return this.take(CONSTANTS.ClassAlgorithms);
}
management() {
return this.take(CONSTANTS.ClassManagement);
}
leadership() {
return this.take(CONSTANTS.ClassLeadership);
}
render() {
const costMult: number = this.props.loc.costMult;
const dataStructuresCost = CONSTANTS.ClassDataStructuresBaseCost * costMult;
const networksCost = CONSTANTS.ClassNetworksBaseCost * costMult;
const algorithmsCost = CONSTANTS.ClassAlgorithmsBaseCost * costMult;
const managementCost = CONSTANTS.ClassManagementBaseCost * costMult;
const leadershipCost = CONSTANTS.ClassLeadershipBaseCost * costMult;
return (
<div>
<StdButton
onClick={this.study}
text={`Study Computer Science (free)`}
/>
<StdButton
onClick={this.dataStructures}
text={`Take Data Structures course (${numeralWrapper.formatMoney(dataStructuresCost)} / sec)`}
/>
<StdButton
onClick={this.networks}
text={`Take Networks course (${numeralWrapper.formatMoney(networksCost)} / sec)`}
/>
<StdButton
onClick={this.algorithms}
text={`Take Algorithms course (${numeralWrapper.formatMoney(algorithmsCost)} / sec)`}
/>
<StdButton
onClick={this.management}
text={`Take Management course (${numeralWrapper.formatMoney(managementCost)} / sec)`}
/>
<StdButton
onClick={this.leadership}
text={`Take Leadership course (${numeralWrapper.formatMoney(leadershipCost)} / sec)`}
/>
</div>
)
}
}

@ -31,7 +31,8 @@ import { joinFaction,
import { FactionWorkType } from "./Faction/FactionWorkTypeEnum";
import { getCostOfNextHacknetNode,
purchaseHacknet } from "./Hacknet/HacknetNode";
import {Locations} from "./Locations";
import { CityName } from "./Locations/data/CityNames";
import { LocationName } from "./Locations/data/LocationNames";
import { Message } from "./Message/Message";
import { Messages } from "./Message/MessageHelpers";
import {inMission} from "./Missions";
@ -2584,30 +2585,30 @@ function NetscriptFunctions(workerScript) {
var costMult, expMult;
switch(universityName.toLowerCase()) {
case Locations.AevumSummitUniversity.toLowerCase():
if (Player.city != Locations.Aevum) {
case LocationName.AevumSummitUniversity.toLowerCase():
if (Player.city != CityName.Aevum) {
workerScript.scriptRef.log("ERROR: You cannot study at Summit University because you are not in Aevum. universityCourse() failed");
return false;
}
Player.location = Locations.AevumSummitUniversity;
Player.gotoLocation(LocationName.AevumSummitUniversity);
costMult = 4;
expMult = 3;
break;
case Locations.Sector12RothmanUniversity.toLowerCase():
if (Player.city != Locations.Sector12) {
case LocationName.Sector12RothmanUniversity.toLowerCase():
if (Player.city != CityName.Sector12) {
workerScript.scriptRef.log("ERROR: You cannot study at Rothman University because you are not in Sector-12. universityCourse() failed");
return false;
}
Player.location = Locations.Sector12RothmanUniversity;
Player.location = LocationName.Sector12RothmanUniversity;
costMult = 3;
expMult = 2;
break;
case Locations.VolhavenZBInstituteOfTechnology.toLowerCase():
if (Player.city != Locations.Volhaven) {
case LocationName.VolhavenZBInstituteOfTechnology.toLowerCase():
if (Player.city != CityName.Volhaven) {
workerScript.scriptRef.log("ERROR: You cannot study at ZB Institute of Technology because you are not in Volhaven. universityCourse() failed");
return false;
}
Player.location = Locations.VolhavenZBInstituteOfTechnology;
Player.location = LocationName.VolhavenZBInstituteOfTechnology;
costMult = 5;
expMult = 4;
break;
@ -2672,48 +2673,48 @@ function NetscriptFunctions(workerScript) {
}
var costMult, expMult;
switch(gymName.toLowerCase()) {
case Locations.AevumCrushFitnessGym.toLowerCase():
if (Player.city != Locations.Aevum) {
case LocationName.AevumCrushFitnessGym.toLowerCase():
if (Player.city != CityName.Aevum) {
workerScript.scriptRef.log("ERROR: You cannot workout at Crush Fitness because you are not in Aevum. gymWorkout() failed");
return false;
}
Player.location = Locations.AevumCrushFitnessGym;
Player.location = LocationName.AevumCrushFitnessGym;
costMult = 3;
expMult = 2;
break;
case Locations.AevumSnapFitnessGym.toLowerCase():
if (Player.city != Locations.Aevum) {
case LocationName.AevumSnapFitnessGym.toLowerCase():
if (Player.city != CityName.Aevum) {
workerScript.scriptRef.log("ERROR: You cannot workout at Snap Fitness because you are not in Aevum. gymWorkout() failed");
return false;
}
Player.location = Locations.AevumSnapFitnessGym;
Player.location = LocationName.AevumSnapFitnessGym;
costMult = 10;
expMult = 5;
break;
case Locations.Sector12IronGym.toLowerCase():
if (Player.city != Locations.Sector12) {
case LocationName.Sector12IronGym.toLowerCase():
if (Player.city != CityName.Sector12) {
workerScript.scriptRef.log("ERROR: You cannot workout at Iron Gym because you are not in Sector-12. gymWorkout() failed");
return false;
}
Player.location = Locations.Sector12IronGym;
Player.location = LocationName.Sector12IronGym;
costMult = 1;
expMult = 1;
break;
case Locations.Sector12PowerhouseGym.toLowerCase():
if (Player.city != Locations.Sector12) {
case LocationName.Sector12PowerhouseGym.toLowerCase():
if (Player.city != CityName.Sector12) {
workerScript.scriptRef.log("ERROR: You cannot workout at Powerhouse Gym because you are not in Sector-12. gymWorkout() failed");
return false;
}
Player.location = Locations.Sector12PowerhouseGym;
Player.location = LocationName.Sector12PowerhouseGym;
costMult = 20;
expMult = 10;
break;
case Locations.VolhavenMilleniumFitnessGym.toLowerCase():
if (Player.city != Locations.Volhaven) {
case LocationName.VolhavenMilleniumFitnessGym.toLowerCase():
if (Player.city != CityName.Volhaven) {
workerScript.scriptRef.log("ERROR: You cannot workout at Millenium Fitness Gym because you are not in Volhaven. gymWorkout() failed");
return false;
}
Player.location = Locations.VolhavenMilleniumFitnessGym;
Player.location = LocationName.VolhavenMilleniumFitnessGym;
costMult = 7;
expMult = 4;
break;
@ -2764,12 +2765,12 @@ function NetscriptFunctions(workerScript) {
}
switch(cityname) {
case Locations.Aevum:
case Locations.Chongqing:
case Locations.Sector12:
case Locations.NewTokyo:
case Locations.Ishima:
case Locations.Volhaven:
case CityName.Aevum:
case CityName.Chongqing:
case CityName.Sector12:
case CityName.NewTokyo:
case CityName.Ishima:
case CityName.Volhaven:
if(Player.money.lt(CONSTANTS.TravelCost)) {
workerScript.scriptRef.log("ERROR: not enough money to travel with travelToCity().");
throw makeRuntimeRejectMsg(workerScript, "ERROR: not enough money to travel with travelToCity().");
@ -3587,29 +3588,8 @@ function NetscriptFunctions(workerScript) {
}
}
//Set Location to slums
switch(Player.city) {
case Locations.Aevum:
Player.location = Locations.AevumSlums;
break;
case Locations.Chongqing:
Player.location = Locations.ChongqingSlums;
break;
case Locations.Sector12:
Player.location = Locations.Sector12Slums;
break;
case Locations.NewTokyo:
Player.location = Locations.NewTokyoSlums;
break;
case Locations.Ishima:
Player.location = Locations.IshimaSlums;
break;
case Locations.Volhaven:
Player.location = Locations.VolhavenSlums;
break;
default:
console.log("Invalid Player.city value");
}
// Set Location to slums
Player.gotoLocation(LocationName.Slums);
const crime = findCrime(crimeRoughName.toLowerCase());
if(crime == null) { // couldn't find crime

@ -1,8 +1,8 @@
// Interface for an object that represents the player (PlayerObject)
// Used because at the time of implementation, the PlayerObject
// cant be converted to TypeScript.
//
// Only contains the needed properties for Sleeve implementation
/**
* Interface for an object that represents the player (PlayerObject)
* Used because at the time of implementation, the PlayerObject
* cant be converted to TypeScript.
*/
import { Resleeve } from "./Resleeving/Resleeve";
import { Sleeve } from "./Sleeve/Sleeve";
@ -12,9 +12,10 @@ import { IPlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugment
import { Company } from "../Company/Company";
import { CompanyPosition } from "../Company/CompanyPosition";
import { CityName } from "../Locations/data/CityNames";
import { HashManager } from "../Hacknet/HashManager";
import { HacknetNode } from "../Hacknet/HacknetNode";
import { HacknetServer } from "../Hacknet/HacknetServer";
import { LocationName } from "../Locations/data/LocationNames";
import { Server } from "../Server/Server";
import { IPlayerOwnedSourceFile } from "../SourceFile/PlayerOwnedSourceFile";
import { MoneySourceTracker } from "../utils/MoneySourceTracker";
@ -28,11 +29,15 @@ export interface IPlayer {
corporation: any;
currentServer: string;
factions: string[];
firstTimeTraveled: boolean;
hacknetNodes: (HacknetNode | string)[]; // HacknetNode object or IP of Hacknet Server
hashManager: HashManager;
hasWseAccount: boolean;
hp: number;
jobs: IMap<string>;
karma: number;
location: LocationName;
max_hp: number;
money: any;
moneySourceA: MoneySourceTracker;
moneySourceB: MoneySourceTracker;
@ -114,15 +119,22 @@ export interface IPlayer {
gainAgilityExp(exp: number): void;
gainCharismaExp(exp: number): void;
gainMoney(money: number): void;
getHomeComputer(): Server;
getNextCompanyPosition(company: Company, entryPosType: CompanyPosition): CompanyPosition;
getUpgradeHomeRamCost(): number;
hasCorporation(): boolean;
hasTorRouter(): boolean;
inBladeburner(): boolean;
inGang(): boolean;
isQualified(company: Company, position: CompanyPosition): boolean;
loseMoney(money: number): void;
reapplyAllAugmentations(resetMultipliers: boolean): void;
reapplyAllSourceFiles(): void;
regenerateHp(amt: number): void;
recordMoneySource(amt: number, source: string): void;
startBladeburner(p: object): void;
startClass(costMult: number, expMult: number, className: string): void;
startCorporation(corpName: string, additionalShares?: number): void;
startCrime(crimeType: string,
hackExp: number,
strExp: number,

@ -1,12 +0,0 @@
import { PlayerObject } from "../../Player";
import { Cities } from "../../Locations/Cities";
PlayerObject.prototype.travel = function(to) {
if (Cities[to] == null) {
console.warn(`Player.travel() called with invalid city: ${to}`);
return false;
}
this.city = to;
return true;
}

@ -22,8 +22,6 @@ import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
import { Crime } from "../../Crime/Crime";
import { Crimes } from "../../Crime/Crimes";
import { CityName } from "../../Locations/data/CityNames";
import { Companies } from "../../Company/Companies";
import { Company } from "../../Company/Company";
import { CompanyPosition } from "../../Company/CompanyPosition";
@ -35,7 +33,8 @@ import { Faction } from "../../Faction/Faction";
import { Factions } from "../../Faction/Factions";
import { FactionWorkType } from "../../Faction/FactionWorkTypeEnum";
import { Locations } from "../../Locations";
import { CityName } from "../../Locations/data/CityNames";
import { LocationName } from "../../Locations/data/LocationNames";
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../../utils/JSONReviver";
@ -586,21 +585,21 @@ export class Sleeve extends Person {
let costMult: number = 1;
let expMult: number = 1;
switch (universityName.toLowerCase()) {
case Locations.AevumSummitUniversity.toLowerCase():
case LocationName.AevumSummitUniversity.toLowerCase():
if (this.city !== CityName.Aevum) { return false; }
this.currentTaskLocation = Locations.AevumSummitUniversity;
this.currentTaskLocation = LocationName.AevumSummitUniversity;
costMult = 4;
expMult = 3;
break;
case Locations.Sector12RothmanUniversity.toLowerCase():
case LocationName.Sector12RothmanUniversity.toLowerCase():
if (this.city !== CityName.Sector12) { return false; }
this.currentTaskLocation = Locations.Sector12RothmanUniversity;
this.currentTaskLocation = LocationName.Sector12RothmanUniversity;
costMult = 3;
expMult = 2;
break;
case Locations.VolhavenZBInstituteOfTechnology.toLowerCase():
case LocationName.VolhavenZBInstituteOfTechnology.toLowerCase():
if (this.city !== CityName.Volhaven) { return false; }
this.currentTaskLocation = Locations.VolhavenZBInstituteOfTechnology;
this.currentTaskLocation = LocationName.VolhavenZBInstituteOfTechnology;
costMult = 5;
expMult = 4;
break;
@ -781,33 +780,33 @@ export class Sleeve extends Person {
let costMult: number = 1;
let expMult: number = 1;
switch (gymName.toLowerCase()) {
case Locations.AevumCrushFitnessGym.toLowerCase():
case LocationName.AevumCrushFitnessGym.toLowerCase():
if (this.city != CityName.Aevum) { return false; }
this.currentTaskLocation = Locations.AevumCrushFitnessGym;
this.currentTaskLocation = LocationName.AevumCrushFitnessGym;
costMult = 3;
expMult = 2;
break;
case Locations.AevumSnapFitnessGym.toLowerCase():
case LocationName.AevumSnapFitnessGym.toLowerCase():
if (this.city != CityName.Aevum) { return false; }
this.currentTaskLocation = Locations.AevumSnapFitnessGym;
this.currentTaskLocation = LocationName.AevumSnapFitnessGym;
costMult = 10;
expMult = 5;
break;
case Locations.Sector12IronGym.toLowerCase():
case LocationName.Sector12IronGym.toLowerCase():
if (this.city != CityName.Sector12) { return false; }
this.currentTaskLocation = Locations.Sector12IronGym;
this.currentTaskLocation = LocationName.Sector12IronGym;
costMult = 1;
expMult = 1;
break;
case Locations.Sector12PowerhouseGym.toLowerCase():
case LocationName.Sector12PowerhouseGym.toLowerCase():
if (this.city != CityName.Sector12) { return false; }
this.currentTaskLocation = Locations.Sector12PowerhouseGym;
this.currentTaskLocation = LocationName.Sector12PowerhouseGym;
costMult = 20;
expMult = 10;
break;
case Locations.VolhavenMilleniumFitnessGym:
case LocationName.VolhavenMilleniumFitnessGym:
if (this.city != CityName.Volhaven) { return false; }
this.currentTaskLocation = Locations.VolhavenMilleniumFitnessGym;
this.currentTaskLocation = LocationName.VolhavenMilleniumFitnessGym;
costMult = 7;
expMult = 4;
break;

@ -9,15 +9,16 @@ import { SleeveFaq } from "./data/SleeveFaq";
import { IPlayer } from "../IPlayer";
import { CONSTANTS } from "../../Constants";
import { Locations } from "../../Locations";
import { Faction } from "../../Faction/Faction";
import { Factions } from "../../Faction/Factions";
import { FactionWorkType } from "../../Faction/FactionWorkTypeEnum";
import { Cities } from "../../Locations/Cities";
import { Crime } from "../../Crime/Crime";
import { Crimes } from "../../Crime/Crimes";
import { Cities } from "../../Locations/Cities";
import { CityName } from "../../Locations/data/CityNames";
import { LocationName } from "../../Locations/data/LocationNames";
import { numeralWrapper } from "../../ui/numeralFormat";
import { Page,
@ -243,20 +244,20 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
`Traveling to a different city costs ${numeralWrapper.formatMoney(CONSTANTS.TravelCost)}. ` +
"It will also CANCEL the sleeve's current task (setting it to idle)",
}));
for (const label in Cities) {
if (sleeve.city === Cities[label]) { continue; }
(function(sleeve, label) {
for (const cityName in Cities) {
if (sleeve.city === cityName) { continue; }
(function(sleeve, cityName) {
popupArguments.push(createElement("div", {
// Reusing this css class. It adds a border and makes it so that
// the background color changes when you hover
class: "cmpy-mgmt-find-employee-option",
innerText: Cities[label],
innerText: cityName,
clickListener: () => {
if (!playerRef!.canAfford(CONSTANTS.TravelCost)) {
dialogBoxCreate("You cannot afford to have this sleeve travel to another city", false);
return false;
}
sleeve.city = Cities[label];
sleeve.city = <CityName>cityName;
playerRef!.loseMoney(CONSTANTS.TravelCost);
sleeve.resetTaskStatus();
removeElementById(popupId);
@ -265,7 +266,7 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
return false;
}
}));
})(sleeve, label);
})(sleeve, cityName);
}
createPopup(popupId, popupArguments);
@ -569,14 +570,14 @@ function updateSleeveTaskSelector(sleeve: Sleeve, elems: ISleeveUIElems, allSlee
// Second selector has which university
switch (sleeve.city) {
case Cities.Aevum:
elems.taskDetailsSelector2!.add(createOptionElement(Locations.AevumSummitUniversity));
case CityName.Aevum:
elems.taskDetailsSelector2!.add(createOptionElement(LocationName.AevumSummitUniversity));
break;
case Cities.Sector12:
elems.taskDetailsSelector2!.add(createOptionElement(Locations.Sector12RothmanUniversity));
case CityName.Sector12:
elems.taskDetailsSelector2!.add(createOptionElement(LocationName.Sector12RothmanUniversity));
break;
case Cities.Volhaven:
elems.taskDetailsSelector2!.add(createOptionElement(Locations.VolhavenZBInstituteOfTechnology));
case CityName.Volhaven:
elems.taskDetailsSelector2!.add(createOptionElement(LocationName.VolhavenZBInstituteOfTechnology));
break;
default:
elems.taskDetailsSelector2!.add(createOptionElement("No university available in city!"));
@ -597,30 +598,30 @@ function updateSleeveTaskSelector(sleeve: Sleeve, elems: ISleeveUIElems, allSlee
// Second selector has gym
// In this switch statement we also set the initial value of the second selector
switch (sleeve.city) {
case Cities.Aevum:
elems.taskDetailsSelector2!.add(createOptionElement(Locations.AevumCrushFitnessGym));
elems.taskDetailsSelector2!.add(createOptionElement(Locations.AevumSnapFitnessGym));
case CityName.Aevum:
elems.taskDetailsSelector2!.add(createOptionElement(LocationName.AevumCrushFitnessGym));
elems.taskDetailsSelector2!.add(createOptionElement(LocationName.AevumSnapFitnessGym));
// Set initial value
if (sleeve.currentTaskLocation === Locations.AevumCrushFitnessGym) {
if (sleeve.currentTaskLocation === LocationName.AevumCrushFitnessGym) {
elems.taskDetailsSelector2!.selectedIndex = 0;
} else if (sleeve.currentTaskLocation === Locations.AevumSnapFitnessGym) {
} else if (sleeve.currentTaskLocation === LocationName.AevumSnapFitnessGym) {
elems.taskDetailsSelector2!.selectedIndex = 1;
}
break;
case Cities.Sector12:
elems.taskDetailsSelector2!.add(createOptionElement(Locations.Sector12IronGym));
elems.taskDetailsSelector2!.add(createOptionElement(Locations.Sector12PowerhouseGym));
case CityName.Sector12:
elems.taskDetailsSelector2!.add(createOptionElement(LocationName.Sector12IronGym));
elems.taskDetailsSelector2!.add(createOptionElement(LocationName.Sector12PowerhouseGym));
// Set initial value
if (sleeve.currentTaskLocation === Locations.Sector12IronGym) {
if (sleeve.currentTaskLocation === LocationName.Sector12IronGym) {
elems.taskDetailsSelector2!.selectedIndex = 0;
} else if (sleeve.currentTaskLocation === Locations.Sector12PowerhouseGym) {
} else if (sleeve.currentTaskLocation === LocationName.Sector12PowerhouseGym) {
elems.taskDetailsSelector2!.selectedIndex = 1;
}
break;
case Cities.Volhaven:
elems.taskDetailsSelector2!.add(createOptionElement(Locations.VolhavenMilleniumFitnessGym));
case CityName.Volhaven:
elems.taskDetailsSelector2!.add(createOptionElement(LocationName.VolhavenMilleniumFitnessGym));
break;
default:
elems.taskDetailsSelector2!.add(createOptionElement("No gym available in city!"));

@ -10,7 +10,7 @@ import { Companies } from "./Company/Companies";
import { getNextCompanyPosition } from "./Company/GetNextCompanyPosition";
import { getJobRequirementText } from "./Company/GetJobRequirementText";
import { CompanyPositions } from "./Company/CompanyPositions";
import * as posNames from "./Company/data/CompanyPositionNames";
import * as posNames from "./Company/data/companypositionnames";
import {CONSTANTS} from "./Constants";
import { Corporation } from "./Corporation/Corporation";
import { Programs } from "./Programs/Programs";
@ -23,7 +23,10 @@ import { displayFactionContent } from "./Faction/FactionHelpers";
import {Gang, resetGangs} from "./Gang";
import { hasHacknetServers } from "./Hacknet/HacknetHelpers";
import { HashManager } from "./Hacknet/HashManager";
import {Locations} from "./Locations";
import { Cities } from "./Locations/Cities";
import { Locations } from "./Locations/Locations";
import { CityName } from "./Locations/data/CityNames";
import { LocationName } from "./Locations/data/LocationNames";
import {hasBn11SF, hasWallStreetSF,hasAISF} from "./NetscriptFunctions";
import { Sleeve } from "./PersonObjects/Sleeve/Sleeve";
import { AllServers,
@ -33,12 +36,14 @@ import {Settings} from "./Settings/Settings";
import {SpecialServerIps, SpecialServerNames} from "./Server/SpecialServerIps";
import {SourceFiles, applySourceFile} from "./SourceFile";
import { SourceFileFlags } from "./SourceFile/SourceFileFlags";
import Decimal from "decimal.js";
import {numeralWrapper} from "./ui/numeralFormat";
import { MoneySourceTracker } from "./utils/MoneySourceTracker";
import {dialogBoxCreate} from "../utils/DialogBox";
import {clearEventListeners} from "../utils/uiHelpers/clearEventListeners";
import {createRandomIp} from "../utils/IPAddress";
import {dialogBoxCreate} from "./../utils/DialogBox";
import {clearEventListeners} from "./../utils/uiHelpers/clearEventListeners";
import {createRandomIp} from "./../utils/IPAddress";
import {Reviver, Generic_toJSON,
Generic_fromJSON} from "../utils/JSONReviver";
import {convertTimeMsToTimeElapsedString} from "../utils/StringHelperFunctions";
@ -102,7 +107,7 @@ function PlayerObject() {
this.homeComputer = "";
//Location information
this.city = Locations.Sector12;
this.city = CityName.Sector12;
this.location = "";
// Jobs that the player holds
@ -271,7 +276,7 @@ PlayerObject.prototype.prestigeAugmentation = function() {
this.money = new Decimal(1000);
this.city = Locations.Sector12;
this.city = CityName.Sector12;
this.location = "";
this.companyName = "";
@ -364,7 +369,7 @@ PlayerObject.prototype.prestigeSourceFile = function() {
this.money = new Decimal(1000);
this.city = Locations.Sector12;
this.city = CityName.Sector12;
this.location = "";
this.companyName = "";
@ -445,26 +450,6 @@ PlayerObject.prototype.prestigeSourceFile = function() {
this.hp = this.max_hp;
}
PlayerObject.prototype.getCurrentServer = function() {
return AllServers[this.currentServer];
}
PlayerObject.prototype.getHomeComputer = function() {
return AllServers[this.homeComputer];
}
PlayerObject.prototype.getUpgradeHomeRamCost = function() {
//Calculate how many times ram has been upgraded (doubled)
const currentRam = this.getHomeComputer().maxRam;
const numUpgrades = Math.log2(currentRam);
//Calculate cost
//Have cost increase by some percentage each time RAM has been upgraded
const mult = Math.pow(1.58, numUpgrades);
var cost = currentRam * CONSTANTS.BaseCostFor1GBOfRamHome * mult * BitNodeMultipliers.HomeComputerRamCost;
return cost;
}
PlayerObject.prototype.receiveInvite = function(factionName) {
if(this.factionInvitations.includes(factionName) || this.factions.includes(factionName)) {
return;
@ -494,7 +479,7 @@ PlayerObject.prototype.updateSkillLevels = function() {
var ratio = this.hp / this.max_hp;
this.max_hp = Math.floor(10 + this.defense / 10);
Player.hp = Math.round(this.max_hp * ratio);
this.hp = Math.round(this.max_hp * ratio);
}
PlayerObject.prototype.resetMultipliers = function() {
@ -538,8 +523,8 @@ PlayerObject.prototype.resetMultipliers = function() {
}
PlayerObject.prototype.hasProgram = function(programName) {
var home = Player.getHomeComputer();
if (home == null) {return false;}
const home = this.getHomeComputer();
if (home == null) { return false; }
for (var i = 0; i < home.programs.length; ++i) {
if (programName.toLowerCase() == home.programs[i].toLowerCase()) {return true;}
@ -661,13 +646,13 @@ PlayerObject.prototype.gainIntelligenceExp = function(exp) {
//Given a string expression like "str" or "strength", returns the given stat
PlayerObject.prototype.queryStatFromString = function(str) {
const tempStr = str.toLowerCase();
if (tempStr.includes("hack")) {return Player.hacking_skill;}
if (tempStr.includes("str")) {return Player.strength;}
if (tempStr.includes("def")) {return Player.defense;}
if (tempStr.includes("dex")) {return Player.dexterity;}
if (tempStr.includes("agi")) {return Player.agility;}
if (tempStr.includes("cha")) {return Player.charisma;}
if (tempStr.includes("int")) {return Player.intelligence;}
if (tempStr.includes("hack")) { return this.hacking_skill; }
if (tempStr.includes("str")) { return this.strength; }
if (tempStr.includes("def")) { return this.defense; }
if (tempStr.includes("dex")) { return this.dexterity; }
if (tempStr.includes("agi")) { return this.agility; }
if (tempStr.includes("cha")) { return this.charisma; }
if (tempStr.includes("int")) { return this.intelligence; }
}
/******* Working functions *******/
@ -752,7 +737,7 @@ PlayerObject.prototype.startWork = function(companyName) {
var newCancelButton = clearEventListeners("work-in-progress-cancel-button");
newCancelButton.innerHTML = "Cancel Work";
newCancelButton.addEventListener("click", function() {
Player.finishWork(true);
this.finishWork(true);
return false;
});
@ -875,7 +860,7 @@ PlayerObject.prototype.startWorkPartTime = function(companyName) {
var newCancelButton = clearEventListeners("work-in-progress-cancel-button");
newCancelButton.innerHTML = "Stop Working";
newCancelButton.addEventListener("click", function() {
Player.finishWorkPartTime();
this.finishWorkPartTime();
return false;
});
@ -985,7 +970,7 @@ PlayerObject.prototype.startFactionWork = function(faction) {
var cancelButton = clearEventListeners("work-in-progress-cancel-button");
cancelButton.innerHTML = "Stop Faction Work";
cancelButton.addEventListener("click", function() {
Player.finishFactionWork(true);
this.finishFactionWork(true);
return false;
});
@ -1322,7 +1307,7 @@ PlayerObject.prototype.startCreateProgramWork = function(programName, time, reqL
var cancelButton = clearEventListeners("work-in-progress-cancel-button");
cancelButton.innerHTML = "Cancel work on creating program";
cancelButton.addEventListener("click", function() {
Player.finishCreateProgramWork(true);
this.finishCreateProgramWork(true);
return false;
});
@ -1464,7 +1449,7 @@ PlayerObject.prototype.startClass = function(costMult, expMult, className) {
cancelButton.innerHTML = "Stop taking course";
}
cancelButton.addEventListener("click", function() {
Player.finishClass();
this.finishClass();
return false;
});
@ -1562,7 +1547,7 @@ PlayerObject.prototype.startCrime = function(crimeType, hackExp, strExp, defExp,
var newCancelButton = clearEventListeners("work-in-progress-cancel-button")
newCancelButton.innerHTML = "Cancel crime"
newCancelButton.addEventListener("click", function() {
Player.finishCrime(true);
this.finishCrime(true);
return false;
});
@ -1604,8 +1589,8 @@ PlayerObject.prototype.finishCrime = function(cancelled) {
console.log(this.crimeType);
dialogBoxCreate("ERR: Unrecognized crime type. This is probably a bug please contact the developer");
}
Player.gainMoney(this.workMoneyGained);
Player.recordMoneySource(this.workMoneyGained, "crime");
this.gainMoney(this.workMoneyGained);
this.recordMoneySource(this.workMoneyGained, "crime");
this.karma -= crime.karma;
this.numPeopleKilled += crime.kills;
if(crime.intelligence_exp > 0) {
@ -1720,7 +1705,7 @@ PlayerObject.prototype.singularityStopWork = function() {
}
//Returns true if hospitalized, false otherwise
// Returns true if hospitalized, false otherwise
PlayerObject.prototype.takeDamage = function(amt) {
if (typeof amt !== "number") {
console.warn(`Player.takeDamage() called without a numeric argument: ${amt}`);
@ -2126,14 +2111,14 @@ PlayerObject.prototype.checkForFactionInvitations = function() {
//ECorp
var ecorpFac = Factions["ECorp"];
if (!ecorpFac.isBanned && !ecorpFac.isMember && !ecorpFac.alreadyInvited &&
checkMegacorpRequirements(Locations.AevumECorp)) {
checkMegacorpRequirements(LocationName.AevumECorp)) {
invitedFactions.push(ecorpFac);
}
//MegaCorp
var megacorpFac = Factions["MegaCorp"];
if (!megacorpFac.isBanned && !megacorpFac.isMember && !megacorpFac.alreadyInvited &&
checkMegacorpRequirements(Locations.Sector12MegaCorp)) {
checkMegacorpRequirements(LocationName.Sector12MegaCorp)) {
invitedFactions.push(megacorpFac);
}
@ -2141,42 +2126,42 @@ PlayerObject.prototype.checkForFactionInvitations = function() {
var bachmanandassociatesFac = Factions["Bachman & Associates"];
if (!bachmanandassociatesFac.isBanned && !bachmanandassociatesFac.isMember &&
!bachmanandassociatesFac.alreadyInvited &&
checkMegacorpRequirements(Locations.AevumBachmanAndAssociates)) {
checkMegacorpRequirements(LocationName.AevumBachmanAndAssociates)) {
invitedFactions.push(bachmanandassociatesFac);
}
//Blade Industries
var bladeindustriesFac = Factions["Blade Industries"];
if (!bladeindustriesFac.isBanned && !bladeindustriesFac.isMember && !bladeindustriesFac.alreadyInvited &&
checkMegacorpRequirements(Locations.Sector12BladeIndustries)) {
checkMegacorpRequirements(LocationName.Sector12BladeIndustries)) {
invitedFactions.push(bladeindustriesFac);
}
//NWO
var nwoFac = Factions["NWO"];
if (!nwoFac.isBanned && !nwoFac.isMember && !nwoFac.alreadyInvited &&
checkMegacorpRequirements(Locations.VolhavenNWO)) {
checkMegacorpRequirements(LocationName.VolhavenNWO)) {
invitedFactions.push(nwoFac);
}
//Clarke Incorporated
var clarkeincorporatedFac = Factions["Clarke Incorporated"];
if (!clarkeincorporatedFac.isBanned && !clarkeincorporatedFac.isMember && !clarkeincorporatedFac.alreadyInvited &&
checkMegacorpRequirements(Locations.AevumClarkeIncorporated)) {
checkMegacorpRequirements(LocationName.AevumClarkeIncorporated)) {
invitedFactions.push(clarkeincorporatedFac);
}
//OmniTek Incorporated
var omnitekincorporatedFac = Factions["OmniTek Incorporated"];
if (!omnitekincorporatedFac.isBanned && !omnitekincorporatedFac.isMember && !omnitekincorporatedFac.alreadyInvited &&
checkMegacorpRequirements(Locations.VolhavenOmniTekIncorporated)) {
checkMegacorpRequirements(LocationName.VolhavenOmniTekIncorporated)) {
invitedFactions.push(omnitekincorporatedFac);
}
//Four Sigma
var foursigmaFac = Factions["Four Sigma"];
if (!foursigmaFac.isBanned && !foursigmaFac.isMember && !foursigmaFac.alreadyInvited &&
checkMegacorpRequirements(Locations.Sector12FourSigma)) {
checkMegacorpRequirements(LocationName.Sector12FourSigma)) {
invitedFactions.push(foursigmaFac);
}
@ -2184,7 +2169,7 @@ PlayerObject.prototype.checkForFactionInvitations = function() {
var kuaigonginternationalFac = Factions["KuaiGong International"];
if (!kuaigonginternationalFac.isBanned && !kuaigonginternationalFac.isMember &&
!kuaigonginternationalFac.alreadyInvited &&
checkMegacorpRequirements(Locations.ChongqingKuaiGongInternational)) {
checkMegacorpRequirements(LocationName.ChongqingKuaiGongInternational)) {
invitedFactions.push(kuaigonginternationalFac);
}
@ -2197,7 +2182,7 @@ PlayerObject.prototype.checkForFactionInvitations = function() {
if (!fulcrumsecrettechonologiesFac.isBanned && !fulcrumsecrettechonologiesFac.isMember &&
!fulcrumsecrettechonologiesFac.alreadyInvited &&
fulcrumSecretServer.manuallyHacked &&
checkMegacorpRequirements(Locations.AevumFulcrumTechnologies, 250e3)) {
checkMegacorpRequirements(LocationName.AevumFulcrumTechnologies, 250e3)) {
invitedFactions.push(fulcrumsecrettechonologiesFac);
}
}
@ -2236,42 +2221,42 @@ PlayerObject.prototype.checkForFactionInvitations = function() {
//Chongqing
var chongqingFac = Factions["Chongqing"];
if (!chongqingFac.isBanned && !chongqingFac.isMember && !chongqingFac.alreadyInvited &&
this.money.gte(20000000) && this.city == Locations.Chongqing) {
this.money.gte(20000000) && this.city == CityName.Chongqing) {
invitedFactions.push(chongqingFac);
}
//Sector-12
var sector12Fac = Factions["Sector-12"];
if (!sector12Fac.isBanned && !sector12Fac.isMember && !sector12Fac.alreadyInvited &&
this.money.gte(15000000) && this.city == Locations.Sector12) {
this.money.gte(15000000) && this.city == CityName.Sector12) {
invitedFactions.push(sector12Fac);
}
//New Tokyo
var newtokyoFac = Factions["New Tokyo"];
if (!newtokyoFac.isBanned && !newtokyoFac.isMember && !newtokyoFac.alreadyInvited &&
this.money.gte(20000000) && this.city == Locations.NewTokyo) {
this.money.gte(20000000) && this.city == CityName.NewTokyo) {
invitedFactions.push(newtokyoFac);
}
//Aevum
var aevumFac = Factions["Aevum"];
if (!aevumFac.isBanned && !aevumFac.isMember && !aevumFac.alreadyInvited &&
this.money.gte(40000000) && this.city == Locations.Aevum) {
this.money.gte(40000000) && this.city == CityName.Aevum) {
invitedFactions.push(aevumFac);
}
//Ishima
var ishimaFac = Factions["Ishima"];
if (!ishimaFac.isBanned && !ishimaFac.isMember && !ishimaFac.alreadyInvited &&
this.money.gte(30000000) && this.city == Locations.Ishima) {
this.money.gte(30000000) && this.city == CityName.Ishima) {
invitedFactions.push(ishimaFac);
}
//Volhaven
var volhavenFac = Factions["Volhaven"];
if (!volhavenFac.isBanned && !volhavenFac.isMember && !volhavenFac.alreadyInvited &&
this.money.gte(50000000) && this.city == Locations.Volhaven) {
this.money.gte(50000000) && this.city == CityName.Volhaven) {
invitedFactions.push(volhavenFac);
}
@ -2280,8 +2265,8 @@ PlayerObject.prototype.checkForFactionInvitations = function() {
if (!speakersforthedeadFac.isBanned && !speakersforthedeadFac.isMember && !speakersforthedeadFac.alreadyInvited &&
this.hacking_skill >= 100 && this.strength >= 300 && this.defense >= 300 &&
this.dexterity >= 300 && this.agility >= 300 && this.numPeopleKilled >= 30 &&
this.karma <= -45 && !allCompanies.includes(Locations.Sector12CIA) &&
!allCompanies.includes(Locations.Sector12NSA)) {
this.karma <= -45 && !allCompanies.includes(LocationName.Sector12CIA) &&
!allCompanies.includes(LocationName.Sector12NSA)) {
invitedFactions.push(speakersforthedeadFac);
}
@ -2289,9 +2274,9 @@ PlayerObject.prototype.checkForFactionInvitations = function() {
var thedarkarmyFac = Factions["The Dark Army"];
if (!thedarkarmyFac.isBanned && !thedarkarmyFac.isMember && !thedarkarmyFac.alreadyInvited &&
this.hacking_skill >= 300 && this.strength >= 300 && this.defense >= 300 &&
this.dexterity >= 300 && this.agility >= 300 && this.city == Locations.Chongqing &&
this.numPeopleKilled >= 5 && this.karma <= -45 && !allCompanies.includes(Locations.Sector12CIA) &&
!allCompanies.includes(Locations.Sector12NSA)) {
this.dexterity >= 300 && this.agility >= 300 && this.city == CityName.Chongqing &&
this.numPeopleKilled >= 5 && this.karma <= -45 && !allCompanies.includes(LocationName.Sector12CIA) &&
!allCompanies.includes(LocationName.Sector12NSA)) {
invitedFactions.push(thedarkarmyFac);
}
@ -2300,9 +2285,9 @@ PlayerObject.prototype.checkForFactionInvitations = function() {
if (!thesyndicateFac.isBanned && !thesyndicateFac.isMember && !thesyndicateFac.alreadyInvited &&
this.hacking_skill >= 200 && this.strength >= 200 && this.defense >= 200 &&
this.dexterity >= 200 && this.agility >= 200 &&
(this.city == Locations.Aevum || this.city == Locations.Sector12) &&
(this.city == CityName.Aevum || this.city == CityName.Sector12) &&
this.money.gte(10000000) && this.karma <= -90 &&
!allCompanies.includes(Locations.Sector12CIA) && !allCompanies.includes(Locations.Sector12NSA)) {
!allCompanies.includes(LocationName.Sector12CIA) && !allCompanies.includes(LocationName.Sector12NSA)) {
invitedFactions.push(thesyndicateFac);
}
@ -2319,8 +2304,8 @@ PlayerObject.prototype.checkForFactionInvitations = function() {
//Tetrads
var tetradsFac = Factions["Tetrads"];
if (!tetradsFac.isBanned && !tetradsFac.isMember && !tetradsFac.alreadyInvited &&
(this.city == Locations.Chongqing || this.city == Locations.NewTokyo ||
this.city == Locations.Ishima) && this.strength >= 75 && this.defense >= 75 &&
(this.city == CityName.Chongqing || this.city == CityName.NewTokyo ||
this.city == CityName.Ishima) && this.strength >= 75 && this.defense >= 75 &&
this.dexterity >= 75 && this.agility >= 75 && this.karma <= -18) {
invitedFactions.push(tetradsFac);
}
@ -2362,8 +2347,8 @@ PlayerObject.prototype.checkForFactionInvitations = function() {
var tiandihuiFac = Factions["Tian Di Hui"];
if (!tiandihuiFac.isBanned && !tiandihuiFac.isMember && !tiandihuiFac.alreadyInvited &&
this.money.gte(1000000) && this.hacking_skill >= 50 &&
(this.city == Locations.Chongqing || this.city == Locations.NewTokyo ||
this.city == Locations.Ishima)) {
(this.city == CityName.Chongqing || this.city == CityName.NewTokyo ||
this.city == CityName.Ishima)) {
invitedFactions.push(tiandihuiFac);
}
@ -2392,18 +2377,6 @@ PlayerObject.prototype.startGang = function(factionName, hacking) {
this.gang = new Gang(factionName, hacking);
}
/*************** Corporation ****************/
PlayerObject.prototype.hasCorporation = function() {
if (this.corporation == null) { return false; }
return (this.corporation instanceof Corporation);
}
/*************** Bladeburner ****************/
PlayerObject.prototype.inBladeburner = function() {
if (this.bladeburner == null) { return false; }
return (this.bladeburner instanceof Bladeburner);
}
/************* BitNodes **************/
PlayerObject.prototype.setBitNodeNumber = function(n) {
this.bitNodeN = n;
@ -2489,8 +2462,85 @@ PlayerObject.prototype.gainCodingContractReward = function(reward, difficulty=1)
/* eslint-enable no-case-declarations */
}
/* Functions for saving and loading the Player data */
function loadPlayer(saveString) {
PlayerObject.prototype.travel = function(to) {
if (Cities[to] == null) {
console.warn(`Player.travel() called with invalid city: ${to}`);
return false;
}
this.city = to;
return true;
}
PlayerObject.prototype.gotoLocation = function(to) {
if (Locations[to] == null) {
console.warn(`Player.gotoLocation() called with invalid location: ${to}`);
return false;
}
this.location = to;
return true;
}
PlayerObject.prototype.hasTorRouter = function() {
return SpecialServerIps.hasOwnProperty("Darkweb Server");
}
PlayerObject.prototype.getCurrentServer = function() {
return AllServers[this.currentServer];
}
PlayerObject.prototype.getHomeComputer = function() {
return AllServers[this.homeComputer];
}
PlayerObject.prototype.getUpgradeHomeRamCost = function() {
//Calculate how many times ram has been upgraded (doubled)
const currentRam = this.getHomeComputer().maxRam;
const numUpgrades = Math.log2(currentRam);
//Calculate cost
//Have cost increase by some percentage each time RAM has been upgraded
const mult = Math.pow(1.58, numUpgrades);
var cost = currentRam * CONSTANTS.BaseCostFor1GBOfRamHome * mult * BitNodeMultipliers.HomeComputerRamCost;
return cost;
}
PlayerObject.prototype.inBladeburner = function() {
if (this.bladeburner == null) { return false; }
return (this.bladeburner instanceof Bladeburner);
}
PlayerObject.prototype.startBladeburner = function() {
this.bladeburner = new Bladeburner({ new: true });
}
PlayerObject.prototype.hasCorporation = function() {
if (this.corporation == null) { return false; }
return (this.corporation instanceof Corporation);
}
PlayerObject.prototype.startCorporation = function(corpName, additionalShares=0) {
this.corporation = new Corporation({
name: corpName
});
this.corporation.totalShares += additionalShares;
}
PlayerObject.prototype.toJSON = function() {
return Generic_toJSON("PlayerObject", this);
}
PlayerObject.fromJSON = function(value) {
return Generic_fromJSON(PlayerObject, value.data);
}
Reviver.constructors.PlayerObject = PlayerObject;
export let Player = new PlayerObject();
export function loadPlayer(saveString) {
Player = JSON.parse(saveString, Reviver);
//Parse Decimal.js objects
@ -2510,16 +2560,3 @@ function loadPlayer(saveString) {
}
}
}
PlayerObject.prototype.toJSON = function() {
return Generic_toJSON("PlayerObject", this);
}
PlayerObject.fromJSON = function(value) {
return Generic_fromJSON(PlayerObject, value.data);
}
Reviver.constructors.PlayerObject = PlayerObject;
let Player = new PlayerObject();
export {Player, loadPlayer};

@ -15,7 +15,6 @@ import { Factions,
initFactions } from "./Faction/Factions";
import { joinFaction } from "./Faction/FactionHelpers";
import {deleteGangDisplayContent} from "./Gang";
import {Locations} from "./Location";
import { Message } from "./Message/Message";
import { initMessages,
Messages } from "./Message/MessageHelpers";

@ -20,7 +20,7 @@ interface IConstructorParams {
organizationName?: string;
}
export abstract class BaseServer {
export class BaseServer {
// Coding Contract files on this server
contracts: CodingContract[] = [];

@ -4,9 +4,8 @@
*/
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
import { CONSTANTS } from "../Constants";
import { Player } from "../Player";
import { AllServers,
AddToAllServers } from "../Server/AllServers";
import { IPlayer } from "../PersonObjects/IPlayer";
import { AddToAllServers } from "../Server/AllServers";
import { Server } from "../Server/Server";
import { dialogBoxCreate } from "../../utils/DialogBox";
import { createRandomIp } from "../../utils/IPAddress";
@ -15,7 +14,11 @@ import { isPowerOfTwo } from "../../utils/helpers/isPowerOfT
// Returns the cost of purchasing a server with the given RAM
// Returns Infinity for invalid 'ram' arguments
export function getPurchaseServerCost(ram) {
/**
* @param ram Amount of RAM on purchased server (GB)
* @returns Cost of purchasing the given server. Returns infinity for invalid arguments
*/
export function getPurchaseServerCost(ram: number) {
const sanitizedRam = Math.round(ram);
if (isNaN(sanitizedRam) || !isPowerOfTwo(sanitizedRam)) {
return Infinity;
@ -40,17 +43,17 @@ export function getPurchaseServerMaxRam() {
}
// Manually purchase a server (NOT through Netscript)
export function purchaseServer(ram) {
export function purchaseServer(ram: number, p: IPlayer) {
const cost = getPurchaseServerCost(ram);
//Check if player has enough money
if (Player.money.lt(cost)) {
dialogBoxCreate("You don't have enough money to purchase this server!");
if (!p.canAfford(cost)) {
dialogBoxCreate("You don't have enough money to purchase this server!", false);
return;
}
//Maximum server limit
if (Player.purchasedServers.length >= getPurchaseServerLimit()) {
if (p.purchasedServers.length >= getPurchaseServerLimit()) {
dialogBoxCreate("You have reached the maximum limit of " + getPurchaseServerLimit() + " servers. " +
"You cannot purchase any more. You can " +
"delete some of your purchased servers using the deleteServer() Netscript function in a script");
@ -71,26 +74,26 @@ export function purchaseServer(ram) {
AddToAllServers(newServ);
//Add to Player's purchasedServers array
Player.purchasedServers.push(newServ.ip);
p.purchasedServers.push(newServ.ip);
//Connect new server to home computer
var homeComputer = Player.getHomeComputer();
var homeComputer = p.getHomeComputer();
homeComputer.serversOnNetwork.push(newServ.ip);
newServ.serversOnNetwork.push(homeComputer.ip);
Player.loseMoney(cost);
p.loseMoney(cost);
dialogBoxCreate("Server successfully purchased with hostname " + hostname);
}
// Manually upgrade RAM on home computer (NOT through Netscript)
export function purchaseRamForHomeComputer(cost) {
if (Player.money.lt(cost)) {
export function purchaseRamForHomeComputer(cost: number, p: IPlayer) {
if (!p.canAfford(cost)) {
dialogBoxCreate("You do not have enough money to purchase additional RAM for your home computer");
return;
}
const homeComputer = Player.getHomeComputer();
const homeComputer = p.getHomeComputer();
if (homeComputer.maxRam >= CONSTANTS.HomeComputerMaxRam) {
dialogBoxCreate(`You cannot upgrade your home computer RAM because it is at its maximum possible value`);
return;
@ -98,7 +101,7 @@ export function purchaseRamForHomeComputer(cost) {
homeComputer.maxRam *= 2;
Player.loseMoney(cost);
p.loseMoney(cost);
dialogBoxCreate("Purchased additional RAM for home computer! It now has " + homeComputer.maxRam + "GB of RAM.");
}

@ -3,7 +3,7 @@ import { getStockMarket4SDataCost,
getStockMarket4STixApiCost } from "./StockMarketCosts";
import {CONSTANTS} from "../Constants";
import {Locations} from "../Locations";
import { LocationName } from "../Locations/data/LocationNames";
import {hasWallStreetSF, wallStreetSFLvl} from "../NetscriptFunctions";
import {WorkerScript} from "../NetscriptWorker";
import {Player} from "../Player";
@ -190,34 +190,34 @@ function loadStockMarket(saveString) {
function initStockSymbols() {
//Stocks for companies at which you can work
StockSymbols[Locations.AevumECorp] = "ECP";
StockSymbols[Locations.Sector12MegaCorp] = "MGCP";
StockSymbols[Locations.Sector12BladeIndustries] = "BLD";
StockSymbols[Locations.AevumClarkeIncorporated] = "CLRK";
StockSymbols[Locations.VolhavenOmniTekIncorporated] = "OMTK";
StockSymbols[Locations.Sector12FourSigma] = "FSIG";
StockSymbols[Locations.ChongqingKuaiGongInternational] = "KGI";
StockSymbols[Locations.AevumFulcrumTechnologies] = "FLCM";
StockSymbols[Locations.IshimaStormTechnologies] = "STM";
StockSymbols[Locations.NewTokyoDefComm] = "DCOMM";
StockSymbols[Locations.VolhavenHeliosLabs] = "HLS";
StockSymbols[Locations.NewTokyoVitaLife] = "VITA";
StockSymbols[Locations.Sector12IcarusMicrosystems] = "ICRS";
StockSymbols[Locations.Sector12UniversalEnergy] = "UNV";
StockSymbols[Locations.AevumAeroCorp] = "AERO";
StockSymbols[Locations.VolhavenOmniaCybersystems] = "OMN";
StockSymbols[Locations.ChongqingSolarisSpaceSystems] = "SLRS";
StockSymbols[Locations.NewTokyoGlobalPharmaceuticals] = "GPH";
StockSymbols[Locations.IshimaNovaMedical] = "NVMD";
StockSymbols[Locations.AevumWatchdogSecurity] = "WDS";
StockSymbols[Locations.VolhavenLexoCorp] = "LXO";
StockSymbols[Locations.AevumRhoConstruction] = "RHOC";
StockSymbols[Locations.Sector12AlphaEnterprises] = "APHE";
StockSymbols[Locations.VolhavenSysCoreSecurities] = "SYSC";
StockSymbols[Locations.VolhavenCompuTek] = "CTK";
StockSymbols[Locations.AevumNetLinkTechnologies] = "NTLK";
StockSymbols[Locations.IshimaOmegaSoftware] = "OMGA";
StockSymbols[Locations.Sector12FoodNStuff] = "FNS";
StockSymbols[LocationName.AevumECorp] = "ECP";
StockSymbols[LocationName.Sector12MegaCorp] = "MGCP";
StockSymbols[LocationName.Sector12BladeIndustries] = "BLD";
StockSymbols[LocationName.AevumClarkeIncorporated] = "CLRK";
StockSymbols[LocationName.VolhavenOmniTekIncorporated] = "OMTK";
StockSymbols[LocationName.Sector12FourSigma] = "FSIG";
StockSymbols[LocationName.ChongqingKuaiGongInternational] = "KGI";
StockSymbols[LocationName.AevumFulcrumTechnologies] = "FLCM";
StockSymbols[LocationName.IshimaStormTechnologies] = "STM";
StockSymbols[LocationName.NewTokyoDefComm] = "DCOMM";
StockSymbols[LocationName.VolhavenHeliosLabs] = "HLS";
StockSymbols[LocationName.NewTokyoVitaLife] = "VITA";
StockSymbols[LocationName.Sector12IcarusMicrosystems] = "ICRS";
StockSymbols[LocationName.Sector12UniversalEnergy] = "UNV";
StockSymbols[LocationName.AevumAeroCorp] = "AERO";
StockSymbols[LocationName.VolhavenOmniaCybersystems] = "OMN";
StockSymbols[LocationName.ChongqingSolarisSpaceSystems] = "SLRS";
StockSymbols[LocationName.NewTokyoGlobalPharmaceuticals] = "GPH";
StockSymbols[LocationName.IshimaNovaMedical] = "NVMD";
StockSymbols[LocationName.AevumWatchdogSecurity] = "WDS";
StockSymbols[LocationName.VolhavenLexoCorp] = "LXO";
StockSymbols[LocationName.AevumRhoConstruction] = "RHOC";
StockSymbols[LocationName.Sector12AlphaEnterprises] = "APHE";
StockSymbols[LocationName.VolhavenSysCoreSecurities] = "SYSC";
StockSymbols[LocationName.VolhavenCompuTek] = "CTK";
StockSymbols[LocationName.AevumNetLinkTechnologies] = "NTLK";
StockSymbols[LocationName.IshimaOmegaSoftware] = "OMGA";
StockSymbols[LocationName.Sector12FoodNStuff] = "FNS";
//Stocks for other companies
StockSymbols["Sigma Cosmetics"] = "SGC";
@ -241,115 +241,115 @@ function initStockMarket() {
const randInt = getRandomInt;
var ecorp = Locations.AevumECorp;
var ecorp = LocationName.AevumECorp;
var ecorpStk = new Stock(ecorp, StockSymbols[ecorp], randInt(40, 50) / 100, true, 19, randInt(17e3, 28e3), 2.4e12);
StockMarket[ecorp] = ecorpStk;
var megacorp = Locations.Sector12MegaCorp;
var megacorp = LocationName.Sector12MegaCorp;
var megacorpStk = new Stock(megacorp, StockSymbols[megacorp], randInt(40,50)/100, true, 19, randInt(24e3, 34e3), 2.4e12);
StockMarket[megacorp] = megacorpStk;
var blade = Locations.Sector12BladeIndustries;
var blade = LocationName.Sector12BladeIndustries;
var bladeStk = new Stock(blade, StockSymbols[blade], randInt(70, 80)/100, true, 13, randInt(12e3, 25e3), 1.6e12);
StockMarket[blade] = bladeStk;
var clarke = Locations.AevumClarkeIncorporated;
var clarke = LocationName.AevumClarkeIncorporated;
var clarkeStk = new Stock(clarke, StockSymbols[clarke], randInt(65, 75)/100, true, 12, randInt(10e3, 25e3), 1.5e12);
StockMarket[clarke] = clarkeStk;
var omnitek = Locations.VolhavenOmniTekIncorporated;
var omnitek = LocationName.VolhavenOmniTekIncorporated;
var omnitekStk = new Stock(omnitek, StockSymbols[omnitek], randInt(60, 70)/100, true, 12, randInt(32e3, 43e3), 1.8e12);
StockMarket[omnitek] = omnitekStk;
var foursigma = Locations.Sector12FourSigma;
var foursigma = LocationName.Sector12FourSigma;
var foursigmaStk = new Stock(foursigma, StockSymbols[foursigma], randInt(100, 110)/100, true, 17, randInt(50e3, 80e3), 2e12);
StockMarket[foursigma] = foursigmaStk;
var kuaigong = Locations.ChongqingKuaiGongInternational;
var kuaigong = LocationName.ChongqingKuaiGongInternational;
var kuaigongStk = new Stock(kuaigong, StockSymbols[kuaigong], randInt(75, 85)/100, true, 10, randInt(16e3, 28e3), 1.9e12);
StockMarket[kuaigong] = kuaigongStk;
var fulcrum = Locations.AevumFulcrumTechnologies;
var fulcrum = LocationName.AevumFulcrumTechnologies;
var fulcrumStk = new Stock(fulcrum, StockSymbols[fulcrum], randInt(120, 130)/100, true, 16, randInt(29e3, 36e3), 2e12);
StockMarket[fulcrum] = fulcrumStk;
var storm = Locations.IshimaStormTechnologies;
var storm = LocationName.IshimaStormTechnologies;
var stormStk = new Stock(storm, StockSymbols[storm], randInt(80, 90)/100, true, 7, randInt(20e3, 25e3), 1.2e12);
StockMarket[storm] = stormStk;
var defcomm = Locations.NewTokyoDefComm;
var defcomm = LocationName.NewTokyoDefComm;
var defcommStk = new Stock(defcomm, StockSymbols[defcomm], randInt(60, 70)/100, true, 10, randInt(6e3, 19e3), 900e9);
StockMarket[defcomm] = defcommStk;
var helios = Locations.VolhavenHeliosLabs;
var helios = LocationName.VolhavenHeliosLabs;
var heliosStk = new Stock(helios, StockSymbols[helios], randInt(55, 65)/100, true, 9, randInt(10e3, 18e3), 825e9);
StockMarket[helios] = heliosStk;
var vitalife = Locations.NewTokyoVitaLife;
var vitalife = LocationName.NewTokyoVitaLife;
var vitalifeStk = new Stock(vitalife, StockSymbols[vitalife], randInt(70, 80)/100, true, 7, randInt(8e3, 14e3), 1e12);
StockMarket[vitalife] = vitalifeStk;
var icarus = Locations.Sector12IcarusMicrosystems;
var icarus = LocationName.Sector12IcarusMicrosystems;
var icarusStk = new Stock(icarus, StockSymbols[icarus], randInt(60, 70)/100, true, 7.5, randInt(12e3, 24e3), 800e9);
StockMarket[icarus] = icarusStk;
var universalenergy = Locations.Sector12UniversalEnergy;
var universalenergy = LocationName.Sector12UniversalEnergy;
var universalenergyStk = new Stock(universalenergy, StockSymbols[universalenergy], randInt(50, 60)/100, true, 10, randInt(16e3, 29e3), 900e9);
StockMarket[universalenergy] = universalenergyStk;
var aerocorp = Locations.AevumAeroCorp;
var aerocorp = LocationName.AevumAeroCorp;
var aerocorpStk = new Stock(aerocorp, StockSymbols[aerocorp], randInt(55, 65)/100, true, 6, randInt(8e3, 17e3), 640e9);
StockMarket[aerocorp] = aerocorpStk;
var omnia = Locations.VolhavenOmniaCybersystems;
var omnia = LocationName.VolhavenOmniaCybersystems;
var omniaStk = new Stock(omnia, StockSymbols[omnia], randInt(65, 75)/100, true, 4.5, randInt(6e3, 15e3), 600e9);
StockMarket[omnia] = omniaStk;
var solaris = Locations.ChongqingSolarisSpaceSystems;
var solaris = LocationName.ChongqingSolarisSpaceSystems;
var solarisStk = new Stock(solaris, StockSymbols[solaris], randInt(70, 80)/100, true, 8.5, randInt(14e3, 28e3), 705e9);
StockMarket[solaris] = solarisStk;
var globalpharm = Locations.NewTokyoGlobalPharmaceuticals;
var globalpharm = LocationName.NewTokyoGlobalPharmaceuticals;
var globalpharmStk = new Stock(globalpharm, StockSymbols[globalpharm], randInt(55, 65)/100, true, 10.5, randInt(12e3, 30e3), 695e9);
StockMarket[globalpharm] = globalpharmStk;
var nova = Locations.IshimaNovaMedical;
var nova = LocationName.IshimaNovaMedical;
var novaStk = new Stock(nova, StockSymbols[nova], randInt(70, 80)/100, true, 5, randInt(15e3, 27e3), 600e9);
StockMarket[nova] = novaStk;
var watchdog = Locations.AevumWatchdogSecurity;
var watchdog = LocationName.AevumWatchdogSecurity;
var watchdogStk = new Stock(watchdog, StockSymbols[watchdog], randInt(240, 260)/100, true, 1.5, randInt(4e3, 8.5e3), 450e9);
StockMarket[watchdog] = watchdogStk;
var lexocorp = Locations.VolhavenLexoCorp;
var lexocorp = LocationName.VolhavenLexoCorp;
var lexocorpStk = new Stock(lexocorp, StockSymbols[lexocorp], randInt(115, 135)/100, true, 6, randInt(4.5e3, 8e3), 300e9);
StockMarket[lexocorp] = lexocorpStk;
var rho = Locations.AevumRhoConstruction;
var rho = LocationName.AevumRhoConstruction;
var rhoStk = new Stock(rho, StockSymbols[rho], randInt(50, 70)/100, true, 1, randInt(2e3, 7e3), 180e9);
StockMarket[rho] = rhoStk;
var alpha = Locations.Sector12AlphaEnterprises;
var alpha = LocationName.Sector12AlphaEnterprises;
var alphaStk = new Stock(alpha, StockSymbols[alpha], randInt(175, 205)/100, true, 10, randInt(4e3, 8.5e3), 240e9);
StockMarket[alpha] = alphaStk;
var syscore = Locations.VolhavenSysCoreSecurities;
var syscore = LocationName.VolhavenSysCoreSecurities;
var syscoreStk = new Stock(syscore, StockSymbols[syscore], randInt(150, 170)/100, true, 3, randInt(3e3, 8e3), 200e9);
StockMarket[syscore] = syscoreStk;
var computek = Locations.VolhavenCompuTek;
var computek = LocationName.VolhavenCompuTek;
var computekStk = new Stock(computek, StockSymbols[computek], randInt(80, 100)/100, true, 4, randInt(1e3, 6e3), 185e9);
StockMarket[computek] = computekStk;
var netlink = Locations.AevumNetLinkTechnologies;
var netlink = LocationName.AevumNetLinkTechnologies;
var netlinkStk = new Stock(netlink, StockSymbols[netlink], randInt(400, 430)/100, true, 1, randInt(1e3, 5e3), 58e9);
StockMarket[netlink] = netlinkStk;
var omega = Locations.IshimaOmegaSoftware;
var omega = LocationName.IshimaOmegaSoftware;
var omegaStk = new Stock(omega, StockSymbols[omega], randInt(90, 110)/100, true, 0.5, randInt(1e3, 8e3), 60e9);
StockMarket[omega] = omegaStk;
var fns = Locations.Sector12FoodNStuff;
var fns = LocationName.Sector12FoodNStuff;
var fnsStk = new Stock(fns, StockSymbols[fns], randInt(70, 80)/100, false, 1, randInt(500, 4.5e3), 45e9);
StockMarket[fns] = fnsStk;

@ -27,15 +27,13 @@ import { displayFactionContent, joinFaction,
processPassiveFactionRepGain,
inviteToFaction } from "./Faction/FactionHelpers";
import { FconfSettings } from "./Fconf/FconfSettings";
import {displayLocationContent,
initLocationButtons} from "./Location";
import {Locations} from "./Locations";
import { hasHacknetServers,
renderHacknetNodesUI,
clearHacknetNodesUI,
processHacknetEarnings } from "./Hacknet/HacknetHelpers";
import {iTutorialStart} from "./InteractiveTutorial";
import {initLiterature} from "./Literature";
import { LocationRoot } from "./Locations/ui/Root";
import { checkForMessagesToSend, initMessages } from "./Message/MessageHelpers";
import {inMission, currMission} from "./Missions";
import {initSingularitySFFlags,
@ -174,7 +172,7 @@ $(document).keydown(function(e) {
Engine.loadHacknetNodesContent();
} else if (e.keyCode === KEY.W && e.altKey) {
e.preventDefault();
Engine.loadWorldContent();
Engine.loadLocationContent();
} else if (e.keyCode === KEY.J && e.altKey) {
e.preventDefault();
Engine.loadJobContent();
@ -233,7 +231,6 @@ const Engine = {
scriptEditorContent: null,
activeScriptsContent: null,
hacknetNodesContent: null,
worldContent: null,
createProgramContent: null,
factionsContent: null,
factionContent: null,
@ -302,14 +299,6 @@ const Engine = {
MainMenuLinks.HacknetNodes.classList.add("active");
},
loadWorldContent: function() {
Engine.hideAllContent();
Engine.Display.worldContent.style.display = "block";
Engine.displayWorldInfo();
routing.navigateTo(Page.World);
MainMenuLinks.City.classList.add("active");
},
loadCreateProgramContent: function() {
Engine.hideAllContent();
Engine.Display.createProgramContent.style.display = "block";
@ -357,40 +346,17 @@ const Engine = {
loadLocationContent: function() {
Engine.hideAllContent();
Engine.Display.locationContent.style.display = "block";
try {
displayLocationContent();
} catch(e) {
exceptionAlert(e);
console.error(e);
}
routing.navigateTo(Page.Location);
const rootComponent = <LocationRoot
engine={Engine}
p={Player}
/>
ReactDOM.render(rootComponent, Engine.Display.locationContent);
},
loadTravelContent: function() {
switch(Player.city) {
case Locations.Aevum:
Player.location = Locations.AevumTravelAgency;
break;
case Locations.Chongqing:
Player.location = Locations.ChongqingTravelAgency;
break;
case Locations.Sector12:
Player.location = Locations.Sector12TravelAgency;
break;
case Locations.NewTokyo:
Player.location = Locations.NewTokyoTravelAgency;
break;
case Locations.Ishima:
Player.location = Locations.IshimaTravelAgency;
break;
case Locations.Volhaven:
Player.location = Locations.VolhavenTravelAgency;
break;
default:
dialogBoxCreate("ERROR: Invalid city. This is a bug please contact game dev");
break;
}
Player.gotoLocation(LocationName.TravelAgency);
Engine.loadLocationContent();
},
@ -510,7 +476,6 @@ const Engine = {
Engine.Display.scriptEditorContent.style.display = "none";
Engine.Display.activeScriptsContent.style.display = "none";
clearHacknetNodesUI();
Engine.Display.worldContent.style.display = "none";
Engine.Display.createProgramContent.style.display = "none";
Engine.Display.factionsContent.style.display = "none";
Engine.Display.factionContent.style.display = "none";
@ -542,14 +507,6 @@ const Engine = {
clearResleevesPage();
clearSleevesPage();
//Location lists
Engine.aevumLocationsList.style.display = "none";
Engine.chongqingLocationsList.style.display = "none";
Engine.sector12LocationsList.style.display = "none";
Engine.newTokyoLocationsList.style.display = "none";
Engine.ishimaLocationsList.style.display = "none";
Engine.volhavenLocationsList.style.display = "none";
//Make nav menu tabs inactive
MainMenuLinks.Terminal.classList.remove("active");
MainMenuLinks.ScriptEditor.classList.remove("active");
@ -592,99 +549,6 @@ const Engine = {
displayCharacterInfo(Engine.Display.characterInfo, Player);
},
/* Display locations in the world*/
aevumLocationsList: null,
chongqingLocationsList: null,
sector12LocationsList: null,
newTokyoLocationsList: null,
ishimaLocationsList: null,
volhavenLocationsList: null,
displayWorldInfo: function() {
Engine.aevumLocationsList.style.display = "none";
Engine.chongqingLocationsList.style.display = "none";
Engine.sector12LocationsList.style.display = "none";
Engine.newTokyoLocationsList.style.display = "none";
Engine.ishimaLocationsList.style.display = "none";
Engine.volhavenLocationsList.style.display = "none";
document.getElementById("world-city-name").innerHTML = Player.city;
var cityDesc = document.getElementById("world-city-desc"); //TODO
switch(Player.city) {
case Locations.Aevum:
Engine.aevumLocationsList.style.display = "inline";
break;
case Locations.Chongqing:
Engine.chongqingLocationsList.style.display = "inline";
break;
case Locations.Sector12:
Engine.sector12LocationsList.style.display = "inline";
//City hall only in BitNode-3/with Source-File 3
if ((Player.bitNodeN === 3 || hasCorporationSF) && Player.bitNodeN !== 8) {
document.getElementById("sector12-cityhall-li").style.display = "block";
} else {
document.getElementById("sector12-cityhall-li").style.display = "none";
}
break;
case Locations.NewTokyo:
Engine.newTokyoLocationsList.style.display = "inline";
break;
case Locations.Ishima:
Engine.ishimaLocationsList.style.display = "inline";
break;
case Locations.Volhaven:
Engine.volhavenLocationsList.style.display = "inline";
break;
default:
console.log("Invalid city value in Player object!");
break;
}
//Generic Locations (common to every city):
// World Stock Exchange
// Corporation (if applicable)
// Bladeburner HQ (if applicable);
var genericLocationsList = document.getElementById("generic-locations-list");
genericLocationsList.style.display = "inline";
removeChildrenFromElement(genericLocationsList);
var li = createElement("li");
li.appendChild(createElement("a", {
innerText:"World Stock Exchange", class:"a-link-button",
clickListener:()=>{
Player.location = Locations.WorldStockExchange;
Engine.loadStockMarketContent();
return false;
}
}));
genericLocationsList.appendChild(li);
if (Player.corporation instanceof Corporation && document.getElementById("location-corporation-button") == null) {
var li = createElement("li");
li.appendChild(createElement("a", {
innerText:Player.corporation.name, id:"location-corporation-button",
class:"a-link-button",
clickListener:()=>{
Engine.loadCorporationContent();
return false;
}
}));
genericLocationsList.appendChild(li);
}
if (Player.bladeburner instanceof Bladeburner) {
var li = createElement("li");
li.appendChild(createElement("a", {
innerText:"Bladeburner Headquarters", class:"a-link-button",
clickListener:()=>{
Engine.loadBladeburnerContent();
return false;
}
}));
genericLocationsList.appendChild(li);
}
},
displayFactionsInfo: function() {
removeChildrenFromElement(Engine.Display.factionsContent);
@ -1343,9 +1207,6 @@ const Engine = {
Engine.Display.hacknetNodesContent = document.getElementById("hacknet-nodes-container");
Engine.Display.hacknetNodesContent.style.display = "none";
Engine.Display.worldContent = document.getElementById("world-container");
Engine.Display.worldContent.style.display = "none";
Engine.Display.createProgramContent = document.getElementById("create-program-container");
Engine.Display.createProgramContent.style.display = "none";
@ -1378,22 +1239,12 @@ const Engine = {
//Character info
Engine.Display.characterInfo = document.getElementById("character-content");
//Location lists
Engine.aevumLocationsList = document.getElementById("aevum-locations-list");
Engine.chongqingLocationsList = document.getElementById("chongqing-locations-list");
Engine.sector12LocationsList = document.getElementById("sector12-locations-list");
Engine.newTokyoLocationsList = document.getElementById("newtokyo-locations-list");
Engine.ishimaLocationsList = document.getElementById("ishima-locations-list");
Engine.volhavenLocationsList = document.getElementById("volhaven-locations-list");
//Location page (page that shows up when you visit a specific location in World)
Engine.Display.locationContent = document.getElementById("location-container");
//Engine.Display.locationContent.style.visibility = "hidden";
Engine.Display.locationContent.style.display = "none";
//Work In Progress
Engine.Display.workInProgressContent = document.getElementById("work-in-progress-container");
//Engine.Display.workInProgressContent.style.visibility = "hidden";
Engine.Display.workInProgressContent.style.display = "none";
//Red Pill / Hack World Daemon
@ -1404,9 +1255,6 @@ const Engine = {
Engine.Display.cinematicTextContent = document.getElementById("cinematic-text-container");
Engine.Display.cinematicTextContent.style.display = "none";
//Init Location buttons
initLocationButtons();
// Initialize references to main menu links
if (!initializeMainMenuLinks()) {
const errorMsg = "Failed to initialize Main Menu Links. Please try refreshing the page. " +
@ -1480,7 +1328,7 @@ const Engine = {
});
MainMenuLinks.City.addEventListener("click", function() {
Engine.loadWorldContent();
Engine.loadLocationContent();
return false;
});

@ -206,11 +206,6 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %>
<!-- React Component -->
</div>
<!-- World -->
<div id="world-container" class="generic-menupage-container">
<!-- React Component -->
</div>
<!-- Create a program(executable) -->
<div id="create-program-container" class="generic-menupage-container">
<p id="create-program-page-text">
@ -238,160 +233,41 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %>
<h1> Tutorial (AKA Links to Documentation) </h1>
<a id="tutorial-getting-started-link" class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/guidesandtips/gettingstartedguideforbeginnerprogrammers.html" >
Getting Started
</a><br><br>
Getting Started</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/servers.html">
Servers & Networking
</a><br><br>
Servers & Networking</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/hacking.html">
Hacking
</a><br><br>
Hacking</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/scripts.html">
Scripts
</a><br><br>
Scripts</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/netscript.html">
Netscript Programming Language
</a><br><br>
Netscript Programming Language</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/world.html">
Traveling
</a><br><br>
Traveling</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/companies.html">
Companies
</a><br><br>
Companies</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/infiltration.html">
Infiltration
</a><br><br>
Infiltration</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/factions.html">
Factions
</a><br><br>
Factions</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/augmentations.html">
Augmentations
</a><br><br>
Augmentations</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/shortcuts.html">
Keyboard Shortcuts
</a>
Keyboard Shortcuts</a>
</div>
<!-- Location (visiting a location in World) -->
<div id="location-container" class="generic-menupage-container">
<a id="location-return-to-world-button" class="a-link-button"> Return to World </a>
<h1 id="location-name"></h1>
<p id="location-info"> </p>
<p id="location-job-title"> </p>
<p id="location-text-divider-1"> --------------- </p>
<p id="location-job-reputation" class="tooltip"> </p>
<p id="location-text-divider-2"> --------------- </p>
<p id="location-company-favor" class="tooltip"> </p>
<p id="location-text-divider-3"> --------------- </p>
<!-- Jobs/Work at a company -->
<a id="location-software-job" class="a-link-button tooltip"> Apply for Software Job</a>
<a id="location-software-consultant-job" class="a-link-button tooltip"> Apply for Software Consultant Job</a>
<a id="location-it-job" class="a-link-button tooltip"> Apply for IT Job </a>
<a id="location-security-engineer-job" class="a-link-button tooltip"> Apply for Security Engineer Job</a>
<a id="location-network-engineer-job" class="a-link-button tooltip"> Apply for Network Engineer Job</a>
<a id="location-business-job" class="a-link-button tooltip"> Apply for Business Job</a>
<a id="location-business-consultant-job" class="a-link-button tooltip"> Apply for Business Consultant Job </a>
<a id="location-security-job" class="a-link-button tooltip"> Apply for Security Job</a>
<a id="location-agent-job" class="a-link-button tooltip"> Apply to be an Agent</a>
<a id="location-employee-job" class="a-link-button tooltip"> Apply to be an Employee </a>
<a id="location-parttime-employee-job" class="a-link-button tooltip"> Apply to be a Part-time Employee </a>
<a id="location-waiter-job" class="a-link-button tooltip"> Apply to be a Waiter</a>
<a id="location-parttime-waiter-job" class="a-link-button tooltip"> Apply to be a Part-time Waiter</a>
<a id="location-work" class="a-link-button"> Work </a>
<!-- Gym -->
<a id="location-gym-train-str" class="a-link-button">Train Strength</a>
<a id="location-gym-train-def" class="a-link-button">Train Defense </a>
<a id="location-gym-train-dex" class="a-link-button">Train Dexterity</a>
<a id="location-gym-train-agi" class="a-link-button">Train Agility</a>
<!-- Study/Take classes at a university -->
<a id="location-study-computer-science" class="a-link-button">Study Computer Science (free)</a>
<a id="location-data-structures-class" class="a-link-button">Take Data Structures course</a>
<a id="location-networks-class" class="a-link-button">Take Networks course</a>
<a id="location-algorithms-class" class="a-link-button">Take Algorithms course</a>
<a id="location-management-class" class="a-link-button">Take Management course</a>
<a id="location-leadership-class" class="a-link-button">Take Leadership course</a>
<!-- Purchase servers -->
<a id="location-purchase-2gb" class="a-link-button"> Purchase 2GB Server - $150,000</a>
<a id="location-purchase-4gb" class="a-link-button"> Purchase 4GB Server - $300,000</a>
<a id="location-purchase-8gb" class="a-link-button"> Purchase 8GB Server - $600,000</a>
<a id="location-purchase-16gb" class="a-link-button"> Purchase 16GB Server - $1,200,000</a>
<a id="location-purchase-32gb" class="a-link-button"> Purchase 32GB Server - $2,400,000</a>
<a id="location-purchase-64gb" class="a-link-button"> Purchase 64GB Server - $4,800,000</a>
<a id="location-purchase-128gb" class="a-link-button"> Purchase 128GB Server - $9,600,000</a>
<a id="location-purchase-256gb" class="a-link-button"> Purchase 256GB Server - $19,200,000</a>
<a id="location-purchase-512gb" class="a-link-button"> Purchase 512GB Server - $38,400,000</a>
<a id="location-purchase-1tb" class="a-link-button"> Purchase 1TB Server - $75,000,000</a>
<a id="location-purchase-tor" class="a-link-button"> Purchase TOR Router - $100,000</a>
<a id="location-purchase-home-ram" class="a-link-button"> Purchase additional RAM for Home computer </a>
<a id="location-purchase-home-cores" class="a-link-button"> Purchase additional Core for Home computer </a>
<!-- Infiltrate -->
<a id="location-infiltrate" class="a-link-button tooltip"> Infiltrate Company
<span class="tooltiptext">
Infiltrate this company's facility to try and steal their classified secrets!
Warning: You may end up hospitalized if you are unsuccessful!
</span>
</a>
<!-- Hospital -->
<a id="location-hospital-treatment" class="a-link-button"> Get Treatment for Wounds </a>
<!-- Travel agency -->
<p id="location-travel-agency-text">
From here, you can travel to any other city! A ticket costs $200,000.
</p>
<a id="location-travel-to-aevum" class="a-link-button"> Travel to Aevum </a>
<a id="location-travel-to-chongqing" class="a-link-button"> Travel to Chongqing</a>
<a id="location-travel-to-sector12" class="a-link-button"> Travel to Sector-12</a>
<a id="location-travel-to-newtokyo" class="a-link-button"> Travel to New Tokyo</a>
<a id="location-travel-to-ishima" class="a-link-button"> Travel to Ishima</a>
<a id="location-travel-to-volhaven" class="a-link-button"> Travel to Volhaven</a>
<!-- Slums -->
<p id="location-slums-description">
You have entered the Slums, a poverty-ridden district filled with gangs, criminals, and
other shadowy entities. The city's government and police have neglected this area for years...
<br /><br /><br />
In the Slums, you can commit crimes to earn money and experience. Crime attempts are not always
successful. Your chance at successfully committing a crime is determined by your stats.
</p>
<a class="a-link-button tooltip" id="location-slums-shoplift"> Shoplift </a>
<a id="location-slums-rob-store" class="a-link-button tooltip"> Rob a store </a>
<a id="location-slums-mug" class="a-link-button tooltip"> Mug someone </a>
<a id="location-slums-larceny" class="a-link-button tooltip"> Commit Larceny </a>
<a id="location-slums-deal-drugs" class="a-link-button tooltip"> Deal Drugs </a>
<a id="location-slums-bond-forgery" class="a-link-button tooltip">Bond Forgery</a>
<a id="location-slums-traffic-arms" class="a-link-button tooltip">Traffick Illegal Arms</a>
<a id="location-slums-homicide" class="a-link-button tooltip">Homicide</a>
<a id="location-slums-gta" class="a-link-button tooltip"> Grand Theft Auto </a>
<a id="location-slums-kidnap" class="a-link-button tooltip"> Kidnap and Ransom </a>
<a id="location-slums-assassinate" class="a-link-button tooltip"> Assassinate </a>
<a id="location-slums-heist" class="a-link-button tooltip"> Heist </a>
<!-- City Hall -->
<a id="location-cityhall-create-corporation" class="a-link-button">Create a Corporation</a>
<!-- Bladeburner @ NSA -->
<a id="location-nsa-bladeburner" class="a-link-button">Bladeburner Division</a>
<!-- Re-sleeving @ VitaLife -->
<a id="location-vitalife-resleeve" class="a-link-button">Re-Sleeve</a>
</div>
<div id="infiltration-container" class="generic-menupage-container">

@ -0,0 +1,70 @@
/**
* Basic stateless button that automatically re-renders itself every X seconds
* Uses the 'std-button' css class
*
* NOT recommended for usage - only if you really have to
*/
import * as React from "react";
interface IProps {
disabled?: boolean;
intervalTime?: number;
onClick?: (e: React.MouseEvent<HTMLElement>) => any;
style?: object;
text: string;
tooltip?: string;
}
interface IState {
i: number;
}
export class AutoupdatingStdButton extends React.Component<IProps, IState> {
/**
* Timer ID for auto-updating implementation (returned value from setInterval())
*/
interval: number = 0;
constructor(props: IProps) {
super(props);
this.state = {
i: 0,
}
}
componentDidMount() {
const time = this.props.intervalTime ? this.props.intervalTime : 1000;
this.interval = setInterval(() => this.tick(), time);
}
componentWillUnmount() {
clearInterval(this.interval);
}
tick() {
this.setState(prevState => ({
i: prevState.i + 1
}));
}
render() {
const hasTooltip = this.props.tooltip !== "";
let className = this.props.disabled ? "std-button-disabled" : "std-button";
if (hasTooltip) {
className += " tooltip"
}
return (
<button className={className} onClick={this.props.onClick} style={this.props.style}>
{this.props.text}
{
hasTooltip &&
<span className={"tooltiptext"}>
{this.props.tooltip}
</span>
}
</button>
)
}
}

@ -4,20 +4,31 @@
*/
import * as React from "react";
export interface IStdButtonProps {
interface IStdButtonProps {
disabled?: boolean;
onClick?: (e: React.MouseEvent<HTMLElement>) => any;
style?: object;
text: string;
tooltip?: string;
}
export class StdButton extends React.Component<IStdButtonProps, any> {
render() {
const className = this.props.disabled ? "std-button-disabled" : "std-button";
const hasTooltip = this.props.tooltip !== "";
let className = this.props.disabled ? "std-button-disabled" : "std-button";
if (hasTooltip) {
className += " tooltip";
}
return (
<button className={className} onClick={this.props.onClick} style={this.props.style}>
{this.props.text}
{
hasTooltip &&
<span className={"tooltiptext"}>
{this.props.tooltip}
</span>
}
</button>
)
}

@ -0,0 +1,20 @@
/**
* Stateless button that represents something that has been purchased.
*/
import * as React from "react";
interface IStdButtonPurchasedProps {
onClick?: (e: React.MouseEvent<HTMLElement>) => any;
style?: object;
text: string;
}
export class StdButtonPurchased extends React.Component<IStdButtonPurchasedProps, any> {
render() {
return (
<button className={"std-button-bought"} onClick={this.props.onClick} style={this.props.style}>
{this.props.text}
</button>
)
}
}

@ -1,28 +0,0 @@
/**
* Basic stateless button with a tooltip
* Uses the 'std-button' css class
*/
import * as React from "react";
export interface IStdButtonWithTooltipProps {
disabled?: boolean;
onClick?: (e: React.MouseEvent<HTMLElement>) => any;
style?: object;
text: string;
tooltip: string;
}
export class StdButtonWithTooltip extends React.Component<IStdButtonWithTooltipProps, any> {
render() {
const className = this.props.disabled ? "std-button-disabled tooltip" : "std-button tooltip";
return (
<button className={className} onClick={this.props.onClick} style={this.props.style}>
{this.props.text}
<span className={"tooltiptext"}>
{this.props.tooltip}
</span>
</button>
)
}
}

@ -28,11 +28,6 @@ export enum Page {
*/
HacknetNodes = "HacknetNodes",
/**
* View the city the player is currently in.
*/
World = "World",
/**
* The list of programs the player could potentially build.
*/
@ -64,7 +59,7 @@ export enum Page {
DevMenu = "Dev Menu",
/**
* Information about the specific location the player at (job, company, etc.);
* Visiting a location in the world
*/
Location = "Location",

@ -1,2 +1,2 @@
export function dialogBoxCreate(txt: string, preformatted: boolean): void;
export var dialogBoxOpened: boolean;
export function dialogBoxCreate(txt: string, preformatted?: boolean): void;
export var dialogBoxOpened: boolean;

@ -6,7 +6,8 @@
* 1. Just a Yes/No response from player
* 2. Popup also includes a text input field in addition to the Yes/No response
*/
import {clearEventListeners} from "./uiHelpers/clearEventListeners";
import { clearEventListeners } from "./uiHelpers/clearEventListeners";
import { KEY } from "./helpers/keyCodes";
export let yesNoBoxOpen: boolean = false;
@ -14,9 +15,9 @@ const yesNoBoxContainer: HTMLElement | null = document.getElementById("yes-no-bo
const yesNoBoxTextElement: HTMLElement | null = document.getElementById("yes-no-box-text");
export function yesNoBoxHotkeyHandler(e: KeyboardEvent) {
if (e.keyCode === 27) {
if (e.keyCode === KEY.ESC) {
yesNoBoxClose();
} else if (e.keyCode === 13) {
} else if (e.keyCode === KEY.ENTER) {
const yesBtn: HTMLElement | null = document.getElementById("yes-no-box-yes");
if (yesBtn) {
yesBtn.click();
@ -78,9 +79,9 @@ const yesNoTextInputBoxInput: HTMLInputElement | null = document.getElementById(
const yesNoTextInputBoxTextElement: HTMLElement | null = document.getElementById("yes-no-text-input-box-text");
export function yesNoTxtInpBoxHotkeyHandler(e: KeyboardEvent) {
if (e.keyCode === 27) {
if (e.keyCode === KEY.ESC) {
yesNoTxtInpBoxClose();
} else if (e.keyCode === 13) {
} else if (e.keyCode === KEY.ENTER) {
const yesBtn: HTMLElement | null = document.getElementById("yes-no-text-input-box-yes");
if (yesBtn) {
yesBtn.click();