mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-18 12:15:44 +01:00
v0.51.2 (#838)
* infiltration use buttons instead of a links * minor accessibility patch * Hospitalization will not cost more than 10% of the players money. * Adde hospitalization netscript function * Removed the suggestion that the combat path will lead to Daedalus, it still will. But new players should not be told that this is a viable path to completing a BitNode. * getMemberInformation now returns everything about the member. * New netscript function to get the players hacknet server hash capacity * yesno dialog box will not keep older messages anymore * v0.51.1 * Casino part 1 * Discord link in options, documentation for getMemberInformation updated, dev menu has more money options, tech vendors now handle max cores or max ram better * Removed text under Factiosn referencing rejected factions. * Removed html element forgotten in plain text * Casino implementation * v0.51.2
This commit is contained in:
parent
db2bf79e3b
commit
925e96345d
4
dist/engine.bundle.js
vendored
4
dist/engine.bundle.js
vendored
File diff suppressed because one or more lines are too long
2
dist/engineStyle.bundle.js
vendored
2
dist/engineStyle.bundle.js
vendored
@ -1,2 +1,2 @@
|
||||
!function(n){function t(t){for(var e,i,f=t[0],c=t[1],l=t[2],p=0,s=[];p<f.length;p++)i=f[p],u[i]&&s.push(u[i][0]),u[i]=0;for(e in c)Object.prototype.hasOwnProperty.call(c,e)&&(n[e]=c[e]);for(a&&a(t);s.length;)s.shift()();return r.push.apply(r,l||[]),o()}function o(){for(var n,t=0;t<r.length;t++){for(var o=r[t],e=!0,f=1;f<o.length;f++){var c=o[f];0!==u[c]&&(e=!1)}e&&(r.splice(t--,1),n=i(i.s=o[0]))}return n}var e={},u={1:0},r=[];function i(t){if(e[t])return e[t].exports;var o=e[t]={i:t,l:!1,exports:{}};return n[t].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=n,i.c=e,i.d=function(n,t,o){i.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:o})},i.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,t){if(1&t&&(n=i(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var e in n)i.d(o,e,function(t){return n[t]}.bind(null,e));return o},i.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(t,"a",t),t},i.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},i.p="";var f=window.webpackJsonp=window.webpackJsonp||[],c=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var a=c;r.push([396,0]),o()}({339:function(n,t,o){},341:function(n,t,o){},343:function(n,t,o){},345:function(n,t,o){},347:function(n,t,o){},349:function(n,t,o){},351:function(n,t,o){},353:function(n,t,o){},355:function(n,t,o){},357:function(n,t,o){},359:function(n,t,o){},361:function(n,t,o){},363:function(n,t,o){},365:function(n,t,o){},367:function(n,t,o){},369:function(n,t,o){},371:function(n,t,o){},373:function(n,t,o){},375:function(n,t,o){},377:function(n,t,o){},379:function(n,t,o){},381:function(n,t,o){},383:function(n,t,o){},385:function(n,t,o){},387:function(n,t,o){},389:function(n,t,o){},391:function(n,t,o){},393:function(n,t,o){},396:function(n,t,o){"use strict";o.r(t);o(395),o(393),o(391),o(389),o(387),o(385),o(383),o(381),o(379),o(377),o(375),o(373),o(371),o(369),o(367),o(365),o(363),o(361),o(359),o(357),o(355),o(353),o(351),o(349),o(347),o(345),o(343),o(341),o(339)}});
|
||||
!function(n){function t(t){for(var e,i,f=t[0],c=t[1],l=t[2],p=0,s=[];p<f.length;p++)i=f[p],u[i]&&s.push(u[i][0]),u[i]=0;for(e in c)Object.prototype.hasOwnProperty.call(c,e)&&(n[e]=c[e]);for(a&&a(t);s.length;)s.shift()();return r.push.apply(r,l||[]),o()}function o(){for(var n,t=0;t<r.length;t++){for(var o=r[t],e=!0,f=1;f<o.length;f++){var c=o[f];0!==u[c]&&(e=!1)}e&&(r.splice(t--,1),n=i(i.s=o[0]))}return n}var e={},u={1:0},r=[];function i(t){if(e[t])return e[t].exports;var o=e[t]={i:t,l:!1,exports:{}};return n[t].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=n,i.c=e,i.d=function(n,t,o){i.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:o})},i.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,t){if(1&t&&(n=i(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var e in n)i.d(o,e,function(t){return n[t]}.bind(null,e));return o},i.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(t,"a",t),t},i.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},i.p="";var f=window.webpackJsonp=window.webpackJsonp||[],c=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var a=c;r.push([398,0]),o()}({341:function(n,t,o){},343:function(n,t,o){},345:function(n,t,o){},347:function(n,t,o){},349:function(n,t,o){},351:function(n,t,o){},353:function(n,t,o){},355:function(n,t,o){},357:function(n,t,o){},359:function(n,t,o){},361:function(n,t,o){},363:function(n,t,o){},365:function(n,t,o){},367:function(n,t,o){},369:function(n,t,o){},371:function(n,t,o){},373:function(n,t,o){},375:function(n,t,o){},377:function(n,t,o){},379:function(n,t,o){},381:function(n,t,o){},383:function(n,t,o){},385:function(n,t,o){},387:function(n,t,o){},389:function(n,t,o){},391:function(n,t,o){},393:function(n,t,o){},395:function(n,t,o){},398:function(n,t,o){"use strict";o.r(t);o(397),o(395),o(393),o(391),o(389),o(387),o(385),o(383),o(381),o(379),o(377),o(375),o(373),o(371),o(369),o(367),o(365),o(363),o(361),o(359),o(357),o(355),o(353),o(351),o(349),o(347),o(345),o(343),o(341)}});
|
||||
//# sourceMappingURL=engineStyle.bundle.js.map
|
26
dist/vendor.bundle.js
vendored
26
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
@ -3,22 +3,40 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
v0.51.2 - 2021-04-09 Vegas, Baby! (hydroflame)
|
||||
----------------------------------------------
|
||||
|
||||
**New location: The Iker Molina Casino**
|
||||
|
||||
* A casino opened in Aevum. However the house is rumored to cheat. If only
|
||||
we could give them a taste of their own medicine.
|
||||
|
||||
**Misc.**
|
||||
|
||||
* Link to discord added under options
|
||||
* 'getMemberInformation' doc updated, oops
|
||||
* tech vendor now handle max ram and cores.
|
||||
|
||||
v0.51.1 - 2021-04-06 Bugfixes because the author of the last patch sucks (it's hydroflame)
|
||||
------------------------------------------------------------------------------------------
|
||||
|
||||
**Netscript**
|
||||
|
||||
* 'getPlayer' returns players faction and tor
|
||||
* 'hospitalization' is a new singularity function.
|
||||
* 'gang.getMemberInformation' now returns more information.
|
||||
* 'hacknet.hashCapacity' is a new hacknet function that returns the maximum hash capacity.
|
||||
|
||||
**Hospitalization**
|
||||
|
||||
* Now only cost at most 10% of your money.
|
||||
|
||||
**Bugfix**
|
||||
|
||||
* confirmation dialog box no longer use previous text
|
||||
|
||||
**Accessibility**
|
||||
|
||||
* The game is a little easier to handle for screen readers (yes, there's an
|
||||
absolute legend playing this game with a screen reader)
|
||||
* Infiltration use buttons instead of a-links
|
||||
@ -26,6 +44,7 @@ v0.51.1 - 2021-04-06 Bugfixes because the author of the last patch sucks (it's h
|
||||
map display as a list of buttons.
|
||||
|
||||
**Misc.**
|
||||
|
||||
* 'fl1ght.exe' will no longer suggest the combat path. Related faction
|
||||
requirements unchanged.
|
||||
|
||||
|
@ -66,7 +66,7 @@ documentation_title = '{0} Documentation'.format(project)
|
||||
# The short X.Y version.
|
||||
version = '0.51'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.51.1'
|
||||
release = '0.51.2'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
@ -5,7 +5,7 @@ calculateExp() Netscript Function
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param number skillLevel: ``skillLevel`` to convert to exp.
|
||||
:param number mult: Assume a specific skill multipler.
|
||||
:param number mult: Assume a specific skill multipler (not exp multiplier).
|
||||
:returns: number of exp required to reach given ``skillLevel`` with that multiplier.
|
||||
|
||||
You must have Source-File 5-1 in order to use this function.
|
||||
|
@ -5,7 +5,7 @@ calculateSkill() Netscript Function
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param number exp: ``exp`` to convert to skillLevel.
|
||||
:param number mult: Assume a specific skill multipler.
|
||||
:param number mult: Assume a specific skill multipler (not exp multiplier).
|
||||
:returns: skillLevel that ``exp`` would reach with that multiplier.
|
||||
|
||||
You must have Source-File 5-1 in order to use this function.
|
||||
|
@ -10,27 +10,35 @@ getMemberInformation() Netscript Function
|
||||
The object has the following structure::
|
||||
|
||||
{
|
||||
agility: Agility stat
|
||||
agilityEquipMult: Agility multiplier from equipment. Decimal form
|
||||
agilityAscensionMult: Agility multiplier from ascension. Decimal form
|
||||
augmentations: Array of names of all owned Augmentations
|
||||
charisma: Charisma stat
|
||||
charismaEquipMult: Charisma multiplier from equipment. Decimal form
|
||||
charismaAscensionMult: Charisma multiplier from ascension. Decimal form
|
||||
defense: Defense stat
|
||||
defenseEquipMult: Defense multiplier from equipment. Decimal form
|
||||
defenseAscensionMult: Defense multiplier from ascension. Decimal form
|
||||
dexterity: Dexterity stat
|
||||
dexterityEquipMult: Dexterity multiplier from equipment. Decimal form
|
||||
dexterityAscensionMult: Dexterity multiplier from ascension. Decimal form
|
||||
equipment: Array of names of all owned Non-Augmentation Equipment
|
||||
hacking: Hacking stat
|
||||
hackingEquipMult: Hacking multiplier from equipment. Decimal form
|
||||
hackingAscensionMult: Hacking multiplier from ascension. Decimal form
|
||||
strength: Strength stat
|
||||
strengthEquipMult: Strength multiplier from equipment. Decimal form
|
||||
strengthAscensionMult: Strength multiplier from ascension. Decimal form
|
||||
task: Name of currently assigned task
|
||||
name: Name of this member.
|
||||
task: Name of currently assigned task.
|
||||
earnedRespect: Total amount of respect earned by this member.
|
||||
hack: Hacking stat
|
||||
str: Strength stat
|
||||
def: Defense stat
|
||||
dex: Dexterity stat
|
||||
agi: Agility stat
|
||||
cha: Charisma stat
|
||||
hack_exp: Hacking experience
|
||||
str_exp: Strength experience
|
||||
def_exp: Defense experience
|
||||
dex_exp: Dexterity experience
|
||||
agi_exp: Agility experience
|
||||
cha_exp: Charisma experience
|
||||
hack_mult: Hacking multiplier from equipment. Decimal form
|
||||
str_mult: Strength multiplier from equipment. Decimal form
|
||||
def_mult: Defense multiplier from equipment. Decimal form
|
||||
dex_mult: Dexterity multiplier from equipment. Decimal form
|
||||
agi_mult: Agility multiplier from equipment. Decimal form
|
||||
cha_mult: Charisma multiplier from equipment. Decimal form
|
||||
hack_asc_mult: Hacking multiplier from ascension. Decimal form
|
||||
str_asc_mult: Strength multiplier from ascension. Decimal form
|
||||
def_asc_mult: Defense multiplier from ascension. Decimal form
|
||||
dex_asc_mult: Dexterity multiplier from ascension. Decimal form
|
||||
agi_asc_mult: Agility multiplier from ascension. Decimal form
|
||||
cha_asc_mult: Charisma multiplier from ascension. Decimal form
|
||||
upgrades: Array of names of all owned Non-Augmentation Equipment
|
||||
augmentations: Array of names of all owned Augmentations
|
||||
}
|
||||
|
||||
Get stat and equipment-related information about a Gang Member
|
@ -559,6 +559,7 @@
|
||||
<div id="game-options-right-panel">
|
||||
<a class="a-link-button" href="https://bitburner.readthedocs.io/en/latest/changelog.html" target="_blank"> Changelog </a>
|
||||
<a class="a-link-button" href="https://bitburner.readthedocs.io/en/latest/index.html" target="_blank">Documentation</a>
|
||||
<a class="a-link-button" href="https://discord.gg/TFc3hKD" target="_blank">Discord</a>
|
||||
<a class="a-link-button" href="https://www.reddit.com/r/bitburner" target="_blank">Subreddit</a>
|
||||
<button id="save-game-link" class="a-link-button"> Save Game </button>
|
||||
<button id="delete-game-link" class="a-link-button"> Delete Game </button>
|
||||
|
89
src/Casino/CoinFlip.tsx
Normal file
89
src/Casino/CoinFlip.tsx
Normal file
@ -0,0 +1,89 @@
|
||||
/**
|
||||
* 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 { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { StdButton } from "../ui/React/StdButton";
|
||||
import { BadRNG } from "./RNG";
|
||||
import { Game } from "./Game";
|
||||
|
||||
type IProps = {
|
||||
p: IPlayer;
|
||||
}
|
||||
|
||||
type IState = {
|
||||
investment: number;
|
||||
result: any;
|
||||
status: string;
|
||||
}
|
||||
|
||||
const maxPlay = 10e3;
|
||||
|
||||
export class CoinFlip extends Game<IProps, IState> {
|
||||
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
investment: 1000,
|
||||
result: <span> </span>,
|
||||
status: '',
|
||||
};
|
||||
|
||||
this.play = this.play.bind(this);
|
||||
this.updateInvestment = this.updateInvestment.bind(this);
|
||||
}
|
||||
|
||||
updateInvestment(e: React.FormEvent<HTMLInputElement>) {
|
||||
let investment: number = parseInt(e.currentTarget.value);
|
||||
if (isNaN(investment)) {
|
||||
investment = 1000;
|
||||
}
|
||||
if (investment > maxPlay) {
|
||||
investment = maxPlay;
|
||||
}
|
||||
this.setState({investment: investment});
|
||||
}
|
||||
|
||||
play(guess: string) {
|
||||
if(this.reachedLimit(this.props.p)) return;
|
||||
const v = BadRNG.random();
|
||||
let letter: string;
|
||||
if (v < 0.5) {
|
||||
letter = 'H';
|
||||
} else {
|
||||
letter = 'T';
|
||||
}
|
||||
const correct: boolean = guess===letter;
|
||||
this.setState({
|
||||
result: <span className={correct ? "text" : "failure"}>{letter}</span>,
|
||||
status: correct ? " win!" : "lose!",
|
||||
});
|
||||
if (correct) {
|
||||
this.win(this.props.p, this.state.investment);
|
||||
} else {
|
||||
this.win(this.props.p, -this.state.investment);
|
||||
}
|
||||
if(this.reachedLimit(this.props.p)) return;
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
return <>
|
||||
<pre>
|
||||
+———————+<br />
|
||||
| | | |<br />
|
||||
| | {this.state.result} | |<br />
|
||||
| | | |<br />
|
||||
+———————+<br />
|
||||
</pre>
|
||||
<span className="text">Play for: </span><input type="number" className='text-input' onChange={this.updateInvestment} value={this.state.investment} /><br />
|
||||
<StdButton onClick={() => this.play('H')} text={"Head!"} />
|
||||
<StdButton onClick={() => this.play('T')} text={"Tail!"} />
|
||||
<h1>{this.state.status}</h1>
|
||||
</>
|
||||
}
|
||||
}
|
20
src/Casino/Game.tsx
Normal file
20
src/Casino/Game.tsx
Normal file
@ -0,0 +1,20 @@
|
||||
import * as React from "react";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { dialogBoxCreate } from "../../utils/DialogBox";
|
||||
|
||||
const gainLimit = 10e9;
|
||||
|
||||
export class Game<T,U> extends React.Component<T, U> {
|
||||
win(p: IPlayer, n: number) {
|
||||
p.gainMoney(n);
|
||||
p.recordMoneySource(n, "casino");
|
||||
}
|
||||
|
||||
reachedLimit(p: IPlayer): boolean {
|
||||
const reached = p.getCasinoWinnings() > gainLimit;
|
||||
if(reached) {
|
||||
dialogBoxCreate(<>Alright cheater get out of here. You're not allowed here anymore.</>);
|
||||
}
|
||||
return reached;
|
||||
}
|
||||
}
|
64
src/Casino/RNG.ts
Normal file
64
src/Casino/RNG.ts
Normal file
@ -0,0 +1,64 @@
|
||||
|
||||
export interface RNG {
|
||||
random(): number
|
||||
}
|
||||
|
||||
/*
|
||||
* very bad RNG, meant to be used as introduction to RNG manipulation. It has a
|
||||
* period of 1024.
|
||||
*/
|
||||
class RNG0 implements RNG {
|
||||
x: number;
|
||||
m: number = 1024;
|
||||
a: number = 341;
|
||||
c: number = 1;
|
||||
|
||||
constructor() {
|
||||
this.x = 0;
|
||||
this.reset();
|
||||
}
|
||||
|
||||
step() {
|
||||
this.x = (this.a*this.x+this.c) % this.m;
|
||||
}
|
||||
|
||||
random(): number {
|
||||
this.step();
|
||||
return this.x/this.m;
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.x = (new Date()).getTime() % this.m;
|
||||
}
|
||||
}
|
||||
|
||||
export const BadRNG: RNG0 = new RNG0();
|
||||
|
||||
/*
|
||||
* Wichmann–Hill PRNG
|
||||
* The period is 6e12.
|
||||
*/
|
||||
export class WHRNG implements RNG {
|
||||
s1: number = 0;
|
||||
s2: number = 0;
|
||||
s3: number = 0;
|
||||
|
||||
constructor(totalPlaytime: number) {
|
||||
// This one is seeded by the players total play time.
|
||||
const v: number = (totalPlaytime/1000)%30000;
|
||||
this.s1 = v;
|
||||
this.s2 = v;
|
||||
this.s3 = v;
|
||||
}
|
||||
|
||||
step() {
|
||||
this.s1 = (171 * this.s1) % 30269;
|
||||
this.s2 = (172 * this.s2) % 30307;
|
||||
this.s3 = (170 * this.s3) % 30323;
|
||||
}
|
||||
|
||||
random(): number {
|
||||
this.step();
|
||||
return (this.s1/30269.0 + this.s2/30307.0 + this.s3/30323.0)%1.0;
|
||||
}
|
||||
}
|
290
src/Casino/Roulette.tsx
Normal file
290
src/Casino/Roulette.tsx
Normal file
@ -0,0 +1,290 @@
|
||||
import * as React from "react";
|
||||
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { StdButton } from "../ui/React/StdButton";
|
||||
import { Money } from "../ui/React/Money";
|
||||
import { Game } from "./Game";
|
||||
import { WHRNG } from "./RNG";
|
||||
|
||||
type IProps = {
|
||||
p: IPlayer;
|
||||
}
|
||||
|
||||
type IState = {
|
||||
investment: number;
|
||||
canPlay: boolean;
|
||||
status: string | JSX.Element;
|
||||
n: number;
|
||||
lock: boolean;
|
||||
strategy: Strategy;
|
||||
}
|
||||
|
||||
const maxPlay = 1e6;
|
||||
|
||||
function isRed(n: number): boolean {
|
||||
return [1, 3, 5, 7, 9, 12, 14, 16, 18, 19,
|
||||
21, 23, 25, 27, 30, 32, 34, 36].includes(n);
|
||||
}
|
||||
|
||||
function isBlack(n: number): boolean {
|
||||
return !isRed(n);
|
||||
}
|
||||
|
||||
type Strategy = {
|
||||
match: (n: number) => boolean;
|
||||
payout: number;
|
||||
}
|
||||
|
||||
const redNumbers: number[] = [1, 3, 5, 7, 9, 12, 14, 16, 18, 19,
|
||||
21, 23, 25, 27, 30, 32, 34, 36];
|
||||
|
||||
const strategies: {
|
||||
Red: Strategy;
|
||||
Black: Strategy;
|
||||
Odd: Strategy;
|
||||
Even: Strategy;
|
||||
High: Strategy;
|
||||
Low: Strategy;
|
||||
Third1: Strategy;
|
||||
Third2: Strategy;
|
||||
Third3: Strategy;
|
||||
} = {
|
||||
Red: {
|
||||
match: (n: number): boolean => {
|
||||
if (n === 0) return false;
|
||||
return redNumbers.includes(n);
|
||||
},
|
||||
payout: 1,
|
||||
},
|
||||
Black: {
|
||||
match: (n: number): boolean => {
|
||||
return !redNumbers.includes(n);
|
||||
},
|
||||
payout: 1,
|
||||
},
|
||||
Odd: {
|
||||
match: (n: number): boolean => {
|
||||
if (n === 0) return false;
|
||||
return n%2 === 1;
|
||||
},
|
||||
payout: 1,
|
||||
},
|
||||
Even: {
|
||||
match: (n: number): boolean => {
|
||||
if (n === 0) return false;
|
||||
return n%2 === 0;
|
||||
},
|
||||
payout: 1,
|
||||
},
|
||||
High: {
|
||||
match: (n: number): boolean => {
|
||||
if (n === 0) return false;
|
||||
return n>18
|
||||
},
|
||||
payout: 1,
|
||||
},
|
||||
Low: {
|
||||
match: (n: number): boolean => {
|
||||
if (n === 0) return false;
|
||||
return n<19;
|
||||
},
|
||||
payout: 1,
|
||||
},
|
||||
Third1: {
|
||||
match: (n: number): boolean => {
|
||||
if (n === 0) return false;
|
||||
return n <= 12;
|
||||
},
|
||||
payout: 2,
|
||||
},
|
||||
Third2: {
|
||||
match: (n: number): boolean => {
|
||||
if (n === 0) return false;
|
||||
return 13 <= n && n <= 24;
|
||||
},
|
||||
payout: 2,
|
||||
},
|
||||
Third3: {
|
||||
match: (n: number): boolean => {
|
||||
if (n === 0) return false;
|
||||
return 25 <= n;
|
||||
},
|
||||
payout: 2,
|
||||
},
|
||||
}
|
||||
|
||||
function Single(s: number): Strategy {
|
||||
return {
|
||||
match: (n: number): boolean => {
|
||||
return s === n;
|
||||
},
|
||||
payout: 36,
|
||||
}
|
||||
}
|
||||
|
||||
export class Roulette extends Game<IProps, IState> {
|
||||
interval: number = -1;
|
||||
rng: WHRNG;
|
||||
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this.rng = new WHRNG((new Date()).getTime());
|
||||
this.state = {
|
||||
investment: 1000,
|
||||
canPlay: true,
|
||||
status: 'waiting',
|
||||
n: 0,
|
||||
lock: true,
|
||||
strategy: {
|
||||
payout: 0,
|
||||
match: (n: number): boolean => { return false },
|
||||
},
|
||||
}
|
||||
|
||||
this.step = this.step.bind(this);
|
||||
this.currentNumber = this.currentNumber.bind(this);
|
||||
this.updateInvestment = this.updateInvestment.bind(this);
|
||||
}
|
||||
|
||||
|
||||
componentDidMount() {
|
||||
this.interval = setInterval(this.step, 50);
|
||||
}
|
||||
|
||||
step() {
|
||||
if (!this.state.lock) {
|
||||
this.setState({n: Math.floor(Math.random()*37)});
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearInterval(this.interval);
|
||||
}
|
||||
|
||||
updateInvestment(e: React.FormEvent<HTMLInputElement>) {
|
||||
let investment: number = parseInt(e.currentTarget.value);
|
||||
if (isNaN(investment)) {
|
||||
investment = 1000;
|
||||
}
|
||||
if (investment > maxPlay) {
|
||||
investment = maxPlay
|
||||
}
|
||||
this.setState({investment: investment});
|
||||
}
|
||||
|
||||
currentNumber() {
|
||||
if (this.state.n === 0) return '0';
|
||||
const color = isRed(this.state.n) ? 'R' : 'B';
|
||||
return `${this.state.n}${color}`;
|
||||
}
|
||||
|
||||
play(s: Strategy) {
|
||||
if(this.reachedLimit(this.props.p)) return;
|
||||
this.setState({
|
||||
canPlay: false,
|
||||
lock: false,
|
||||
status: 'playing',
|
||||
strategy: s,
|
||||
})
|
||||
setTimeout(() => {
|
||||
let n = Math.floor(this.rng.random()*37);
|
||||
let status = <></>;
|
||||
let gain = 0;
|
||||
let playerWin = this.state.strategy.match(n)
|
||||
// oh yeah, the house straight up cheats. Try finding the seed now!
|
||||
if(playerWin && Math.random() > 0.9) {
|
||||
playerWin = false;
|
||||
while(this.state.strategy.match(n)) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
if(playerWin) {
|
||||
gain = this.state.investment*this.state.strategy.payout;
|
||||
status = <>won {Money(gain)}</>;
|
||||
} else {
|
||||
gain = -this.state.investment;
|
||||
status = <>lost {Money(-gain)}</>;
|
||||
}
|
||||
this.win(this.props.p, gain);
|
||||
this.setState({
|
||||
canPlay: true,
|
||||
lock: true,
|
||||
status: status,
|
||||
n: n,
|
||||
});
|
||||
this.reachedLimit(this.props.p);
|
||||
}, 1600);
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
return <>
|
||||
<h1>{this.currentNumber()}</h1>
|
||||
<input type="number" className='text-input' onChange={this.updateInvestment} placeholder={"Amount to play"} value={this.state.investment} disabled={!this.state.canPlay} />
|
||||
<h1>{this.state.status}</h1>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><StdButton text={"3"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(3))} /></td>
|
||||
<td><StdButton text={"6"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(6))} /></td>
|
||||
<td><StdButton text={"9"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(9))} /></td>
|
||||
<td><StdButton text={"12"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(12))} /></td>
|
||||
<td><StdButton text={"15"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(15))} /></td>
|
||||
<td><StdButton text={"18"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(18))} /></td>
|
||||
<td><StdButton text={"21"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(21))} /></td>
|
||||
<td><StdButton text={"24"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(24))} /></td>
|
||||
<td><StdButton text={"27"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(27))} /></td>
|
||||
<td><StdButton text={"30"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(30))} /></td>
|
||||
<td><StdButton text={"33"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(33))} /></td>
|
||||
<td><StdButton text={"36"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(36))} /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><StdButton text={"2"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(2))} /></td>
|
||||
<td><StdButton text={"5"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(5))} /></td>
|
||||
<td><StdButton text={"8"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(8))} /></td>
|
||||
<td><StdButton text={"11"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(11))} /></td>
|
||||
<td><StdButton text={"14"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(14))} /></td>
|
||||
<td><StdButton text={"17"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(17))} /></td>
|
||||
<td><StdButton text={"20"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(20))} /></td>
|
||||
<td><StdButton text={"23"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(23))} /></td>
|
||||
<td><StdButton text={"26"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(26))} /></td>
|
||||
<td><StdButton text={"29"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(29))} /></td>
|
||||
<td><StdButton text={"32"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(32))} /></td>
|
||||
<td><StdButton text={"35"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(35))} /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><StdButton text={"1"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(1))} /></td>
|
||||
<td><StdButton text={"4"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(4))} /></td>
|
||||
<td><StdButton text={"7"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(7))} /></td>
|
||||
<td><StdButton text={"10"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(10))} /></td>
|
||||
<td><StdButton text={"13"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(13))} /></td>
|
||||
<td><StdButton text={"16"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(16))} /></td>
|
||||
<td><StdButton text={"19"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(19))} /></td>
|
||||
<td><StdButton text={"22"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(22))} /></td>
|
||||
<td><StdButton text={"25"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(25))} /></td>
|
||||
<td><StdButton text={"28"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(28))} /></td>
|
||||
<td><StdButton text={"31"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(31))} /></td>
|
||||
<td><StdButton text={"34"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(34))} /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colSpan={4}><StdButton text={"1 to 12"} disabled={!this.state.canPlay} onClick={()=>this.play(strategies.Third1)} /></td>
|
||||
<td colSpan={4}><StdButton text={"13 to 24"} disabled={!this.state.canPlay} onClick={()=>this.play(strategies.Third2)} /></td>
|
||||
<td colSpan={4}><StdButton text={"25 to 36"} disabled={!this.state.canPlay} onClick={()=>this.play(strategies.Third3)} /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colSpan={2}><StdButton text={"Red"} disabled={!this.state.canPlay} onClick={()=>this.play(strategies.Red)} /></td>
|
||||
<td colSpan={2}><StdButton text={"Black"} disabled={!this.state.canPlay} onClick={()=>this.play(strategies.Black)} /></td>
|
||||
<td colSpan={2}><StdButton text={"Odd"} disabled={!this.state.canPlay} onClick={()=>this.play(strategies.Odd)} /></td>
|
||||
<td colSpan={2}><StdButton text={"Even"} disabled={!this.state.canPlay} onClick={()=>this.play(strategies.Even)} /></td>
|
||||
<td colSpan={2}><StdButton text={"High"} disabled={!this.state.canPlay} onClick={()=>this.play(strategies.High)} /></td>
|
||||
<td colSpan={2}><StdButton text={"Low"} disabled={!this.state.canPlay} onClick={()=>this.play(strategies.Low)} /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><StdButton text={"0"} disabled={!this.state.canPlay} onClick={()=>this.play(Single(0))} /></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</>
|
||||
}
|
||||
}
|
234
src/Casino/SlotMachine.tsx
Normal file
234
src/Casino/SlotMachine.tsx
Normal file
@ -0,0 +1,234 @@
|
||||
import * as React from "react";
|
||||
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { StdButton } from "../ui/React/StdButton";
|
||||
import { Money } from "../ui/React/Money";
|
||||
import { WHRNG } from "./RNG";
|
||||
import { Game } from "./Game";
|
||||
|
||||
type IProps = {
|
||||
p: IPlayer;
|
||||
}
|
||||
|
||||
type IState = {
|
||||
index: number[];
|
||||
locks: number[];
|
||||
investment: number;
|
||||
canPlay: boolean;
|
||||
status: string | JSX.Element;
|
||||
}
|
||||
|
||||
// statically shuffled array of symbols.
|
||||
let symbols = ["D", "C", "$", "?", "♥", "A", "C", "B", "C", "E", "B", "E", "C",
|
||||
"*", "D", "♥", "B", "A", "A", "A", "C", "A", "D", "B", "E", "?", "D", "*",
|
||||
"@", "♥", "B", "E", "?"];
|
||||
|
||||
function getPayout(s: string, n: number): number {
|
||||
switch (s) {
|
||||
case "$":
|
||||
return [20, 200, 1000][n];
|
||||
case "@":
|
||||
return [8, 80, 400][n];
|
||||
case "♥":
|
||||
case "?":
|
||||
return [6, 20, 150][n];
|
||||
case "D":
|
||||
case "E":
|
||||
return [1, 8, 30][n];
|
||||
default:
|
||||
return [1, 5, 20][n];
|
||||
}
|
||||
}
|
||||
|
||||
const payLines = [
|
||||
// lines
|
||||
[[0, 0], [0, 1], [0, 2], [0, 3], [0, 4]],
|
||||
[[1, 0], [1, 1], [1, 2], [1, 3], [1, 4]],
|
||||
[[2, 0], [2, 1], [2, 2], [2, 3], [2, 4]],
|
||||
|
||||
// Vs
|
||||
[[2, 0], [1, 1], [0, 2], [1, 3], [2, 4]],
|
||||
[[0, 0], [1, 1], [2, 2], [1, 3], [0, 4]],
|
||||
|
||||
// rest
|
||||
[[0, 0], [1, 1], [1, 2], [1, 3], [0, 4]],
|
||||
[[2, 0], [1, 1], [1, 2], [1, 3], [2, 4]],
|
||||
[[1, 0], [0, 1], [0, 2], [0, 3], [1, 4]],
|
||||
[[1, 0], [2, 1], [2, 2], [2, 3], [1, 4]],
|
||||
];
|
||||
|
||||
const maxPlay = 1e6;
|
||||
|
||||
export class SlotMachine extends Game<IProps, IState> {
|
||||
rng: WHRNG;
|
||||
interval: number = -1;
|
||||
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
this.rng = new WHRNG(this.props.p.totalPlaytime);
|
||||
|
||||
this.state = {
|
||||
index: [0, 0, 0, 0, 0],
|
||||
investment: 1000,
|
||||
locks: [0, 0, 0, 0, 0],
|
||||
canPlay: true,
|
||||
status: 'waiting',
|
||||
};
|
||||
|
||||
this.play = this.play.bind(this);
|
||||
this.lock = this.lock.bind(this);
|
||||
this.unlock = this.unlock.bind(this);
|
||||
this.step = this.step.bind(this);
|
||||
this.checkWinnings = this.checkWinnings.bind(this);
|
||||
this.getTable = this.getTable.bind(this);
|
||||
this.updateInvestment = this.updateInvestment.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.interval = setInterval(this.step, 50);
|
||||
}
|
||||
|
||||
step() {
|
||||
let stoppedOne = false;
|
||||
const index = this.state.index.slice();
|
||||
for(const i in index) {
|
||||
if (index[i] === this.state.locks[i] && !stoppedOne) continue;
|
||||
index[i] = (index[i] + 1) % symbols.length;
|
||||
stoppedOne = true;
|
||||
}
|
||||
|
||||
this.setState({index: index});
|
||||
|
||||
if(stoppedOne && index.every((e, i) => e === this.state.locks[i])) {
|
||||
this.checkWinnings();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearInterval(this.interval);
|
||||
}
|
||||
|
||||
getTable(): string[][] {
|
||||
return [
|
||||
[symbols[(this.state.index[0]+symbols.length-1)%symbols.length], symbols[(this.state.index[1]+symbols.length-1)%symbols.length], symbols[(this.state.index[2]+symbols.length-1)%symbols.length], symbols[(this.state.index[3]+symbols.length-1)%symbols.length], symbols[(this.state.index[4]+symbols.length-1)%symbols.length]],
|
||||
[symbols[this.state.index[0]], symbols[this.state.index[1]], symbols[this.state.index[2]], symbols[this.state.index[3]], symbols[this.state.index[4]]],
|
||||
[symbols[(this.state.index[0]+1)%symbols.length], symbols[(this.state.index[1]+1)%symbols.length], symbols[(this.state.index[2]+1)%symbols.length], symbols[(this.state.index[3]+1)%symbols.length], symbols[(this.state.index[4]+1)%symbols.length]],
|
||||
];
|
||||
}
|
||||
|
||||
play() {
|
||||
if(this.reachedLimit(this.props.p)) return;
|
||||
this.setState({status: 'playing'});
|
||||
this.win(this.props.p, -this.state.investment);
|
||||
if(!this.state.canPlay) return;
|
||||
this.unlock();
|
||||
setTimeout(this.lock, this.rng.random()*2000+1000);
|
||||
}
|
||||
|
||||
lock() {
|
||||
this.setState({
|
||||
locks: [
|
||||
Math.floor(this.rng.random()*symbols.length),
|
||||
Math.floor(this.rng.random()*symbols.length),
|
||||
Math.floor(this.rng.random()*symbols.length),
|
||||
Math.floor(this.rng.random()*symbols.length),
|
||||
Math.floor(this.rng.random()*symbols.length),
|
||||
],
|
||||
})
|
||||
}
|
||||
|
||||
checkWinnings() {
|
||||
const t = this.getTable();
|
||||
const getPaylineData = function(payline: number[][]): string[] {
|
||||
let data = [];
|
||||
for(const point of payline) {
|
||||
data.push(t[point[0]][point[1]]);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
const countSequence = function(data: string[]): number {
|
||||
let count = 1;
|
||||
for(let i = 1; i < data.length; i++) {
|
||||
if (data[i]!==data[i-1]) break;
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
let gains = -this.state.investment;
|
||||
for (const payline of payLines) {
|
||||
const data = getPaylineData(payline);
|
||||
const count = countSequence(data);
|
||||
if (count < 3) continue;
|
||||
const payout = getPayout(data[0], count-3);
|
||||
gains += this.state.investment*payout;
|
||||
this.win(this.props.p, this.state.investment*payout);
|
||||
}
|
||||
|
||||
this.setState({
|
||||
status: <>{gains>0?"gained":"lost"} {Money(Math.abs(gains))}</>,
|
||||
canPlay: true,
|
||||
})
|
||||
if(this.reachedLimit(this.props.p)) return;
|
||||
}
|
||||
|
||||
unlock() {
|
||||
this.setState({
|
||||
locks: [-1, -1, -1, -1, -1],
|
||||
canPlay: false,
|
||||
})
|
||||
}
|
||||
|
||||
updateInvestment(e: React.FormEvent<HTMLInputElement>) {
|
||||
let investment: number = parseInt(e.currentTarget.value);
|
||||
if (isNaN(investment)) {
|
||||
investment = 1000;
|
||||
}
|
||||
if (investment > maxPlay) {
|
||||
investment = maxPlay;
|
||||
}
|
||||
this.setState({investment: investment});
|
||||
}
|
||||
|
||||
render() {
|
||||
const t = this.getTable();
|
||||
return <>
|
||||
<pre>
|
||||
+———————————————————————+<br />
|
||||
| | {t[0][0]} | {t[0][1]} | {t[0][2]} | {t[0][3]} | {t[0][4]} | |<br />
|
||||
| | | | | | | |<br />
|
||||
| | {symbols[this.state.index[0]]} | {symbols[this.state.index[1]]} | {symbols[this.state.index[2]]} | {symbols[this.state.index[3]]} | {symbols[this.state.index[4]]} | |<br />
|
||||
| | | | | | | |<br />
|
||||
| | {symbols[(this.state.index[0]+1)%symbols.length]} | {symbols[(this.state.index[1]+1)%symbols.length]} | {symbols[(this.state.index[2]+1)%symbols.length]} | {symbols[(this.state.index[3]+1)%symbols.length]} | {symbols[(this.state.index[4]+1)%symbols.length]} | |<br />
|
||||
+———————————————————————+<br />
|
||||
</pre>
|
||||
<input type="number" className='text-input' onChange={this.updateInvestment} placeholder={"Amount to play"} value={this.state.investment} disabled={!this.state.canPlay} />
|
||||
<StdButton onClick={this.play} text={"Spin!"} disabled={!this.state.canPlay} />
|
||||
<h1>{this.state.status}</h1>
|
||||
<h2>Pay lines</h2>
|
||||
<pre>
|
||||
----- ····· ····· <br />
|
||||
····· ----- ····· <br />
|
||||
····· ····· ----- <br />
|
||||
</pre>
|
||||
<br />
|
||||
|
||||
<pre>
|
||||
··^·· \···/ \···/<br />
|
||||
·/·\· ·\·/· ·---·<br />
|
||||
/···\ ··v·· ·····<br />
|
||||
</pre>
|
||||
<br />
|
||||
|
||||
<pre>
|
||||
····· ·---· ·····<br />
|
||||
·---· /···\ \···/<br />
|
||||
/···\ ····· ·---·<br />
|
||||
</pre>
|
||||
</>
|
||||
}
|
||||
}
|
||||
|
||||
// https://felgo.com/doc/how-to-make-a-slot-game-tutorial/
|
@ -6,7 +6,7 @@
|
||||
import { IMap } from "./types";
|
||||
|
||||
export let CONSTANTS: IMap<any> = {
|
||||
Version: "0.51.1",
|
||||
Version: "0.51.2",
|
||||
|
||||
/** Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience
|
||||
* and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then
|
||||
@ -228,30 +228,16 @@ export let CONSTANTS: IMap<any> = {
|
||||
|
||||
LatestUpdate:
|
||||
`
|
||||
v0.51.1 - 2021-04-06 Bugfixes because the author of the last patch sucks (it's hydroflame)
|
||||
v0.51.2 - 2021-04-09 Vegas, Baby! (hydroflame)
|
||||
-------
|
||||
|
||||
Netscript
|
||||
* 'getPlayer' returns players faction and tor
|
||||
* 'hospitalization' is a new singularity function.
|
||||
* 'gang.getMemberInformation' now returns more information.
|
||||
* 'hacknet.hashCapacity' is a new hacknet function that returns the maximum hash capacity.
|
||||
|
||||
Hospitalization
|
||||
* Now only cost at most 10% of your money.
|
||||
|
||||
Bugfix
|
||||
* confirmation dialog box no longer use previous text
|
||||
|
||||
Accessibility
|
||||
* The game is a little easier to handle for screen readers (yes, there's an
|
||||
absolute legend playing this game with a screen reader)
|
||||
* Infiltration use buttons instead of a-links
|
||||
* New option to disable ASCII art. This will make the metro map and world
|
||||
map display as a list of buttons.
|
||||
New location: The Iker Molina Casino
|
||||
* A casino opened in Aevum. However the house is rumored to cheat. If only
|
||||
we could give them a taste of their own medicine.
|
||||
|
||||
Misc.
|
||||
* 'fl1ght.exe' will no longer suggest the combat path. Related faction
|
||||
requirements unchanged.
|
||||
* Link to discord added under options
|
||||
* 'getMemberInformation' doc updated, oops
|
||||
* tech vendor now handle max ram and cores.
|
||||
`
|
||||
}
|
||||
|
@ -708,8 +708,11 @@ class DevMenuComponent extends Component {
|
||||
<h2>Generic</h2>
|
||||
</div>
|
||||
<div className="row">
|
||||
<button className="std-button" onClick={this.addMoney(1e6)}>Add $1m</button>
|
||||
<button className="std-button" onClick={this.addMoney(1e9)}>Add $1b</button>
|
||||
<button className="std-button" onClick={this.addMoney(1e12)}>Add $1t</button>
|
||||
<button className="std-button" onClick={this.addMoney(1e15)}>Add $1000t</button>
|
||||
<button className="std-button" onClick={this.addMoney(1e27)}>Add $1e27</button>
|
||||
<button className="std-button" onClick={this.upgradeRam}>Upgrade Home Computer's RAM</button>
|
||||
</div>
|
||||
<div className="row">
|
||||
|
@ -11,4 +11,5 @@ export enum LocationType {
|
||||
TechVendor,
|
||||
TravelAgency,
|
||||
University,
|
||||
Casino,
|
||||
}
|
||||
|
@ -47,14 +47,14 @@ Cities[CityName.Aevum].asciiArt = `
|
||||
\\ 56 B
|
||||
x \\ [summit university]
|
||||
\\ \\ 28
|
||||
\\ [snap fitness gym] x o--L------------
|
||||
\\ [snap fitness gym] x o--L-----------N
|
||||
K \\ /
|
||||
\\ \\ P
|
||||
\\ \\ Q [casino]
|
||||
x 58 \\ / [travel agency]
|
||||
\\ 94 95 o
|
||||
90 x 59 o------o |
|
||||
\\ / \\ | 98 102 103
|
||||
o--------N------x----o 93 96 o-----+------------o o----o
|
||||
o--------O------x----o 93 96 o-----+------------o o----o
|
||||
\\ | \\ /
|
||||
[hospital] \\ 61 [ecorp] x 31 99 o-F-o 101
|
||||
o |
|
||||
@ -69,13 +69,13 @@ Cities[CityName.Aevum].asciiArt = `
|
||||
| 34 x \\
|
||||
[clarke inc.] C | \\ [world stock exchange]
|
||||
| | \\
|
||||
| | o-M-------Q--------o
|
||||
| | o-M-------R--------o
|
||||
[galactic cybersystems] G 35 x
|
||||
| [watchdog security]
|
||||
|
|
||||
67 o
|
||||
|
||||
[the slums] O `
|
||||
[the slums] P `
|
||||
Cities[CityName.Chongqing].asciiArt = `
|
||||
|
|
||||
75 o
|
||||
|
@ -198,7 +198,12 @@ export function createStartCorporationPopup(p: IPlayer) {
|
||||
*/
|
||||
export function createUpgradeHomeCoresPopup(p: IPlayer) {
|
||||
const currentCores = p.getHomeComputer().cpuCores;
|
||||
if (currentCores >= 8) { return; } // Max of 8 cores
|
||||
if (currentCores >= 8) {
|
||||
dialogBoxCreate(<>
|
||||
You've have the maximum amount of CPU cores on your home computer.
|
||||
</>);
|
||||
return;
|
||||
}
|
||||
|
||||
// Cost of purchasing another cost is found by indexing this array with number of current cores
|
||||
const allCosts = [
|
||||
@ -255,6 +260,14 @@ export function createUpgradeHomeRamPopup(p: IPlayer) {
|
||||
const noBtn = yesNoBoxGetNoButton();
|
||||
if (yesBtn == null || noBtn == null) { return; }
|
||||
|
||||
const homeComputer = p.getHomeComputer();
|
||||
if (homeComputer.maxRam >= CONSTANTS.HomeComputerMaxRam) {
|
||||
dialogBoxCreate(<>
|
||||
You've have the maximum amount of RAM on your home computer.
|
||||
</>);
|
||||
return;
|
||||
}
|
||||
|
||||
yesBtn.innerText = "Purchase";
|
||||
yesBtn.addEventListener("click", ()=>{
|
||||
purchaseRamForHomeComputer(cost, p);
|
||||
|
@ -24,6 +24,7 @@ export enum LocationName {
|
||||
AevumSnapFitnessGym = "Snap Fitness Gym",
|
||||
AevumSummitUniversity = "Summit University",
|
||||
AevumWatchdogSecurity = "Watchdog Security",
|
||||
AevumCasino = "Iker Molina Casino",
|
||||
|
||||
// Chongqing locations
|
||||
ChongqingKuaiGongInternational = "KuaiGong International",
|
||||
|
@ -145,6 +145,11 @@ export const LocationsMetadata: IConstructorParams[] = [
|
||||
name: LocationName.AevumWatchdogSecurity,
|
||||
types: [LocationType.Company],
|
||||
},
|
||||
{
|
||||
city: CityName.Aevum,
|
||||
name: LocationName.AevumCasino,
|
||||
types: [LocationType.Casino],
|
||||
},
|
||||
{
|
||||
city: CityName.Chongqing,
|
||||
infiltrationData: {
|
||||
|
89
src/Locations/ui/CasinoLocation.tsx
Normal file
89
src/Locations/ui/CasinoLocation.tsx
Normal file
@ -0,0 +1,89 @@
|
||||
/**
|
||||
* 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";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { SlotMachine } from "../../Casino/SlotMachine";
|
||||
import { CoinFlip } from "../../Casino/CoinFlip";
|
||||
import { Roulette } from "../../Casino/Roulette";
|
||||
|
||||
type IProps = {
|
||||
p: IPlayer;
|
||||
}
|
||||
|
||||
type IState = {
|
||||
game: string;
|
||||
}
|
||||
|
||||
export class CasinoLocation extends React.Component<IProps, IState> {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
game: '',
|
||||
}
|
||||
|
||||
this.updateGame = this.updateGame.bind(this);
|
||||
}
|
||||
|
||||
updateGame(game: string) {
|
||||
this.setState({
|
||||
game: game,
|
||||
});
|
||||
}
|
||||
|
||||
renderGames() {
|
||||
return (<>
|
||||
<StdButton
|
||||
onClick={() => this.updateGame('coin')}
|
||||
text={"Play coin flip"}
|
||||
/><br />
|
||||
<StdButton
|
||||
onClick={() => this.updateGame('slots')}
|
||||
text={"Play slots"}
|
||||
/><br />
|
||||
<StdButton
|
||||
onClick={() => this.updateGame('roulette')}
|
||||
text={"Play roulette"}
|
||||
/>
|
||||
</>)
|
||||
}
|
||||
|
||||
renderGame() {
|
||||
let elem;
|
||||
switch(this.state.game) {
|
||||
case 'coin':
|
||||
elem = <CoinFlip p={this.props.p} />
|
||||
break;
|
||||
case 'slots':
|
||||
elem = <SlotMachine p={this.props.p} />
|
||||
break;
|
||||
case 'roulette':
|
||||
elem = <Roulette p={this.props.p} />
|
||||
break;
|
||||
}
|
||||
|
||||
return (<>
|
||||
<StdButton onClick={() => this.updateGame('')} text={"Stop playing"} />
|
||||
{elem}
|
||||
</>)
|
||||
}
|
||||
|
||||
render() {
|
||||
if(!this.state.game) {
|
||||
return this.renderGames();
|
||||
} else {
|
||||
return this.renderGame();
|
||||
}
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ import { SpecialLocation } from "./SpecialLocation";
|
||||
import { TechVendorLocation } from "./TechVendorLocation";
|
||||
import { TravelAgencyLocation } from "./TravelAgencyLocation";
|
||||
import { UniversityLocation } from "./UniversityLocation";
|
||||
import { CasinoLocation } from "./CasinoLocation";
|
||||
|
||||
import { Location } from "../Location";
|
||||
import { LocationType } from "../LocationTypeEnum";
|
||||
@ -131,6 +132,15 @@ export class GenericLocation extends React.Component<IProps, any> {
|
||||
)
|
||||
}
|
||||
|
||||
if (this.props.loc.types.includes(LocationType.Casino)) {
|
||||
content.push(
|
||||
<CasinoLocation
|
||||
key={"casinoLocation"}
|
||||
p={this.props.p}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
|
@ -179,4 +179,5 @@ export interface IPlayer {
|
||||
giveExploit(exploit: Exploit): void;
|
||||
queryStatFromString(str: string): number;
|
||||
getIntelligenceBonus(weight: number): number;
|
||||
getCasinoWinnings(): number;
|
||||
}
|
||||
|
@ -2335,7 +2335,10 @@ export function giveExploit(exploit) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function getIntelligenceBonus(weight) {
|
||||
return calculateIntelligenceBonus(this.intelligence, weight);
|
||||
}
|
||||
|
||||
export function getCasinoWinnings() {
|
||||
return this.moneySourceA.casino;
|
||||
}
|
@ -612,8 +612,7 @@ const Engine = {
|
||||
}));
|
||||
Engine.Display.factionsContent.appendChild(createElement("p", {
|
||||
width:"70%",
|
||||
innerText:"Lists factions you have been invited to, as well as " +
|
||||
"factions you have previously rejected. You can accept " +
|
||||
innerText:"Lists factions you have been invited to. You can accept " +
|
||||
"these faction invitations at any time."
|
||||
}));
|
||||
var invitationsList = createElement("ul");
|
||||
|
@ -572,6 +572,7 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %>
|
||||
<div id="game-options-right-panel">
|
||||
<a class="a-link-button" href="https://bitburner.readthedocs.io/en/latest/changelog.html" target="_blank"> Changelog </a>
|
||||
<a class="a-link-button" href="https://bitburner.readthedocs.io/en/latest/index.html" target="_blank">Documentation</a>
|
||||
<a class="a-link-button" href="https://discord.gg/TFc3hKD" target="_blank">Discord</a>
|
||||
<a class="a-link-button" href="https://www.reddit.com/r/bitburner" target="_blank">Subreddit</a>
|
||||
<button id="save-game-link" class="a-link-button"> Save Game </button>
|
||||
<button id="delete-game-link" class="a-link-button"> Delete Game </button>
|
||||
|
@ -42,7 +42,7 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
|
||||
if(!(p.bitNodeN === 9 || SourceFileFlags[9] > 0)) {
|
||||
return <><span>{`Hacknet Nodes owned: ${p.hacknetNodes.length}</span>`}</span><br /></>
|
||||
} else {
|
||||
return <><span>{`Hacknet Servers owned: ${p.hacknetNodes.length} / ${HacknetServerConstants.MaxServers}</span>`}</span><br /></>
|
||||
return <><span>{`Hacknet Servers owned: ${p.hacknetNodes.length} / ${HacknetServerConstants.MaxServers}`}</span><br /></>
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,6 +59,7 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
|
||||
if (src.hospitalization) { parts.push([`Hospitalization:`, Money(src.hospitalization)]) };
|
||||
if (src.infiltration) { parts.push([`Infiltration:`, Money(src.infiltration)]) };
|
||||
if (src.stock) { parts.push([`Stock Market:`, Money(src.stock)]) };
|
||||
if (src.casino) { parts.push([`Casino:`, Money(src.casino)]) };
|
||||
|
||||
return StatsTable(parts, "");
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ export class MoneySourceTracker {
|
||||
stock: number = 0;
|
||||
total: number = 0;
|
||||
work: number = 0;
|
||||
casino: number = 0;
|
||||
|
||||
[key: string]: number | Function;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user