diff --git a/markdown/bitburner.go.getcurrentplayer.md b/markdown/bitburner.go.getcurrentplayer.md index 03bb8d61d..b0596f1b3 100644 --- a/markdown/bitburner.go.getcurrentplayer.md +++ b/markdown/bitburner.go.getcurrentplayer.md @@ -17,3 +17,7 @@ getCurrentPlayer(): "White" | "Black" | "None"; "White" \| "Black" \| "None" +## Remarks + +RAM cost: 0 GB + diff --git a/markdown/bitburner.go.getgamestate.md b/markdown/bitburner.go.getgamestate.md index 49ab3fd69..185823b49 100644 --- a/markdown/bitburner.go.getgamestate.md +++ b/markdown/bitburner.go.getgamestate.md @@ -22,3 +22,7 @@ getGameState(): { { currentPlayer: "White" \| "Black" \| "None"; whiteScore: number; blackScore: number; previousMove: \[number, number\] \| null; komi: number; bonusCycles: number; } +## Remarks + +RAM cost: 0 GB + diff --git a/markdown/bitburner.go.getmovehistory.md b/markdown/bitburner.go.getmovehistory.md index e9e378a43..eabc448fe 100644 --- a/markdown/bitburner.go.getmovehistory.md +++ b/markdown/bitburner.go.getmovehistory.md @@ -31,3 +31,7 @@ getMoveHistory(): string[][]; string\[\]\[\] +## Remarks + +RAM cost: 0 GB + diff --git a/markdown/bitburner.go.getopponent.md b/markdown/bitburner.go.getopponent.md index f3cec0df1..8436fc725 100644 --- a/markdown/bitburner.go.getopponent.md +++ b/markdown/bitburner.go.getopponent.md @@ -15,3 +15,7 @@ getOpponent(): GoOpponent; [GoOpponent](./bitburner.goopponent.md) +## Remarks + +RAM cost: 0 GB + diff --git a/src/DarkNet/effects/labyrinth.ts b/src/DarkNet/effects/labyrinth.ts index 041a3de3d..3beea417b 100644 --- a/src/DarkNet/effects/labyrinth.ts +++ b/src/DarkNet/effects/labyrinth.ts @@ -31,6 +31,7 @@ type LabDetails = { mazeWidth: number; mazeHeight: number; manual: boolean; + offsetStartAndEnd: boolean; }; export const labData: Record = { @@ -41,6 +42,7 @@ export const labData: Record = { mazeWidth: 20, mazeHeight: 14, manual: true, + offsetStartAndEnd: false, }, [SpecialServers.CruelLab]: { name: SpecialServers.CruelLab, @@ -49,6 +51,7 @@ export const labData: Record = { mazeWidth: 30, mazeHeight: 20, manual: true, + offsetStartAndEnd: false, }, [SpecialServers.MercilessLab]: { name: SpecialServers.MercilessLab, @@ -57,6 +60,7 @@ export const labData: Record = { mazeWidth: 40, mazeHeight: 26, manual: false, + offsetStartAndEnd: false, }, [SpecialServers.UberLab]: { name: SpecialServers.UberLab, @@ -65,6 +69,7 @@ export const labData: Record = { mazeWidth: 60, mazeHeight: 40, manual: false, + offsetStartAndEnd: true, }, [SpecialServers.EternalLab]: { name: SpecialServers.EternalLab, @@ -73,6 +78,7 @@ export const labData: Record = { mazeWidth: 60, mazeHeight: 40, manual: false, + offsetStartAndEnd: true, }, [SpecialServers.EndlessLab]: { name: SpecialServers.EndlessLab, @@ -81,6 +87,7 @@ export const labData: Record = { mazeWidth: 60, mazeHeight: 40, manual: false, + offsetStartAndEnd: true, }, [SpecialServers.FinalLab]: { name: SpecialServers.FinalLab, @@ -89,6 +96,7 @@ export const labData: Record = { mazeWidth: 60, mazeHeight: 40, manual: false, + offsetStartAndEnd: true, }, [SpecialServers.BonusLab]: { name: SpecialServers.BonusLab, @@ -97,6 +105,7 @@ export const labData: Record = { mazeWidth: 60, mazeHeight: 40, manual: false, + offsetStartAndEnd: true, }, } as const; @@ -185,6 +194,7 @@ export const getSurroundingsVisualized = ( showEnd = false, ): string => { const result: string[] = []; + const [endpointY, endpointX] = DarknetState.labEndpoint ?? [maze[0].length - 2, maze.length - 2]; for (let i = y - range; i <= y + range; i++) { let row = ""; for (let j = x - range; j <= x + range; j++) { @@ -192,7 +202,7 @@ export const getSurroundingsVisualized = ( row += "@"; continue; } - if (i === maze.length - 2 && j === maze[0].length - 2 && showEnd) { + if (i === endpointX && j === endpointY && showEnd) { row += "X"; continue; } @@ -205,7 +215,7 @@ export const getSurroundingsVisualized = ( }; const getLocationStatus = (pid: number): LocationStatus => { - const [initialX, initialY] = DarknetState.labLocations[pid] ?? [1, 1]; + const [initialX, initialY] = getPositionInLab(pid); const surroundings = getSurroundingsVisualized(getLabMaze(), initialX, initialY).split("\n"); return { coords: [initialX, initialY], @@ -245,11 +255,8 @@ export const handleLabyrinthPassword = ( } const maze = getLabMaze(); - if (!DarknetState.labLocations[pid]) { - DarknetState.labLocations[pid] = [1, 1]; - } - const [initialX, initialY] = DarknetState.labLocations[pid]; - const end = [maze[0].length - 2, maze.length - 2]; + const [initialX, initialY] = getPositionInLab(pid); + const end = DarknetState.labEndpoint ?? [maze[0].length - 2, maze.length - 2]; const [dx, dy] = getDirectionFromInput(attemptedPassword); const newLocation: [number, number] = [initialX + dx * 2, initialY + dy * 2]; @@ -324,6 +331,12 @@ export const handleLabyrinthPassword = ( }; }; +export const getPositionInLab = (pid: number): [number, number] => { + const [offsetX, offsetY] = getRandomOffset(); + DarknetState.labLocations[pid] ??= [1 + offsetX, 1 + offsetY]; + return DarknetState.labLocations[pid]; +}; + const getDirectionFromInput = (input: string): number[] => { const direction = input .split(" ") @@ -352,10 +365,22 @@ export const getLabMaze = (): string[] => { if (!DarknetState.labyrinth) { const { mazeWidth, mazeHeight } = getLabyrinthDetails(); DarknetState.labyrinth = generateMaze(mazeWidth, mazeHeight); + const [offsetX, offsetY] = getRandomOffset(); + DarknetState.labEndpoint = [ + DarknetState.labyrinth[0].length - 2 - offsetX, + DarknetState.labyrinth.length - 2 - offsetY, + ]; } return DarknetState.labyrinth; }; +const getRandomOffset = () => { + const { offsetStartAndEnd } = getLabyrinthDetails(); + const offsetX = offsetStartAndEnd ? Math.floor(Math.random() * 3) * 2 : 0; + const offsetY = offsetStartAndEnd ? Math.floor(Math.random() * 3) * 2 : 0; + return [offsetX, offsetY]; +}; + export const getLabyrinthServerNames = () => { const labHostnames: string[] = Object.keys(labData); return labHostnames; @@ -455,6 +480,7 @@ export const getLabyrinthDetails = (): { mazeHeight: number; cha: number; name: string; + offsetStartAndEnd: boolean; } => { // Lab not unlocked yet if (!hasFullDarknetAccess()) { @@ -466,6 +492,7 @@ export const getLabyrinthDetails = (): { lab: null, depth: 5, manual: false, + offsetStartAndEnd: false, }; } @@ -480,6 +507,7 @@ export const getLabyrinthDetails = (): { mazeHeight: labDetails.mazeHeight, cha: labDetails.cha, name: labDetails.name, + offsetStartAndEnd: labDetails.offsetStartAndEnd, }; }; diff --git a/src/DarkNet/models/DarknetState.ts b/src/DarkNet/models/DarknetState.ts index 0419dbf38..5fa2d7f20 100644 --- a/src/DarkNet/models/DarknetState.ts +++ b/src/DarkNet/models/DarknetState.ts @@ -40,11 +40,12 @@ export const DarknetState = { Network: new Array(MAX_NET_DEPTH).fill(null).map(() => new Array(NET_WIDTH).fill(null)), labyrinth: null as string[] | null, + labEndpoint: null as [number, number] | null, /** * This property may contain data of dead PIDs. Call cleanUpLabyrinthLocations before using this property if you * want to get data of alive PIDs. */ - labLocations: { "-1": [1, 1] } as Record, + labLocations: {} as Record, lastPhishingCacheTime: new Date(), lastCctRewardTime: new Date(), @@ -90,7 +91,7 @@ export function prestigeDarknetState(prestigeSourceFile: boolean): void { DarknetState.cyclesSinceLastMutation = 0; DarknetState.Network = new Array(MAX_NET_DEPTH).fill(null).map(() => new Array(NET_WIDTH).fill(null)); DarknetState.labyrinth = null; - DarknetState.labLocations = { "-1": [1, 1] }; + DarknetState.labLocations = {}; DarknetState.lastPhishingCacheTime = new Date(); DarknetState.lastStormTime = new Date(); DarknetState.stockPromotions = {}; diff --git a/src/DarkNet/ui/LabyrinthSummary.tsx b/src/DarkNet/ui/LabyrinthSummary.tsx index 2e6f41590..8855ea7e2 100644 --- a/src/DarkNet/ui/LabyrinthSummary.tsx +++ b/src/DarkNet/ui/LabyrinthSummary.tsx @@ -144,7 +144,7 @@ export const LabyrinthSummary = ({ isAuthenticating }: LabyrinthSummaryProps): R <>
- {!lab.manual ? ( + {!lab.manual && currentPerspective === -1 ? ( This lab cannot be completed manually. Select a script PID that is attempting the labyrinth from the options below to view its progress. diff --git a/src/DarkNet/ui/NetworkDisplayWrapper.tsx b/src/DarkNet/ui/NetworkDisplayWrapper.tsx index db0a54e21..7f9f58c5d 100644 --- a/src/DarkNet/ui/NetworkDisplayWrapper.tsx +++ b/src/DarkNet/ui/NetworkDisplayWrapper.tsx @@ -120,51 +120,35 @@ export function NetworkDisplayWrapper(): React.ReactElement { } }; - const zoomIn = useCallback(() => { - if (zoomIndex >= zoomOptions.length - 1) { - return; - } - DarknetState.zoomIndex = Math.max(zoomIndex + 1, 0); - setZoomIndex(DarknetState.zoomIndex); - const zoom = zoomOptions[zoomIndex]; - const background = draggableBackground.current; - scrollTo( - (background?.scrollTop ?? 0) + ((background?.clientHeight ?? 0) / 4) * zoom, - (background?.scrollLeft ?? 0) + ((background?.clientWidth ?? 0) / 4) * zoom, - ); - }, [zoomIndex, setZoomIndex, zoomOptions, scrollTo]); - - const zoomOut = useCallback(() => { - if (zoomIndex <= 0) { - return; - } - DarknetState.zoomIndex = Math.min(zoomIndex - 1, zoomOptions.length - 1); - setZoomIndex(DarknetState.zoomIndex); - const zoom = zoomOptions[zoomIndex]; - const background = draggableBackground.current; - scrollTo( - (background?.scrollTop ?? 0) - ((background?.clientHeight ?? 0) / 4) * zoom, - (background?.scrollLeft ?? 0) - ((background?.clientWidth ?? 0) / 4) * zoom, - ); - }, [zoomIndex, setZoomIndex, zoomOptions, scrollTo]); + const changeZoom = useCallback( + (out = true, mouseX?: number, mouseY?: number) => { + if (out && zoomIndex <= 0) return; + if (!out && zoomIndex >= zoomOptions.length - 1) return; + const newZoomIndex = out ? zoomIndex - 1 : zoomIndex + 1; + const oldZoom = zoomOptions[zoomIndex]; + const newZoom = zoomOptions[newZoomIndex]; + DarknetState.zoomIndex = newZoomIndex; + setZoomIndex(newZoomIndex); + const background = draggableBackground.current; + const mx = mouseX ?? (background?.clientWidth ?? 0) / 2; + const my = mouseY ?? (background?.clientHeight ?? 0) / 2; + scrollTo( + (((background?.scrollTop ?? 0) + my) / oldZoom) * newZoom - my, + (((background?.scrollLeft ?? 0) + mx) / oldZoom) * newZoom - mx, + ); + }, + [zoomIndex, setZoomIndex, zoomOptions, scrollTo], + ); const zoom = useCallback( (wheelEvent: WheelEvent) => { - const target = wheelEvent.target as HTMLDivElement; - if (!draggableBackground.current || DarknetState.openServer) { - return; - } - if (wheelEvent.deltaY < 0) { - zoomIn(); - } else { - zoomOut(); - } - - if (!target?.parentElement?.getBoundingClientRect()) { - return; - } + if (!draggableBackground.current || DarknetState.openServer) return; + const rect = draggableBackground.current.getBoundingClientRect(); + const mouseX = wheelEvent.clientX - rect.left; + const mouseY = wheelEvent.clientY - rect.top; + changeZoom(wheelEvent.deltaY > 0, mouseX, mouseY); }, - [draggableBackground, zoomOut, zoomIn], + [draggableBackground, changeZoom], ); const zoomRef = useRef(zoom); @@ -311,10 +295,10 @@ export function NetworkDisplayWrapper(): React.ReactElement {
- -
diff --git a/src/NetscriptFunctions/Darknet.ts b/src/NetscriptFunctions/Darknet.ts index 730887029..d28e0411f 100644 --- a/src/NetscriptFunctions/Darknet.ts +++ b/src/NetscriptFunctions/Darknet.ts @@ -21,6 +21,7 @@ import { getPasswordType } from "../DarkNet/controllers/ServerGenerator"; import { checkPassword, getAuthResult, isAuthenticated } from "../DarkNet/effects/authentication"; import { getLabMaze, + getPositionInLab, getLabyrinthDetails, getLabyrinthLocationReport, getSurroundingsVisualized, @@ -695,7 +696,7 @@ export function NetscriptDarknet(): InternalAPI { const authenticationTime = calculateAuthenticationTime(lab, Player, ctx.workerScript.scriptRef.threads); await helpers.netscriptDelay(ctx, authenticationTime); - const [x, y] = DarknetState.labLocations[pid] ?? [1, 1]; + const [x, y] = getPositionInLab(pid); return { success: true, message: getSurroundingsVisualized(getLabMaze(), x, y, 3, true, true), diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts index 7c2913df4..b3858db0b 100644 --- a/src/ScriptEditor/NetscriptDefinitions.d.ts +++ b/src/ScriptEditor/NetscriptDefinitions.d.ts @@ -5646,12 +5646,18 @@ export interface Go { * ".XO.#", * *] + * + * @remarks + * RAM cost: 0 GB */ getMoveHistory(): string[][]; /** * Returns the color of the current player, or 'None' if the game is over. * @returns "White" | "Black" | "None" + * + * @remarks + * RAM cost: 0 GB */ getCurrentPlayer(): "White" | "Black" | "None"; @@ -5659,6 +5665,9 @@ export interface Go { * Gets the status of the current game. * Shows the current player, current score, and the previous move coordinates. * Previous move will be null for a pass, or if there are no prior moves. + * + * @remarks + * RAM cost: 0 GB */ getGameState(): { currentPlayer: "White" | "Black" | "None"; @@ -5671,6 +5680,9 @@ export interface Go { /** * Returns the name of the opponent faction in the current subnet. + * + * @remarks + * RAM cost: 0 GB */ getOpponent(): GoOpponent;