Added BitNode multipliers for purchased servers. Fixed bugs in new Script Editor implementation. Added documentation for script editors

This commit is contained in:
danielyxie
2019-01-29 22:02:27 -08:00
parent d54f0906f0
commit a09ea46a38
31 changed files with 3355 additions and 2558 deletions
+40 -17
View File
@@ -16,6 +16,7 @@ import { Person,
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
import { Crime } from "../../Crime/Crime";
import { Crimes } from "../../Crime/Crimes";
import { Cities } from "../../Locations/Cities";
@@ -42,6 +43,12 @@ export class Sleeve extends Person {
return Generic_fromJSON(Sleeve, value.data);
}
/**
* Stores the type of crime the sleeve is currently attempting
* Must match the name of a Crime object
*/
crimeType: string = "";
/**
* Enum value for current task
*/
@@ -136,8 +143,10 @@ export class Sleeve extends Person {
/**
* Commit crimes
*/
commitCrime(p: IPlayer, crime: Crime): boolean {
commitCrime(p: IPlayer, crimeKey: string): boolean {
const crime: Crime | null = Crimes[crimeKey];
if (!(crime instanceof Crime)) { return false; }
if (this.currentTask !== SleeveTaskType.Idle) {
this.finishTask(p);
} else {
@@ -154,19 +163,7 @@ export class Sleeve extends Person {
this.currentTaskLocation = String(this.gainRatesForTask.money);
// We'll determine success now and adjust the earnings accordingly
if (Math.random() < crime.successRate(p)) {
this.gainRatesForTask.hack *= 2;
this.gainRatesForTask.str *= 2;
this.gainRatesForTask.def *= 2;
this.gainRatesForTask.dex *= 2;
this.gainRatesForTask.agi *= 2;
this.gainRatesForTask.cha *= 2;
} else {
this.gainRatesForTask.money = 0;
}
this.crimeType = crimeKey;
this.currentTaskMaxTime = crime.time;
this.currentTask = SleeveTaskType.Crime;
return true;
@@ -181,8 +178,26 @@ export class Sleeve extends Person {
if (this.currentTask === SleeveTaskType.Crime) {
// For crimes, all experience and money is gained at the end
if (this.currentTaskTime >= this.currentTaskMaxTime) {
retValue = this.gainExperience(p, this.gainRatesForTask);
this.gainMoney(p, this.gainRatesForTask);
const crime: Crime | null = Crimes[this.crimeType];
if (!(crime instanceof Crime)) {
console.error(`Invalid data stored in sleeve.crimeType: ${this.crimeType}`);
this.resetTaskStatus();
return retValue;
}
if (Math.random() < crime.successRate(p)) {
// Success
const successGainRates: ITaskTracker = createTaskTracker();
const keysForIteration: (keyof ITaskTracker)[] = (<(keyof ITaskTracker)[]>Object.keys(successGainRates));
for (let i = 0; i < keysForIteration.length; ++i) {
const key = keysForIteration[i];
successGainRates[key] = this.gainRatesForTask[key] * 2;
}
retValue = this.gainExperience(p, successGainRates);
this.gainMoney(p, this.gainRatesForTask);
} else {
retValue = this.gainExperience(p, this.gainRatesForTask);
}
// Do not reset task to IDLE
this.currentTaskTime = 0;
@@ -261,7 +276,7 @@ export class Sleeve extends Person {
this.defense_exp += pDefExp;
p.gainDefenseExp(pDefExp);
this.earningsForPlayer.def += pDefExp;
this.earningsForTask.dex += pDefExp;
this.earningsForTask.def += pDefExp;
}
if (pDexExp > 0) {
@@ -464,6 +479,9 @@ export class Sleeve extends Person {
this.currentTaskTime = 0;
this.currentTaskMaxTime = 0;
this.factionWorkType = FactionWorkType.None;
this.crimeType = "";
this.currentTaskLocation = "";
this.gymStatType = "";
}
/**
@@ -630,12 +648,16 @@ export class Sleeve extends Person {
this.resetTaskStatus();
}
const factionInfo = Factions[factionName].getInfo();
// Set type of work (hacking/field/security), and the experience gains
const sanitizedWorkType: string = workType.toLowerCase();
if (sanitizedWorkType.includes("hack")) {
if (!factionInfo.offerHackingWork) { return false; }
this.factionWorkType = FactionWorkType.Hacking;
this.gainRatesForTask.hack = .15 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
} else if (sanitizedWorkType.includes("field")) {
if (!factionInfo.offerFieldWork) { return false; }
this.factionWorkType = FactionWorkType.Field;
this.gainRatesForTask.hack = .1 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.str = .1 * this.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
@@ -644,6 +666,7 @@ export class Sleeve extends Person {
this.gainRatesForTask.agi = .1 * this.agility_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.cha = .1 * this.charisma_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
} else if (sanitizedWorkType.includes("security")) {
if (!factionInfo.offerSecurityWork) { return false; }
this.factionWorkType = FactionWorkType.Security;
this.gainRatesForTask.hack = .1 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.gainRatesForTask.str = .15 * this.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
+66 -32
View File
@@ -10,8 +10,12 @@ 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 { numeralWrapper } from "../../ui/numeralFormat";
@@ -23,6 +27,7 @@ import { dialogBoxCreate } from "../../../utils/DialogBox";
import { createProgressBarText } from "../../../utils/helpers/createProgressBarText";
import { exceptionAlert } from "../../../utils/helpers/exceptionAlert";
import { clearEventListeners } from "../../../utils/uiHelpers/clearEventListeners";
import { createElement } from "../../../utils/uiHelpers/createElement";
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
import { createPopup } from "../../../utils/uiHelpers/createPopup";
@@ -229,7 +234,7 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
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)}.` +
`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) {
@@ -250,6 +255,7 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
sleeve.resetTaskStatus();
removeElementById(popupId);
updateSleeveUi(sleeve, elems);
updateSleeveTaskSelector(sleeve, elems, allSleeves);
return false;
}
}));
@@ -401,12 +407,6 @@ function updateSleeveUi(sleeve: Sleeve, elems: ISleeveUIElems) {
}
}
const factionWorkTypeSelectorOptions: string[] = [
"Hacking Contracts",
"Security Work",
"Field Work"
];
const universitySelectorOptions: string[] = [
"Study Computer Science",
"Data Structures",
@@ -450,6 +450,7 @@ function updateSleeveTaskSelector(sleeve: Sleeve, elems: ISleeveUIElems, allSlee
// Reset Selectors
removeChildrenFromElement(elems.taskDetailsSelector);
removeChildrenFromElement(elems.taskDetailsSelector2);
elems.taskDetailsSelector2 = clearEventListeners(elems.taskDetailsSelector2!) as HTMLSelectElement;
const value: string = getSelectValue(elems.taskSelector);
switch(value) {
@@ -486,29 +487,57 @@ function updateSleeveTaskSelector(sleeve: Sleeve, elems: ISleeveUIElems, allSlee
++factionCount;
}
}
for (let i = 0; i < factionWorkTypeSelectorOptions.length; ++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;
}
// The available faction work types depends on the faction
elems.taskDetailsSelector!.addEventListener("change", () => {
const facName = getSelectValue(elems.taskDetailsSelector!);
const faction: Faction | null = Factions[facName];
if (faction == null) {
console.warn(`Invalid faction name when trying to update Sleeve Task Selector: ${facName}`);
return;
}
const facInfo = faction.getInfo();
removeChildrenFromElement(elems.taskDetailsSelector2!);
let numOptionsAdded = 0;
if (facInfo.offerHackingWork) {
elems.taskDetailsSelector2!.add(createOptionElement("Hacking Contracts"));
if (sleeve.factionWorkType === FactionWorkType.Hacking) {
elems.taskDetailsSelector2!.selectedIndex = numOptionsAdded;
}
++numOptionsAdded;
}
if (facInfo.offerFieldWork) {
elems.taskDetailsSelector2!.add(createOptionElement("Field Work"));
if (sleeve.factionWorkType === FactionWorkType.Field) {
elems.taskDetailsSelector2!.selectedIndex = numOptionsAdded;
}
++numOptionsAdded;
}
if (facInfo.offerSecurityWork) {
elems.taskDetailsSelector2!.add(createOptionElement("Security Work"));
if (sleeve.factionWorkType === FactionWorkType.Security) {
elems.taskDetailsSelector2!.selectedIndex = numOptionsAdded;
}
++numOptionsAdded;
}
});
elems.taskDetailsSelector!.dispatchEvent(new Event("change"));
break;
case "Commit Crime":
let i = 0;
for (const crimeLabel in Crimes) {
const name: string = Crimes[crimeLabel].name;
elems.taskDetailsSelector!.add(createOptionElement(name, crimeLabel));
// Set initial value for crime type
if (sleeve.crimeType === "") { continue; }
const crime: Crime | null = Crimes[sleeve.crimeType];
if (crime == null) { continue; }
if (name === crime!.name) {
elems.taskDetailsSelector!.selectedIndex = i;
}
++i;
}
elems.taskDetailsSelector2!.add(createOptionElement("------"));
@@ -614,7 +643,7 @@ function setSleeveTask(sleeve: Sleeve, elems: ISleeveUIElems): boolean {
res = sleeve.workForFaction(playerRef!, detailValue, detailValue2);
break;
case "Commit Crime":
res = sleeve.commitCrime(playerRef!, Crimes[detailValue]);
res = sleeve.commitCrime(playerRef!, detailValue);
break;
case "Take University Course":
res = sleeve.takeUniversityCourse(playerRef!, detailValue2, detailValue);
@@ -637,7 +666,15 @@ function setSleeveTask(sleeve: Sleeve, elems: ISleeveUIElems): boolean {
if (res) {
updateSleeveTaskDescription(sleeve, elems);
} else {
elems.taskDescription!.innerText = "Failed to assign sleeve to task. Invalid choice(s).";
switch (taskValue) {
case "Work for Faction":
elems.taskDescription!.innerText = "Failed to assign sleeve to task. This is most likely because the selected faction does not offer the selected work type.";
break;
default:
elems.taskDescription!.innerText = "Failed to assign sleeve to task. Invalid choice(s).";
break;
}
}
if (routing.isOn(Page.Sleeves)) {
@@ -672,16 +709,13 @@ function updateSleeveTaskDescription(sleeve: Sleeve, elems: ISleeveUIElems): voi
elems.taskDescription!.innerText = "This sleeve is currently idle";
break;
case "Work for Company":
elems.taskDescription!.innerText = `This sleeve is currently working your ` +
`job at ${sleeve.currentTaskLocation}.`;
elems.taskDescription!.innerText = `This sleeve is currently working your job at ${sleeve.currentTaskLocation}.`;
break;
case "Work for Faction":
elems.taskDescription!.innerText = `This sleeve is currently doing ${detailValue2} for ` +
`${sleeve.currentTaskLocation}.`;
elems.taskDescription!.innerText = `This sleeve is currently doing ${detailValue2} for ${sleeve.currentTaskLocation}.`;
break;
case "Commit Crime":
elems.taskDescription!.innerText = `This sleeve is currently attempting to ` +
`${Crimes[detailValue].type}.`;
elems.taskDescription!.innerText = `This sleeve is currently attempting to ${Crimes[detailValue].type} (Success Rate: ${numeralWrapper.formatPercentage(Crimes[detailValue].successRate(playerRef))}).`;
break;
case "Take University Course":
elems.taskDescription!.innerText = `This sleeve is currently studying/taking a course at ${sleeve.currentTaskLocation}.`;