您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Displays a mini map of the Race Track Version 2. 1st version is made by toonidy:) Subscribe to MV Typing on YouTube!
- // ==UserScript==
- // @name Nitro Type - Racing Mini Map by MV Typing
- // @version 0.2.0
- // @description Displays a mini map of the Race Track Version 2. 1st version is made by toonidy:) Subscribe to MV Typing on YouTube!
- // @author MV Typing
- // @match *://*.nitrotype.com/race
- // @match *://*.nitrotype.com/race/*
- // @icon https://i.ibb.co/YRs06pc/toonidy-userscript.png
- // @grant none
- // @require https://cdnjs.cloudflare.com/ajax/libs/pixi.js/6.5.4/browser/pixi.min.js
- // @require https://greasyfork.org/scripts/443718-nitro-type-userscript-utils/code/Nitro%20Type%20Userscript%20Utils.js?version=1042360
- // @license MIT
- // @namespace https://greasyfork.org/users/858426
- // ==/UserScript==
- /* globals PIXI findReact createLogger */
- const config = {
- colors: {
- me: 0xf2887f,
- opponentPlayer: 0x9E00FF,
- opponentBot: 0xF3FF00,
- opponentWampus: 0xFF8000,
- nitro: 0xFF00D8,
- background: 0x696969,
- raceLane: 0xFF0000,
- startLine: 0x00F3FF,
- finishLine: 0x3200FF,
- },
- trackLocally: true, // whether to track your player's position without server data
- moveDestination: {
- enabled: true,
- alpha: 0.5, // range 0.0 - 1.0 (the lower the value, the more transparent)
- },
- }
- const logging = createLogger("Nitro Type Racing Mini Map"),
- raceContainer = document.querySelector("#raceContainer"),
- raceObj = raceContainer ? findReact(raceContainer) : null
- if (!raceContainer || !raceObj) {
- logging.error("Init")("Could not find the race track")
- return
- }
- if (!raceObj.props.user.loggedIn) {
- logging.error("Init")("This userscript is not available for Guest Racing")
- return
- }
- PIXI.utils.skipHello()
- const style = document.createElement("style")
- style.appendChild(
- document.createTextNode(`
- .nt-racing-mini-map-root canvas {
- display: block;
- }`))
- document.head.appendChild(style)
- const racingMiniMap = new PIXI.Application({ width: 1024, height: 100, backgroundColor: config.colors.background }),
- container = document.createElement("div");
- container.className = "nt-racing-mini-map-root"
- ///////////////////////
- // Prepare Objects //
- ///////////////////////
- const RACER_WIDTH = 28,
- CROSSING_LINE_WIDTH = 32,
- PADDING = 2,
- racers = Array(5).fill(null),
- server = raceObj.server,
- currentUserID = raceObj.props.user.userID
- // Draw mini racetrack
- const raceTrackBG = new PIXI.TilingSprite.from("/dist/site/images/backgrounds/bg-noise.png", { width: racingMiniMap.renderer.width, height: racingMiniMap.renderer.height} ),
- startLine = PIXI.Sprite.from(PIXI.Texture.WHITE),
- finishLine = PIXI.Sprite.from(PIXI.Texture.WHITE)
- startLine.x = CROSSING_LINE_WIDTH
- startLine.y = 0
- startLine.width = 1
- startLine.height = racingMiniMap.renderer.height
- startLine.tint = config.colors.startLine
- finishLine.x = racingMiniMap.renderer.width - CROSSING_LINE_WIDTH - 1
- finishLine.y = 0
- finishLine.width = 1
- finishLine.height = racingMiniMap.renderer.height
- finishLine.tint = config.colors.finishLine
- raceTrackBG.addChild(startLine, finishLine)
- for (let i = 1; i < 5; i++) {
- const lane = PIXI.Sprite.from(PIXI.Texture.WHITE)
- lane.x = 0
- lane.y = i * (racingMiniMap.renderer.height / 5)
- lane.width = racingMiniMap.renderer.width
- lane.height = 1
- lane.tint = config.colors.raceLane
- raceTrackBG.addChild(lane)
- }
- racingMiniMap.stage.addChild(raceTrackBG)
- /* Mini Map movement animation update. */
- function animateRacerTicker() {
- const r = this
- const lapse = Date.now() - r.lastUpdated
- if (r.sprite.x < r.toX) {
- const distance = r.toX - r.fromX
- r.sprite.x = r.fromX + Math.min(distance, distance * (lapse / r.moveMS))
- if (r.ghostSprite && r.sprite.x === r.ghostSprite.x) {
- r.ghostSprite.renderable = false
- }
- }
- if (r.skipped > 0) {
- const nitroTargetWidth = r.nitroToX - r.nitroFromX
- if (r.nitroSprite.width < nitroTargetWidth) {
- r.nitroSprite.width = Math.min(nitroTargetWidth, r.sprite.x - r.nitroFromX)
- } else if (r.nitroSprite.width === nitroTargetWidth && r.nitroSprite.alpha > 0 && !r.nitroDisableFade) {
- if (r.nitroSprite.alpha === 1) {
- r.nitroStartFadeStamp = Date.now() - 1
- }
- r.nitroSprite.alpha = Math.max(0, 1 - ((Date.now() - r.nitroStartFadeStamp) / 1e3))
- }
- }
- if (r.completeStamp !== null && r.sprite.x === r.toX && r.nitroSprite.alpha === 0) {
- racingMiniMap.ticker.remove(animateRacerTicker, this)
- }
- }
- /* Handle adding in players on the mini map. */
- server.on("joined", (e) => {
- const { lane, userID } = e
- let color = config.colors.opponentBot
- if (userID === currentUserID) {
- color = config.colors.me
- } else if (!e.robot) {
- color = config.colors.opponentPlayer
- } else if (e.profile.specialRobot === "wampus") {
- color = config.colors.opponentWampus
- }
- if (racers[lane]) {
- racers[lane].ghostSprite.tint = color
- racers[lane].sprite.tint = color
- racers[lane].sprite.x = 0 - RACER_WIDTH + PADDING
- racers[lane].lastUpdated = Date.now()
- racers[lane].fromX = racers[lane].sprite.x
- racers[lane].toX = PADDING
- racers[lane].sprite.renderable = true
- return
- }
- const r = PIXI.Sprite.from(PIXI.Texture.WHITE)
- r.x = 0 - RACER_WIDTH + PADDING
- r.y = PADDING + (lane > 0 ? 1 : 0) + (lane * (racingMiniMap.renderer.height / 5))
- r.tint = color
- r.width = RACER_WIDTH
- r.height = 16 - (lane > 0 ? 1 : 0)
- const n = PIXI.Sprite.from(PIXI.Texture.WHITE)
- n.y = r.y + ((16 - (lane > 0 ? 1 : 0)) / 2) - 1
- n.renderable = false
- n.tint = config.colors.nitro
- n.width = 1
- n.height = 2
- racers[lane] = {
- lane,
- sprite: r,
- userID: userID,
- ghostSprite: null,
- nitroSprite: n,
- lastUpdated: Date.now(),
- fromX: r.x,
- toX: PADDING,
- skipped: 0,
- nitroStartFadeStamp: null,
- nitroFromX: null,
- nitroToX: null,
- nitroDisableFade: false,
- moveMS: 500,
- completeStamp: null,
- }
- if (config.moveDestination.enabled) {
- const g = PIXI.Sprite.from(PIXI.Texture.WHITE)
- g.x = PADDING
- g.y = PADDING + (lane > 0 ? 1 : 0) + (lane * (racingMiniMap.renderer.height / 5))
- g.tint = color
- g.alpha = config.moveDestination.alpha
- g.width = RACER_WIDTH
- g.height = 16 - (lane > 0 ? 1 : 0)
- g.renderable = false
- racers[lane].ghostSprite = g
- racingMiniMap.stage.addChild(g)
- }
- racingMiniMap.stage.addChild(n)
- racingMiniMap.stage.addChild(r)
- racingMiniMap.ticker.add(animateRacerTicker, racers[lane])
- })
- /* Handle any players leaving the race track. */
- server.on("left", (e) => {
- const lane = racers.findIndex((r) => r?.userID === e)
- if (racers[lane]) {
- racers[lane].sprite.renderable = false
- racers[lane].ghostSprite.renderable = false
- racers[lane].nitroSprite.renderable = false
- }
- })
- /* Handle race map progress position updates. */
- server.on("update", (e) => {
- let moveFinishMS = 500
- const payloadUpdateRacers = e.racers.slice().sort((a, b) => {
- if (a.progress.completeStamp === b.progress.completeStamp) {
- return 0
- }
- if (a.progress.completeStamp === null) {
- return 1
- }
- return a.progress.completeStamp > 0 && b.progress.completeStamp > 0 && a.progress.completeStamp > b.progress.completeStamp ? 1 : -1
- })
- for (let i = 0; i < payloadUpdateRacers.length; i++) {
- const r = payloadUpdateRacers[i],
- { completeStamp, skipped } = r.progress,
- racerObj = racers[r.lane]
- if (!racerObj || racerObj.completeStamp > 0 || (r.userID === currentUserID && completeStamp <= 0 && config.trackLocally)) {
- continue
- }
- if (r.disqualified) {
- racingMiniMap.ticker.remove(animateRacerTicker, racerObj)
- racingMiniMap.stage.removeChild(racerObj.sprite, racerObj.nitroSprite)
- if (racerObj.ghostSprite) {
- racingMiniMap.stage.removeChild(racerObj.ghostSprite)
- }
- racerObj.sprite.destroy()
- racerObj.ghostSprite.destroy()
- racerObj.nitroSprite.destroy()
- racers[r.lane] = null
- continue
- }
- racerObj.lastUpdated = Date.now()
- racerObj.fromX = racerObj.sprite.x
- if (racerObj.completeStamp === null && completeStamp > 0) {
- racerObj.completeStamp = completeStamp
- racerObj.toX = racingMiniMap.renderer.width - RACER_WIDTH - PADDING
- racerObj.moveMS = moveFinishMS
- if (racerObj.nitroDisableFade) {
- racerObj.nitroToX = racingMiniMap.renderer.width - RACER_WIDTH - PADDING
- racerObj.nitroDisableFade = false
- }
- } else {
- racerObj.moveMS = 1e3
- racerObj.toX = r.progress.percentageFinished * (racingMiniMap.renderer.width - RACER_WIDTH - CROSSING_LINE_WIDTH - PADDING - 1)
- racerObj.sprite.x = racerObj.fromX
- }
- if (racerObj.ghostSprite) {
- racerObj.ghostSprite.x = racerObj.toX
- racerObj.ghostSprite.renderable = true
- }
- if (skipped !== racerObj.skipped) {
- if (racerObj.skipped === 0) {
- racerObj.nitroFromX = racerObj.fromX
- racerObj.nitroSprite.x = racerObj.fromX
- racerObj.nitroSprite.renderable = true
- }
- racerObj.skipped = skipped // because infinite nitros exist? :/
- racerObj.nitroToX = racerObj.toX
- racerObj.nitroSprite.alpha = 1
- if (racerObj.completeStamp !== null) {
- racerObj.nitroToX = racingMiniMap.renderer.width - RACER_WIDTH - PADDING
- }
- }
- if (completeStamp > 0 && i + 1 < payloadUpdateRacers.length) {
- const nextRacer = payloadUpdateRacers[i + 1],
- nextRacerObj = racers[nextRacer?.lane]
- if (nextRacerObj && nextRacerObj.completeStamp === null && nextRacer.progress.completeStamp > 0 && nextRacer.progress.completeStamp > completeStamp) {
- moveFinishMS += 250
- }
- }
- }
- })
- if (config.trackLocally) {
- let lessonLength = 0
- server.on("status", (e) => {
- if (e.status === "countdown") {
- lessonLength = e.lessonLength
- }
- })
- const originalSendPlayerUpdate = server.sendPlayerUpdate
- server.sendPlayerUpdate = (data) => {
- originalSendPlayerUpdate(data)
- const racerObj = racers.find((r) => r?.userID === currentUserID)
- if (!racerObj) {
- return
- }
- const percentageFinished = (data.t / (lessonLength || 1))
- racerObj.lastUpdated = Date.now()
- racerObj.fromX = racerObj.sprite.x
- racerObj.moveMS = 500
- racerObj.toX = percentageFinished * (racingMiniMap.renderer.width - RACER_WIDTH - CROSSING_LINE_WIDTH - PADDING - 1)
- racerObj.sprite.x = racerObj.fromX
- if (racerObj.ghostSprite) {
- racerObj.ghostSprite.x = racerObj.toX
- racerObj.ghostSprite.renderable = true
- }
- if (data.s) {
- if (racerObj.skipped === 0) {
- racerObj.nitroFromX = racerObj.fromX
- racerObj.nitroSprite.x = racerObj.fromX
- racerObj.nitroSprite.renderable = true
- }
- racerObj.skipped = data.s // because infinite nitros exist? but I'm not going to test that! :/
- racerObj.nitroToX = racerObj.toX
- racerObj.nitroSprite.alpha = 1
- racerObj.nitroDisableFade = percentageFinished === 1
- if (racerObj.completeStamp !== null) {
- racerObj.nitroToX = racingMiniMap.renderer.width - RACER_WIDTH - PADDING
- }
- }
- }
- }
- /////////////
- // Final //
- /////////////
- container.append(racingMiniMap.view)
- raceContainer.before(container)// ==UserScript==
- // @name New Userscript
- // @namespace http://tampermonkey.net/
- // @version 0.1
- // @description try to take over the world!
- // @author You
- // @match https://www.nitrotype.com/garage
- // @icon https://www.google.com/s2/favicons?sz=64&domain=nitrotype.com
- // @grant none
- // ==/UserScript==
- (function() {
- 'use strict';
- // Your code here...
- })();