mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-22 15:43:49 +01:00
More bug fixes for Sleeve/Resleeve features. Rebalancing for Sleeve/Resleeve and stock market. Added an option to remove source files in the dev menu
This commit is contained in:
parent
5573e778bb
commit
a2237d4319
@ -31,13 +31,12 @@
|
|||||||
border: 1px solid #fff;
|
border: 1px solid #fff;
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bladeburner-nav-button {
|
.bladeburner-nav-button {
|
||||||
@extend %bladeburner-nav-button;
|
@extend %bladeburner-nav-button;
|
||||||
|
|
||||||
color: #fff;
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: #3d4044;
|
background-color: #3d4044;
|
||||||
}
|
}
|
||||||
|
3986
dist/engine.bundle.js
vendored
3986
dist/engine.bundle.js
vendored
File diff suppressed because it is too large
Load Diff
9
dist/engine.css
vendored
9
dist/engine.css
vendored
@ -2054,12 +2054,11 @@ button {
|
|||||||
.bladeburner-nav-button, .bladeburner-nav-button-inactive {
|
.bladeburner-nav-button, .bladeburner-nav-button-inactive {
|
||||||
border: 1px solid #fff;
|
border: 1px solid #fff;
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
padding: 2px; }
|
padding: 2px;
|
||||||
|
|
||||||
.bladeburner-nav-button {
|
|
||||||
color: #fff; }
|
color: #fff; }
|
||||||
.bladeburner-nav-button:hover {
|
|
||||||
background-color: #3d4044; }
|
.bladeburner-nav-button:hover {
|
||||||
|
background-color: #3d4044; }
|
||||||
|
|
||||||
.bladeburner-nav-button-inactive {
|
.bladeburner-nav-button-inactive {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
400
dist/vendor.bundle.js
vendored
400
dist/vendor.bundle.js
vendored
File diff suppressed because it is too large
Load Diff
@ -52,3 +52,16 @@ it decreases by assigning sleeves to the 'Shock Recovery' task.
|
|||||||
|
|
||||||
Re-sleeving
|
Re-sleeving
|
||||||
^^^^^^^^^^^
|
^^^^^^^^^^^
|
||||||
|
Re-sleeving is the process of digitizing and transferring your consciousness into a
|
||||||
|
new human body, or "sleeve". When you re-sleeve into a new body, your stat experience
|
||||||
|
and Augmentations get replaced with those of the new body.
|
||||||
|
|
||||||
|
In order to re-sleeve, you must purchase new bodies. This can be done at VitaLife in
|
||||||
|
New Tokyo. Once you purchase a body to re-sleeve into, the effects will take
|
||||||
|
place immediately.
|
||||||
|
|
||||||
|
Note that resleeving **REMOVES** all of your currently-installed Augmentations,
|
||||||
|
and replaces them with the ones provided by the purchased sleeve. However,
|
||||||
|
Augmentations that are purchased but not installed will **not** be removed. If you have purchased
|
||||||
|
an Augmentation and then re-sleeve into a body which already has that Augmentation,
|
||||||
|
it will be removed since you cannot have duplicate Augmentations.
|
||||||
|
@ -26,7 +26,7 @@ List of all Source-Files
|
|||||||
| | * Increases the player's charisma and company salary multipliers by 8%/12%/14% |
|
| | * Increases the player's charisma and company salary multipliers by 8%/12%/14% |
|
||||||
+------------------------------------+-------------------------------------------------------------------------------------+
|
+------------------------------------+-------------------------------------------------------------------------------------+
|
||||||
| BitNode-4: The Singularity | * Lets the player access and use Netscript Singularity Functions in other BitNodes. |
|
| BitNode-4: The Singularity | * Lets the player access and use Netscript Singularity Functions in other BitNodes. |
|
||||||
| | Each level of this Source-File opens up more of the Singularity Functions to use |
|
| | * Each level of this Source-File opens up more of the Singularity Functions to use |
|
||||||
+------------------------------------+-------------------------------------------------------------------------------------+
|
+------------------------------------+-------------------------------------------------------------------------------------+
|
||||||
| BitNode-5: Artificial Intelligence | * Unlocks :ref:`gameplay_intelligence` |
|
| BitNode-5: Artificial Intelligence | * Unlocks :ref:`gameplay_intelligence` |
|
||||||
| | * Unlocks getBitNodeMultipliers() Netscript function |
|
| | * Unlocks getBitNodeMultipliers() Netscript function |
|
||||||
@ -56,7 +56,7 @@ List of all Source-Files
|
|||||||
+------------------------------------+-------------------------------------------------------------------------------------+
|
+------------------------------------+-------------------------------------------------------------------------------------+
|
||||||
| BitNode-12: The Recursion | * There is no maximum level for this Source-File |
|
| BitNode-12: The Recursion | * There is no maximum level for this Source-File |
|
||||||
| | * Each level of this Source-File increases all of the player's multipliers by 1%. |
|
| | * Each level of this Source-File increases all of the player's multipliers by 1%. |
|
||||||
| | This affect is multiplicative with itself. This means that level N of this |
|
| | * This affect is multiplicative with itself. This means that level N of this |
|
||||||
| | Source-File will result in a multiplier of 1.01^N (or 0.99^N for multipliers |
|
| | Source-File will result in a multiplier of 1.01^N (or 0.99^N for multipliers |
|
||||||
| | that decrease) |
|
| | that decrease) |
|
||||||
+------------------------------------+-------------------------------------------------------------------------------------+
|
+------------------------------------+-------------------------------------------------------------------------------------+
|
||||||
|
@ -64,9 +64,9 @@ documentation_title = '{0} Documentation'.format(project)
|
|||||||
# built documents.
|
# built documents.
|
||||||
#
|
#
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = '1.0'
|
version = '0.43'
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = '1.0'
|
release = '0.43.0'
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
@ -94,6 +94,9 @@ todo_include_todos = True
|
|||||||
#
|
#
|
||||||
#html_theme = 'agogo'
|
#html_theme = 'agogo'
|
||||||
html_theme = "sphinx_rtd_theme"
|
html_theme = "sphinx_rtd_theme"
|
||||||
|
html_theme_options = {
|
||||||
|
"navigation_depth": 5,
|
||||||
|
}
|
||||||
|
|
||||||
# Theme options are theme-specific and customize the look and feel of a theme
|
# Theme options are theme-specific and customize the look and feel of a theme
|
||||||
# further. For a list of options available for each theme, see the
|
# further. For a list of options available for each theme, see the
|
||||||
@ -179,7 +182,10 @@ texinfo_documents = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Example configuration for intersphinx: refer to the Python standard library.
|
# Example configuration for intersphinx: refer to the Python standard library.
|
||||||
intersphinx_mapping = {'https://docs.python.org/': None}
|
intersphinx_mapping = {'https://docs.python.org/': None}
|
||||||
|
|
||||||
|
|
||||||
|
def setup(app):
|
||||||
|
print("Initializing (setup())");
|
||||||
|
app.add_stylesheet('maxwidthoverride.css')
|
||||||
|
3
doc/source/ystatic/maxwidthoverride.css
Normal file
3
doc/source/ystatic/maxwidthoverride.css
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.wy-nav-content {
|
||||||
|
max-width: none;
|
||||||
|
}
|
@ -94,8 +94,8 @@ let NetscriptFunctions =
|
|||||||
"installAugmentations|" +
|
"installAugmentations|" +
|
||||||
|
|
||||||
// TIX API
|
// TIX API
|
||||||
"getStockPrice|getStockPosition|getStockSymbols|buyStock|sellStock|" +
|
"getStockPrice|getStockPosition|getStockSymbols|getStockMaxShares|" +
|
||||||
"shortStock|sellShort|" +
|
"buyStock|sellStock|shortStock|sellShort|" +
|
||||||
"placeOrder|cancelOrder|getOrders|getStockVolatility|getStockForecast|" +
|
"placeOrder|cancelOrder|getOrders|getStockVolatility|getStockForecast|" +
|
||||||
"purchase4SMarketData|purchase4SMarketDataTixApi|" +
|
"purchase4SMarketData|purchase4SMarketDataTixApi|" +
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Augmentation } from "./Augmentation";
|
import { Augmentation } from "./Augmentation";
|
||||||
import { Augmentations } from "./Augmentations";
|
import { Augmentations } from "./Augmentations";
|
||||||
|
import { PlayerOwnedAugmentation } from "./PlayerOwnedAugmentation";
|
||||||
import { AugmentationNames } from "./data/AugmentationNames";
|
import { AugmentationNames } from "./data/AugmentationNames";
|
||||||
|
|
||||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||||
@ -11,7 +12,8 @@ import { addWorkerScript } from "../NetscriptWorker";
|
|||||||
import { Player } from "../Player";
|
import { Player } from "../Player";
|
||||||
import { prestigeAugmentation } from "../Prestige";
|
import { prestigeAugmentation } from "../Prestige";
|
||||||
import { saveObject } from "../SaveObject";
|
import { saveObject } from "../SaveObject";
|
||||||
import { Script , RunningScript} from "../Script";
|
import { Script,
|
||||||
|
RunningScript} from "../Script";
|
||||||
import { Server } from "../Server";
|
import { Server } from "../Server";
|
||||||
import { OwnedAugmentationsOrderSetting } from "../SettingEnums";
|
import { OwnedAugmentationsOrderSetting } from "../SettingEnums";
|
||||||
import { Settings } from "../Settings";
|
import { Settings } from "../Settings";
|
||||||
|
@ -19,7 +19,7 @@ export let CONSTANTS: IMap<any> = {
|
|||||||
BaseCostFor1GBOfRamServer: 55000, //1 GB of RAM
|
BaseCostFor1GBOfRamServer: 55000, //1 GB of RAM
|
||||||
BaseCostFor1GBOfRamHacknetNode: 30000,
|
BaseCostFor1GBOfRamHacknetNode: 30000,
|
||||||
|
|
||||||
TravelCost: 200000,
|
TravelCost: 200e3,
|
||||||
|
|
||||||
BaseCostForHacknetNode: 1000,
|
BaseCostForHacknetNode: 1000,
|
||||||
BaseCostForHacknetNodeCore: 500000,
|
BaseCostForHacknetNodeCore: 500000,
|
||||||
@ -130,7 +130,7 @@ export let CONSTANTS: IMap<any> = {
|
|||||||
WSEAccountCost: 200e6,
|
WSEAccountCost: 200e6,
|
||||||
TIXAPICost: 5e9,
|
TIXAPICost: 5e9,
|
||||||
MarketData4SCost: 1e9,
|
MarketData4SCost: 1e9,
|
||||||
MarketDataTixApi4SCost: 20e9,
|
MarketDataTixApi4SCost: 25e9,
|
||||||
StockMarketCommission: 100e3,
|
StockMarketCommission: 100e3,
|
||||||
|
|
||||||
//Hospital/Health
|
//Hospital/Health
|
||||||
@ -512,10 +512,11 @@ export let CONSTANTS: IMap<any> = {
|
|||||||
`
|
`
|
||||||
v0.43.0
|
v0.43.0
|
||||||
* Added BitNode-10: Digital Carbon
|
* Added BitNode-10: Digital Carbon
|
||||||
|
|
||||||
* Stock Market Changes:
|
* Stock Market Changes:
|
||||||
** Each stock now has a maximum number of shares you can purchase (both Long and Short positions combined)
|
** Each stock now has a maximum number of shares you can purchase (both Long and Short positions combined)
|
||||||
** Added getStockMaxShares() Netscript function to the TIX API
|
** Added getStockMaxShares() Netscript function to the TIX API
|
||||||
|
** The cost of 4S Market Data TIX API Access increased from $20b to $25b
|
||||||
|
|
||||||
* Job Changes:
|
* Job Changes:
|
||||||
** You can now hold multiple jobs at once. This means you no longer lose reputation when leaving a company
|
** You can now hold multiple jobs at once. This means you no longer lose reputation when leaving a company
|
||||||
|
@ -9,10 +9,14 @@ import { StockMarket,
|
|||||||
SymbolToStockMap } from "./StockMarket/StockMarket";
|
SymbolToStockMap } from "./StockMarket/StockMarket";
|
||||||
import { Stock } from "./StockMarket/Stock";
|
import { Stock } from "./StockMarket/Stock";
|
||||||
import { Terminal } from "./Terminal";
|
import { Terminal } from "./Terminal";
|
||||||
|
|
||||||
import { numeralWrapper } from "./ui/numeralFormat";
|
import { numeralWrapper } from "./ui/numeralFormat";
|
||||||
|
|
||||||
import { dialogBoxCreate } from "../utils/DialogBox";
|
import { dialogBoxCreate } from "../utils/DialogBox";
|
||||||
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
||||||
import { createElement } from "../utils/uiHelpers/createElement";
|
import { createElement } from "../utils/uiHelpers/createElement";
|
||||||
|
import { createOptionElement } from "../utils/uiHelpers/createOptionElement";
|
||||||
|
import { getSelectText } from "../utils/uiHelpers/getSelectData";
|
||||||
import { removeElementById } from "../utils/uiHelpers/removeElementById";
|
import { removeElementById } from "../utils/uiHelpers/removeElementById";
|
||||||
|
|
||||||
const devMenuContainerId = "dev-menu-container";
|
const devMenuContainerId = "dev-menu-container";
|
||||||
@ -222,7 +226,7 @@ export function createDevMenu() {
|
|||||||
innerText: "Receive Invite to Faction",
|
innerText: "Receive Invite to Faction",
|
||||||
});
|
});
|
||||||
|
|
||||||
// Augmentations / Source Files
|
// Augmentations
|
||||||
const augmentationsHeader = createElement("h2", {innerText: "Augmentations"});
|
const augmentationsHeader = createElement("h2", {innerText: "Augmentations"});
|
||||||
|
|
||||||
const augmentationsDropdown = createElement("select", {
|
const augmentationsDropdown = createElement("select", {
|
||||||
@ -242,6 +246,32 @@ export function createDevMenu() {
|
|||||||
innerText: "Queue Augmentation",
|
innerText: "Queue Augmentation",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Source Files
|
||||||
|
const sourceFilesHeader = createElement("h2", { innerText: "Source-Files" });
|
||||||
|
|
||||||
|
const removeSourceFileDropdown = createElement("select", {
|
||||||
|
class: "dropdown",
|
||||||
|
margin: "5px",
|
||||||
|
});
|
||||||
|
for (let i = 0; i < 24; ++i) {
|
||||||
|
removeSourceFileDropdown.add(createOptionElement(String(i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeSourceFileButton = createElement("button", {
|
||||||
|
class: "std-button",
|
||||||
|
clickListener: () => {
|
||||||
|
const numToRemove = parseInt(getSelectText(removeSourceFileDropdown));
|
||||||
|
for (let i = 0; i < Player.sourceFiles.length; ++i) {
|
||||||
|
if (Player.sourceFiles[i].n === numToRemove) {
|
||||||
|
Player.sourceFiles.splice(i, 1);
|
||||||
|
hackWorldDaemon(Player.bitNodeN, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
innerText: "Remove Source File and Trigger Bitflume",
|
||||||
|
});
|
||||||
|
|
||||||
// Programs
|
// Programs
|
||||||
const programsHeader = createElement("h2", {innerText: "Programs"});
|
const programsHeader = createElement("h2", {innerText: "Programs"});
|
||||||
|
|
||||||
@ -508,6 +538,9 @@ export function createDevMenu() {
|
|||||||
devMenuContainer.appendChild(augmentationsHeader);
|
devMenuContainer.appendChild(augmentationsHeader);
|
||||||
devMenuContainer.appendChild(augmentationsDropdown);
|
devMenuContainer.appendChild(augmentationsDropdown);
|
||||||
devMenuContainer.appendChild(augmentationsQueueButton);
|
devMenuContainer.appendChild(augmentationsQueueButton);
|
||||||
|
devMenuContainer.appendChild(sourceFilesHeader);
|
||||||
|
devMenuContainer.appendChild(removeSourceFileDropdown);
|
||||||
|
devMenuContainer.appendChild(removeSourceFileButton);
|
||||||
devMenuContainer.appendChild(programsHeader);
|
devMenuContainer.appendChild(programsHeader);
|
||||||
devMenuContainer.appendChild(programsAddDropdown);
|
devMenuContainer.appendChild(programsAddDropdown);
|
||||||
devMenuContainer.appendChild(programsAddButton);
|
devMenuContainer.appendChild(programsAddButton);
|
||||||
|
@ -347,6 +347,9 @@ function processNetscript1Imports(code, workerScript) {
|
|||||||
ImportDeclaration: (node) => {
|
ImportDeclaration: (node) => {
|
||||||
hasImports = true;
|
hasImports = true;
|
||||||
let scriptName = node.source.value;
|
let scriptName = node.source.value;
|
||||||
|
if (scriptName.startsWith("./")) {
|
||||||
|
scriptName = scriptName.slice(2);
|
||||||
|
}
|
||||||
let script = getScript(scriptName);
|
let script = getScript(scriptName);
|
||||||
if (script == null) {
|
if (script == null) {
|
||||||
throw new Error("'Import' failed due to invalid script: " + scriptName);
|
throw new Error("'Import' failed due to invalid script: " + scriptName);
|
||||||
|
@ -6,7 +6,6 @@ import { Person } from "../Person";
|
|||||||
|
|
||||||
import { Augmentation } from "../../Augmentation/Augmentation";
|
import { Augmentation } from "../../Augmentation/Augmentation";
|
||||||
import { Augmentations } from "../../Augmentation/Augmentations";
|
import { Augmentations } from "../../Augmentation/Augmentations";
|
||||||
import { CONSTANTS } from "../../Constants";
|
|
||||||
|
|
||||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../../utils/JSONReviver";
|
||||||
|
|
||||||
@ -24,10 +23,10 @@ export class Resleeve extends Person {
|
|||||||
|
|
||||||
getCost(): number {
|
getCost(): number {
|
||||||
// Each experience point adds this to the cost
|
// Each experience point adds this to the cost
|
||||||
const CostPerExp: number = 4;
|
const CostPerExp: number = 10e3;
|
||||||
|
|
||||||
// Final cost is multiplied by # Augs ^ this constant
|
// Final cost is multiplied by this constant ^ # Augs
|
||||||
const NumAugsExponent: number = 1.05;
|
const NumAugsExponent: number = 1.12;
|
||||||
|
|
||||||
// Get total exp in this re-sleeve
|
// Get total exp in this re-sleeve
|
||||||
let totalExp: number = this.hacking_exp +
|
let totalExp: number = this.hacking_exp +
|
||||||
@ -48,7 +47,7 @@ export class Resleeve extends Person {
|
|||||||
totalAugmentationCost += aug!.baseCost;
|
totalAugmentationCost += aug!.baseCost;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (totalExp * CostPerExp) + (totalAugmentationCost * Math.pow(this.augmentations.length, NumAugsExponent));
|
return (totalExp * CostPerExp) + (totalAugmentationCost * Math.pow(NumAugsExponent, this.augmentations.length));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -64,7 +64,7 @@ export function purchaseResleeve(r: Resleeve, p: IPlayer): boolean {
|
|||||||
for (let i = p.queuedAugmentations.length - 1; i >= 0; --i) {
|
for (let i = p.queuedAugmentations.length - 1; i >= 0; --i) {
|
||||||
const name: string = p.queuedAugmentations[i].name;
|
const name: string = p.queuedAugmentations[i].name;
|
||||||
|
|
||||||
if (p.augmentations.filter((e: IPlayerOwnedAugmentation) => {e.name !== AugmentationNames.NeuroFluxGovernor && e.name === name}).length >= 1) {
|
if (p.augmentations.filter((e: IPlayerOwnedAugmentation) => {return e.name !== AugmentationNames.NeuroFluxGovernor && e.name === name}).length >= 1) {
|
||||||
p.queuedAugmentations.splice(i, 1);
|
p.queuedAugmentations.splice(i, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ export function createResleevesPage(p: IPlayer) {
|
|||||||
"into a new human body, or 'sleeve'. Here at VitaLife, you can purchase new " +
|
"into a new human body, or 'sleeve'. Here at VitaLife, you can purchase new " +
|
||||||
"specially-engineered bodies for the re-sleeve process. Many of these bodies " +
|
"specially-engineered bodies for the re-sleeve process. Many of these bodies " +
|
||||||
"even come with genetic and cybernetic Augmentations!<br><br>" +
|
"even come with genetic and cybernetic Augmentations!<br><br>" +
|
||||||
"Re-sleeving will chance your experience for every stat. It will also REMOVE " +
|
"Re-sleeving will change your experience for every stat. It will also REMOVE " +
|
||||||
"all of your currently-installed Augmentations, and replace " +
|
"all of your currently-installed Augmentations, and replace " +
|
||||||
"them with the ones provided by the purchased sleeve. However, Augmentations that you have " +
|
"them with the ones provided by the purchased sleeve. However, Augmentations that you have " +
|
||||||
"purchased but not installed will NOT be removed. If you have purchased an " +
|
"purchased but not installed will NOT be removed. If you have purchased an " +
|
||||||
|
@ -92,6 +92,11 @@ export class Sleeve extends Person {
|
|||||||
*/
|
*/
|
||||||
gainRatesForTask: ITaskTracker = createTaskTracker();
|
gainRatesForTask: ITaskTracker = createTaskTracker();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String that stores what stat the sleeve is training at the gym
|
||||||
|
*/
|
||||||
|
gymStatType: string = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keeps track of events/notifications for this sleeve
|
* Keeps track of events/notifications for this sleeve
|
||||||
*/
|
*/
|
||||||
@ -196,7 +201,37 @@ export class Sleeve extends Person {
|
|||||||
* Earn experience for any stats (supports multiple)
|
* Earn experience for any stats (supports multiple)
|
||||||
* This function also handles experience propogating to Player and other sleeves
|
* This function also handles experience propogating to Player and other sleeves
|
||||||
*/
|
*/
|
||||||
gainExperience(p: IPlayer, exp: ITaskTracker, numCycles: number=1): ITaskTracker {
|
gainExperience(p: IPlayer, exp: ITaskTracker, numCycles: number=1, fromOtherSleeve: boolean=false): ITaskTracker {
|
||||||
|
// If the experience is coming from another sleeve, it is not multiplied by anything.
|
||||||
|
// Also the player does not earn anything
|
||||||
|
if (fromOtherSleeve) {
|
||||||
|
if (exp.hack > 0) {
|
||||||
|
this.hacking_exp += exp.hack;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exp.str > 0) {
|
||||||
|
this.strength_exp += exp.str;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exp.def > 0) {
|
||||||
|
this.defense_exp += exp.def;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exp.dex > 0) {
|
||||||
|
this.dexterity_exp += exp.dex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exp.agi > 0) {
|
||||||
|
this.agility_exp += exp.agi;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exp.cha > 0) {
|
||||||
|
this.charisma_exp += exp.cha;
|
||||||
|
}
|
||||||
|
|
||||||
|
return createTaskTracker();
|
||||||
|
}
|
||||||
|
|
||||||
// Experience is first multiplied by shock. Then 'synchronization'
|
// Experience is first multiplied by shock. Then 'synchronization'
|
||||||
// is accounted for
|
// is accounted for
|
||||||
const multFac = (this.shock / 100) * (this.sync / 100) * numCycles;
|
const multFac = (this.shock / 100) * (this.sync / 100) * numCycles;
|
||||||
@ -696,6 +731,7 @@ export class Sleeve extends Person {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.gymStatType = stat;
|
||||||
this.currentTask = SleeveTaskType.Gym;
|
this.currentTask = SleeveTaskType.Gym;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -7,8 +7,10 @@ import { SleeveFaq } from "./data/SleeveFaq";
|
|||||||
|
|
||||||
import { IPlayer } from "../IPlayer";
|
import { IPlayer } from "../IPlayer";
|
||||||
|
|
||||||
|
import { CONSTANTS } from "../../Constants";
|
||||||
import { Locations } from "../../Locations";
|
import { Locations } from "../../Locations";
|
||||||
|
|
||||||
|
import { FactionWorkType } from "../../Faction/FactionWorkTypeEnum";
|
||||||
import { Cities } from "../../Locations/Cities";
|
import { Cities } from "../../Locations/Cities";
|
||||||
import { Crimes } from "../../Crime/Crimes";
|
import { Crimes } from "../../Crime/Crimes";
|
||||||
|
|
||||||
@ -23,9 +25,12 @@ import { exceptionAlert } from "../../../utils/helpers/exceptionAlert";
|
|||||||
|
|
||||||
import { createElement } from "../../../utils/uiHelpers/createElement";
|
import { createElement } from "../../../utils/uiHelpers/createElement";
|
||||||
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
|
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
|
||||||
|
import { createPopup } from "../../../utils/uiHelpers/createPopup";
|
||||||
|
import { createPopupCloseButton } from "../../../utils/uiHelpers/createPopupCloseButton";
|
||||||
import { getSelectValue } from "../../../utils/uiHelpers/getSelectData";
|
import { getSelectValue } from "../../../utils/uiHelpers/getSelectData";
|
||||||
import { removeChildrenFromElement } from "../../../utils/uiHelpers/removeChildrenFromElement";
|
import { removeChildrenFromElement } from "../../../utils/uiHelpers/removeChildrenFromElement";
|
||||||
import { removeElement } from "../../../utils/uiHelpers/removeElement";
|
import { removeElement } from "../../../utils/uiHelpers/removeElement";
|
||||||
|
import { removeElementById } from "../../../utils/uiHelpers/removeElementById";
|
||||||
|
|
||||||
// Object that keeps track of all DOM elements for the UI for a single Sleeve
|
// Object that keeps track of all DOM elements for the UI for a single Sleeve
|
||||||
interface ISleeveUIElems {
|
interface ISleeveUIElems {
|
||||||
@ -33,6 +38,7 @@ interface ISleeveUIElems {
|
|||||||
statsPanel: HTMLElement | null;
|
statsPanel: HTMLElement | null;
|
||||||
stats: HTMLElement | null;
|
stats: HTMLElement | null;
|
||||||
moreStatsButton: HTMLElement | null;
|
moreStatsButton: HTMLElement | null;
|
||||||
|
travelButton: HTMLElement | null;
|
||||||
taskPanel: HTMLElement | null;
|
taskPanel: HTMLElement | null;
|
||||||
taskSelector: HTMLSelectElement | null;
|
taskSelector: HTMLSelectElement | null;
|
||||||
taskDetailsSelector: HTMLSelectElement | null;
|
taskDetailsSelector: HTMLSelectElement | null;
|
||||||
@ -156,6 +162,7 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
|
|||||||
statsPanel: null,
|
statsPanel: null,
|
||||||
stats: null,
|
stats: null,
|
||||||
moreStatsButton: null,
|
moreStatsButton: null,
|
||||||
|
travelButton: null,
|
||||||
taskPanel: null,
|
taskPanel: null,
|
||||||
taskSelector: null,
|
taskSelector: null,
|
||||||
taskDetailsSelector: null,
|
taskDetailsSelector: null,
|
||||||
@ -212,8 +219,49 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
elems.travelButton = createElement("button", {
|
||||||
|
class: "std-button",
|
||||||
|
innerText: "Travel",
|
||||||
|
clickListener: () => {
|
||||||
|
const popupId: string = "sleeve-travel-popup";
|
||||||
|
const popupArguments: HTMLElement[] = [];
|
||||||
|
popupArguments.push(createPopupCloseButton(popupId, { class: "std-button" }));
|
||||||
|
popupArguments.push(createElement("p", {
|
||||||
|
innerText: "Have this sleeve travel to a different city. This affects " +
|
||||||
|
"the gyms and universities at which this sleeve can study. " +
|
||||||
|
`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) {
|
||||||
|
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],
|
||||||
|
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];
|
||||||
|
playerRef!.loseMoney(CONSTANTS.TravelCost);
|
||||||
|
sleeve.resetTaskStatus();
|
||||||
|
removeElementById(popupId);
|
||||||
|
updateSleeveUi(sleeve, elems);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
})(sleeve, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
createPopup(popupId, popupArguments);
|
||||||
|
}
|
||||||
|
})
|
||||||
elems.statsPanel.appendChild(elems.stats);
|
elems.statsPanel.appendChild(elems.stats);
|
||||||
elems.statsPanel.appendChild(elems.moreStatsButton);
|
elems.statsPanel.appendChild(elems.moreStatsButton);
|
||||||
|
elems.statsPanel.appendChild(elems.travelButton);
|
||||||
|
|
||||||
elems.taskPanel = createElement("div", { class: "sleeve-panel", width: "40%" });
|
elems.taskPanel = createElement("div", { class: "sleeve-panel", width: "40%" });
|
||||||
elems.taskSelector = createElement("select") as HTMLSelectElement;
|
elems.taskSelector = createElement("select") as HTMLSelectElement;
|
||||||
@ -225,13 +273,13 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
|
|||||||
elems.taskSelector.add(createOptionElement("Workout at Gym"));
|
elems.taskSelector.add(createOptionElement("Workout at Gym"));
|
||||||
elems.taskSelector.add(createOptionElement("Shock Recovery"));
|
elems.taskSelector.add(createOptionElement("Shock Recovery"));
|
||||||
elems.taskSelector.add(createOptionElement("Synchronize"));
|
elems.taskSelector.add(createOptionElement("Synchronize"));
|
||||||
elems.taskSelector.addEventListener("change", () => {
|
|
||||||
updateSleeveTaskSelector(sleeve, elems, allSleeves);
|
|
||||||
});
|
|
||||||
elems.taskDetailsSelector = createElement("select") as HTMLSelectElement;
|
elems.taskDetailsSelector = createElement("select") as HTMLSelectElement;
|
||||||
elems.taskDetailsSelector2 = createElement("select") as HTMLSelectElement;
|
elems.taskDetailsSelector2 = createElement("select") as HTMLSelectElement;
|
||||||
elems.taskDescription = createElement("p");
|
elems.taskDescription = createElement("p");
|
||||||
elems.taskProgressBar = createElement("p");
|
elems.taskProgressBar = createElement("p");
|
||||||
|
elems.taskSelector.addEventListener("change", () => {
|
||||||
|
updateSleeveTaskSelector(sleeve, elems, allSleeves);
|
||||||
|
});
|
||||||
elems.taskSelector.selectedIndex = sleeve.currentTask; // Set initial value for Task Selector
|
elems.taskSelector.selectedIndex = sleeve.currentTask; // Set initial value for Task Selector
|
||||||
elems.taskSelector.dispatchEvent(new Event('change'));
|
elems.taskSelector.dispatchEvent(new Event('change'));
|
||||||
updateSleeveTaskDescription(sleeve, elems);
|
updateSleeveTaskDescription(sleeve, elems);
|
||||||
@ -308,7 +356,8 @@ function updateSleeveUi(sleeve: Sleeve, elems: ISleeveUIElems) {
|
|||||||
`Dexterity: ${numeralWrapper.format(sleeve.dexterity, "0,0")}`,
|
`Dexterity: ${numeralWrapper.format(sleeve.dexterity, "0,0")}`,
|
||||||
`Agility: ${numeralWrapper.format(sleeve.agility, "0,0")}`,
|
`Agility: ${numeralWrapper.format(sleeve.agility, "0,0")}`,
|
||||||
`Charisma: ${numeralWrapper.format(sleeve.charisma, "0,0")}`,
|
`Charisma: ${numeralWrapper.format(sleeve.charisma, "0,0")}`,
|
||||||
`HP: ${numeralWrapper.format(sleeve.hp, "0,0")} / ${numeralWrapper.format(sleeve.max_hp, "0,0")}<br>`,
|
`HP: ${numeralWrapper.format(sleeve.hp, "0,0")} / ${numeralWrapper.format(sleeve.max_hp, "0,0")}`,
|
||||||
|
`City: ${sleeve.city}`,
|
||||||
`Shock: ${numeralWrapper.format(100 - sleeve.shock, "0,0.000")}`,
|
`Shock: ${numeralWrapper.format(100 - sleeve.shock, "0,0.000")}`,
|
||||||
`Sync: ${numeralWrapper.format(sleeve.sync, "0,0.000")}`].join("<br>");
|
`Sync: ${numeralWrapper.format(sleeve.sync, "0,0.000")}`].join("<br>");
|
||||||
|
|
||||||
@ -405,6 +454,7 @@ function updateSleeveTaskSelector(sleeve: Sleeve, elems: ISleeveUIElems, allSlee
|
|||||||
const value: string = getSelectValue(elems.taskSelector);
|
const value: string = getSelectValue(elems.taskSelector);
|
||||||
switch(value) {
|
switch(value) {
|
||||||
case "Work for Company":
|
case "Work for Company":
|
||||||
|
let companyCount: number = 0;
|
||||||
const allJobs: string[] = Object.keys(playerRef!.jobs!);
|
const allJobs: string[] = Object.keys(playerRef!.jobs!);
|
||||||
for (let i = 0; i < allJobs.length; ++i) {
|
for (let i = 0; i < allJobs.length; ++i) {
|
||||||
if (!forbiddenCompanies.includes(allJobs[i])) {
|
if (!forbiddenCompanies.includes(allJobs[i])) {
|
||||||
@ -412,14 +462,17 @@ function updateSleeveTaskSelector(sleeve: Sleeve, elems: ISleeveUIElems, allSlee
|
|||||||
|
|
||||||
// Set initial value of the 'Details' selector
|
// Set initial value of the 'Details' selector
|
||||||
if (sleeve.currentTaskLocation === allJobs[i]) {
|
if (sleeve.currentTaskLocation === allJobs[i]) {
|
||||||
elems.taskDetailsSelector!.selectedIndex = i;
|
elems.taskDetailsSelector!.selectedIndex = companyCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
++companyCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
elems.taskDetailsSelector2!.add(createOptionElement("------"));
|
elems.taskDetailsSelector2!.add(createOptionElement("------"));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "Work for Faction":
|
case "Work for Faction":
|
||||||
|
let factionCount: number = 0;
|
||||||
for (let i = 0; i < playerRef!.factions!.length; ++i) {
|
for (let i = 0; i < playerRef!.factions!.length; ++i) {
|
||||||
const fac: string = playerRef!.factions[i]!;
|
const fac: string = playerRef!.factions[i]!;
|
||||||
if (!forbiddenFactions.includes(fac)) {
|
if (!forbiddenFactions.includes(fac)) {
|
||||||
@ -427,13 +480,30 @@ function updateSleeveTaskSelector(sleeve: Sleeve, elems: ISleeveUIElems, allSlee
|
|||||||
|
|
||||||
// Set initial value of the 'Details' Selector
|
// Set initial value of the 'Details' Selector
|
||||||
if (sleeve.currentTaskLocation === fac) {
|
if (sleeve.currentTaskLocation === fac) {
|
||||||
elems.taskDetailsSelector!.selectedIndex = i;
|
elems.taskDetailsSelector!.selectedIndex = factionCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
++factionCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let i = 0; i < factionWorkTypeSelectorOptions.length; ++i) {
|
for (let i = 0; i < factionWorkTypeSelectorOptions.length; ++i) {
|
||||||
elems.taskDetailsSelector2!.add(createOptionElement(factionWorkTypeSelectorOptions[i]));
|
elems.taskDetailsSelector2!.add(createOptionElement(factionWorkTypeSelectorOptions[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set initial value for faction work type
|
||||||
|
switch (sleeve.factionWorkType) {
|
||||||
|
case FactionWorkType.Hacking:
|
||||||
|
elems.taskDetailsSelector2!.selectedIndex = 0;
|
||||||
|
break;
|
||||||
|
case FactionWorkType.Security:
|
||||||
|
elems.taskDetailsSelector2!.selectedIndex = 0;
|
||||||
|
break;
|
||||||
|
case FactionWorkType.Field:
|
||||||
|
elems.taskDetailsSelector2!.selectedIndex = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "Commit Crime":
|
case "Commit Crime":
|
||||||
for (const crimeLabel in Crimes) {
|
for (const crimeLabel in Crimes) {
|
||||||
@ -469,17 +539,37 @@ function updateSleeveTaskSelector(sleeve: Sleeve, elems: ISleeveUIElems, allSlee
|
|||||||
// First selector has what stat is being trained
|
// First selector has what stat is being trained
|
||||||
for (let i = 0; i < gymSelectorOptions.length; ++i) {
|
for (let i = 0; i < gymSelectorOptions.length; ++i) {
|
||||||
elems.taskDetailsSelector!.add(createOptionElement(gymSelectorOptions[i]));
|
elems.taskDetailsSelector!.add(createOptionElement(gymSelectorOptions[i]));
|
||||||
|
|
||||||
|
// Set initial value
|
||||||
|
if (sleeve.gymStatType === gymSelectorOptions[i]) {
|
||||||
|
elems.taskDetailsSelector!.selectedIndex = i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second selector has gym
|
// Second selector has gym
|
||||||
|
// In this switch statement we also set the initial value of the second selector
|
||||||
switch (sleeve.city) {
|
switch (sleeve.city) {
|
||||||
case Cities.Aevum:
|
case Cities.Aevum:
|
||||||
elems.taskDetailsSelector2!.add(createOptionElement(Locations.AevumCrushFitnessGym));
|
elems.taskDetailsSelector2!.add(createOptionElement(Locations.AevumCrushFitnessGym));
|
||||||
elems.taskDetailsSelector2!.add(createOptionElement(Locations.AevumSnapFitnessGym));
|
elems.taskDetailsSelector2!.add(createOptionElement(Locations.AevumSnapFitnessGym));
|
||||||
|
|
||||||
|
// Set initial value
|
||||||
|
if (sleeve.currentTaskLocation === Locations.AevumCrushFitnessGym) {
|
||||||
|
elems.taskDetailsSelector2!.selectedIndex = 0;
|
||||||
|
} else if (sleeve.currentTaskLocation === Locations.AevumSnapFitnessGym) {
|
||||||
|
elems.taskDetailsSelector2!.selectedIndex = 1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Cities.Sector12:
|
case Cities.Sector12:
|
||||||
elems.taskDetailsSelector2!.add(createOptionElement(Locations.Sector12IronGym));
|
elems.taskDetailsSelector2!.add(createOptionElement(Locations.Sector12IronGym));
|
||||||
elems.taskDetailsSelector2!.add(createOptionElement(Locations.Sector12PowerhouseGym));
|
elems.taskDetailsSelector2!.add(createOptionElement(Locations.Sector12PowerhouseGym));
|
||||||
|
|
||||||
|
// Set initial value
|
||||||
|
if (sleeve.currentTaskLocation === Locations.Sector12IronGym) {
|
||||||
|
elems.taskDetailsSelector2!.selectedIndex = 0;
|
||||||
|
} else if (sleeve.currentTaskLocation === Locations.Sector12PowerhouseGym) {
|
||||||
|
elems.taskDetailsSelector2!.selectedIndex = 1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Cities.Volhaven:
|
case Cities.Volhaven:
|
||||||
elems.taskDetailsSelector2!.add(createOptionElement(Locations.VolhavenMilleniumFitnessGym));
|
elems.taskDetailsSelector2!.add(createOptionElement(Locations.VolhavenMilleniumFitnessGym));
|
||||||
@ -552,6 +642,11 @@ function setSleeveTask(sleeve: Sleeve, elems: ISleeveUIElems): boolean {
|
|||||||
|
|
||||||
if (routing.isOn(Page.Sleeves)) {
|
if (routing.isOn(Page.Sleeves)) {
|
||||||
updateSleevesPage();
|
updateSleevesPage();
|
||||||
|
|
||||||
|
// Update the task selector for all sleeves by triggering a change event
|
||||||
|
for (const e of UIElems.sleeves!) {
|
||||||
|
e.taskSelector!.dispatchEvent(new Event('change'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -279,6 +279,12 @@ PlayerObject.prototype.prestigeAugmentation = function() {
|
|||||||
|
|
||||||
this.resleeves = [];
|
this.resleeves = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < this.sleeves.length; ++i) {
|
||||||
|
if (this.sleeves[i] instanceof Sleeve) {
|
||||||
|
this.sleeves[i].resetTaskStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.isWorking = false;
|
this.isWorking = false;
|
||||||
this.currentWorkFactionName = "";
|
this.currentWorkFactionName = "";
|
||||||
this.currentWorkFactionDescription = "";
|
this.currentWorkFactionDescription = "";
|
||||||
|
@ -483,8 +483,11 @@ async function parseOnlyRamCalculate(server, code, workerScript) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const script = server.getScript(nextModule);
|
const script = server.getScript(nextModule.startsWith("./") ? nextModule.slice(2) : nextModule);
|
||||||
if (!script) return -1; // No such script on the server.
|
if (!script) {
|
||||||
|
console.warn("Invalid script");
|
||||||
|
return -1; // No such script on the server.
|
||||||
|
}
|
||||||
code = script.code;
|
code = script.code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,6 +78,13 @@ export class Stock {
|
|||||||
*/
|
*/
|
||||||
readonly symbol: string;
|
readonly symbol: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Total number of shares of this stock
|
||||||
|
* This is different than maxShares, as this is like authorized stock while
|
||||||
|
* maxShares is outstanding stock.
|
||||||
|
*/
|
||||||
|
readonly totalShares: number;
|
||||||
|
|
||||||
constructor(name: string = "",
|
constructor(name: string = "",
|
||||||
symbol: string = "",
|
symbol: string = "",
|
||||||
mv: number = 1,
|
mv: number = 1,
|
||||||
@ -97,9 +104,13 @@ export class Stock {
|
|||||||
this.otlkMag = otlkMag;
|
this.otlkMag = otlkMag;
|
||||||
this.cap = getRandomInt(initPrice * 1e3, initPrice * 25e3);
|
this.cap = getRandomInt(initPrice * 1e3, initPrice * 25e3);
|
||||||
|
|
||||||
// Maximum shares is determined by market cap, and is rounded to nearest millions
|
// Total shares is determined by market cap, and is rounded to nearest millions
|
||||||
let maxSharesUnrounded: number = (marketCap / initPrice);
|
let totalSharesUnrounded: number = (marketCap / initPrice);
|
||||||
this.maxShares = Math.round(maxSharesUnrounded / 1e6) * 1e6;
|
this.totalShares = Math.round(totalSharesUnrounded / 1e6) * 1e6;
|
||||||
|
|
||||||
|
// Max Shares (Outstanding shares) is a percentage of total shares
|
||||||
|
const outstandingSharePercentage: number = 0.25;
|
||||||
|
this.maxShares = Math.round((this.totalShares * outstandingSharePercentage) / 1e6) * 1e6;
|
||||||
|
|
||||||
this.posTxtEl = null;
|
this.posTxtEl = null;
|
||||||
}
|
}
|
||||||
|
@ -278,7 +278,7 @@ function initStockMarket() {
|
|||||||
StockMarket[vitalife] = vitalifeStk;
|
StockMarket[vitalife] = vitalifeStk;
|
||||||
|
|
||||||
var icarus = Locations.Sector12IcarusMicrosystems;
|
var icarus = Locations.Sector12IcarusMicrosystems;
|
||||||
var icarusStk = new Stock(icarus, StockSymbols[icarus], randInt(60, 70)/100, true, 7.5, randInt(12e3, 24e3), 800e12);
|
var icarusStk = new Stock(icarus, StockSymbols[icarus], randInt(60, 70)/100, true, 7.5, randInt(12e3, 24e3), 800e9);
|
||||||
StockMarket[icarus] = icarusStk;
|
StockMarket[icarus] = icarusStk;
|
||||||
|
|
||||||
var universalenergy = Locations.Sector12UniversalEnergy;
|
var universalenergy = Locations.Sector12UniversalEnergy;
|
||||||
|
@ -969,7 +969,7 @@ const Engine = {
|
|||||||
if (expForOtherSleeves == null) { continue; }
|
if (expForOtherSleeves == null) { continue; }
|
||||||
for (let j = 0; j < Player.sleeves.length; ++j) {
|
for (let j = 0; j < Player.sleeves.length; ++j) {
|
||||||
if (j === i) { continue; }
|
if (j === i) { continue; }
|
||||||
Player.sleeves[j].gainExperience(Player, expForOtherSleeves, numCycles);
|
Player.sleeves[j].gainExperience(Player, expForOtherSleeves, numCycles, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1336,7 +1336,7 @@ const Engine = {
|
|||||||
if (expForOtherSleeves == null) { continue; }
|
if (expForOtherSleeves == null) { continue; }
|
||||||
for (let j = 0; j < Player.sleeves.length; ++j) {
|
for (let j = 0; j < Player.sleeves.length; ++j) {
|
||||||
if (j === i) { continue; }
|
if (j === i) { continue; }
|
||||||
Player.sleeves[j].gainExperience(Player, expForOtherSleeves, numCyclesOffline);
|
Player.sleeves[j].gainExperience(Player, expForOtherSleeves, numCyclesOffline, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
export function getSelectValue(selector: HTMLSelectElement | null): string {
|
export function getSelectValue(selector: HTMLSelectElement | null): string {
|
||||||
if (selector == null) { return ""; }
|
if (selector == null) { return ""; }
|
||||||
if (selector.options.length <= 0) { return ""; }
|
if (selector.options.length <= 0) { return ""; }
|
||||||
|
if (selector.selectedIndex < 0) { return ""; }
|
||||||
return selector.options[selector.selectedIndex].value;
|
return selector.options[selector.selectedIndex].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSelectText(selector: HTMLSelectElement | null): string {
|
export function getSelectText(selector: HTMLSelectElement | null): string {
|
||||||
if (selector == null) { return ""; }
|
if (selector == null) { return ""; }
|
||||||
if (selector.options.length <= 0) { return ""; }
|
if (selector.options.length <= 0) { return ""; }
|
||||||
|
if (selector.selectedIndex < 0) { return ""; }
|
||||||
return selector.options[selector.selectedIndex].text;
|
return selector.options[selector.selectedIndex].text;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user