[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\nindent_style = space\nindent_size = 2\nend_of_line = crlf\ncharset = utf-8\ninsert_final_newline = true\nmax_line_length = 120\n\n[*.lua]\nindent_size = 4\nmax_line_length = 160"
  },
  {
    "path": ".github/actions/bump-package-version.js",
    "content": "const packageJson = await Bun.file('./package.json').json();\n\nconst newVersion = process.env.TGT_RELEASE_VERSION;\npackageJson.version = newVersion.replace('v', '');\n\nawait Bun.write('./package.json', JSON.stringify(packageJson, null, 2));\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Create release\n\non:\n  push:\n    tags:\n      - \"v*.*.*\"\n\npermissions:\n  id-token: write # Required for OIDC\n  contents: write\n\njobs:\n  create-release:\n    if: github.actor_id != 278903378\n    runs-on: ubuntu-latest\n    steps:\n      - name: Install zip\n        run: sudo apt install zip\n\n      - name: Install Bun\n        uses: oven-sh/setup-bun@v2\n        with:\n          bun-version: latest\n\n      - name: Generate GitHub App token\n        id: app_token\n        uses: tibdex/github-app-token@v2\n        with:\n          app_id: ${{ secrets.APP_ID }}\n          private_key: ${{ secrets.APP_PRIVATE_KEY }}\n\n      - name: Get latest code\n        uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n          ref: ${{ github.event.repository.default_branch }}\n          token: ${{ steps.app_token.outputs.token }}\n\n      - name: Setup Node.js\n        uses: actions/setup-node@v6\n        with:\n          node-version: \"24\"\n\n      - name: Install Bun\n        uses: oven-sh/setup-bun@v2\n        with:\n          bun-version: latest\n\n      - name: Bump package version\n        run: bun run .github/actions/bump-package-version.js\n        env:\n          TGT_RELEASE_VERSION: ${{ github.ref_name }}\n\n      - name: Push version bump change\n        uses: EndBug/add-and-commit@v9\n        with:\n          add: package.json\n          push: true\n          default_author: github_actions\n          message: \"chore: bump version to ${{ github.ref_name }}\"\n\n      - name: Build\n        run: |\n          bun install --frozen-lockfile\n          bun run build\n        env:\n          TGT_RELEASE_VERSION: ${{ github.ref_name }}\n\n      - name: Bundle files\n        run: |\n          mkdir -p ./temp/ox_core/common\n          cp ./{LICENSE,README.md,fxmanifest.lua} ./temp/ox_core\n          cp -r ./{lib,locales,sql,dist} ./temp/ox_core\n          cp -r ./common/data ./temp/ox_core/common/data\n          cd ./temp && zip -r ../ox_core.zip ./ox_core\n\n      - name: Publish package to npm registry\n        run: npm publish --access public\n\n      - name: Create release\n        uses: \"marvinpinto/action-automatic-releases@v1.2.1\"\n        with:\n          repo_token: ${{ secrets.GITHUB_TOKEN }}\n          prerelease: false\n          files: ox_core.zip\n\n      - name: Update tag\n        uses: EndBug/latest-tag@v1\n        with:\n          ref: ${{ github.ref_name }}\n"
  },
  {
    "path": ".gitignore",
    "content": "# ignore\nnode_modules\ndist\nfxmanifest.lua\n.yarn.installed\n*.zip\n**.d.ts\n*.tgz\n*.tsbuildinfo\n/package/\n/temp/\n\n# keep\n!./build.js\n"
  },
  {
    "path": ".npmignore",
    "content": "!/package/\n!**.d.ts\n!**.js\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "## Found a bug?\n\n- Check if the bug has already been reported under under [Issues](https://github.com/overextended/ox_core/issues).\n- If an **active** issue matches your own, provide additional information on the existing issue.\n- If there is no **open** issue related to the bug, create a new issue. Include a **descriptive title and clear description** with as much relevant information as possible, and include **code samples** or **reproduction steps**.\n- Use the relevant bug report template when creating an issue.\n\n## Patched a bug?\n\n- Open a new pull request including **only** the related changes.\n- Clearly describe the problem being fixed, and the solution. If the patch resolves any issues, mention them in the description.\n\n## Want to share an improvement or add a new feature?\n\n- Create an issue discussing the change and wait for feedback.\n- If you've already worked on the change you can submit a **draft** pull request for feedback and review.\n- Not all features and changes are desired! Changes may be messy, poorly-planned, incomplete, or simply incompatible with our design philosophy.\n\n## Is your change cosmetic (e.g. formatting)?\n\n- We will not accept pull requests that do not make substantial changes to the stability or functionality of the resource.\n\n## Submitting pull requests\n\n- Fork the repo and create a new branch.\n- If relevant, include example code to demonstrate your changes.\n- If you have modified or changed APIs, submit the changes to our [documentation](https://github.com/overextended/docs).\n- Ensure your coding style is consistent with the project.\n"
  },
  {
    "path": "LICENSE",
    "content": "                   GNU LESSER GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n\n  This version of the GNU Lesser General Public License incorporates\nthe terms and conditions of version 3 of the GNU General Public\nLicense, supplemented by the additional permissions listed below.\n\n  0. Additional Definitions.\n\n  As used herein, \"this License\" refers to version 3 of the GNU Lesser\nGeneral Public License, and the \"GNU GPL\" refers to version 3 of the GNU\nGeneral Public License.\n\n  \"The Library\" refers to a covered work governed by this License,\nother than an Application or a Combined Work as defined below.\n\n  An \"Application\" is any work that makes use of an interface provided\nby the Library, but which is not otherwise based on the Library.\nDefining a subclass of a class defined by the Library is deemed a mode\nof using an interface provided by the Library.\n\n  A \"Combined Work\" is a work produced by combining or linking an\nApplication with the Library.  The particular version of the Library\nwith which the Combined Work was made is also called the \"Linked\nVersion\".\n\n  The \"Minimal Corresponding Source\" for a Combined Work means the\nCorresponding Source for the Combined Work, excluding any source code\nfor portions of the Combined Work that, considered in isolation, are\nbased on the Application, and not on the Linked Version.\n\n  The \"Corresponding Application Code\" for a Combined Work means the\nobject code and/or source code for the Application, including any data\nand utility programs needed for reproducing the Combined Work from the\nApplication, but excluding the System Libraries of the Combined Work.\n\n  1. Exception to Section 3 of the GNU GPL.\n\n  You may convey a covered work under sections 3 and 4 of this License\nwithout being bound by section 3 of the GNU GPL.\n\n  2. Conveying Modified Versions.\n\n  If you modify a copy of the Library, and, in your modifications, a\nfacility refers to a function or data to be supplied by an Application\nthat uses the facility (other than as an argument passed when the\nfacility is invoked), then you may convey a copy of the modified\nversion:\n\n   a) under this License, provided that you make a good faith effort to\n   ensure that, in the event an Application does not supply the\n   function or data, the facility still operates, and performs\n   whatever part of its purpose remains meaningful, or\n\n   b) under the GNU GPL, with none of the additional permissions of\n   this License applicable to that copy.\n\n  3. Object Code Incorporating Material from Library Header Files.\n\n  The object code form of an Application may incorporate material from\na header file that is part of the Library.  You may convey such object\ncode under terms of your choice, provided that, if the incorporated\nmaterial is not limited to numerical parameters, data structure\nlayouts and accessors, or small macros, inline functions and templates\n(ten or fewer lines in length), you do both of the following:\n\n   a) Give prominent notice with each copy of the object code that the\n   Library is used in it and that the Library and its use are\n   covered by this License.\n\n   b) Accompany the object code with a copy of the GNU GPL and this license\n   document.\n\n  4. Combined Works.\n\n  You may convey a Combined Work under terms of your choice that,\ntaken together, effectively do not restrict modification of the\nportions of the Library contained in the Combined Work and reverse\nengineering for debugging such modifications, if you also do each of\nthe following:\n\n   a) Give prominent notice with each copy of the Combined Work that\n   the Library is used in it and that the Library and its use are\n   covered by this License.\n\n   b) Accompany the Combined Work with a copy of the GNU GPL and this license\n   document.\n\n   c) For a Combined Work that displays copyright notices during\n   execution, include the copyright notice for the Library among\n   these notices, as well as a reference directing the user to the\n   copies of the GNU GPL and this license document.\n\n   d) Do one of the following:\n\n       0) Convey the Minimal Corresponding Source under the terms of this\n       License, and the Corresponding Application Code in a form\n       suitable for, and under terms that permit, the user to\n       recombine or relink the Application with a modified version of\n       the Linked Version to produce a modified Combined Work, in the\n       manner specified by section 6 of the GNU GPL for conveying\n       Corresponding Source.\n\n       1) Use a suitable shared library mechanism for linking with the\n       Library.  A suitable mechanism is one that (a) uses at run time\n       a copy of the Library already present on the user's computer\n       system, and (b) will operate properly with a modified version\n       of the Library that is interface-compatible with the Linked\n       Version.\n\n   e) Provide Installation Information, but only if you would otherwise\n   be required to provide such information under section 6 of the\n   GNU GPL, and only to the extent that such information is\n   necessary to install and execute a modified version of the\n   Combined Work produced by recombining or relinking the\n   Application with a modified version of the Linked Version. (If\n   you use option 4d0, the Installation Information must accompany\n   the Minimal Corresponding Source and Corresponding Application\n   Code. If you use option 4d1, you must provide the Installation\n   Information in the manner specified by section 6 of the GNU GPL\n   for conveying Corresponding Source.)\n\n  5. Combined Libraries.\n\n  You may place library facilities that are a work based on the\nLibrary side by side in a single library together with other library\nfacilities that are not Applications and are not covered by this\nLicense, and convey such a combined library under terms of your\nchoice, if you do both of the following:\n\n   a) Accompany the combined library with a copy of the same work based\n   on the Library, uncombined with any other library facilities,\n   conveyed under the terms of this License.\n\n   b) Give prominent notice with the combined library that part of it\n   is a work based on the Library, and explaining where to find the\n   accompanying uncombined form of the same work.\n\n  6. Revised Versions of the GNU Lesser General Public License.\n\n  The Free Software Foundation may publish revised and/or new versions\nof the GNU Lesser General Public License from time to time. Such new\nversions will be similar in spirit to the present version, but may\ndiffer in detail to address new problems or concerns.\n\n  Each version is given a distinguishing version number. If the\nLibrary as you received it specifies that a certain numbered version\nof the GNU Lesser General Public License \"or any later version\"\napplies to it, you have the option of following the terms and\nconditions either of that published version or of any later version\npublished by the Free Software Foundation. If the Library as you\nreceived it does not specify a version number of the GNU Lesser\nGeneral Public License, you may choose any version of the GNU Lesser\nGeneral Public License ever published by the Free Software Foundation.\n\n  If the Library as you received it specifies that a proxy can decide\nwhether future versions of the GNU Lesser General Public License shall\napply, that proxy's public statement of acceptance of any version is\npermanent authorization for you to choose that version for the\nLibrary.\n"
  },
  {
    "path": "README.md",
    "content": "# ox_core\n\nA modern FiveM framework.\n\n![](https://img.shields.io/github/downloads/overextended/ox_core/total?logo=github)\n![](https://img.shields.io/github/downloads/overextended/ox_core/latest/total?logo=github)\n![](https://img.shields.io/github/contributors/overextended/ox_core?logo=github)\n![](https://img.shields.io/github/v/release/overextended/ox_core?logo=github) \n\n## 🔗 Links\n- 📚 [Documentation](https://overextended.dev/ox_core)\n  - For installation, setup, and everything else.\n- 🧾 [txAdmin recipe](https://github.com/overextended/txAdminRecipe)\n  - Install and configure ox_core in minutes.\n- 📦 [npm](https://www.npmjs.com/package/@overextended/ox_core)\n  - Use our npm package to create JavaScript resources using ox_core.\n- 🛤️ [Cfx.re](https://forum.cfx.re/t/pre-release-ox-core-player-and-vehicle-management/5253275)\n  - See our release thread for discussions or other information.\n\n## Third-party resources\n\nWhen releasing a resource using the this framework _do not use the ox prefix_. This creates confusion about the creator of the resource, and causes conflicts between similarly named resources.\n\n## Copyright\n\nCopyright © 2024 Overextended <https://github.com/overextended>\n\nThis program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.\n\nYou should have received a copy of the GNU Lesser General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "biome.json",
    "content": "{\n  \"files\": {\n    \"include\": [\"./client/*.ts\", \"./common/*.ts\", \"./server/*.ts\"],\n    \"ignore\": [\"**/*.d.ts\"]\n  },\n  \"linter\": {\n    \"enabled\": false,\n    \"rules\": {\n      \"suspicious\": {\n        \"noConfusingLabels\": \"off\",\n        \"noAssignInExpressions\": \"off\",\n        \"noExplicitAny\": \"off\",\n        \"noFallthroughSwitchClause\": \"off\",\n        \"noGlobalIsNan\": \"off\",\n        \"noControlCharactersInRegex\": \"off\"\n      },\n      \"correctness\": {\n        \"noUnusedLabels\": \"off\",\n        \"noVoidTypeReturn\": \"off\"\n      },\n      \"style\": {\n        \"useEnumInitializers\": \"off\",\n        \"noNonNullAssertion\": \"off\",\n        \"noParameterAssign\": \"off\",\n        \"noArguments\": \"off\",\n        \"noUnusedTemplateLiteral\": {\n          \"fix\": \"safe\"\n        }\n      },\n      \"performance\": {\n        \"noDelete\": \"off\"\n      },\n      \"complexity\": {\n        \"noForEach\": \"off\",\n        \"noUselessConstructor\": \"off\",\n        \"noStaticOnlyClass\": \"off\",\n        \"noThisInStatic\": \"off\"\n      }\n    }\n  },\n  \"formatter\": {\n    \"enabled\": true,\n    \"formatWithErrors\": false,\n    \"ignore\": [],\n    \"attributePosition\": \"auto\",\n    \"indentStyle\": \"space\",\n    \"indentWidth\": 2,\n    \"lineWidth\": 120,\n    \"lineEnding\": \"lf\"\n  },\n  \"javascript\": {\n    \"formatter\": {\n      \"arrowParentheses\": \"always\",\n      \"bracketSameLine\": false,\n      \"bracketSpacing\": true,\n      \"jsxQuoteStyle\": \"single\",\n      \"quoteProperties\": \"asNeeded\",\n      \"quoteStyle\": \"single\",\n      \"semicolons\": \"always\",\n      \"trailingCommas\": \"all\"\n    }\n  },\n  \"json\": {\n    \"formatter\": {\n      \"trailingCommas\": \"none\"\n    }\n  }\n}\n"
  },
  {
    "path": "build.js",
    "content": "//@ts-check\n\nimport { createBuilder, createFxmanifest } from \"@overextended/fx-utils\";\nimport { spawn } from \"child_process\";\n\nconst watch = process.argv.includes(\"--watch\");\n\nfunction exec(command) {\n  return new Promise((resolve) => {\n    const child = spawn(command, { stdio: \"inherit\", shell: true });\n\n    child.on(\"exit\", (code) => {\n      resolve(code === 0);\n    });\n  });\n}\n\nif (!watch) {\n  const tsc = await exec(`tsc --build ${watch ? \"--watch --preserveWatchOutput\" : \"\"} && tsc-alias`);\n\n  if (!tsc) process.exit(0);\n}\n\ncreateBuilder(\n  watch,\n  {\n    dropLabels: !watch ? [\"DEV\"] : undefined,\n  },\n  [\n    {\n      name: \"server\",\n      options: {\n        platform: \"node\",\n        target: [\"node22\"],\n        format: \"cjs\",\n        entryPoints: [`./server/index.ts`],\n      },\n    },\n    {\n      name: \"client\",\n      options: {\n        platform: \"browser\",\n        target: [\"es2023\"],\n        format: \"iife\",\n        entryPoints: [`./client/index.ts`],\n      },\n    },\n  ],\n  async (files) => {\n    await createFxmanifest({\n      client_scripts: [files.client],\n      server_scripts: [files.server],\n      files: [\"lib/init.lua\", \"lib/client/**.lua\", \"locales/*.json\", \"common/data/*.json\"],\n      dependencies: [\"/server:12913\", \"/onesync\"],\n      metadata: { node_version: \"22\" },\n    });\n  },\n);\n"
  },
  {
    "path": "client/config.ts",
    "content": "export * from '../common/config';\n\nexport const DEATH_SYSTEM = GetConvarInt('ox:deathSystem', 1) === 1;\nexport const CHARACTER_SELECT = GetConvarInt('ox:characterSelect', 1) === 1;\nexport const SPAWN_LOCATION = JSON.parse(GetConvar('ox:spawnLocation', '[-258.211, -293.077, 21.6132, 206.0]'));\nexport const HOSPITAL_BLIPS = GetConvarInt('ox:hospitalBlips', 1) === 1;\n"
  },
  {
    "path": "client/death.ts",
    "content": "import { cache, requestAnimDict, sleep } from \"@overextended/ox_lib/client\";\nimport { Vector3, Vector4 } from \"@nativewrappers/fivem\";\nimport { OxPlayer } from \"player\";\nimport { DEATH_SYSTEM, DEBUG, HOSPITAL_BLIPS } from \"config\";\nimport { LoadDataFile } from \"../common\";\n\nconst hospitals: Vector4[] = LoadDataFile(\"hospitals\").map((vec: number[]) => {\n  const hospital = Vector4.fromArray(vec);\n\n  if (HOSPITAL_BLIPS) {\n    const blip = AddBlipForCoord(hospital.x, hospital.y, hospital.z);\n\n    SetBlipSprite(blip, 61);\n    SetBlipDisplay(blip, 8);\n    SetBlipScale(blip, 0.8);\n    SetBlipColour(blip, 35);\n    SetBlipAsShortRange(blip, true);\n  }\n\n  return hospital;\n});\n\nconst anims = [\n  [\"missfinale_c1@\", \"lying_dead_player0\"],\n  [\"veh@low@front_ps@idle_duck\", \"sit\"],\n  [\"dead\", \"dead_a\"],\n];\n\nlet playerIsDead = false;\n\nasync function ClearDeath(tickId: number, bleedOut: boolean) {\n  const anim = cache.vehicle ? anims[1] : anims[0];\n\n  clearTick(tickId);\n\n  if (bleedOut) {\n    const coords = Vector3.fromArray(GetEntityCoords(cache.ped, true));\n    let distance = 1000;\n    const hospital = hospitals.reduce((closest, hospital) => {\n      const hospitalDistance = coords.distance(hospital);\n\n      if (hospitalDistance > distance) return closest;\n\n      distance = hospitalDistance;\n      return hospital;\n    });\n\n    DoScreenFadeOut(500);\n    RequestCollisionAtCoord(hospital.x, hospital.y, hospital.z);\n\n    while (!IsScreenFadedOut()) await sleep(0);\n\n    StopAnimTask(cache.ped, anim[0], anim[1], 8.0);\n    SetEntityCoordsNoOffset(cache.ped, hospital.x, hospital.y, hospital.z, false, false, false);\n    SetEntityHeading(cache.ped, hospital.w);\n    SetGameplayCamRelativeHeading(0);\n\n    await sleep(500);\n\n    DoScreenFadeIn(500);\n\n    while (!IsScreenFadedIn()) await sleep(0);\n  } else {\n    StopAnimTask(cache.ped, anim[0], anim[1], 8.0);\n  }\n\n  ClearPedBloodDamage(cache.ped);\n  SetPlayerControl(cache.playerId, false, 0);\n  SetEveryoneIgnorePlayer(cache.playerId, false);\n  SetPlayerControl(cache.playerId, true, 0);\n  SetPlayerInvincible(cache.playerId, false);\n\n  for (let index = 0; index < anims.length; index++) RemoveAnimDict(anims[index][0]);\n\n  emit(\"ox:playerRevived\");\n}\n\nconst bleedOutTime = DEBUG ? 100 : 1000;\n\nasync function OnPlayerDeath() {\n  OxPlayer.state.set(\"isDead\", true, true);\n  emit(\"ox_inventory:disarm\");\n  emit(\"ox:playerDeath\");\n\n  if (!DEATH_SYSTEM) return;\n\n  for (let index = 0; index < anims.length; index++) await requestAnimDict(anims[index][0]);\n\n  ShakeGameplayCam(\"DEATH_FAIL_IN_EFFECT_SHAKE\", 1.0);\n\n  let bleedOut = 0;\n  const tickId = setTick(() => {\n    const anim = cache.vehicle ? anims[1] : anims[0];\n\n    if (!IsEntityPlayingAnim(cache.ped, anim[0], anim[1], 3))\n      TaskPlayAnim(cache.ped, anim[0], anim[1], 50.0, 8.0, -1, 1, 1.0, false, false, false);\n\n    DisableFirstPersonCamThisFrame();\n\n    bleedOut++;\n\n    if (bleedOut > bleedOutTime) ClearDeath(tickId, true);\n  });\n\n  const coords = GetEntityCoords(cache.ped, true);\n  const health = Math.floor(Math.max(100, GetEntityMaxHealth(cache.ped) * 0.8));\n\n  NetworkResurrectLocalPlayer(coords[0], coords[1], coords[2], GetEntityHeading(cache.ped), 0, false);\n\n  if (cache.vehicle) SetPedIntoVehicle(cache.ped, cache.vehicle, cache.seat as number);\n\n  SetEntityInvincible(cache.ped, true);\n  SetEntityHealth(cache.ped, health);\n  SetEveryoneIgnorePlayer(cache.playerId, true);\n}\n\nAddStateBagChangeHandler(\"isDead\", `player:${cache.serverId}`, async (_bagName: string, _key: string, value: any) => {\n  playerIsDead = value;\n});\n\nfunction ResetDeathState() {\n  OxPlayer.state.set(\"isDead\", false, true);\n}\n\non(\"ox:playerLogout\", ResetDeathState);\non(\"ox:playerRevived\", ResetDeathState);\n\non(\"ox:playerLoaded\", () => {\n  const id: CitizenTimer = setInterval(() => {\n    if (!OxPlayer.isLoaded) return clearInterval(id);\n\n    if (!playerIsDead && IsPedDeadOrDying(PlayerPedId(), true)) OnPlayerDeath();\n  }, 200);\n});\n"
  },
  {
    "path": "client/index.ts",
    "content": "export * from '../common';\nimport { PLATE_PATTERN } from 'config';\nimport 'player';\nimport 'spawn';\nimport 'death';\nimport 'vehicle';\n\nfor (let i = 0; i < GetNumberOfVehicleNumberPlates(); i++) {\n  SetDefaultVehicleNumberPlateTextPattern(i, PLATE_PATTERN);\n}\n"
  },
  {
    "path": "client/player/index.ts",
    "content": "import { netEvent } from 'utils';\nimport type { Character, Dict, OxGroup, OxStatus, PlayerMetadata } from 'types';\nimport { GetGroupPermissions } from '../../common';\n\nexport const Statuses: Dict<OxStatus> = {};\nconst callableMethods: Dict<true> = {};\n\nclass PlayerSingleton {\n  userId: number;\n  charId?: number;\n  stateId?: string;\n  #isLoaded: boolean;\n  #groups: Dict<number>;\n  #statuses: Dict<number>;\n  #metadata: Dict<any>;\n  #state: StateBagInterface;\n\n  constructor() {\n    this.#isLoaded = false;\n    this.#groups = {};\n    this.#statuses = {};\n    this.#metadata = {};\n    this.#state = LocalPlayer.state;\n\n    Object.entries(Object.getOwnPropertyDescriptors(this.constructor.prototype)).reduce(\n      (methods: { [key: string]: true }, [name, desc]) => {\n        if (name !== 'constructor' && desc.writable && typeof desc.value === 'function') methods[name] = true;\n\n        return methods;\n      },\n      callableMethods,\n    );\n\n    netEvent('ox:startCharacterSelect', (userId: number) => {\n      this.userId = userId;\n\n      for (const key in this.#groups) delete this.#groups[key];\n\n      for (const key in this.#metadata) delete this.#metadata[key];\n    });\n\n    netEvent('ox:setActiveCharacter', async (character: Character, groups: Record<string, number>) => {\n      OxPlayer.charId = character.charId;\n      OxPlayer.stateId = character.stateId;\n\n      for (const key in groups) this.#groups[key] = groups[key];\n\n      DEV: {\n        console.log(this);\n        console.log(this.#groups);\n        console.log(this.#statuses);\n      }\n    });\n\n    netEvent('ox:setPlayerData', (key: string, value: any) => {\n      if (!this.charId) return;\n\n      this.#metadata[key] = value;\n      emit(`ox:player:${key}`, value);\n    });\n\n    netEvent('ox:setPlayerStatus', (key: string, value: number, set?: boolean) => {\n      if (set) {\n        Statuses[key] = GlobalState[`status.${key}`];\n      }\n\n      this.#statuses[key] = value;\n    });\n\n    netEvent('ox:setGroup', (name: string, grade: number) => {\n      this.#groups[name] = grade;\n    });\n\n    exports('GetPlayer', () => this);\n\n    exports('GetPlayerCalls', () => callableMethods);\n\n    exports('CallPlayer', (method: string, ...args: any[]) => {\n      const fn = (this as any)[method];\n\n      if (!fn) return console.error(`cannot call method ${method} (method does not exist)`);\n\n      if (!callableMethods[method]) return console.error(`cannot call method ${method} (method is not exported)`);\n\n      return fn.bind(this)(...args); // why :\\\n    });\n  }\n\n  get isLoaded() {\n    return this.#isLoaded;\n  }\n\n  set isLoaded(state: boolean) {\n    this.#isLoaded = state;\n  }\n\n  get state() {\n    return this.#state;\n  }\n\n  get<K extends string>(key: K | keyof PlayerMetadata): K extends keyof PlayerMetadata ? PlayerMetadata[K] : any;\n  get(key?: string) {\n    if (!key) return OxPlayer;\n\n    return this.#metadata[key];\n  }\n\n  getGroup(filter: string): number;\n  getGroup(filter: string[] | Record<string, number>): [string, number] | [];\n  getGroup(filter: string | string[] | Record<string, number>) {\n    if (typeof filter === 'string') {\n      return this.#groups[filter];\n    }\n\n    if (Array.isArray(filter)) {\n      for (const name of filter) {\n        const grade = this.#groups[name];\n        if (grade) return [name, grade];\n      }\n    } else if (typeof filter === 'object') {\n      for (const [name, requiredGrade] of Object.entries(filter)) {\n        const grade = this.#groups[name];\n        if (grade && (requiredGrade as number) <= grade) {\n          return [name, grade];\n        }\n      }\n    }\n  }\n\n  getGroupByType(type: string) {\n    const groupNames: string[] = GlobalState.groups;\n    const groups = groupNames.reduce((acc, groupName) => {\n      const group: OxGroup = GlobalState[`group.${groupName}`];\n\n      if (group.type === type) acc.push(groupName);\n\n      return acc;\n    }, [] as string[]);\n\n    return this.getGroup(groups);\n  }\n\n  getGroups() {\n    return this.#groups;\n  }\n\n  getStatus(name: string) {\n    return this.#statuses[name];\n  }\n\n  getStatuses() {\n    return this.#statuses;\n  }\n\n  setStatus(name: string, value: number) {\n    if (this.#statuses[name] === undefined) return false;\n\n    this.#statuses[name] = value < 0 ? 0 : value > 100 ? 100 : Number.parseFloat((value).toPrecision(8));\n    return true;\n  }\n\n  addStatus(name: string, value: number) {\n    if (this.#statuses[name] === undefined) return false;\n\n    const newValue = this.#statuses[name] + value;\n    this.#statuses[name] = newValue < 0 ? 0 : newValue > 100 ? 100 : Number.parseFloat((newValue).toPrecision(8));\n    return true;\n  }\n\n  removeStatus(name: string, value: number) {\n    if (this.#statuses[name] === undefined) return false;\n\n    const newValue = this.#statuses[name] - value;\n    this.#statuses[name] = newValue < 0 ? 0 : newValue > 100 ? 100 : Number.parseFloat((newValue).toPrecision(8));\n    return true;\n  }\n\n  hasPermission(permission: string): boolean {\n    const matchResult = permission.match(/^group\\.([^.]+)\\.(.*)/);\n    const groupName = matchResult?.[1];\n    permission = matchResult?.[2] ?? permission;\n\n    if (groupName) {\n      const grade = this.#groups[groupName];\n\n      if (!grade) return false;\n\n      const permissions = GetGroupPermissions(groupName);\n\n      for (let g = grade; g > 0; g--) {\n        const value = permissions[g] && permissions[g][permission];\n\n        if (value !== undefined) return value;\n      }\n    }\n\n    return false;\n  }\n}\n\nexport const OxPlayer = new PlayerSingleton();\n\nimport './status';\n"
  },
  {
    "path": "client/player/status.ts",
    "content": "import { OxPlayer, Statuses } from 'player';\n\nfunction UpdateStatuses() {\n  for (const name in Statuses) {\n    const status = Statuses[name];\n\n    if (!status?.onTick) continue;\n\n    const curValue = OxPlayer.getStatus(name) ?? status.default;\n    const newValue = curValue + status.onTick;\n\n    OxPlayer.setStatus(\n      name,\n      newValue < 0 ? 0 : newValue > 100 ? 100 : Number.parseFloat((newValue).toPrecision(8)),\n    );\n  }\n\n  emit('ox:statusTick', OxPlayer.getStatuses());\n  emitNet('ox:updateStatuses', OxPlayer.getStatuses());\n}\n\non('ox:playerLoaded', () => {\n  const id: CitizenTimer = setInterval(() => {\n    if (!OxPlayer.isLoaded) return clearInterval(id);\n\n    UpdateStatuses();\n  }, 1000);\n});\n"
  },
  {
    "path": "client/spawn.ts",
    "content": "import { sleep, waitFor } from \"@overextended/ox_lib\";\nimport { cache, inputDialog } from \"@overextended/ox_lib/client\";\nimport { OxPlayer } from \"./player\";\nimport { netEvent } from \"utils\";\nimport { CHARACTER_SELECT, SPAWN_LOCATION } from \"config\";\nimport locale from \"../common/locales\";\nimport type { Character, NewCharacter } from \"types\";\n\nDoScreenFadeOut(0);\nNetworkStartSoloTutorialSession();\nsetTimeout(() => emitNet(\"ox:playerJoined\"));\n\nasync function StartSession() {\n  if (IsPlayerSwitchInProgress()) {\n    StopPlayerSwitch();\n  }\n\n  if (GetIsLoadingScreenActive()) {\n    SendLoadingScreenMessage('{\"fullyLoaded\": true}');\n    ShutdownLoadingScreenNui();\n  }\n\n  NetworkStartSoloTutorialSession();\n  DoScreenFadeOut(0);\n  ShutdownLoadingScreen();\n  SetPlayerControl(cache.playerId, false, 0);\n  SetPlayerInvincible(cache.playerId, true);\n\n  while (!OxPlayer.isLoaded) {\n    DisableAllControlActions(0);\n    ThefeedHideThisFrame();\n    HideHudAndRadarThisFrame();\n\n    await sleep(0);\n  }\n\n  NetworkEndTutorialSession();\n  SetPlayerControl(cache.playerId, true, 0);\n  SetPlayerInvincible(cache.playerId, false);\n  SetMaxWantedLevel(0);\n  NetworkSetFriendlyFireOption(true);\n  SetPlayerHealthRechargeMultiplier(cache.playerId, 0.0);\n}\n\nnetEvent(\"ox:startCharacterSelect\", async (_userId: number, characters: Character[]) => {\n  if (OxPlayer.isLoaded) {\n    OxPlayer.isLoaded = false;\n\n    emit(\"ox:playerLogout\");\n  }\n\n  StartSession();\n\n  if (!CHARACTER_SELECT) return;\n\n  const character = characters[0];\n  const [x, y, z] = [\n    character?.x || SPAWN_LOCATION[0],\n    character?.y || SPAWN_LOCATION[1],\n    character?.z || SPAWN_LOCATION[2],\n  ];\n  const heading = character?.heading || SPAWN_LOCATION[3];\n\n  RequestCollisionAtCoord(x, y, z);\n  FreezeEntityPosition(cache.ped, true);\n  SetEntityCoordsNoOffset(cache.ped, x, y, z, true, true, false);\n  SetEntityHeading(cache.ped, heading);\n\n  SwitchOutPlayer(cache.ped, 1 | 8192, 1);\n\n  while (GetPlayerSwitchState() !== 5) await sleep(0);\n\n  DoScreenFadeIn(200);\n\n  if (character) {\n    return emitNet(\"ox:setActiveCharacter\", character.charId);\n  }\n\n  const input = await inputDialog(\n    locale(\"create_character\"),\n    [\n      {\n        type: \"input\",\n        required: true,\n        icon: \"user-pen\",\n        label: locale(\"firstname\"),\n        placeholder: \"John\",\n      },\n      {\n        type: \"input\",\n        required: true,\n        icon: \"user-pen\",\n        label: locale(\"lastname\"),\n        placeholder: \"Smith\",\n      },\n      {\n        type: \"select\",\n        required: true,\n        icon: \"circle-user\",\n        label: locale(\"gender\"),\n        options: [\n          {\n            label: locale(\"male\"),\n            value: \"male\",\n          },\n          {\n            label: locale(\"female\"),\n            value: \"female\",\n          },\n          {\n            label: locale(\"non_binary\"),\n            value: \"non_binary\",\n          },\n        ],\n      },\n      {\n        type: \"date\",\n        required: true,\n        icon: \"calendar-days\",\n        label: locale(\"date_of_birth\"),\n        format: \"YYYY-MM-DD\",\n        min: \"1900-01-01\",\n        max: \"2006-01-01\",\n        default: \"2006-01-01\",\n      },\n    ],\n    {\n      allowCancel: false,\n    },\n  );\n\n  if (!input) return;\n\n  emitNet(\"ox:setActiveCharacter\", <NewCharacter>{\n    firstName: input[0] as string,\n    lastName: input[1] as string,\n    gender: input[2] as string,\n    date: input[3] as number,\n  });\n});\n\nnetEvent(\"ox:setActiveCharacter\", async (character: Character) => {\n  if (CHARACTER_SELECT) {\n    SwitchInPlayer(PlayerPedId());\n    SetGameplayCamRelativeHeading(0);\n  }\n\n  await waitFor(() => (IsScreenFadedIn() && !IsPlayerSwitchInProgress() ? true : undefined), \"\", 0);\n\n  SetEntityHealth(cache.ped, character.health ?? GetEntityMaxHealth(cache.ped));\n  SetPedArmour(cache.ped, character.armour ?? 0);\n  FreezeEntityPosition(cache.ped, false);\n\n  OxPlayer.isLoaded = true;\n\n  emit(\"playerSpawned\");\n  emit(\"ox:playerLoaded\", OxPlayer, character.isNew);\n});\n"
  },
  {
    "path": "client/tsconfig.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"types\": [\"@citizenfx/client\"],\n    \"composite\": true,\n    \"paths\": {\n      \"types\": [\"../types\"]\n    }\n  },\n  \"include\": [\"./\", \"../types\", \"../common/\", \"../locales/en.json\"]\n}\n"
  },
  {
    "path": "client/utils.ts",
    "content": "export function netEvent(event: string, fn: Function) {\n  onNet(event, (...args: any[]) => {\n    if ((source as any) !== '') fn(...args);\n  });\n}\n"
  },
  {
    "path": "client/vehicle/index.ts",
    "content": "import { cache, onServerCallback, waitFor } from \"@overextended/ox_lib/client\";\nimport { Vector3 } from \"@nativewrappers/fivem\";\nimport { DEBUG } from \"../config\";\n\nif (DEBUG) import(\"./parser\");\n\nonServerCallback(\"ox:getNearbyVehicles\", (radius: number) => {\n  const nearbyEntities: number[] = [];\n  const playerCoords = Vector3.fromArray(GetEntityCoords(cache.ped, true));\n\n  (GetGamePool(\"CVehicle\") as number[]).forEach((entityId) => {\n    const coords = Vector3.fromArray(GetEntityCoords(entityId, true));\n    const distance = coords.distance(playerCoords);\n\n    if (distance <= (radius ?? 2) && NetworkGetEntityIsNetworked(entityId)) nearbyEntities.push(VehToNet(entityId));\n  });\n\n  return nearbyEntities;\n});\n\nAddStateBagChangeHandler(\"initVehicle\", \"\", async (bagName: string, key: string, value: any) => {\n  if (!value) return;\n\n  await waitFor(() => (!NetworkIsInTutorialSession() ? true : undefined), \"\", 0);\n\n  const entity = await waitFor(\n    async () => {\n      const entity = GetEntityFromStateBagName(bagName);\n\n      if (entity) return entity;\n    },\n    `failed to get entity from statebag name ${bagName}`,\n    10000,\n  );\n\n  if (!entity) return;\n\n  await waitFor(async () => {\n    if (!IsEntityWaitingForWorldCollision(entity)) return true;\n  });\n\n  if (NetworkGetEntityOwner(entity) !== cache.playerId) return;\n\n  SetVehicleOnGroundProperly(entity);\n  setTimeout(() => Entity(entity).state.set(key, null, true));\n});\n"
  },
  {
    "path": "client/vehicle/parser.ts",
    "content": "import { cache, notify, onServerCallback, requestModel, sleep } from \"@overextended/ox_lib/client\";\nimport { GetTopVehicleStats, GetVehicleData } from \"../../common/vehicles\";\nimport type { VehicleData, VehicleTypes, VehicleCategories } from \"types\";\n\nconst PRICE_WEIGHTS: Record<VehicleTypes, number> = {\n  automobile: 1600,\n  bicycle: 150,\n  bike: 500,\n  boat: 6000,\n  heli: 90000,\n  plane: 16000,\n  quadbike: 1100,\n  train: 6000,\n  submarinecar: 26000,\n  submarine: 22000,\n  blimp: 14000,\n  trailer: 10000,\n  amphibious_automobile: 6400,\n  amphibious_quadbike: 4600,\n};\n\nconst BATCH_SIZE = 10;\nconst vehicles = GetVehicleData();\n\nfunction GetVehicleModels(parseAll: boolean): string[] {\n  return GetAllVehicleModels()\n    .filter((vehicle: string) => parseAll || !vehicles[vehicle])\n    .sort();\n}\n\nasync function IsModelValid(hash: number): Promise<boolean> {\n  try {\n    await requestModel(hash, 10000);\n    return true;\n  } catch {\n    return false;\n  }\n}\n\nfunction SpawnVehicle(hash: number, coords: [number, number, number]): number {\n  const entity = CreateVehicle(hash, ...coords, 0, false, false);\n  SetPedIntoVehicle(cache.ped, entity, -1);\n  return entity;\n}\n\nfunction GetVehicleTypeEx(entity: number): VehicleTypes {\n  switch (GetVehicleTypeRaw(entity)) {\n    case 0:\n    default:\n      return \"automobile\";\n    case 1:\n      return \"plane\";\n    case 2:\n      return \"trailer\";\n    case 3:\n      return \"quadbike\";\n    case 5:\n      return \"submarinecar\";\n    case 6:\n      return \"amphibious_automobile\";\n    case 7:\n      return \"amphibious_quadbike\";\n    case 8:\n      return \"heli\";\n    case 9:\n      return \"blimp\";\n    case 11:\n      return \"bike\";\n    case 12:\n      return \"bicycle\";\n    case 13:\n      return \"boat\";\n    case 14:\n      return \"train\";\n    case 15:\n      return \"submarine\";\n  }\n}\n\nfunction ParseVehicleData(entity: number, hash: number, model: string): VehicleData {\n  let make = GetMakeNameFromVehicleModel(hash);\n  if (!make) make = GetMakeNameFromVehicleModel(model.replace(/\\W/g, \"\")) || \"\";\n\n  const vehicleType = GetVehicleTypeEx(entity);\n  const vehicleCategory: VehicleCategories =\n    vehicleType === \"heli\" || vehicleType === \"plane\" || vehicleType === \"blimp\"\n      ? \"air\"\n      : vehicleType === \"boat\" || vehicleType === \"submarine\"\n        ? \"sea\"\n        : \"land\";\n\n  const data: VehicleData = {\n    acceleration: +GetVehicleModelAcceleration(hash).toFixed(4),\n    braking: +GetVehicleModelMaxBraking(hash).toFixed(4),\n    handling: +GetVehicleModelEstimatedAgility(hash).toFixed(4),\n    speed: +GetVehicleModelEstimatedMaxSpeed(hash).toFixed(4),\n    traction: +GetVehicleModelMaxTraction(hash).toFixed(4),\n    name: GetLabelText(GetDisplayNameFromVehicleModel(hash)),\n    make: make ? GetLabelText(make) : \"\",\n    class: GetVehicleClass(entity),\n    seats: GetVehicleModelNumberOfSeats(hash),\n    doors: GetNumberOfVehicleDoors(entity),\n    type: vehicleType,\n    price: 0,\n    category: vehicleCategory,\n  };\n\n  if (DoesVehicleHaveWeapons(entity)) data.weapons = true;\n\n  CalculateVehiclePrice(data, entity);\n\n  console.log(`^5Parsed valid model ${model} (${data.make || \"?\"} ${data.name})^0`);\n\n  return data;\n}\n\nfunction CalculateVehiclePrice(data: VehicleData, entity: number) {\n  let price = data.braking + data.acceleration + data.handling + data.speed;\n\n  if (GetVehicleHasKers(entity)) price *= 2;\n  if (GetHasRocketBoost(entity)) price *= 3;\n  if (GetCanVehicleJump(entity)) price *= 1.5;\n  if (GetVehicleHasParachute(entity)) price *= 1.5;\n  if (data.weapons) price *= 5;\n\n  data.price = Math.floor(price * (PRICE_WEIGHTS[data.type] ?? 1));\n}\n\nfunction CleanupVehicle(entity: number, coords: [number, number, number]) {\n  SetVehicleAsNoLongerNeeded(entity);\n  SetModelAsNoLongerNeeded(GetEntityModel(entity));\n  DeleteEntity(entity);\n  SetEntityCoordsNoOffset(cache.ped, ...coords, false, false, false);\n}\n\n/**\n * An event only registered when DEBUG is enabled.\n * Allows external scripts to freely modify vehicle data.\n */\non(\"ox:setVehicleData\", (model: string, data: Record<string, any>) => {\n  if (!vehicles[model]) console.error(`Cannot set vehicle data for ${model} (invalid model)`);\n\n  Object.assign(vehicles[model], data);\n});\n\nonServerCallback(\"ox:generateVehicleData\", async (parseAll: boolean) => {\n  const coords = GetEntityCoords(cache.ped, true) as [number, number, number];\n  const invalidVehicles: string[] = [];\n  const vehicleModels = GetVehicleModels(parseAll);\n\n  SetPlayerControl(cache.playerId, false, 1 << 8);\n  FreezeEntityPosition(cache.ped, true);\n\n  notify({ title: \"Generating vehicle data\", description: `${vehicleModels.length} models loaded.`, type: \"inform\" });\n\n  let parsed = 0;\n\n  for (let i = 0; i < vehicleModels.length; i += BATCH_SIZE) {\n    await Promise.all(\n      vehicleModels.slice(i, i + BATCH_SIZE).map(async (model) => {\n        model = model.toLowerCase();\n        const hash = GetHashKey(model);\n        const isValid = await IsModelValid(hash);\n\n        if (!isValid) return invalidVehicles.push(model);\n\n        try {\n          const entity = SpawnVehicle(hash, coords);\n          vehicles[model] = ParseVehicleData(entity, hash, model);\n          emit(`ox:parsedVehicle`, model, entity);\n          ++parsed;\n\n          CleanupVehicle(entity, coords);\n        } catch {\n          invalidVehicles.push(model);\n        }\n      }),\n    );\n  }\n\n  SetPlayerControl(cache.playerId, true, 0);\n  FreezeEntityPosition(cache.ped, false);\n\n  notify({\n    title: \"Generated vehicle data\",\n    description: `Generated data for ${parsed}/${vehicleModels.length} models.`,\n    type: \"success\",\n  });\n\n  console.log(`^5Generated data for ${parsed}/${vehicleModels.length} models.^0`);\n\n  if (invalidVehicles.length)\n    console.log(\n      `^3Failed to parse data for ${invalidVehicles.length} invalid vehicles.\\n${JSON.stringify(invalidVehicles, null, 2)}^0`,\n    );\n\n  await sleep(5000);\n\n  return [vehicles, GetTopVehicleStats(), invalidVehicles];\n});\n"
  },
  {
    "path": "common/config.ts",
    "content": "export const SV_LAN = GetConvarInt('sv_lan', 0) === 1;\nexport const CHARACTER_SLOTS = GetConvarInt('ox:characterSlots', 1);\nexport const PLATE_PATTERN = GetConvar('ox:plateFormat', '........').toUpperCase();\nexport const DEFAULT_VEHICLE_STORE = GetConvar('ox:defaultVehicleStore', 'impound');\n\nexport const DEBUG = (() => {\n  DEV: return true;\n  //@ts-ignore\n  return SV_LAN || GetConvarInt('ox:debug', 0) === 1;\n})();\n"
  },
  {
    "path": "common/data/hospitals.json",
    "content": "[\n  [340.5, -1396.8, 32.5, 60.1],\n  [-449.3, -340.2, 34.5, 76.2],\n  [295.6, -583.9, 43.2, 79.5],\n  [1840.1, 3670.7, 33.9, 207.6],\n  [1153.2, -1526.4, 34.8, 352.4],\n  [-244.7, 6328.3, 32.4, 242.1]\n]\n"
  },
  {
    "path": "common/data/vehicleStats.json",
    "content": "{\n  \"air\": {\n    \"acceleration\": 21.56,\n    \"braking\": 22.417,\n    \"handling\": 21.56,\n    \"speed\": 109.7643,\n    \"traction\": 2.15\n  },\n  \"land\": {\n    \"acceleration\": 0.82,\n    \"braking\": 3.1,\n    \"handling\": 1.2,\n    \"speed\": 53.8674,\n    \"traction\": 3.2925\n  },\n  \"sea\": {\n    \"acceleration\": 18,\n    \"braking\": 0.4,\n    \"handling\": 18.38,\n    \"speed\": 46.6667,\n    \"traction\": 0\n  }\n}"
  },
  {
    "path": "common/data/vehicles.json",
    "content": "{\n  \"adder\": {\n    \"acceleration\": 0.32,\n    \"braking\": 1,\n    \"handling\": 0.7,\n    \"speed\": 51.771,\n    \"traction\": 2.5,\n    \"name\": \"Adder\",\n    \"make\": \"Truffade\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 86065,\n    \"category\": \"land\"\n  },\n  \"airbus\": {\n    \"acceleration\": 0.12,\n    \"braking\": 0.25,\n    \"handling\": 0.5,\n    \"speed\": 25.5809,\n    \"traction\": 1.45,\n    \"name\": \"Airport Bus\",\n    \"make\": \"\",\n    \"class\": 17,\n    \"seats\": 16,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 42321,\n    \"category\": \"land\"\n  },\n  \"airtug\": {\n    \"acceleration\": 0.06,\n    \"braking\": 0.3,\n    \"handling\": 0.44,\n    \"speed\": 10.9417,\n    \"traction\": 1.15,\n    \"name\": \"Airtug\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"automobile\",\n    \"price\": 18786,\n    \"category\": \"land\"\n  },\n  \"akula\": {\n    \"acceleration\": 5.88,\n    \"braking\": 3.592,\n    \"handling\": 5.88,\n    \"speed\": 61.0891,\n    \"traction\": 1.3,\n    \"name\": \"Akula\",\n    \"make\": \"\",\n    \"class\": 15,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"heli\",\n    \"price\": 34398495,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"akuma\": {\n    \"acceleration\": 0.4,\n    \"braking\": 1.2,\n    \"handling\": 0.78,\n    \"speed\": 48.3333,\n    \"traction\": 2.15,\n    \"name\": \"Akuma\",\n    \"make\": \"Dinka\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 25356,\n    \"category\": \"land\"\n  },\n  \"aleutian\": {\n    \"acceleration\": 0.2795,\n    \"braking\": 0.75,\n    \"handling\": 0.6595,\n    \"speed\": 39.6667,\n    \"traction\": 2.098,\n    \"name\": \"Aleutian\",\n    \"make\": \"Vapid\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 66169,\n    \"category\": \"land\"\n  },\n  \"alkonost\": {\n    \"acceleration\": 13.524,\n    \"braking\": 11.1734,\n    \"handling\": 13.524,\n    \"speed\": 82.6192,\n    \"traction\": 1.85,\n    \"name\": \"RO-86 Alkonost\",\n    \"make\": \"\",\n    \"class\": 16,\n    \"seats\": 10,\n    \"doors\": 2,\n    \"type\": \"plane\",\n    \"price\": 1933449,\n    \"category\": \"air\"\n  },\n  \"alpha\": {\n    \"acceleration\": 0.33,\n    \"braking\": 1,\n    \"handling\": 0.71,\n    \"speed\": 49.5388,\n    \"traction\": 2.5,\n    \"name\": \"Alpha\",\n    \"make\": \"Albany\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 82526,\n    \"category\": \"land\"\n  },\n  \"alphaz1\": {\n    \"acceleration\": 20.58,\n    \"braking\": 20.58,\n    \"handling\": 20.58,\n    \"speed\": 100,\n    \"traction\": 1.15,\n    \"name\": \"Alpha-Z1\",\n    \"make\": \"Buckingham\",\n    \"class\": 16,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"plane\",\n    \"price\": 2587840,\n    \"category\": \"air\"\n  },\n  \"ambulance\": {\n    \"acceleration\": 0.18,\n    \"braking\": 0.6,\n    \"handling\": 0.56,\n    \"speed\": 39.9117,\n    \"traction\": 1.95,\n    \"name\": \"Ambulance\",\n    \"make\": \"\",\n    \"class\": 18,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 66002,\n    \"category\": \"land\"\n  },\n  \"annihilator\": {\n    \"acceleration\": 4.606,\n    \"braking\": 2.1766,\n    \"handling\": 4.606,\n    \"speed\": 47.2565,\n    \"traction\": 1.3,\n    \"name\": \"Annihilator\",\n    \"make\": \"\",\n    \"class\": 15,\n    \"seats\": 6,\n    \"doors\": 2,\n    \"type\": \"heli\",\n    \"price\": 26390295,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"annihilator2\": {\n    \"acceleration\": 5.292,\n    \"braking\": 2.7894,\n    \"handling\": 5.292,\n    \"speed\": 52.7096,\n    \"traction\": 1.3,\n    \"name\": \"Annihilator Stealth\",\n    \"make\": \"\",\n    \"class\": 15,\n    \"seats\": 6,\n    \"doors\": 4,\n    \"type\": \"heli\",\n    \"price\": 29737349,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"apc\": {\n    \"acceleration\": 0.21,\n    \"braking\": 0.2,\n    \"handling\": 0.59,\n    \"speed\": 23.0063,\n    \"traction\": 2.4,\n    \"name\": \"APC\",\n    \"make\": \"HVY\",\n    \"class\": 19,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"amphibious_automobile\",\n    \"price\": 768201,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"ardent\": {\n    \"acceleration\": 0.285,\n    \"braking\": 0.9,\n    \"handling\": 0.665,\n    \"speed\": 47.791,\n    \"traction\": 2.65,\n    \"name\": \"Ardent\",\n    \"make\": \"Ocelot\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 397128,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"armytanker\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5051,\n    \"traction\": 1.8,\n    \"name\": \"Army Trailer\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 0,\n    \"type\": \"trailer\",\n    \"price\": 5749,\n    \"category\": \"land\"\n  },\n  \"armytrailer\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5132,\n    \"traction\": 3,\n    \"name\": \"Army Trailer\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 0,\n    \"type\": \"trailer\",\n    \"price\": 5668,\n    \"category\": \"land\"\n  },\n  \"armytrailer2\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5132,\n    \"traction\": 3,\n    \"name\": \"Army Trailer\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 0,\n    \"type\": \"trailer\",\n    \"price\": 5668,\n    \"category\": \"land\"\n  },\n  \"asbo\": {\n    \"acceleration\": 0.234,\n    \"braking\": 0.47,\n    \"handling\": 0.614,\n    \"speed\": 38.0701,\n    \"traction\": 1.92,\n    \"name\": \"Asbo\",\n    \"make\": \"Maxwell\",\n    \"class\": 0,\n    \"seats\": 2,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 63020,\n    \"category\": \"land\"\n  },\n  \"asea\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.4,\n    \"handling\": 0.58,\n    \"speed\": 38.4289,\n    \"traction\": 2.05,\n    \"name\": \"Asea\",\n    \"make\": \"Declasse\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 63374,\n    \"category\": \"land\"\n  },\n  \"asea2\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.4,\n    \"handling\": 0.58,\n    \"speed\": 38.4289,\n    \"traction\": 2.05,\n    \"name\": \"Asea\",\n    \"make\": \"Declasse\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 63374,\n    \"category\": \"land\"\n  },\n  \"asterope\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.9,\n    \"handling\": 0.58,\n    \"speed\": 38.4289,\n    \"traction\": 2.5,\n    \"name\": \"Asterope\",\n    \"make\": \"Karin\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 64174,\n    \"category\": \"land\"\n  },\n  \"asterope2\": {\n    \"acceleration\": 0.238,\n    \"braking\": 0.9,\n    \"handling\": 0.618,\n    \"speed\": 42.8105,\n    \"traction\": 2.335,\n    \"name\": \"Asterope GZ\",\n    \"make\": \"Karin\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 71306,\n    \"category\": \"land\"\n  },\n  \"astron\": {\n    \"acceleration\": 0.324,\n    \"braking\": 0.48,\n    \"handling\": 0.704,\n    \"speed\": 49.5667,\n    \"traction\": 2.185,\n    \"name\": \"Astron\",\n    \"make\": \"Pfister\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 81719,\n    \"category\": \"land\"\n  },\n  \"autarch\": {\n    \"acceleration\": 0.377,\n    \"braking\": 1.2,\n    \"handling\": 0.757,\n    \"speed\": 51.2899,\n    \"traction\": 2.705,\n    \"name\": \"Autarch\",\n    \"make\": \"Overflod\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 85798,\n    \"category\": \"land\"\n  },\n  \"avarus\": {\n    \"acceleration\": 0.27,\n    \"braking\": 1,\n    \"handling\": 0.65,\n    \"speed\": 44.1369,\n    \"traction\": 1.85,\n    \"name\": \"Avarus\",\n    \"make\": \"LCC\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 23028,\n    \"category\": \"land\"\n  },\n  \"avenger\": {\n    \"acceleration\": 8.82,\n    \"braking\": 8.4657,\n    \"handling\": 8.82,\n    \"speed\": 95.9834,\n    \"traction\": 2.15,\n    \"name\": \"Avenger\",\n    \"make\": \"Mammoth\",\n    \"class\": 16,\n    \"seats\": 3,\n    \"doors\": 3,\n    \"type\": \"plane\",\n    \"price\": 9767128,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"avenger2\": {\n    \"acceleration\": 8.82,\n    \"braking\": 8.4657,\n    \"handling\": 8.82,\n    \"speed\": 95.9834,\n    \"traction\": 2.15,\n    \"name\": \"Avenger\",\n    \"make\": \"Mammoth\",\n    \"class\": 16,\n    \"seats\": 3,\n    \"doors\": 3,\n    \"type\": \"plane\",\n    \"price\": 9767128,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"avenger3\": {\n    \"acceleration\": 8.82,\n    \"braking\": 8.4657,\n    \"handling\": 8.82,\n    \"speed\": 95.9834,\n    \"traction\": 2.15,\n    \"name\": \"Avenger\",\n    \"make\": \"Mammoth\",\n    \"class\": 16,\n    \"seats\": 3,\n    \"doors\": 3,\n    \"type\": \"plane\",\n    \"price\": 9767128,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"avenger4\": {\n    \"acceleration\": 8.82,\n    \"braking\": 8.4657,\n    \"handling\": 8.82,\n    \"speed\": 95.9834,\n    \"traction\": 2.15,\n    \"name\": \"Avenger\",\n    \"make\": \"Mammoth\",\n    \"class\": 16,\n    \"seats\": 3,\n    \"doors\": 3,\n    \"type\": \"plane\",\n    \"price\": 9767128,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"avisa\": {\n    \"acceleration\": 10.5,\n    \"braking\": 0.4,\n    \"handling\": 10.88,\n    \"speed\": 25,\n    \"traction\": 0,\n    \"name\": \"Avisa\",\n    \"make\": \"Kraken\",\n    \"class\": 14,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"submarine\",\n    \"price\": 1029160,\n    \"category\": \"sea\"\n  },\n  \"bagger\": {\n    \"acceleration\": 0.21,\n    \"braking\": 1.2,\n    \"handling\": 0.59,\n    \"speed\": 37.8686,\n    \"traction\": 1.65,\n    \"name\": \"Bagger\",\n    \"make\": \"Western\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 19934,\n    \"category\": \"land\"\n  },\n  \"baletrailer\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5132,\n    \"traction\": 3.3,\n    \"name\": \"Baletrailer\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 0,\n    \"type\": \"trailer\",\n    \"price\": 5668,\n    \"category\": \"land\"\n  },\n  \"baller\": {\n    \"acceleration\": 0.21,\n    \"braking\": 0.6,\n    \"handling\": 0.59,\n    \"speed\": 39.6177,\n    \"traction\": 1.9,\n    \"name\": \"Baller\",\n    \"make\": \"Gallivanter\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 65628,\n    \"category\": \"land\"\n  },\n  \"baller2\": {\n    \"acceleration\": 0.27,\n    \"braking\": 0.6,\n    \"handling\": 0.65,\n    \"speed\": 45,\n    \"traction\": 2,\n    \"name\": \"Baller\",\n    \"make\": \"Gallivanter\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 74432,\n    \"category\": \"land\"\n  },\n  \"baller3\": {\n    \"acceleration\": 0.275,\n    \"braking\": 0.6,\n    \"handling\": 0.655,\n    \"speed\": 45,\n    \"traction\": 2,\n    \"name\": \"Baller LE\",\n    \"make\": \"Gallivanter\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 74448,\n    \"category\": \"land\"\n  },\n  \"baller4\": {\n    \"acceleration\": 0.27,\n    \"braking\": 0.57,\n    \"handling\": 0.65,\n    \"speed\": 45,\n    \"traction\": 2,\n    \"name\": \"Baller LE LWB\",\n    \"make\": \"Gallivanter\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 74384,\n    \"category\": \"land\"\n  },\n  \"baller5\": {\n    \"acceleration\": 0.27,\n    \"braking\": 0.58,\n    \"handling\": 0.65,\n    \"speed\": 45,\n    \"traction\": 2,\n    \"name\": \"Baller LE (Armored)\",\n    \"make\": \"Gallivanter\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 74400,\n    \"category\": \"land\"\n  },\n  \"baller6\": {\n    \"acceleration\": 0.265,\n    \"braking\": 0.55,\n    \"handling\": 0.645,\n    \"speed\": 45,\n    \"traction\": 2,\n    \"name\": \"Baller LE LWB (Armored)\",\n    \"make\": \"Gallivanter\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 74336,\n    \"category\": \"land\"\n  },\n  \"baller7\": {\n    \"acceleration\": 0.3025,\n    \"braking\": 0.7,\n    \"handling\": 0.6825,\n    \"speed\": 46.5833,\n    \"traction\": 2.2,\n    \"name\": \"Baller ST\",\n    \"make\": \"Gallivanter\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 77229,\n    \"category\": \"land\"\n  },\n  \"baller8\": {\n    \"acceleration\": 0.295,\n    \"braking\": 0.9225,\n    \"handling\": 0.675,\n    \"speed\": 46.6667,\n    \"traction\": 2.283,\n    \"name\": \"Baller ST-D\",\n    \"make\": \"Gallivanter\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 77694,\n    \"category\": \"land\"\n  },\n  \"banshee\": {\n    \"acceleration\": 0.34,\n    \"braking\": 1,\n    \"handling\": 0.82,\n    \"speed\": 47.5245,\n    \"traction\": 2.42,\n    \"name\": \"Banshee\",\n    \"make\": \"Bravado\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 79495,\n    \"category\": \"land\"\n  },\n  \"banshee2\": {\n    \"acceleration\": 0.3475,\n    \"braking\": 1,\n    \"handling\": 0.7275,\n    \"speed\": 44.7295,\n    \"traction\": 2.5,\n    \"name\": \"Banshee 900R\",\n    \"make\": \"Bravado\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 74887,\n    \"category\": \"land\"\n  },\n  \"banshee3\": {\n    \"acceleration\": 0.3878,\n    \"braking\": 0.72,\n    \"handling\": 0.8478,\n    \"speed\": 53.8674,\n    \"traction\": 2.6065,\n    \"name\": \"Banshee GTS\",\n    \"make\": \"Bravado\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 89316,\n    \"category\": \"land\"\n  },\n  \"barracks\": {\n    \"acceleration\": 0.11,\n    \"braking\": 0.3,\n    \"handling\": 0.49,\n    \"speed\": 32.4021,\n    \"traction\": 1.65,\n    \"name\": \"Barracks\",\n    \"make\": \"\",\n    \"class\": 19,\n    \"seats\": 10,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 53283,\n    \"category\": \"land\"\n  },\n  \"barracks2\": {\n    \"acceleration\": 0.23,\n    \"braking\": 1,\n    \"handling\": 0.61,\n    \"speed\": 35.7058,\n    \"traction\": 1.55,\n    \"name\": \"Barracks Semi\",\n    \"make\": \"HVY\",\n    \"class\": 19,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 60073,\n    \"category\": \"land\"\n  },\n  \"barracks3\": {\n    \"acceleration\": 0.11,\n    \"braking\": 0.3,\n    \"handling\": 0.49,\n    \"speed\": 32.4021,\n    \"traction\": 1.65,\n    \"name\": \"Barracks\",\n    \"make\": \"\",\n    \"class\": 19,\n    \"seats\": 10,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 53283,\n    \"category\": \"land\"\n  },\n  \"barrage\": {\n    \"acceleration\": 0.2225,\n    \"braking\": 0.85,\n    \"handling\": 0.6025,\n    \"speed\": 39.938,\n    \"traction\": 1.75,\n    \"name\": \"Barrage\",\n    \"make\": \"\",\n    \"class\": 19,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 332904,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"bati\": {\n    \"acceleration\": 0.3,\n    \"braking\": 1.4,\n    \"handling\": 0.68,\n    \"speed\": 49.296,\n    \"traction\": 2.32,\n    \"name\": \"Bati 801\",\n    \"make\": \"Pegassi\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 25838,\n    \"category\": \"land\"\n  },\n  \"bati2\": {\n    \"acceleration\": 0.3,\n    \"braking\": 1.4,\n    \"handling\": 0.68,\n    \"speed\": 49.296,\n    \"traction\": 2.32,\n    \"name\": \"Bati 801RR\",\n    \"make\": \"Pegassi\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 25838,\n    \"category\": \"land\"\n  },\n  \"benson\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.25,\n    \"handling\": 0.54,\n    \"speed\": 36.9472,\n    \"traction\": 1.75,\n    \"name\": \"Benson\",\n    \"make\": \"Vapid\",\n    \"class\": 20,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 60635,\n    \"category\": \"land\"\n  },\n  \"benson2\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.25,\n    \"handling\": 0.54,\n    \"speed\": 36.9472,\n    \"traction\": 1.75,\n    \"name\": \"Benson (Cluckin' Bell)\",\n    \"make\": \"Vapid\",\n    \"class\": 20,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 60635,\n    \"category\": \"land\"\n  },\n  \"besra\": {\n    \"acceleration\": 21.07,\n    \"braking\": 18.4796,\n    \"handling\": 21.07,\n    \"speed\": 87.7058,\n    \"traction\": 2.15,\n    \"name\": \"Besra\",\n    \"make\": \"Western\",\n    \"class\": 16,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"plane\",\n    \"price\": 2373206,\n    \"category\": \"air\"\n  },\n  \"bestiagts\": {\n    \"acceleration\": 0.32,\n    \"braking\": 1,\n    \"handling\": 0.7,\n    \"speed\": 47.7946,\n    \"traction\": 2.42,\n    \"name\": \"Bestia GTS\",\n    \"make\": \"Grotti\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 79703,\n    \"category\": \"land\"\n  },\n  \"bf400\": {\n    \"acceleration\": 0.29,\n    \"braking\": 1.1,\n    \"handling\": 0.67,\n    \"speed\": 44.1479,\n    \"traction\": 2.15,\n    \"name\": \"BF400\",\n    \"make\": \"Nagasaki\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 23103,\n    \"category\": \"land\"\n  },\n  \"bfinjection\": {\n    \"acceleration\": 0.22,\n    \"braking\": 0.62,\n    \"handling\": 0.6,\n    \"speed\": 40.7799,\n    \"traction\": 1.85,\n    \"name\": \"Injection\",\n    \"make\": \"BF\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 67551,\n    \"category\": \"land\"\n  },\n  \"biff\": {\n    \"acceleration\": 0.12,\n    \"braking\": 0.3,\n    \"handling\": 0.5,\n    \"speed\": 34.4979,\n    \"traction\": 1.65,\n    \"name\": \"Biff\",\n    \"make\": \"HVY\",\n    \"class\": 20,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 56668,\n    \"category\": \"land\"\n  },\n  \"bifta\": {\n    \"acceleration\": 0.26,\n    \"braking\": 0.7,\n    \"handling\": 0.64,\n    \"speed\": 45.1953,\n    \"traction\": 2.05,\n    \"name\": \"Bifta\",\n    \"make\": \"BF\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 0,\n    \"type\": \"automobile\",\n    \"price\": 74872,\n    \"category\": \"land\"\n  },\n  \"bison\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.6,\n    \"handling\": 0.58,\n    \"speed\": 37.5559,\n    \"traction\": 2.05,\n    \"name\": \"Bison\",\n    \"make\": \"Bravado\",\n    \"class\": 12,\n    \"seats\": 6,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 62297,\n    \"category\": \"land\"\n  },\n  \"bison2\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.6,\n    \"handling\": 0.58,\n    \"speed\": 37.5559,\n    \"traction\": 2.05,\n    \"name\": \"Bison\",\n    \"make\": \"Bravado\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 62297,\n    \"category\": \"land\"\n  },\n  \"bison3\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.6,\n    \"handling\": 0.58,\n    \"speed\": 37.5559,\n    \"traction\": 2.05,\n    \"name\": \"Bison\",\n    \"make\": \"Bravado\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 62297,\n    \"category\": \"land\"\n  },\n  \"bjxl\": {\n    \"acceleration\": 0.19,\n    \"braking\": 0.8,\n    \"handling\": 0.57,\n    \"speed\": 36.3729,\n    \"traction\": 2.05,\n    \"name\": \"BeeJay XL\",\n    \"make\": \"Karin\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 60692,\n    \"category\": \"land\"\n  },\n  \"blade\": {\n    \"acceleration\": 0.324,\n    \"braking\": 0.8,\n    \"handling\": 0.704,\n    \"speed\": 42.2471,\n    \"traction\": 2.23,\n    \"name\": \"Blade\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 70520,\n    \"category\": \"land\"\n  },\n  \"blazer\": {\n    \"acceleration\": 0.2,\n    \"braking\": 1,\n    \"handling\": 0.58,\n    \"speed\": 33.9831,\n    \"traction\": 2.6,\n    \"name\": \"Blazer\",\n    \"make\": \"Nagasaki\",\n    \"class\": 9,\n    \"seats\": 1,\n    \"doors\": 0,\n    \"type\": \"quadbike\",\n    \"price\": 39339,\n    \"category\": \"land\"\n  },\n  \"blazer2\": {\n    \"acceleration\": 0.12,\n    \"braking\": 0.8,\n    \"handling\": 0.5,\n    \"speed\": 24.7121,\n    \"traction\": 2,\n    \"name\": \"Blazer Lifeguard\",\n    \"make\": \"Nagasaki\",\n    \"class\": 9,\n    \"seats\": 1,\n    \"doors\": 0,\n    \"type\": \"quadbike\",\n    \"price\": 28745,\n    \"category\": \"land\"\n  },\n  \"blazer3\": {\n    \"acceleration\": 0.2,\n    \"braking\": 1,\n    \"handling\": 0.58,\n    \"speed\": 33.9831,\n    \"traction\": 2.6,\n    \"name\": \"Hot Rod Blazer\",\n    \"make\": \"Nagasaki\",\n    \"class\": 9,\n    \"seats\": 1,\n    \"doors\": 0,\n    \"type\": \"quadbike\",\n    \"price\": 39339,\n    \"category\": \"land\"\n  },\n  \"blazer4\": {\n    \"acceleration\": 0.25,\n    \"braking\": 1,\n    \"handling\": 0.63,\n    \"speed\": 38.876,\n    \"traction\": 2.7,\n    \"name\": \"Street Blazer\",\n    \"make\": \"Nagasaki\",\n    \"class\": 9,\n    \"seats\": 1,\n    \"doors\": 0,\n    \"type\": \"quadbike\",\n    \"price\": 44831,\n    \"category\": \"land\"\n  },\n  \"blazer5\": {\n    \"acceleration\": 0.272,\n    \"braking\": 1,\n    \"handling\": 0.652,\n    \"speed\": 40.8773,\n    \"traction\": 2.7,\n    \"name\": \"Blazer Aqua\",\n    \"make\": \"Nagasaki\",\n    \"class\": 9,\n    \"seats\": 1,\n    \"doors\": 0,\n    \"type\": \"amphibious_quadbike\",\n    \"price\": 984429,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"blimp\": {\n    \"acceleration\": 5.684,\n    \"braking\": 3.9788,\n    \"handling\": 5.684,\n    \"speed\": 70,\n    \"traction\": 0.65,\n    \"name\": \"Atomic Blimp\",\n    \"make\": \"\",\n    \"class\": 16,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"blimp\",\n    \"price\": 1194855,\n    \"category\": \"air\"\n  },\n  \"blimp2\": {\n    \"acceleration\": 6.076,\n    \"braking\": 4.2532,\n    \"handling\": 6.076,\n    \"speed\": 70,\n    \"traction\": 0.65,\n    \"name\": \"Xero Blimp\",\n    \"make\": \"\",\n    \"class\": 16,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"blimp\",\n    \"price\": 1209672,\n    \"category\": \"air\"\n  },\n  \"blimp3\": {\n    \"acceleration\": 5.684,\n    \"braking\": 3.9788,\n    \"handling\": 5.684,\n    \"speed\": 70,\n    \"traction\": 0.65,\n    \"name\": \"Blimp\",\n    \"make\": \"\",\n    \"class\": 16,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"blimp\",\n    \"price\": 1194855,\n    \"category\": \"air\"\n  },\n  \"blista\": {\n    \"acceleration\": 0.23,\n    \"braking\": 0.6,\n    \"handling\": 0.61,\n    \"speed\": 41.9174,\n    \"traction\": 2.05,\n    \"name\": \"Blista\",\n    \"make\": \"Dinka\",\n    \"class\": 0,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 69371,\n    \"category\": \"land\"\n  },\n  \"blista2\": {\n    \"acceleration\": 0.23,\n    \"braking\": 0.55,\n    \"handling\": 0.61,\n    \"speed\": 41.9174,\n    \"traction\": 2.1,\n    \"name\": \"Blista Compact\",\n    \"make\": \"Dinka\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 69291,\n    \"category\": \"land\"\n  },\n  \"blista3\": {\n    \"acceleration\": 0.23,\n    \"braking\": 0.55,\n    \"handling\": 0.61,\n    \"speed\": 41.9174,\n    \"traction\": 2.1,\n    \"name\": \"Go Go Monkey Blista\",\n    \"make\": \"Dinka\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 69291,\n    \"category\": \"land\"\n  },\n  \"bmx\": {\n    \"acceleration\": 0.16,\n    \"braking\": 3,\n    \"handling\": 0.54,\n    \"speed\": 14.5335,\n    \"traction\": 1.85,\n    \"name\": \"BMX\",\n    \"make\": \"\",\n    \"class\": 13,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bicycle\",\n    \"price\": 2735,\n    \"category\": \"land\"\n  },\n  \"boattrailer\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5132,\n    \"traction\": 3.3,\n    \"name\": \"Boat Trailer\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 0,\n    \"type\": \"trailer\",\n    \"price\": 5668,\n    \"category\": \"land\"\n  },\n  \"boattrailer2\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5132,\n    \"traction\": 3.3,\n    \"name\": \"Boat Trailer\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 0,\n    \"type\": \"trailer\",\n    \"price\": 5668,\n    \"category\": \"land\"\n  },\n  \"boattrailer3\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5132,\n    \"traction\": 3.3,\n    \"name\": \"Boat Trailer\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 0,\n    \"type\": \"trailer\",\n    \"price\": 5668,\n    \"category\": \"land\"\n  },\n  \"bobcatxl\": {\n    \"acceleration\": 0.18,\n    \"braking\": 0.8,\n    \"handling\": 0.56,\n    \"speed\": 35.1601,\n    \"traction\": 1.95,\n    \"name\": \"Bobcat XL\",\n    \"make\": \"Vapid\",\n    \"class\": 12,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 58720,\n    \"category\": \"land\"\n  },\n  \"bodhi2\": {\n    \"acceleration\": 0.215,\n    \"braking\": 1.1,\n    \"handling\": 0.595,\n    \"speed\": 35.5074,\n    \"traction\": 2.25,\n    \"name\": \"Bodhi\",\n    \"make\": \"Canis\",\n    \"class\": 9,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 59867,\n    \"category\": \"land\"\n  },\n  \"bombushka\": {\n    \"acceleration\": 5.39,\n    \"braking\": 1.9682,\n    \"handling\": 5.39,\n    \"speed\": 36.5148,\n    \"traction\": 0.85,\n    \"name\": \"RM-10 Bombushka\",\n    \"make\": \"\",\n    \"class\": 16,\n    \"seats\": 6,\n    \"doors\": 3,\n    \"type\": \"plane\",\n    \"price\": 3941040,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"boor\": {\n    \"acceleration\": 0.267,\n    \"braking\": 0.68,\n    \"handling\": 0.647,\n    \"speed\": 40.4296,\n    \"traction\": 2.065,\n    \"name\": \"Boor\",\n    \"make\": \"Karin\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 67237,\n    \"category\": \"land\"\n  },\n  \"boxville\": {\n    \"acceleration\": 0.11,\n    \"braking\": 0.25,\n    \"handling\": 0.49,\n    \"speed\": 28.6961,\n    \"traction\": 1.55,\n    \"name\": \"Boxville\",\n    \"make\": \"Brute\",\n    \"class\": 12,\n    \"seats\": 6,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 47273,\n    \"category\": \"land\"\n  },\n  \"boxville2\": {\n    \"acceleration\": 0.11,\n    \"braking\": 0.25,\n    \"handling\": 0.49,\n    \"speed\": 28.6961,\n    \"traction\": 1.55,\n    \"name\": \"Boxville\",\n    \"make\": \"\",\n    \"class\": 12,\n    \"seats\": 6,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 47273,\n    \"category\": \"land\"\n  },\n  \"boxville3\": {\n    \"acceleration\": 0.11,\n    \"braking\": 0.25,\n    \"handling\": 0.49,\n    \"speed\": 28.6961,\n    \"traction\": 1.55,\n    \"name\": \"Boxville\",\n    \"make\": \"Brute\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 47273,\n    \"category\": \"land\"\n  },\n  \"boxville4\": {\n    \"acceleration\": 0.11,\n    \"braking\": 0.25,\n    \"handling\": 0.49,\n    \"speed\": 28.6961,\n    \"traction\": 1.55,\n    \"name\": \"Boxville\",\n    \"make\": \"Brute\",\n    \"class\": 12,\n    \"seats\": 6,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 47273,\n    \"category\": \"land\"\n  },\n  \"boxville5\": {\n    \"acceleration\": 0.32,\n    \"braking\": 0.35,\n    \"handling\": 0.7,\n    \"speed\": 39.4684,\n    \"traction\": 2.175,\n    \"name\": \"Armored Boxville\",\n    \"make\": \"\",\n    \"class\": 12,\n    \"seats\": 5,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 326707,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"boxville6\": {\n    \"acceleration\": 0.11,\n    \"braking\": 0.25,\n    \"handling\": 0.49,\n    \"speed\": 28.6961,\n    \"traction\": 1.55,\n    \"name\": \"Boxville (LSDS)\",\n    \"make\": \"Brute\",\n    \"class\": 12,\n    \"seats\": 6,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 47273,\n    \"category\": \"land\"\n  },\n  \"brawler\": {\n    \"acceleration\": 0.28,\n    \"braking\": 0.88,\n    \"handling\": 0.66,\n    \"speed\": 46.6667,\n    \"traction\": 1.92,\n    \"name\": \"Brawler\",\n    \"make\": \"Coil\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 77578,\n    \"category\": \"land\"\n  },\n  \"brickade\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.4,\n    \"handling\": 0.58,\n    \"speed\": 32.8303,\n    \"traction\": 2,\n    \"name\": \"Brickade\",\n    \"make\": \"MTL\",\n    \"class\": 17,\n    \"seats\": 6,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 54416,\n    \"category\": \"land\"\n  },\n  \"brickade2\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.4,\n    \"handling\": 0.58,\n    \"speed\": 32.8303,\n    \"traction\": 2,\n    \"name\": \"Brickade 6x6\",\n    \"make\": \"MTL\",\n    \"class\": 17,\n    \"seats\": 6,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 54416,\n    \"category\": \"land\"\n  },\n  \"brigham\": {\n    \"acceleration\": 0.21,\n    \"braking\": 0.38,\n    \"handling\": 0.59,\n    \"speed\": 38.7112,\n    \"traction\": 1.905,\n    \"name\": \"Brigham\",\n    \"make\": \"Albany\",\n    \"class\": 4,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 63825,\n    \"category\": \"land\"\n  },\n  \"brioso\": {\n    \"acceleration\": 0.29,\n    \"braking\": 0.6,\n    \"handling\": 0.77,\n    \"speed\": 41.536,\n    \"traction\": 2.3,\n    \"name\": \"Brioso R/A\",\n    \"make\": \"Grotti\",\n    \"class\": 0,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 69113,\n    \"category\": \"land\"\n  },\n  \"brioso2\": {\n    \"acceleration\": 0.179,\n    \"braking\": 0.25,\n    \"handling\": 0.559,\n    \"speed\": 32.9442,\n    \"traction\": 1.885,\n    \"name\": \"Brioso 300\",\n    \"make\": \"Grotti\",\n    \"class\": 0,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 54291,\n    \"category\": \"land\"\n  },\n  \"brioso3\": {\n    \"acceleration\": 0.216,\n    \"braking\": 0.25,\n    \"handling\": 0.596,\n    \"speed\": 37.2714,\n    \"traction\": 1.995,\n    \"name\": \"Brioso 300 Widebody\",\n    \"make\": \"Grotti\",\n    \"class\": 0,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 61333,\n    \"category\": \"land\"\n  },\n  \"broadway\": {\n    \"acceleration\": 0.195,\n    \"braking\": 0.32,\n    \"handling\": 0.575,\n    \"speed\": 37.4739,\n    \"traction\": 1.995,\n    \"name\": \"Broadway\",\n    \"make\": \"Classique\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 61702,\n    \"category\": \"land\"\n  },\n  \"bruiser\": {\n    \"acceleration\": 0.26,\n    \"braking\": 0.5,\n    \"handling\": 0.64,\n    \"speed\": 38.4047,\n    \"traction\": 1.75,\n    \"name\": \"Apocalypse Bruiser\",\n    \"make\": \"Benefactor\",\n    \"class\": 9,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 63687,\n    \"category\": \"land\"\n  },\n  \"bruiser2\": {\n    \"acceleration\": 0.26,\n    \"braking\": 0.5,\n    \"handling\": 0.64,\n    \"speed\": 38.4047,\n    \"traction\": 1.75,\n    \"name\": \"Future Shock Bruiser\",\n    \"make\": \"Benefactor\",\n    \"class\": 9,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 63687,\n    \"category\": \"land\"\n  },\n  \"bruiser3\": {\n    \"acceleration\": 0.26,\n    \"braking\": 0.5,\n    \"handling\": 0.64,\n    \"speed\": 38.4047,\n    \"traction\": 1.75,\n    \"name\": \"Nightmare Bruiser\",\n    \"make\": \"Benefactor\",\n    \"class\": 9,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 63687,\n    \"category\": \"land\"\n  },\n  \"brutus\": {\n    \"acceleration\": 0.27,\n    \"braking\": 0.6,\n    \"handling\": 0.65,\n    \"speed\": 42.3068,\n    \"traction\": 2,\n    \"name\": \"Apocalypse Brutus\",\n    \"make\": \"Declasse\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 70122,\n    \"category\": \"land\"\n  },\n  \"brutus2\": {\n    \"acceleration\": 0.27,\n    \"braking\": 0.6,\n    \"handling\": 0.65,\n    \"speed\": 42.3068,\n    \"traction\": 2,\n    \"name\": \"Future Shock Brutus\",\n    \"make\": \"Declasse\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 70122,\n    \"category\": \"land\"\n  },\n  \"brutus3\": {\n    \"acceleration\": 0.27,\n    \"braking\": 0.6,\n    \"handling\": 0.65,\n    \"speed\": 42.3068,\n    \"traction\": 2,\n    \"name\": \"Nightmare Brutus\",\n    \"make\": \"Declasse\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 70122,\n    \"category\": \"land\"\n  },\n  \"btype\": {\n    \"acceleration\": 0.27,\n    \"braking\": 0.55,\n    \"handling\": 0.65,\n    \"speed\": 41.6667,\n    \"traction\": 2.1,\n    \"name\": \"Roosevelt\",\n    \"make\": \"Albany\",\n    \"class\": 5,\n    \"seats\": 6,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 69018,\n    \"category\": \"land\"\n  },\n  \"btype2\": {\n    \"acceleration\": 0.355,\n    \"braking\": 0.55,\n    \"handling\": 0.735,\n    \"speed\": 45,\n    \"traction\": 1.94,\n    \"name\": \"Fränken Stange\",\n    \"make\": \"Albany\",\n    \"class\": 5,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 74624,\n    \"category\": \"land\"\n  },\n  \"btype3\": {\n    \"acceleration\": 0.27,\n    \"braking\": 0.55,\n    \"handling\": 0.65,\n    \"speed\": 41.6667,\n    \"traction\": 2.1,\n    \"name\": \"Roosevelt Valor\",\n    \"make\": \"Albany\",\n    \"class\": 5,\n    \"seats\": 6,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 69018,\n    \"category\": \"land\"\n  },\n  \"buccaneer\": {\n    \"acceleration\": 0.28,\n    \"braking\": 0.8,\n    \"handling\": 0.66,\n    \"speed\": 46.1566,\n    \"traction\": 2.15,\n    \"name\": \"Buccaneer\",\n    \"make\": \"Albany\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 76634,\n    \"category\": \"land\"\n  },\n  \"buccaneer2\": {\n    \"acceleration\": 0.28,\n    \"braking\": 0.8,\n    \"handling\": 0.66,\n    \"speed\": 46.1566,\n    \"traction\": 2.15,\n    \"name\": \"Buccaneer Custom\",\n    \"make\": \"Albany\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 76634,\n    \"category\": \"land\"\n  },\n  \"buffalo\": {\n    \"acceleration\": 0.27,\n    \"braking\": 0.9,\n    \"handling\": 0.65,\n    \"speed\": 45.1527,\n    \"traction\": 2.45,\n    \"name\": \"Buffalo\",\n    \"make\": \"Bravado\",\n    \"class\": 6,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 75156,\n    \"category\": \"land\"\n  },\n  \"buffalo2\": {\n    \"acceleration\": 0.29,\n    \"braking\": 0.9,\n    \"handling\": 0.67,\n    \"speed\": 46.2816,\n    \"traction\": 2.45,\n    \"name\": \"Buffalo S\",\n    \"make\": \"Bravado\",\n    \"class\": 6,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 77026,\n    \"category\": \"land\"\n  },\n  \"buffalo3\": {\n    \"acceleration\": 0.31,\n    \"braking\": 1,\n    \"handling\": 0.69,\n    \"speed\": 48.1652,\n    \"traction\": 2.45,\n    \"name\": \"Sprunk Buffalo\",\n    \"make\": \"Bravado\",\n    \"class\": 6,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 80264,\n    \"category\": \"land\"\n  },\n  \"buffalo4\": {\n    \"acceleration\": 0.3425,\n    \"braking\": 0.95,\n    \"handling\": 0.7225,\n    \"speed\": 48.308,\n    \"traction\": 2.58,\n    \"name\": \"Buffalo STX\",\n    \"make\": \"Bravado\",\n    \"class\": 4,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 80516,\n    \"category\": \"land\"\n  },\n  \"buffalo5\": {\n    \"acceleration\": 0.382,\n    \"braking\": 0.985,\n    \"handling\": 0.842,\n    \"speed\": 49.8737,\n    \"traction\": 2.42,\n    \"name\": \"Buffalo EVX\",\n    \"make\": \"Bravado\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 83332,\n    \"category\": \"land\"\n  },\n  \"bulldozer\": {\n    \"acceleration\": 0.14,\n    \"braking\": 0.2,\n    \"handling\": 0.52,\n    \"speed\": 5,\n    \"traction\": 1.1,\n    \"name\": \"Dozer\",\n    \"make\": \"HVY\",\n    \"class\": 10,\n    \"seats\": 1,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 9376,\n    \"category\": \"land\"\n  },\n  \"bullet\": {\n    \"acceleration\": 0.33,\n    \"braking\": 0.8,\n    \"handling\": 0.71,\n    \"speed\": 49.7632,\n    \"traction\": 2.55,\n    \"name\": \"Bullet\",\n    \"make\": \"Vapid\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 82565,\n    \"category\": \"land\"\n  },\n  \"burrito\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.6,\n    \"handling\": 0.54,\n    \"speed\": 36.9472,\n    \"traction\": 1.95,\n    \"name\": \"Burrito\",\n    \"make\": \"Declasse\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 61195,\n    \"category\": \"land\"\n  },\n  \"burrito2\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.6,\n    \"handling\": 0.54,\n    \"speed\": 36.9472,\n    \"traction\": 1.95,\n    \"name\": \"Bugstars Burrito\",\n    \"make\": \"Declasse\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 61195,\n    \"category\": \"land\"\n  },\n  \"burrito3\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.6,\n    \"handling\": 0.54,\n    \"speed\": 36.9472,\n    \"traction\": 1.95,\n    \"name\": \"Burrito\",\n    \"make\": \"Declasse\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 61195,\n    \"category\": \"land\"\n  },\n  \"burrito4\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.6,\n    \"handling\": 0.54,\n    \"speed\": 36.9472,\n    \"traction\": 1.95,\n    \"name\": \"Burrito\",\n    \"make\": \"Declasse\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 61195,\n    \"category\": \"land\"\n  },\n  \"burrito5\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.6,\n    \"handling\": 0.54,\n    \"speed\": 36.9472,\n    \"traction\": 1.95,\n    \"name\": \"Burrito\",\n    \"make\": \"Declasse\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 61195,\n    \"category\": \"land\"\n  },\n  \"bus\": {\n    \"acceleration\": 0.12,\n    \"braking\": 0.35,\n    \"handling\": 0.5,\n    \"speed\": 25.5809,\n    \"traction\": 1.45,\n    \"name\": \"Bus\",\n    \"make\": \"\",\n    \"class\": 17,\n    \"seats\": 16,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 42481,\n    \"category\": \"land\"\n  },\n  \"buzzard\": {\n    \"acceleration\": 5.39,\n    \"braking\": 3.1212,\n    \"handling\": 5.39,\n    \"speed\": 57.9072,\n    \"traction\": 1.3,\n    \"name\": \"Buzzard Attack Chopper\",\n    \"make\": \"\",\n    \"class\": 15,\n    \"seats\": 4,\n    \"doors\": 2,\n    \"type\": \"heli\",\n    \"price\": 32313780,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"buzzard2\": {\n    \"acceleration\": 5.39,\n    \"braking\": 3.1212,\n    \"handling\": 5.39,\n    \"speed\": 57.9072,\n    \"traction\": 1.3,\n    \"name\": \"Buzzard\",\n    \"make\": \"\",\n    \"class\": 15,\n    \"seats\": 4,\n    \"doors\": 2,\n    \"type\": \"heli\",\n    \"price\": 32313780,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"cablecar\": {\n    \"acceleration\": 0.2,\n    \"braking\": 5,\n    \"handling\": 0.58,\n    \"speed\": 26.6667,\n    \"traction\": 2.5,\n    \"name\": \"Cable Car\",\n    \"make\": \"\",\n    \"class\": 21,\n    \"seats\": 4,\n    \"doors\": 2,\n    \"type\": \"train\",\n    \"price\": 194680,\n    \"category\": \"land\"\n  },\n  \"caddy\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.2,\n    \"handling\": 0.68,\n    \"speed\": 21.6667,\n    \"traction\": 1.5,\n    \"name\": \"Caddy\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 2,\n    \"doors\": 0,\n    \"type\": \"automobile\",\n    \"price\": 36554,\n    \"category\": \"land\"\n  },\n  \"caddy2\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.2,\n    \"handling\": 0.68,\n    \"speed\": 21.6667,\n    \"traction\": 1.45,\n    \"name\": \"Caddy\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 2,\n    \"doors\": 0,\n    \"type\": \"automobile\",\n    \"price\": 36554,\n    \"category\": \"land\"\n  },\n  \"caddy3\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.2,\n    \"handling\": 0.68,\n    \"speed\": 21.3342,\n    \"traction\": 1.45,\n    \"name\": \"Caddy\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 2,\n    \"doors\": 0,\n    \"type\": \"automobile\",\n    \"price\": 36022,\n    \"category\": \"land\"\n  },\n  \"calico\": {\n    \"acceleration\": 0.3385,\n    \"braking\": 0.825,\n    \"handling\": 0.7185,\n    \"speed\": 49.4621,\n    \"traction\": 2.435,\n    \"name\": \"Calico GTF\",\n    \"make\": \"Karin\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 82150,\n    \"category\": \"land\"\n  },\n  \"camper\": {\n    \"acceleration\": 0.12,\n    \"braking\": 0.25,\n    \"handling\": 0.5,\n    \"speed\": 30.462,\n    \"traction\": 1.5,\n    \"name\": \"Camper\",\n    \"make\": \"Brute\",\n    \"class\": 12,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 50131,\n    \"category\": \"land\"\n  },\n  \"caracara\": {\n    \"acceleration\": 0.27,\n    \"braking\": 0.27,\n    \"handling\": 0.65,\n    \"speed\": 38.6133,\n    \"traction\": 2.25,\n    \"name\": \"Caracara\",\n    \"make\": \"Vapid\",\n    \"class\": 9,\n    \"seats\": 5,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 318426,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"caracara2\": {\n    \"acceleration\": 0.27,\n    \"braking\": 0.3,\n    \"handling\": 0.65,\n    \"speed\": 39.2704,\n    \"traction\": 2.05,\n    \"name\": \"Caracara 4x4\",\n    \"make\": \"Vapid\",\n    \"class\": 9,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 64784,\n    \"category\": \"land\"\n  },\n  \"carbonizzare\": {\n    \"acceleration\": 0.35,\n    \"braking\": 0.8,\n    \"handling\": 0.73,\n    \"speed\": 48.3368,\n    \"traction\": 2.38,\n    \"name\": \"Carbonizzare\",\n    \"make\": \"Grotti\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 80346,\n    \"category\": \"land\"\n  },\n  \"carbonrs\": {\n    \"acceleration\": 0.3,\n    \"braking\": 1.3,\n    \"handling\": 0.68,\n    \"speed\": 47.0182,\n    \"traction\": 2.15,\n    \"name\": \"Carbon RS\",\n    \"make\": \"Nagasaki\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 24649,\n    \"category\": \"land\"\n  },\n  \"cargobob\": {\n    \"acceleration\": 4.998,\n    \"braking\": 2.495,\n    \"handling\": 4.998,\n    \"speed\": 49.92,\n    \"traction\": 1.3,\n    \"name\": \"Cargobob\",\n    \"make\": \"\",\n    \"class\": 15,\n    \"seats\": 10,\n    \"doors\": 3,\n    \"type\": \"heli\",\n    \"price\": 5616990,\n    \"category\": \"air\"\n  },\n  \"cargobob2\": {\n    \"acceleration\": 4.998,\n    \"braking\": 2.495,\n    \"handling\": 4.998,\n    \"speed\": 49.92,\n    \"traction\": 1.3,\n    \"name\": \"Cargobob\",\n    \"make\": \"\",\n    \"class\": 15,\n    \"seats\": 10,\n    \"doors\": 3,\n    \"type\": \"heli\",\n    \"price\": 5616990,\n    \"category\": \"air\"\n  },\n  \"cargobob3\": {\n    \"acceleration\": 4.998,\n    \"braking\": 2.495,\n    \"handling\": 4.998,\n    \"speed\": 49.92,\n    \"traction\": 1.3,\n    \"name\": \"Cargobob\",\n    \"make\": \"\",\n    \"class\": 15,\n    \"seats\": 10,\n    \"doors\": 3,\n    \"type\": \"heli\",\n    \"price\": 5616990,\n    \"category\": \"air\"\n  },\n  \"cargobob4\": {\n    \"acceleration\": 4.998,\n    \"braking\": 2.495,\n    \"handling\": 4.998,\n    \"speed\": 49.92,\n    \"traction\": 1.3,\n    \"name\": \"Cargobob\",\n    \"make\": \"\",\n    \"class\": 15,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"heli\",\n    \"price\": 5616990,\n    \"category\": \"air\"\n  },\n  \"cargobob5\": {\n    \"acceleration\": 5.88,\n    \"braking\": 3.524,\n    \"handling\": 5.88,\n    \"speed\": 59.9315,\n    \"traction\": 1.3,\n    \"name\": \"DH-7 Iron Mule\",\n    \"make\": \"Buckingham\",\n    \"class\": 15,\n    \"seats\": 16,\n    \"doors\": 6,\n    \"type\": \"heli\",\n    \"price\": 6769394,\n    \"category\": \"air\"\n  },\n  \"cargoplane\": {\n    \"acceleration\": 6.174,\n    \"braking\": 4.8714,\n    \"handling\": 6.174,\n    \"speed\": 78.9023,\n    \"traction\": 0.85,\n    \"name\": \"Cargo Plane\",\n    \"make\": \"\",\n    \"class\": 16,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"plane\",\n    \"price\": 1537947,\n    \"category\": \"air\"\n  },\n  \"cargoplane2\": {\n    \"acceleration\": 6.174,\n    \"braking\": 4.8714,\n    \"handling\": 6.174,\n    \"speed\": 78.9023,\n    \"traction\": 0.85,\n    \"name\": \"Cargo Plane\",\n    \"make\": \"\",\n    \"class\": 16,\n    \"seats\": 5,\n    \"doors\": 4,\n    \"type\": \"plane\",\n    \"price\": 1537947,\n    \"category\": \"air\"\n  },\n  \"casco\": {\n    \"acceleration\": 0.32,\n    \"braking\": 0.6,\n    \"handling\": 0.7,\n    \"speed\": 50.3333,\n    \"traction\": 2.3,\n    \"name\": \"Casco\",\n    \"make\": \"Lampadati\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 83125,\n    \"category\": \"land\"\n  },\n  \"castigator\": {\n    \"acceleration\": 0.2905,\n    \"braking\": 0.76,\n    \"handling\": 0.6705,\n    \"speed\": 49.2117,\n    \"traction\": 2.264,\n    \"name\": \"Castigator\",\n    \"make\": \"Canis\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 81492,\n    \"category\": \"land\"\n  },\n  \"cavalcade\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.6,\n    \"handling\": 0.58,\n    \"speed\": 38.4289,\n    \"traction\": 1.9,\n    \"name\": \"Cavalcade\",\n    \"make\": \"Albany\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 63694,\n    \"category\": \"land\"\n  },\n  \"cavalcade2\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.6,\n    \"handling\": 0.58,\n    \"speed\": 38.4289,\n    \"traction\": 1.9,\n    \"name\": \"Cavalcade\",\n    \"make\": \"Albany\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 63694,\n    \"category\": \"land\"\n  },\n  \"cavalcade3\": {\n    \"acceleration\": 0.2765,\n    \"braking\": 0.875,\n    \"handling\": 0.6565,\n    \"speed\": 40.6667,\n    \"traction\": 2.225,\n    \"name\": \"Cavalcade XL\",\n    \"make\": \"Albany\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 67959,\n    \"category\": \"land\"\n  },\n  \"cerberus\": {\n    \"acceleration\": 0.19,\n    \"braking\": 0.25,\n    \"handling\": 0.57,\n    \"speed\": 37.2117,\n    \"traction\": 1.7,\n    \"name\": \"Apocalypse Cerberus\",\n    \"make\": \"MTL\",\n    \"class\": 20,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 305773,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"cerberus2\": {\n    \"acceleration\": 0.19,\n    \"braking\": 0.25,\n    \"handling\": 0.57,\n    \"speed\": 37.2117,\n    \"traction\": 1.7,\n    \"name\": \"Future Shock Cerberus\",\n    \"make\": \"MTL\",\n    \"class\": 20,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 305773,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"cerberus3\": {\n    \"acceleration\": 0.19,\n    \"braking\": 0.25,\n    \"handling\": 0.57,\n    \"speed\": 37.2117,\n    \"traction\": 1.7,\n    \"name\": \"Nightmare Cerberus\",\n    \"make\": \"MTL\",\n    \"class\": 20,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 305773,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"champion\": {\n    \"acceleration\": 0.359,\n    \"braking\": 1.15,\n    \"handling\": 0.739,\n    \"speed\": 51.8663,\n    \"traction\": 2.5662,\n    \"name\": \"Champion\",\n    \"make\": \"Dewbauchee\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 86582,\n    \"category\": \"land\"\n  },\n  \"chavosv6\": {\n    \"acceleration\": 0.274,\n    \"braking\": 0.69,\n    \"handling\": 0.654,\n    \"speed\": 46.6629,\n    \"traction\": 2.554,\n    \"name\": \"Chavos V6\",\n    \"make\": \"Dinka\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 77249,\n    \"category\": \"land\"\n  },\n  \"cheburek\": {\n    \"acceleration\": 0.265,\n    \"braking\": 0.8,\n    \"handling\": 0.645,\n    \"speed\": 44.644,\n    \"traction\": 2.25,\n    \"name\": \"Cheburek\",\n    \"make\": \"RUNE\",\n    \"class\": 5,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 74166,\n    \"category\": \"land\"\n  },\n  \"cheetah\": {\n    \"acceleration\": 0.32,\n    \"braking\": 0.8,\n    \"handling\": 0.7,\n    \"speed\": 50.0095,\n    \"traction\": 2.65,\n    \"name\": \"Cheetah\",\n    \"make\": \"Grotti\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 82927,\n    \"category\": \"land\"\n  },\n  \"cheetah2\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.8,\n    \"handling\": 0.68,\n    \"speed\": 49.923,\n    \"traction\": 2.65,\n    \"name\": \"Cheetah Classic\",\n    \"make\": \"Grotti\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 82724,\n    \"category\": \"land\"\n  },\n  \"chernobog\": {\n    \"acceleration\": 0.12,\n    \"braking\": 0.1,\n    \"handling\": 0.5,\n    \"speed\": 22.5872,\n    \"traction\": 2,\n    \"name\": \"Chernobog\",\n    \"make\": \"\",\n    \"class\": 19,\n    \"seats\": 2,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 186457,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"chimera\": {\n    \"acceleration\": 0.275,\n    \"braking\": 1,\n    \"handling\": 0.655,\n    \"speed\": 35.4249,\n    \"traction\": 2.1,\n    \"name\": \"Chimera\",\n    \"make\": \"Nagasaki\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 0,\n    \"type\": \"quadbike\",\n    \"price\": 41090,\n    \"category\": \"land\"\n  },\n  \"chino\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.6,\n    \"handling\": 0.58,\n    \"speed\": 35.2769,\n    \"traction\": 2.05,\n    \"name\": \"Chino\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 58651,\n    \"category\": \"land\"\n  },\n  \"chino2\": {\n    \"acceleration\": 0.21,\n    \"braking\": 0.6,\n    \"handling\": 0.59,\n    \"speed\": 36.3465,\n    \"traction\": 2.07,\n    \"name\": \"Chino Custom\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 60394,\n    \"category\": \"land\"\n  },\n  \"cinquemila\": {\n    \"acceleration\": 0.3535,\n    \"braking\": 0.975,\n    \"handling\": 0.7335,\n    \"speed\": 48.236,\n    \"traction\": 2.63,\n    \"name\": \"Cinquemila\",\n    \"make\": \"Lampadati\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 80476,\n    \"category\": \"land\"\n  },\n  \"cliffhanger\": {\n    \"acceleration\": 0.318,\n    \"braking\": 1.1,\n    \"handling\": 0.698,\n    \"speed\": 49.1271,\n    \"traction\": 2.25,\n    \"name\": \"Cliffhanger\",\n    \"make\": \"Western\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 25621,\n    \"category\": \"land\"\n  },\n  \"clique\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.85,\n    \"handling\": 0.68,\n    \"speed\": 45.9981,\n    \"traction\": 2.35,\n    \"name\": \"Clique\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 76524,\n    \"category\": \"land\"\n  },\n  \"clique2\": {\n    \"acceleration\": 0.198,\n    \"braking\": 0.35,\n    \"handling\": 0.578,\n    \"speed\": 33.1878,\n    \"traction\": 2.08,\n    \"name\": \"Clique Wagon\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 54902,\n    \"category\": \"land\"\n  },\n  \"club\": {\n    \"acceleration\": 0.2375,\n    \"braking\": 0.72,\n    \"handling\": 0.6175,\n    \"speed\": 41.7599,\n    \"traction\": 2.05,\n    \"name\": \"Club\",\n    \"make\": \"BF\",\n    \"class\": 0,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 69335,\n    \"category\": \"land\"\n  },\n  \"coach\": {\n    \"acceleration\": 0.12,\n    \"braking\": 0.25,\n    \"handling\": 0.5,\n    \"speed\": 25.5809,\n    \"traction\": 1.45,\n    \"name\": \"Dashound\",\n    \"make\": \"\",\n    \"class\": 17,\n    \"seats\": 10,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 42321,\n    \"category\": \"land\"\n  },\n  \"cog55\": {\n    \"acceleration\": 0.265,\n    \"braking\": 0.57,\n    \"handling\": 0.645,\n    \"speed\": 46.2961,\n    \"traction\": 2.2,\n    \"name\": \"Cognoscenti 55\",\n    \"make\": \"Enus\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 76441,\n    \"category\": \"land\"\n  },\n  \"cog552\": {\n    \"acceleration\": 0.26,\n    \"braking\": 0.55,\n    \"handling\": 0.64,\n    \"speed\": 45.7596,\n    \"traction\": 2.2,\n    \"name\": \"Cognoscenti 55 (Armored)\",\n    \"make\": \"Enus\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 75535,\n    \"category\": \"land\"\n  },\n  \"cogcabrio\": {\n    \"acceleration\": 0.26,\n    \"braking\": 0.6,\n    \"handling\": 0.64,\n    \"speed\": 45.1953,\n    \"traction\": 2.3,\n    \"name\": \"Cognoscenti Cabrio\",\n    \"make\": \"Enus\",\n    \"class\": 3,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 74712,\n    \"category\": \"land\"\n  },\n  \"cognoscenti\": {\n    \"acceleration\": 0.26,\n    \"braking\": 0.55,\n    \"handling\": 0.64,\n    \"speed\": 45.7596,\n    \"traction\": 2.1,\n    \"name\": \"Cognoscenti\",\n    \"make\": \"Enus\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 75535,\n    \"category\": \"land\"\n  },\n  \"cognoscenti2\": {\n    \"acceleration\": 0.255,\n    \"braking\": 0.52,\n    \"handling\": 0.635,\n    \"speed\": 45.2183,\n    \"traction\": 2.1,\n    \"name\": \"Cognoscenti (Armored)\",\n    \"make\": \"Enus\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 74605,\n    \"category\": \"land\"\n  },\n  \"comet2\": {\n    \"acceleration\": 0.34,\n    \"braking\": 0.8,\n    \"handling\": 0.72,\n    \"speed\": 50.1961,\n    \"traction\": 2.6,\n    \"name\": \"Comet\",\n    \"make\": \"Pfister\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 83289,\n    \"category\": \"land\"\n  },\n  \"comet3\": {\n    \"acceleration\": 0.34,\n    \"braking\": 0.8,\n    \"handling\": 0.72,\n    \"speed\": 50.1737,\n    \"traction\": 2.8,\n    \"name\": \"Comet Retro Custom\",\n    \"make\": \"Pfister\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 83253,\n    \"category\": \"land\"\n  },\n  \"comet4\": {\n    \"acceleration\": 0.2925,\n    \"braking\": 0.8,\n    \"handling\": 0.6725,\n    \"speed\": 47.166,\n    \"traction\": 2.1,\n    \"name\": \"Comet Safari\",\n    \"make\": \"Pfister\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 78289,\n    \"category\": \"land\"\n  },\n  \"comet5\": {\n    \"acceleration\": 0.32,\n    \"braking\": 1.2,\n    \"handling\": 0.7,\n    \"speed\": 46.8946,\n    \"traction\": 2.7,\n    \"name\": \"Comet SR\",\n    \"make\": \"Pfister\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 78583,\n    \"category\": \"land\"\n  },\n  \"comet6\": {\n    \"acceleration\": 0.346,\n    \"braking\": 0.88,\n    \"handling\": 0.726,\n    \"speed\": 50.1596,\n    \"traction\": 2.655,\n    \"name\": \"Comet S2\",\n    \"make\": \"Pfister\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 83378,\n    \"category\": \"land\"\n  },\n  \"comet7\": {\n    \"acceleration\": 0.3495,\n    \"braking\": 0.89,\n    \"handling\": 0.7295,\n    \"speed\": 50.3806,\n    \"traction\": 2.655,\n    \"name\": \"Comet S2 Cabrio\",\n    \"make\": \"Pfister\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 83759,\n    \"category\": \"land\"\n  },\n  \"conada\": {\n    \"acceleration\": 5.6644,\n    \"braking\": 3.5215,\n    \"handling\": 5.6644,\n    \"speed\": 62.169,\n    \"traction\": 1.3,\n    \"name\": \"Conada\",\n    \"make\": \"Buckingham\",\n    \"class\": 15,\n    \"seats\": 4,\n    \"doors\": 2,\n    \"type\": \"heli\",\n    \"price\": 6931737,\n    \"category\": \"air\"\n  },\n  \"conada2\": {\n    \"acceleration\": 5.684,\n    \"braking\": 3.4855,\n    \"handling\": 5.684,\n    \"speed\": 61.3214,\n    \"traction\": 1.3,\n    \"name\": \"Weaponized Conada\",\n    \"make\": \"Buckingham\",\n    \"class\": 15,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"heli\",\n    \"price\": 34278704,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"contender\": {\n    \"acceleration\": 0.26,\n    \"braking\": 0.6,\n    \"handling\": 0.64,\n    \"speed\": 41.3615,\n    \"traction\": 2.1,\n    \"name\": \"Contender\",\n    \"make\": \"Vapid\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 68578,\n    \"category\": \"land\"\n  },\n  \"coquette\": {\n    \"acceleration\": 0.33,\n    \"braking\": 0.8,\n    \"handling\": 0.71,\n    \"speed\": 50.4563,\n    \"traction\": 2.55,\n    \"name\": \"Coquette\",\n    \"make\": \"Invetero\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 83674,\n    \"category\": \"land\"\n  },\n  \"coquette2\": {\n    \"acceleration\": 0.34,\n    \"braking\": 0.5,\n    \"handling\": 0.72,\n    \"speed\": 49.5374,\n    \"traction\": 2.3,\n    \"name\": \"Coquette Classic\",\n    \"make\": \"Invetero\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 81755,\n    \"category\": \"land\"\n  },\n  \"coquette3\": {\n    \"acceleration\": 0.29,\n    \"braking\": 0.6,\n    \"handling\": 0.67,\n    \"speed\": 45.0781,\n    \"traction\": 2.25,\n    \"name\": \"Coquette BlackFin\",\n    \"make\": \"Invetero\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 74620,\n    \"category\": \"land\"\n  },\n  \"coquette4\": {\n    \"acceleration\": 0.32,\n    \"braking\": 0.6,\n    \"handling\": 0.7,\n    \"speed\": 48.8621,\n    \"traction\": 2.6,\n    \"name\": \"Coquette D10\",\n    \"make\": \"Invetero\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 80771,\n    \"category\": \"land\"\n  },\n  \"coquette5\": {\n    \"acceleration\": 0.278,\n    \"braking\": 0.6,\n    \"handling\": 0.658,\n    \"speed\": 47.3099,\n    \"traction\": 2.325,\n    \"name\": \"Coquette D1\",\n    \"make\": \"Invetero\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 78153,\n    \"category\": \"land\"\n  },\n  \"coquette6\": {\n    \"acceleration\": 0.325,\n    \"braking\": 0.7,\n    \"handling\": 0.705,\n    \"speed\": 49.3143,\n    \"traction\": 2.637,\n    \"name\": \"Coquette D5\",\n    \"make\": \"Invetero\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 81670,\n    \"category\": \"land\"\n  },\n  \"corsita\": {\n    \"acceleration\": 0.4,\n    \"braking\": 1.3,\n    \"handling\": 0.78,\n    \"speed\": 52.2801,\n    \"traction\": 2.726,\n    \"name\": \"Corsita\",\n    \"make\": \"Lampadati\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 87616,\n    \"category\": \"land\"\n  },\n  \"coureur\": {\n    \"acceleration\": 0.37,\n    \"braking\": 0.8,\n    \"handling\": 0.81,\n    \"speed\": 46.6167,\n    \"traction\": 2.435,\n    \"name\": \"La Coureuse\",\n    \"make\": \"Penaud\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 77754,\n    \"category\": \"land\"\n  },\n  \"cruiser\": {\n    \"acceleration\": 0.08,\n    \"braking\": 2.8,\n    \"handling\": 0.46,\n    \"speed\": 15,\n    \"traction\": 1.8,\n    \"name\": \"Cruiser\",\n    \"make\": \"\",\n    \"class\": 13,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bicycle\",\n    \"price\": 2751,\n    \"category\": \"land\"\n  },\n  \"crusader\": {\n    \"acceleration\": 0.18,\n    \"braking\": 0.3,\n    \"handling\": 0.56,\n    \"speed\": 35.9639,\n    \"traction\": 1.9,\n    \"name\": \"Crusader\",\n    \"make\": \"Canis\",\n    \"class\": 19,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 59206,\n    \"category\": \"land\"\n  },\n  \"cuban800\": {\n    \"acceleration\": 5.88,\n    \"braking\": 4.5156,\n    \"handling\": 5.88,\n    \"speed\": 76.7957,\n    \"traction\": 2.15,\n    \"name\": \"Cuban 800\",\n    \"make\": \"\",\n    \"class\": 16,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"plane\",\n    \"price\": 1489140,\n    \"category\": \"air\"\n  },\n  \"cutter\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.3,\n    \"handling\": 0.54,\n    \"speed\": 12.7612,\n    \"traction\": 1.62,\n    \"name\": \"Cutter\",\n    \"make\": \"HVY\",\n    \"class\": 10,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"automobile\",\n    \"price\": 22017,\n    \"category\": \"land\"\n  },\n  \"cyclone\": {\n    \"acceleration\": 0.2725,\n    \"braking\": 1.2,\n    \"handling\": 0.6525,\n    \"speed\": 40.9219,\n    \"traction\": 2.25,\n    \"name\": \"Cyclone\",\n    \"make\": \"Coil\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 68875,\n    \"category\": \"land\"\n  },\n  \"cypher\": {\n    \"acceleration\": 0.326,\n    \"braking\": 0.7,\n    \"handling\": 0.706,\n    \"speed\": 45.5658,\n    \"traction\": 2.59,\n    \"name\": \"Cypher\",\n    \"make\": \"Ubermacht\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 75676,\n    \"category\": \"land\"\n  },\n  \"daemon\": {\n    \"acceleration\": 0.26,\n    \"braking\": 0.6,\n    \"handling\": 0.64,\n    \"speed\": 43.1425,\n    \"traction\": 1.85,\n    \"name\": \"Daemon\",\n    \"make\": \"Western\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 22321,\n    \"category\": \"land\"\n  },\n  \"daemon2\": {\n    \"acceleration\": 0.262,\n    \"braking\": 0.6,\n    \"handling\": 0.642,\n    \"speed\": 43.3429,\n    \"traction\": 1.85,\n    \"name\": \"Daemon\",\n    \"make\": \"Western\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 22423,\n    \"category\": \"land\"\n  },\n  \"deathbike\": {\n    \"acceleration\": 0.3125,\n    \"braking\": 1.1,\n    \"handling\": 0.6925,\n    \"speed\": 48.2865,\n    \"traction\": 2.05,\n    \"name\": \"Apocalypse Deathbike\",\n    \"make\": \"Western\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 25195,\n    \"category\": \"land\"\n  },\n  \"deathbike2\": {\n    \"acceleration\": 0.3125,\n    \"braking\": 1.1,\n    \"handling\": 0.6925,\n    \"speed\": 48.2865,\n    \"traction\": 2.05,\n    \"name\": \"Future Shock Deathbike\",\n    \"make\": \"Western\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 25195,\n    \"category\": \"land\"\n  },\n  \"deathbike3\": {\n    \"acceleration\": 0.3125,\n    \"braking\": 1.1,\n    \"handling\": 0.6925,\n    \"speed\": 48.2865,\n    \"traction\": 2.05,\n    \"name\": \"Nightmare Deathbike\",\n    \"make\": \"Western\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 25195,\n    \"category\": \"land\"\n  },\n  \"defiler\": {\n    \"acceleration\": 0.405,\n    \"braking\": 1.2,\n    \"handling\": 0.785,\n    \"speed\": 48.8436,\n    \"traction\": 2.15,\n    \"name\": \"Defiler\",\n    \"make\": \"Shitzu\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 25616,\n    \"category\": \"land\"\n  },\n  \"deity\": {\n    \"acceleration\": 0.2925,\n    \"braking\": 0.65,\n    \"handling\": 0.6725,\n    \"speed\": 44.3737,\n    \"traction\": 2.15,\n    \"name\": \"Deity\",\n    \"make\": \"Enus\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 73581,\n    \"category\": \"land\"\n  },\n  \"deluxo\": {\n    \"acceleration\": 0.2275,\n    \"braking\": 0.7,\n    \"handling\": 0.6075,\n    \"speed\": 42.6766,\n    \"traction\": 2.05,\n    \"name\": \"Deluxo\",\n    \"make\": \"Imponte\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 70738,\n    \"category\": \"land\"\n  },\n  \"deveste\": {\n    \"acceleration\": 0.42,\n    \"braking\": 1,\n    \"handling\": 0.85,\n    \"speed\": 52.6778,\n    \"traction\": 2.725,\n    \"name\": \"Deveste Eight\",\n    \"make\": \"Principe\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 87916,\n    \"category\": \"land\"\n  },\n  \"deviant\": {\n    \"acceleration\": 0.29,\n    \"braking\": 0.5,\n    \"handling\": 0.67,\n    \"speed\": 42.457,\n    \"traction\": 2.25,\n    \"name\": \"Deviant\",\n    \"make\": \"Schyster\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 70267,\n    \"category\": \"land\"\n  },\n  \"diablous\": {\n    \"acceleration\": 0.312,\n    \"braking\": 1.2,\n    \"handling\": 0.692,\n    \"speed\": 47.2867,\n    \"traction\": 1.95,\n    \"name\": \"Diabolus\",\n    \"make\": \"Principe\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 24745,\n    \"category\": \"land\"\n  },\n  \"diablous2\": {\n    \"acceleration\": 0.32,\n    \"braking\": 1.25,\n    \"handling\": 0.7,\n    \"speed\": 47.5333,\n    \"traction\": 2,\n    \"name\": \"Diabolus Custom\",\n    \"make\": \"Principe\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 24901,\n    \"category\": \"land\"\n  },\n  \"dilettante\": {\n    \"acceleration\": 0.1,\n    \"braking\": 0.6,\n    \"handling\": 0.48,\n    \"speed\": 24.0066,\n    \"traction\": 1.76,\n    \"name\": \"Dilettante\",\n    \"make\": \"Karin\",\n    \"class\": 0,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 40298,\n    \"category\": \"land\"\n  },\n  \"dilettante2\": {\n    \"acceleration\": 0.1,\n    \"braking\": 0.6,\n    \"handling\": 0.48,\n    \"speed\": 24.0066,\n    \"traction\": 1.76,\n    \"name\": \"Dilettante\",\n    \"make\": \"Karin\",\n    \"class\": 0,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 40298,\n    \"category\": \"land\"\n  },\n  \"dinghy\": {\n    \"acceleration\": 16,\n    \"braking\": 0.4,\n    \"handling\": 16.38,\n    \"speed\": 41.6667,\n    \"traction\": 0,\n    \"name\": \"Dinghy\",\n    \"make\": \"Nagasaki\",\n    \"class\": 14,\n    \"seats\": 4,\n    \"doors\": 0,\n    \"type\": \"boat\",\n    \"price\": 2233400,\n    \"category\": \"sea\",\n    \"weapons\": true\n  },\n  \"dinghy2\": {\n    \"acceleration\": 16,\n    \"braking\": 0.4,\n    \"handling\": 16.38,\n    \"speed\": 41.6667,\n    \"traction\": 0,\n    \"name\": \"Dinghy\",\n    \"make\": \"Nagasaki\",\n    \"class\": 14,\n    \"seats\": 2,\n    \"doors\": 0,\n    \"type\": \"boat\",\n    \"price\": 446680,\n    \"category\": \"sea\"\n  },\n  \"dinghy3\": {\n    \"acceleration\": 16,\n    \"braking\": 0.4,\n    \"handling\": 16.38,\n    \"speed\": 41.6667,\n    \"traction\": 0,\n    \"name\": \"Dinghy\",\n    \"make\": \"Nagasaki\",\n    \"class\": 14,\n    \"seats\": 4,\n    \"doors\": 0,\n    \"type\": \"boat\",\n    \"price\": 2233400,\n    \"category\": \"sea\",\n    \"weapons\": true\n  },\n  \"dinghy4\": {\n    \"acceleration\": 16,\n    \"braking\": 0.4,\n    \"handling\": 16.38,\n    \"speed\": 41.6667,\n    \"traction\": 0,\n    \"name\": \"Dinghy\",\n    \"make\": \"Nagasaki\",\n    \"class\": 14,\n    \"seats\": 4,\n    \"doors\": 0,\n    \"type\": \"boat\",\n    \"price\": 2233400,\n    \"category\": \"sea\",\n    \"weapons\": true\n  },\n  \"dinghy5\": {\n    \"acceleration\": 16,\n    \"braking\": 0.4,\n    \"handling\": 16.38,\n    \"speed\": 41.6667,\n    \"traction\": 0,\n    \"name\": \"Weaponized Dinghy\",\n    \"make\": \"Nagasaki\",\n    \"class\": 14,\n    \"seats\": 5,\n    \"doors\": 0,\n    \"type\": \"boat\",\n    \"price\": 2233400,\n    \"category\": \"sea\",\n    \"weapons\": true\n  },\n  \"dloader\": {\n    \"acceleration\": 0.17,\n    \"braking\": 0.6,\n    \"handling\": 0.55,\n    \"speed\": 33.1998,\n    \"traction\": 1.7,\n    \"name\": \"Duneloader\",\n    \"make\": \"Bravado\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 55231,\n    \"category\": \"land\"\n  },\n  \"docktrailer\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5132,\n    \"traction\": 3.3,\n    \"name\": \"NULL\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 0,\n    \"type\": \"trailer\",\n    \"price\": 5668,\n    \"category\": \"land\"\n  },\n  \"docktug\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.5,\n    \"handling\": 0.58,\n    \"speed\": 24.6406,\n    \"traction\": 1.4,\n    \"name\": \"Docktug\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"automobile\",\n    \"price\": 41472,\n    \"category\": \"land\"\n  },\n  \"dodo\": {\n    \"acceleration\": 4.9,\n    \"braking\": 3.399,\n    \"handling\": 4.9,\n    \"speed\": 69.3676,\n    \"traction\": 2.15,\n    \"name\": \"Dodo\",\n    \"make\": \"Mammoth\",\n    \"class\": 16,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"plane\",\n    \"price\": 1321065,\n    \"category\": \"air\"\n  },\n  \"dominator\": {\n    \"acceleration\": 0.29,\n    \"braking\": 0.8,\n    \"handling\": 0.67,\n    \"speed\": 48.3333,\n    \"traction\": 2.25,\n    \"name\": \"Dominator\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 80149,\n    \"category\": \"land\"\n  },\n  \"dominator10\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.69,\n    \"handling\": 0.68,\n    \"speed\": 49.296,\n    \"traction\": 2.383,\n    \"name\": \"Dominator FX\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 81545,\n    \"category\": \"land\"\n  },\n  \"dominator2\": {\n    \"acceleration\": 0.31,\n    \"braking\": 0.9,\n    \"handling\": 0.69,\n    \"speed\": 49,\n    \"traction\": 2.3,\n    \"name\": \"Pisswasser Dominator\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 81440,\n    \"category\": \"land\"\n  },\n  \"dominator3\": {\n    \"acceleration\": 0.335,\n    \"braking\": 0.5,\n    \"handling\": 0.715,\n    \"speed\": 47.114,\n    \"traction\": 2.57,\n    \"name\": \"Dominator GTX\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 77862,\n    \"category\": \"land\"\n  },\n  \"dominator4\": {\n    \"acceleration\": 0.375,\n    \"braking\": 0.8,\n    \"handling\": 0.755,\n    \"speed\": 48.4233,\n    \"traction\": 2.35,\n    \"name\": \"Apocalypse Dominator\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 80565,\n    \"category\": \"land\"\n  },\n  \"dominator5\": {\n    \"acceleration\": 0.375,\n    \"braking\": 0.8,\n    \"handling\": 0.755,\n    \"speed\": 48.4233,\n    \"traction\": 2.35,\n    \"name\": \"Future Shock Dominator\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 80565,\n    \"category\": \"land\"\n  },\n  \"dominator6\": {\n    \"acceleration\": 0.375,\n    \"braking\": 0.8,\n    \"handling\": 0.755,\n    \"speed\": 48.4233,\n    \"traction\": 2.35,\n    \"name\": \"Nightmare Dominator\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 80565,\n    \"category\": \"land\"\n  },\n  \"dominator7\": {\n    \"acceleration\": 0.342,\n    \"braking\": 0.92,\n    \"handling\": 0.722,\n    \"speed\": 50.0913,\n    \"traction\": 2.535,\n    \"name\": \"Dominator ASP\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 83320,\n    \"category\": \"land\"\n  },\n  \"dominator8\": {\n    \"acceleration\": 0.3027,\n    \"braking\": 0.75,\n    \"handling\": 0.6827,\n    \"speed\": 45.9496,\n    \"traction\": 2.5,\n    \"name\": \"Dominator GTT\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 76295,\n    \"category\": \"land\"\n  },\n  \"dominator9\": {\n    \"acceleration\": 0.3448,\n    \"braking\": 0.93,\n    \"handling\": 0.7248,\n    \"speed\": 49.6897,\n    \"traction\": 2.545,\n    \"name\": \"Dominator GT\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 82702,\n    \"category\": \"land\"\n  },\n  \"dorado\": {\n    \"acceleration\": 0.2168,\n    \"braking\": 0.5,\n    \"handling\": 0.5968,\n    \"speed\": 42.173,\n    \"traction\": 1.845,\n    \"name\": \"Dorado\",\n    \"make\": \"Bravado\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 69578,\n    \"category\": \"land\"\n  },\n  \"double\": {\n    \"acceleration\": 0.31,\n    \"braking\": 1.4,\n    \"handling\": 0.69,\n    \"speed\": 47.9473,\n    \"traction\": 2.18,\n    \"name\": \"Double-T\",\n    \"make\": \"Dinka\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 25173,\n    \"category\": \"land\"\n  },\n  \"drafter\": {\n    \"acceleration\": 0.342,\n    \"braking\": 1,\n    \"handling\": 0.722,\n    \"speed\": 47.8784,\n    \"traction\": 2.695,\n    \"name\": \"8F Drafter\",\n    \"make\": \"Obey\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 79907,\n    \"category\": \"land\"\n  },\n  \"draugur\": {\n    \"acceleration\": 0.3425,\n    \"braking\": 0.484,\n    \"handling\": 0.7225,\n    \"speed\": 43.84,\n    \"traction\": 2.485,\n    \"name\": \"Draugur\",\n    \"make\": \"Declasse\",\n    \"class\": 9,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 72622,\n    \"category\": \"land\"\n  },\n  \"driftcheburek\": {\n    \"acceleration\": 0.7075,\n    \"braking\": 0.59,\n    \"handling\": 1.0875,\n    \"speed\": 44.4167,\n    \"traction\": 1.53,\n    \"name\": \"Cheburek\",\n    \"make\": \"RUNE\",\n    \"class\": 5,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 74882,\n    \"category\": \"land\"\n  },\n  \"driftcypher\": {\n    \"acceleration\": 0.7075,\n    \"braking\": 0.83,\n    \"handling\": 1.0875,\n    \"speed\": 44.4167,\n    \"traction\": 1.53,\n    \"name\": \"Cypher\",\n    \"make\": \"Ubermacht\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 75266,\n    \"category\": \"land\"\n  },\n  \"drifteuros\": {\n    \"acceleration\": 0.711,\n    \"braking\": 0.85,\n    \"handling\": 1.091,\n    \"speed\": 44.95,\n    \"traction\": 1.53,\n    \"name\": \"Euros\",\n    \"make\": \"Annis\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 76163,\n    \"category\": \"land\"\n  },\n  \"driftfr36\": {\n    \"acceleration\": 0.7125,\n    \"braking\": 0.765,\n    \"handling\": 1.0925,\n    \"speed\": 44.3333,\n    \"traction\": 1.53,\n    \"name\": \"FR36\",\n    \"make\": \"Fathom\",\n    \"class\": 3,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 75045,\n    \"category\": \"land\"\n  },\n  \"driftfuto\": {\n    \"acceleration\": 0.71,\n    \"braking\": 0.765,\n    \"handling\": 1.09,\n    \"speed\": 44.3333,\n    \"traction\": 1.53,\n    \"name\": \"Futo GTX\",\n    \"make\": \"Karin\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 75037,\n    \"category\": \"land\"\n  },\n  \"driftfuto2\": {\n    \"acceleration\": 0.71,\n    \"braking\": 0.66,\n    \"handling\": 1.09,\n    \"speed\": 44.3333,\n    \"traction\": 1.53,\n    \"name\": \"Futo\",\n    \"make\": \"Karin\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 74869,\n    \"category\": \"land\"\n  },\n  \"driftjester\": {\n    \"acceleration\": 0.706,\n    \"braking\": 0.875,\n    \"handling\": 1.086,\n    \"speed\": 44.1667,\n    \"traction\": 1.53,\n    \"name\": \"Jester RR\",\n    \"make\": \"Dinka\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 74933,\n    \"category\": \"land\"\n  },\n  \"driftjester3\": {\n    \"acceleration\": 0.711,\n    \"braking\": 0.65,\n    \"handling\": 1.091,\n    \"speed\": 44.6667,\n    \"traction\": 1.53,\n    \"name\": \"Jester Classic\",\n    \"make\": \"Dinka\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 75389,\n    \"category\": \"land\"\n  },\n  \"driftnebula\": {\n    \"acceleration\": 0.725,\n    \"braking\": 0.74,\n    \"handling\": 1.105,\n    \"speed\": 45.2667,\n    \"traction\": 1.53,\n    \"name\": \"Nebula Turbo\",\n    \"make\": \"Vulcar\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 76538,\n    \"category\": \"land\"\n  },\n  \"driftremus\": {\n    \"acceleration\": 0.712,\n    \"braking\": 0.87,\n    \"handling\": 1.092,\n    \"speed\": 46.2667,\n    \"traction\": 1.53,\n    \"name\": \"Remus\",\n    \"make\": \"Annis\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 78305,\n    \"category\": \"land\"\n  },\n  \"driftsentinel\": {\n    \"acceleration\": 0.716,\n    \"braking\": 0.85,\n    \"handling\": 1.096,\n    \"speed\": 44.6667,\n    \"traction\": 1.53,\n    \"name\": \"Sentinel Classic Widebody\",\n    \"make\": \"Ubermacht\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 75725,\n    \"category\": \"land\"\n  },\n  \"drifttampa\": {\n    \"acceleration\": 0.712,\n    \"braking\": 0.8,\n    \"handling\": 1.092,\n    \"speed\": 46.3333,\n    \"traction\": 1.53,\n    \"name\": \"Drift Tampa\",\n    \"make\": \"Declasse\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 78299,\n    \"category\": \"land\"\n  },\n  \"driftvorschlag\": {\n    \"acceleration\": 0.7085,\n    \"braking\": 0.725,\n    \"handling\": 1.0885,\n    \"speed\": 45.0667,\n    \"traction\": 1.53,\n    \"name\": \"Vorschlaghammer\",\n    \"make\": \"Benefactor\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 76141,\n    \"category\": \"land\"\n  },\n  \"driftyosemite\": {\n    \"acceleration\": 0.718,\n    \"braking\": 0.82,\n    \"handling\": 1.098,\n    \"speed\": 41.6667,\n    \"traction\": 1.53,\n    \"name\": \"Drift Yosemite\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 70884,\n    \"category\": \"land\"\n  },\n  \"driftzr350\": {\n    \"acceleration\": 0.708,\n    \"braking\": 0.85,\n    \"handling\": 1.088,\n    \"speed\": 44.2667,\n    \"traction\": 1.53,\n    \"name\": \"ZR350\",\n    \"make\": \"Annis\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 75060,\n    \"category\": \"land\"\n  },\n  \"dubsta\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.8,\n    \"handling\": 0.58,\n    \"speed\": 37.5559,\n    \"traction\": 2.15,\n    \"name\": \"Dubsta\",\n    \"make\": \"Benefactor\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 62617,\n    \"category\": \"land\"\n  },\n  \"dubsta2\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.8,\n    \"handling\": 0.58,\n    \"speed\": 37.5559,\n    \"traction\": 2.15,\n    \"name\": \"Dubsta\",\n    \"make\": \"Benefactor\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 62617,\n    \"category\": \"land\"\n  },\n  \"dubsta3\": {\n    \"acceleration\": 0.28,\n    \"braking\": 0.6,\n    \"handling\": 0.66,\n    \"speed\": 38.8077,\n    \"traction\": 2,\n    \"name\": \"Dubsta 6x6\",\n    \"make\": \"Benefactor\",\n    \"class\": 9,\n    \"seats\": 6,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 64556,\n    \"category\": \"land\"\n  },\n  \"dukes\": {\n    \"acceleration\": 0.32,\n    \"braking\": 0.8,\n    \"handling\": 0.7,\n    \"speed\": 47.7946,\n    \"traction\": 2.25,\n    \"name\": \"Dukes\",\n    \"make\": \"Imponte\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 79383,\n    \"category\": \"land\"\n  },\n  \"dukes2\": {\n    \"acceleration\": 0.35,\n    \"braking\": 0.9,\n    \"handling\": 0.73,\n    \"speed\": 46.5269,\n    \"traction\": 2.26,\n    \"name\": \"Duke O'Death\",\n    \"make\": \"Imponte\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 77611,\n    \"category\": \"land\"\n  },\n  \"dukes3\": {\n    \"acceleration\": 0.315,\n    \"braking\": 0.75,\n    \"handling\": 0.695,\n    \"speed\": 47.3507,\n    \"traction\": 2.2,\n    \"name\": \"Beater Dukes\",\n    \"make\": \"Imponte\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 78577,\n    \"category\": \"land\"\n  },\n  \"dump\": {\n    \"acceleration\": 0.19,\n    \"braking\": 0.3,\n    \"handling\": 0.57,\n    \"speed\": 14.3333,\n    \"traction\": 1.45,\n    \"name\": \"Dump\",\n    \"make\": \"HVY\",\n    \"class\": 10,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"automobile\",\n    \"price\": 24629,\n    \"category\": \"land\"\n  },\n  \"dune\": {\n    \"acceleration\": 0.25,\n    \"braking\": 0.63,\n    \"handling\": 0.63,\n    \"speed\": 38.876,\n    \"traction\": 2.2,\n    \"name\": \"Dune Buggy\",\n    \"make\": \"BF\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 0,\n    \"type\": \"automobile\",\n    \"price\": 64617,\n    \"category\": \"land\"\n  },\n  \"dune2\": {\n    \"acceleration\": 0.24,\n    \"braking\": 0.63,\n    \"handling\": 0.62,\n    \"speed\": 37.9382,\n    \"traction\": 2,\n    \"name\": \"Space Docker\",\n    \"make\": \"\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 0,\n    \"type\": \"automobile\",\n    \"price\": 63085,\n    \"category\": \"land\"\n  },\n  \"dune3\": {\n    \"acceleration\": 0.25,\n    \"braking\": 0.63,\n    \"handling\": 0.63,\n    \"speed\": 38.876,\n    \"traction\": 2.2,\n    \"name\": \"Dune FAV\",\n    \"make\": \"BF\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 0,\n    \"type\": \"automobile\",\n    \"price\": 323087,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"dune4\": {\n    \"acceleration\": 0.324,\n    \"braking\": 1,\n    \"handling\": 0.704,\n    \"speed\": 49.2242,\n    \"traction\": 2.65,\n    \"name\": \"Ramp Buggy\",\n    \"make\": \"\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 0,\n    \"type\": \"automobile\",\n    \"price\": 82003,\n    \"category\": \"land\"\n  },\n  \"dune5\": {\n    \"acceleration\": 0.32,\n    \"braking\": 1,\n    \"handling\": 0.7,\n    \"speed\": 48.84,\n    \"traction\": 2.65,\n    \"name\": \"Ramp Buggy\",\n    \"make\": \"\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 0,\n    \"type\": \"automobile\",\n    \"price\": 81376,\n    \"category\": \"land\"\n  },\n  \"duster\": {\n    \"acceleration\": 4.9,\n    \"braking\": 3.399,\n    \"handling\": 4.9,\n    \"speed\": 69.3676,\n    \"traction\": 2.15,\n    \"name\": \"Duster\",\n    \"make\": \"\",\n    \"class\": 16,\n    \"seats\": 2,\n    \"doors\": 0,\n    \"type\": \"plane\",\n    \"price\": 1321065,\n    \"category\": \"air\"\n  },\n  \"duster2\": {\n    \"acceleration\": 6.566,\n    \"braking\": 5.9026,\n    \"handling\": 6.566,\n    \"speed\": 89.897,\n    \"traction\": 2.15,\n    \"name\": \"Duster 300-H\",\n    \"make\": \"Western\",\n    \"class\": 16,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"plane\",\n    \"price\": 1742905,\n    \"category\": \"air\"\n  },\n  \"dynasty\": {\n    \"acceleration\": 0.18,\n    \"braking\": 0.4,\n    \"handling\": 0.56,\n    \"speed\": 35.6353,\n    \"traction\": 1.7,\n    \"name\": \"Dynasty\",\n    \"make\": \"Weeny\",\n    \"class\": 5,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 58840,\n    \"category\": \"land\"\n  },\n  \"elegy\": {\n    \"acceleration\": 0.33,\n    \"braking\": 1,\n    \"handling\": 0.71,\n    \"speed\": 47.1697,\n    \"traction\": 2.7,\n    \"name\": \"Elegy Retro Custom\",\n    \"make\": \"Annis\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 78735,\n    \"category\": \"land\"\n  },\n  \"elegy2\": {\n    \"acceleration\": 0.33,\n    \"braking\": 0.5,\n    \"handling\": 0.71,\n    \"speed\": 48.6724,\n    \"traction\": 2.7,\n    \"name\": \"Elegy RH8\",\n    \"make\": \"Annis\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 80339,\n    \"category\": \"land\"\n  },\n  \"ellie\": {\n    \"acceleration\": 0.325,\n    \"braking\": 0.5,\n    \"handling\": 0.705,\n    \"speed\": 45.8341,\n    \"traction\": 2.55,\n    \"name\": \"Ellie\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 75782,\n    \"category\": \"land\"\n  },\n  \"emerus\": {\n    \"acceleration\": 0.378,\n    \"braking\": 1.2,\n    \"handling\": 0.758,\n    \"speed\": 50.8594,\n    \"traction\": 2.78,\n    \"name\": \"Emerus\",\n    \"make\": \"Progen\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 85112,\n    \"category\": \"land\"\n  },\n  \"emperor\": {\n    \"acceleration\": 0.14,\n    \"braking\": 0.6,\n    \"handling\": 0.52,\n    \"speed\": 33.8088,\n    \"traction\": 1.9,\n    \"name\": \"Emperor\",\n    \"make\": \"Albany\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 56110,\n    \"category\": \"land\"\n  },\n  \"emperor2\": {\n    \"acceleration\": 0.14,\n    \"braking\": 0.6,\n    \"handling\": 0.52,\n    \"speed\": 33.8088,\n    \"traction\": 1.9,\n    \"name\": \"Emperor\",\n    \"make\": \"Albany\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 56110,\n    \"category\": \"land\"\n  },\n  \"emperor3\": {\n    \"acceleration\": 0.14,\n    \"braking\": 0.6,\n    \"handling\": 0.52,\n    \"speed\": 33.8088,\n    \"traction\": 1.9,\n    \"name\": \"Emperor\",\n    \"make\": \"Albany\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 56110,\n    \"category\": \"land\"\n  },\n  \"enduro\": {\n    \"acceleration\": 0.3,\n    \"braking\": 1.05,\n    \"handling\": 0.68,\n    \"speed\": 39.6667,\n    \"traction\": 2.16,\n    \"name\": \"Enduro\",\n    \"make\": \"Dinka\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 20848,\n    \"category\": \"land\"\n  },\n  \"entity2\": {\n    \"acceleration\": 0.355,\n    \"braking\": 1,\n    \"handling\": 0.735,\n    \"speed\": 53.7141,\n    \"traction\": 2.77,\n    \"name\": \"Entity XXR\",\n    \"make\": \"Overflod\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 89286,\n    \"category\": \"land\"\n  },\n  \"entity3\": {\n    \"acceleration\": 0.3545,\n    \"braking\": 1,\n    \"handling\": 0.7845,\n    \"speed\": 53.6165,\n    \"traction\": 2.782,\n    \"name\": \"Entity MT\",\n    \"make\": \"Overflod\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 89208,\n    \"category\": \"land\"\n  },\n  \"entityxf\": {\n    \"acceleration\": 0.33,\n    \"braking\": 0.9,\n    \"handling\": 0.71,\n    \"speed\": 50.9358,\n    \"traction\": 2.75,\n    \"name\": \"Entity XF\",\n    \"make\": \"Overflod\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 84601,\n    \"category\": \"land\"\n  },\n  \"envisage\": {\n    \"acceleration\": 0.175,\n    \"braking\": 0.82,\n    \"handling\": 0.555,\n    \"speed\": 33.3943,\n    \"traction\": 2.72,\n    \"name\": \"Envisage\",\n    \"make\": \"Bollokan\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 55910,\n    \"category\": \"land\"\n  },\n  \"esskey\": {\n    \"acceleration\": 0.295,\n    \"braking\": 1.2,\n    \"handling\": 0.675,\n    \"speed\": 44.1064,\n    \"traction\": 2.15,\n    \"name\": \"Esskey\",\n    \"make\": \"Pegassi\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 23138,\n    \"category\": \"land\"\n  },\n  \"eudora\": {\n    \"acceleration\": 0.195,\n    \"braking\": 0.265,\n    \"handling\": 0.575,\n    \"speed\": 40.7273,\n    \"traction\": 1.89,\n    \"name\": \"Eudora\",\n    \"make\": \"Willard\",\n    \"class\": 4,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 66819,\n    \"category\": \"land\"\n  },\n  \"euros\": {\n    \"acceleration\": 0.324,\n    \"braking\": 0.9,\n    \"handling\": 0.704,\n    \"speed\": 47.3475,\n    \"traction\": 2.5615,\n    \"name\": \"Euros\",\n    \"make\": \"Annis\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 78840,\n    \"category\": \"land\"\n  },\n  \"eurosx32\": {\n    \"acceleration\": 0.28,\n    \"braking\": 0.8,\n    \"handling\": 0.71,\n    \"speed\": 44.1427,\n    \"traction\": 2.287,\n    \"name\": \"Euros X32\",\n    \"make\": \"Annis\",\n    \"class\": 3,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 73492,\n    \"category\": \"land\"\n  },\n  \"everon\": {\n    \"acceleration\": 0.295,\n    \"braking\": 0.3,\n    \"handling\": 0.675,\n    \"speed\": 41.7322,\n    \"traction\": 2.05,\n    \"name\": \"Everon\",\n    \"make\": \"Karin\",\n    \"class\": 9,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 68803,\n    \"category\": \"land\"\n  },\n  \"everon2\": {\n    \"acceleration\": 0.3395,\n    \"braking\": 0.685,\n    \"handling\": 0.7195,\n    \"speed\": 48.1577,\n    \"traction\": 2.5445,\n    \"name\": \"Hotring Everon\",\n    \"make\": \"Karin\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 79842,\n    \"category\": \"land\"\n  },\n  \"exemplar\": {\n    \"acceleration\": 0.26,\n    \"braking\": 0.9,\n    \"handling\": 0.64,\n    \"speed\": 48.1321,\n    \"traction\": 2.6,\n    \"name\": \"Exemplar\",\n    \"make\": \"Dewbauchee\",\n    \"class\": 3,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 79891,\n    \"category\": \"land\"\n  },\n  \"f620\": {\n    \"acceleration\": 0.24,\n    \"braking\": 0.9,\n    \"handling\": 0.62,\n    \"speed\": 47.9948,\n    \"traction\": 2.5,\n    \"name\": \"F620\",\n    \"make\": \"Ocelot\",\n    \"class\": 3,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 79607,\n    \"category\": \"land\"\n  },\n  \"faction\": {\n    \"acceleration\": 0.28,\n    \"braking\": 0.8,\n    \"handling\": 0.66,\n    \"speed\": 46.6667,\n    \"traction\": 2.25,\n    \"name\": \"Faction\",\n    \"make\": \"Willard\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 77450,\n    \"category\": \"land\"\n  },\n  \"faction2\": {\n    \"acceleration\": 0.28,\n    \"braking\": 0.8,\n    \"handling\": 0.66,\n    \"speed\": 46.6667,\n    \"traction\": 2.25,\n    \"name\": \"Faction Custom\",\n    \"make\": \"Willard\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 77450,\n    \"category\": \"land\"\n  },\n  \"faction3\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.8,\n    \"handling\": 0.58,\n    \"speed\": 35.2769,\n    \"traction\": 2.35,\n    \"name\": \"Faction Custom Donk\",\n    \"make\": \"Willard\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 58971,\n    \"category\": \"land\"\n  },\n  \"fagaloa\": {\n    \"acceleration\": 0.21,\n    \"braking\": 0.775,\n    \"handling\": 0.59,\n    \"speed\": 34.3913,\n    \"traction\": 2.375,\n    \"name\": \"Fagaloa\",\n    \"make\": \"Vulcar\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 57546,\n    \"category\": \"land\"\n  },\n  \"faggio\": {\n    \"acceleration\": 0.1975,\n    \"braking\": 0.4,\n    \"handling\": 0.5775,\n    \"speed\": 28.2827,\n    \"traction\": 1.7,\n    \"name\": \"Faggio Sport\",\n    \"make\": \"Pegassi\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 14728,\n    \"category\": \"land\"\n  },\n  \"faggio2\": {\n    \"acceleration\": 0.1,\n    \"braking\": 0.4,\n    \"handling\": 0.48,\n    \"speed\": 23.5477,\n    \"traction\": 1.6,\n    \"name\": \"Faggio\",\n    \"make\": \"Pegassi\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 12263,\n    \"category\": \"land\"\n  },\n  \"faggio3\": {\n    \"acceleration\": 0.195,\n    \"braking\": 0.4,\n    \"handling\": 0.575,\n    \"speed\": 27.4138,\n    \"traction\": 1.7,\n    \"name\": \"Faggio Mod\",\n    \"make\": \"Pegassi\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 14291,\n    \"category\": \"land\"\n  },\n  \"fbi\": {\n    \"acceleration\": 0.28,\n    \"braking\": 0.9,\n    \"handling\": 0.66,\n    \"speed\": 46.1566,\n    \"traction\": 2.45,\n    \"name\": \"FIB\",\n    \"make\": \"\",\n    \"class\": 18,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 76794,\n    \"category\": \"land\"\n  },\n  \"fbi2\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.8,\n    \"handling\": 0.58,\n    \"speed\": 37.5559,\n    \"traction\": 2.15,\n    \"name\": \"FIB\",\n    \"make\": \"\",\n    \"class\": 18,\n    \"seats\": 8,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 62617,\n    \"category\": \"land\"\n  },\n  \"fcr\": {\n    \"acceleration\": 0.305,\n    \"braking\": 1.2,\n    \"handling\": 0.685,\n    \"speed\": 46.4526,\n    \"traction\": 2.1,\n    \"name\": \"FCR 1000\",\n    \"make\": \"Pegassi\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 24321,\n    \"category\": \"land\"\n  },\n  \"fcr2\": {\n    \"acceleration\": 0.31,\n    \"braking\": 1.25,\n    \"handling\": 0.69,\n    \"speed\": 46.7333,\n    \"traction\": 2.15,\n    \"name\": \"FCR 1000 Custom\",\n    \"make\": \"Pegassi\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 24491,\n    \"category\": \"land\"\n  },\n  \"felon\": {\n    \"acceleration\": 0.24,\n    \"braking\": 0.9,\n    \"handling\": 0.62,\n    \"speed\": 45.7952,\n    \"traction\": 2.55,\n    \"name\": \"Felon\",\n    \"make\": \"Lampadati\",\n    \"class\": 3,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 76088,\n    \"category\": \"land\"\n  },\n  \"felon2\": {\n    \"acceleration\": 0.24,\n    \"braking\": 0.9,\n    \"handling\": 0.62,\n    \"speed\": 43.455,\n    \"traction\": 2.5,\n    \"name\": \"Felon GT\",\n    \"make\": \"Lampadati\",\n    \"class\": 3,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 72344,\n    \"category\": \"land\"\n  },\n  \"feltzer2\": {\n    \"acceleration\": 0.34,\n    \"braking\": 0.8,\n    \"handling\": 0.72,\n    \"speed\": 49.5374,\n    \"traction\": 2.65,\n    \"name\": \"Feltzer\",\n    \"make\": \"Benefactor\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 82235,\n    \"category\": \"land\"\n  },\n  \"feltzer3\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.8,\n    \"handling\": 0.68,\n    \"speed\": 45.9981,\n    \"traction\": 2.35,\n    \"name\": \"Stirling GT\",\n    \"make\": \"Benefactor\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 76444,\n    \"category\": \"land\"\n  },\n  \"firebolt\": {\n    \"acceleration\": 0.2962,\n    \"braking\": 0.39,\n    \"handling\": 0.7362,\n    \"speed\": 46.6612,\n    \"traction\": 2.34,\n    \"name\": \"Firebolt ASP\",\n    \"make\": \"Vapid\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 76933,\n    \"category\": \"land\"\n  },\n  \"firetruk\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.5,\n    \"handling\": 0.54,\n    \"speed\": 39.2959,\n    \"traction\": 1.7,\n    \"name\": \"Fire Truck\",\n    \"make\": \"MTL\",\n    \"class\": 18,\n    \"seats\": 8,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 323967,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"fixter\": {\n    \"acceleration\": 0.135,\n    \"braking\": 0.4,\n    \"handling\": 0.515,\n    \"speed\": 17.851,\n    \"traction\": 1.85,\n    \"name\": \"Fixter\",\n    \"make\": \"\",\n    \"class\": 13,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bicycle\",\n    \"price\": 2835,\n    \"category\": \"land\"\n  },\n  \"flashgt\": {\n    \"acceleration\": 0.32,\n    \"braking\": 1,\n    \"handling\": 0.7,\n    \"speed\": 44.1615,\n    \"traction\": 2.45,\n    \"name\": \"Flash GT\",\n    \"make\": \"Vapid\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 73890,\n    \"category\": \"land\"\n  },\n  \"flatbed\": {\n    \"acceleration\": 0.14,\n    \"braking\": 0.25,\n    \"handling\": 0.52,\n    \"speed\": 28.2361,\n    \"traction\": 1.65,\n    \"name\": \"Flatbed\",\n    \"make\": \"MTL\",\n    \"class\": 10,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 46633,\n    \"category\": \"land\"\n  },\n  \"fmj\": {\n    \"acceleration\": 0.3655,\n    \"braking\": 1.1,\n    \"handling\": 0.7455,\n    \"speed\": 52.8,\n    \"traction\": 2.7,\n    \"name\": \"FMJ\",\n    \"make\": \"Vapid\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 88017,\n    \"category\": \"land\"\n  },\n  \"forklift\": {\n    \"acceleration\": 0.18,\n    \"braking\": 0.3,\n    \"handling\": 0.56,\n    \"speed\": 10,\n    \"traction\": 1.15,\n    \"name\": \"Forklift\",\n    \"make\": \"HVY\",\n    \"class\": 11,\n    \"seats\": 1,\n    \"doors\": 0,\n    \"type\": \"automobile\",\n    \"price\": 17664,\n    \"category\": \"land\"\n  },\n  \"formula\": {\n    \"acceleration\": 0.75,\n    \"braking\": 1.25,\n    \"handling\": 1.13,\n    \"speed\": 52.5647,\n    \"traction\": 3.25,\n    \"name\": \"PR4\",\n    \"make\": \"Progen\",\n    \"class\": 22,\n    \"seats\": 1,\n    \"doors\": 0,\n    \"type\": \"automobile\",\n    \"price\": 178223,\n    \"category\": \"land\"\n  },\n  \"formula2\": {\n    \"acceleration\": 0.745,\n    \"braking\": 1.25,\n    \"handling\": 1.125,\n    \"speed\": 52.3861,\n    \"traction\": 3.1325,\n    \"name\": \"R88\",\n    \"make\": \"Ocelot\",\n    \"class\": 22,\n    \"seats\": 1,\n    \"doors\": 0,\n    \"type\": \"automobile\",\n    \"price\": 177619,\n    \"category\": \"land\"\n  },\n  \"fq2\": {\n    \"acceleration\": 0.18,\n    \"braking\": 0.25,\n    \"handling\": 0.56,\n    \"speed\": 39.9117,\n    \"traction\": 2,\n    \"name\": \"FQ 2\",\n    \"make\": \"Fathom\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 65442,\n    \"category\": \"land\"\n  },\n  \"fr36\": {\n    \"acceleration\": 0.301,\n    \"braking\": 0.86,\n    \"handling\": 0.681,\n    \"speed\": 47.3251,\n    \"traction\": 2.383,\n    \"name\": \"FR36\",\n    \"make\": \"Fathom\",\n    \"class\": 3,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 78667,\n    \"category\": \"land\"\n  },\n  \"freecrawler\": {\n    \"acceleration\": 0.24,\n    \"braking\": 0.3,\n    \"handling\": 0.62,\n    \"speed\": 36.6234,\n    \"traction\": 2.05,\n    \"name\": \"Freecrawler\",\n    \"make\": \"Canis\",\n    \"class\": 9,\n    \"seats\": 4,\n    \"doors\": 7,\n    \"type\": \"automobile\",\n    \"price\": 60453,\n    \"category\": \"land\"\n  },\n  \"freight\": {\n    \"acceleration\": 0.2,\n    \"braking\": 5,\n    \"handling\": 0.58,\n    \"speed\": 26.6667,\n    \"traction\": 2.5,\n    \"name\": \"Freight Train\",\n    \"make\": \"\",\n    \"class\": 21,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"train\",\n    \"price\": 194680,\n    \"category\": \"land\"\n  },\n  \"freight2\": {\n    \"acceleration\": 0.2,\n    \"braking\": 5,\n    \"handling\": 0.58,\n    \"speed\": 26.6667,\n    \"traction\": 2.5,\n    \"name\": \"Freight Train\",\n    \"make\": \"\",\n    \"class\": 21,\n    \"seats\": 2,\n    \"doors\": 0,\n    \"type\": \"train\",\n    \"price\": 194680,\n    \"category\": \"land\"\n  },\n  \"freightcar\": {\n    \"acceleration\": 0.2,\n    \"braking\": 5,\n    \"handling\": 0.58,\n    \"speed\": 26.6667,\n    \"traction\": 2.5,\n    \"name\": \"Freight Train\",\n    \"make\": \"\",\n    \"class\": 21,\n    \"seats\": 0,\n    \"doors\": 0,\n    \"type\": \"train\",\n    \"price\": 194680,\n    \"category\": \"land\"\n  },\n  \"freightcar2\": {\n    \"acceleration\": 0.2,\n    \"braking\": 5,\n    \"handling\": 0.58,\n    \"speed\": 26.6667,\n    \"traction\": 2.5,\n    \"name\": \"Freight Train\",\n    \"make\": \"\",\n    \"class\": 21,\n    \"seats\": 0,\n    \"doors\": 0,\n    \"type\": \"train\",\n    \"price\": 194680,\n    \"category\": \"land\"\n  },\n  \"freightcar3\": {\n    \"acceleration\": 0.2,\n    \"braking\": 5,\n    \"handling\": 0.58,\n    \"speed\": 26.6667,\n    \"traction\": 2.5,\n    \"name\": \"Freight Train\",\n    \"make\": \"\",\n    \"class\": 21,\n    \"seats\": 0,\n    \"doors\": 0,\n    \"type\": \"train\",\n    \"price\": 194680,\n    \"category\": \"land\"\n  },\n  \"freightcont1\": {\n    \"acceleration\": 0.2,\n    \"braking\": 5,\n    \"handling\": 0.58,\n    \"speed\": 26.6667,\n    \"traction\": 2.5,\n    \"name\": \"Freight Train\",\n    \"make\": \"\",\n    \"class\": 21,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"train\",\n    \"price\": 194680,\n    \"category\": \"land\"\n  },\n  \"freightcont2\": {\n    \"acceleration\": 0.2,\n    \"braking\": 5,\n    \"handling\": 0.58,\n    \"speed\": 26.6667,\n    \"traction\": 2.5,\n    \"name\": \"Freight Train\",\n    \"make\": \"\",\n    \"class\": 21,\n    \"seats\": 2,\n    \"doors\": 0,\n    \"type\": \"train\",\n    \"price\": 194680,\n    \"category\": \"land\"\n  },\n  \"freightgrain\": {\n    \"acceleration\": 0.2,\n    \"braking\": 5,\n    \"handling\": 0.58,\n    \"speed\": 26.6667,\n    \"traction\": 2.5,\n    \"name\": \"Freight Train\",\n    \"make\": \"\",\n    \"class\": 21,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"train\",\n    \"price\": 194680,\n    \"category\": \"land\"\n  },\n  \"freighttrailer\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5132,\n    \"traction\": 3,\n    \"name\": \"NULL\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 0,\n    \"type\": \"trailer\",\n    \"price\": 5668,\n    \"category\": \"land\"\n  },\n  \"frogger\": {\n    \"acceleration\": 5.488,\n    \"braking\": 3.1099,\n    \"handling\": 5.488,\n    \"speed\": 56.6681,\n    \"traction\": 1.3,\n    \"name\": \"Frogger\",\n    \"make\": \"\",\n    \"class\": 15,\n    \"seats\": 4,\n    \"doors\": 2,\n    \"type\": \"heli\",\n    \"price\": 31839300,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"frogger2\": {\n    \"acceleration\": 5.488,\n    \"braking\": 3.1099,\n    \"handling\": 5.488,\n    \"speed\": 56.6681,\n    \"traction\": 1.3,\n    \"name\": \"Frogger\",\n    \"make\": \"\",\n    \"class\": 15,\n    \"seats\": 4,\n    \"doors\": 2,\n    \"type\": \"heli\",\n    \"price\": 31839300,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"fugitive\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.9,\n    \"handling\": 0.58,\n    \"speed\": 40.3933,\n    \"traction\": 2.5,\n    \"name\": \"Fugitive\",\n    \"make\": \"Cheval\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 67317,\n    \"category\": \"land\"\n  },\n  \"furia\": {\n    \"acceleration\": 0.365,\n    \"braking\": 1,\n    \"handling\": 0.745,\n    \"speed\": 49.8338,\n    \"traction\": 2.7,\n    \"name\": \"Furia\",\n    \"make\": \"Grotti\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 83110,\n    \"category\": \"land\"\n  },\n  \"furoregt\": {\n    \"acceleration\": 0.335,\n    \"braking\": 1,\n    \"handling\": 0.715,\n    \"speed\": 50.6667,\n    \"traction\": 2.56,\n    \"name\": \"Furore GT\",\n    \"make\": \"Lampadati\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 84346,\n    \"category\": \"land\"\n  },\n  \"fusilade\": {\n    \"acceleration\": 0.32,\n    \"braking\": 0.9,\n    \"handling\": 0.7,\n    \"speed\": 48.8621,\n    \"traction\": 2.45,\n    \"name\": \"Fusilade\",\n    \"make\": \"Schyster\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 81251,\n    \"category\": \"land\"\n  },\n  \"futo\": {\n    \"acceleration\": 0.29,\n    \"braking\": 0.5,\n    \"handling\": 0.67,\n    \"speed\": 45,\n    \"traction\": 2.05,\n    \"name\": \"Futo\",\n    \"make\": \"Karin\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 74336,\n    \"category\": \"land\"\n  },\n  \"futo2\": {\n    \"acceleration\": 0.2965,\n    \"braking\": 0.525,\n    \"handling\": 0.6765,\n    \"speed\": 45.6667,\n    \"traction\": 2.095,\n    \"name\": \"Futo GTX\",\n    \"make\": \"Karin\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 75463,\n    \"category\": \"land\"\n  },\n  \"gargoyle\": {\n    \"acceleration\": 0.3125,\n    \"braking\": 1.1,\n    \"handling\": 0.6925,\n    \"speed\": 48.2865,\n    \"traction\": 2.25,\n    \"name\": \"Gargoyle\",\n    \"make\": \"Western\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 25195,\n    \"category\": \"land\"\n  },\n  \"gauntlet\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.9,\n    \"handling\": 0.68,\n    \"speed\": 47.0182,\n    \"traction\": 2.5,\n    \"name\": \"Gauntlet\",\n    \"make\": \"Bravado\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 78237,\n    \"category\": \"land\"\n  },\n  \"gauntlet2\": {\n    \"acceleration\": 0.315,\n    \"braking\": 0.9,\n    \"handling\": 0.695,\n    \"speed\": 48.4065,\n    \"traction\": 2.51,\n    \"name\": \"Redwood Gauntlet\",\n    \"make\": \"Bravado\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 80506,\n    \"category\": \"land\"\n  },\n  \"gauntlet3\": {\n    \"acceleration\": 0.28,\n    \"braking\": 0.9,\n    \"handling\": 0.66,\n    \"speed\": 44.1427,\n    \"traction\": 2.5,\n    \"name\": \"Gauntlet Classic\",\n    \"make\": \"Bravado\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 73572,\n    \"category\": \"land\"\n  },\n  \"gauntlet4\": {\n    \"acceleration\": 0.36,\n    \"braking\": 0.9,\n    \"handling\": 0.74,\n    \"speed\": 48.6553,\n    \"traction\": 2.35,\n    \"name\": \"Gauntlet Hellfire\",\n    \"make\": \"Bravado\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 81048,\n    \"category\": \"land\"\n  },\n  \"gauntlet5\": {\n    \"acceleration\": 0.29,\n    \"braking\": 0.9,\n    \"handling\": 0.67,\n    \"speed\": 48.2968,\n    \"traction\": 2.25,\n    \"name\": \"Gauntlet Classic Custom\",\n    \"make\": \"Bravado\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 80250,\n    \"category\": \"land\"\n  },\n  \"gauntlet6\": {\n    \"acceleration\": 0.3668,\n    \"braking\": 0.935,\n    \"handling\": 0.7467,\n    \"speed\": 48.9926,\n    \"traction\": 2.482,\n    \"name\": \"Hotring Hellfire\",\n    \"make\": \"Bravado\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 81665,\n    \"category\": \"land\"\n  },\n  \"gb200\": {\n    \"acceleration\": 0.315,\n    \"braking\": 1,\n    \"handling\": 0.695,\n    \"speed\": 44.574,\n    \"traction\": 2.3,\n    \"name\": \"GB200\",\n    \"make\": \"Vapid\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 74534,\n    \"category\": \"land\"\n  },\n  \"gburrito\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.6,\n    \"handling\": 0.54,\n    \"speed\": 36.9472,\n    \"traction\": 1.95,\n    \"name\": \"Gang Burrito\",\n    \"make\": \"Declasse\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 61195,\n    \"category\": \"land\"\n  },\n  \"gburrito2\": {\n    \"acceleration\": 0.18,\n    \"braking\": 0.7,\n    \"handling\": 0.56,\n    \"speed\": 39.9117,\n    \"traction\": 2.05,\n    \"name\": \"Gang Burrito\",\n    \"make\": \"Declasse\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 66162,\n    \"category\": \"land\"\n  },\n  \"glendale\": {\n    \"acceleration\": 0.235,\n    \"braking\": 0.65,\n    \"handling\": 0.615,\n    \"speed\": 39.718,\n    \"traction\": 2.05,\n    \"name\": \"Glendale\",\n    \"make\": \"Benefactor\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 65948,\n    \"category\": \"land\"\n  },\n  \"glendale2\": {\n    \"acceleration\": 0.233,\n    \"braking\": 0.625,\n    \"handling\": 0.613,\n    \"speed\": 39.8451,\n    \"traction\": 2.25,\n    \"name\": \"Glendale Custom\",\n    \"make\": \"Benefactor\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 66105,\n    \"category\": \"land\"\n  },\n  \"gp1\": {\n    \"acceleration\": 0.37,\n    \"braking\": 1.2,\n    \"handling\": 0.75,\n    \"speed\": 50.3181,\n    \"traction\": 2.68,\n    \"name\": \"GP1\",\n    \"make\": \"Progen\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 84220,\n    \"category\": \"land\"\n  },\n  \"graintrailer\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5132,\n    \"traction\": 3.3,\n    \"name\": \"NULL\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 1,\n    \"type\": \"trailer\",\n    \"price\": 5668,\n    \"category\": \"land\"\n  },\n  \"granger\": {\n    \"acceleration\": 0.19,\n    \"braking\": 0.8,\n    \"handling\": 0.57,\n    \"speed\": 36.3729,\n    \"traction\": 2.15,\n    \"name\": \"Granger\",\n    \"make\": \"Declasse\",\n    \"class\": 2,\n    \"seats\": 8,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 60692,\n    \"category\": \"land\"\n  },\n  \"granger2\": {\n    \"acceleration\": 0.2075,\n    \"braking\": 0.84,\n    \"handling\": 0.5875,\n    \"speed\": 34.0257,\n    \"traction\": 2.18,\n    \"name\": \"Granger 3600LX\",\n    \"make\": \"Declasse\",\n    \"class\": 2,\n    \"seats\": 8,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 57057,\n    \"category\": \"land\"\n  },\n  \"greenwood\": {\n    \"acceleration\": 0.282,\n    \"braking\": 0.7,\n    \"handling\": 0.662,\n    \"speed\": 47.6667,\n    \"traction\": 2.3,\n    \"name\": \"Greenwood\",\n    \"make\": \"Bravado\",\n    \"class\": 4,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 78897,\n    \"category\": \"land\"\n  },\n  \"gresley\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.6,\n    \"handling\": 0.58,\n    \"speed\": 38.4289,\n    \"traction\": 1.9,\n    \"name\": \"Gresley\",\n    \"make\": \"Bravado\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 63694,\n    \"category\": \"land\"\n  },\n  \"growler\": {\n    \"acceleration\": 0.3338,\n    \"braking\": 0.84,\n    \"handling\": 0.7138,\n    \"speed\": 49.7596,\n    \"traction\": 2.63,\n    \"name\": \"Growler\",\n    \"make\": \"Pfister\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 82635,\n    \"category\": \"land\"\n  },\n  \"gt500\": {\n    \"acceleration\": 0.29,\n    \"braking\": 0.77,\n    \"handling\": 0.67,\n    \"speed\": 45.8691,\n    \"traction\": 2.2,\n    \"name\": \"GT500\",\n    \"make\": \"Grotti\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 76158,\n    \"category\": \"land\"\n  },\n  \"guardian\": {\n    \"acceleration\": 0.21,\n    \"braking\": 0.6,\n    \"handling\": 0.59,\n    \"speed\": 39.6177,\n    \"traction\": 2,\n    \"name\": \"Guardian\",\n    \"make\": \"Vapid\",\n    \"class\": 10,\n    \"seats\": 6,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 65628,\n    \"category\": \"land\"\n  },\n  \"habanero\": {\n    \"acceleration\": 0.18,\n    \"braking\": 0.25,\n    \"handling\": 0.56,\n    \"speed\": 39.9117,\n    \"traction\": 2.1,\n    \"name\": \"Habanero\",\n    \"make\": \"Emperor\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 65442,\n    \"category\": \"land\"\n  },\n  \"hakuchou\": {\n    \"acceleration\": 0.315,\n    \"braking\": 1.4,\n    \"handling\": 0.695,\n    \"speed\": 49.5412,\n    \"traction\": 2.3,\n    \"name\": \"Hakuchou\",\n    \"make\": \"Shitzu\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 25975,\n    \"category\": \"land\"\n  },\n  \"hakuchou2\": {\n    \"acceleration\": 0.425,\n    \"braking\": 1.4,\n    \"handling\": 0.885,\n    \"speed\": 52.0387,\n    \"traction\": 2.9,\n    \"name\": \"Hakuchou Drag\",\n    \"make\": \"Shitzu\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 27374,\n    \"category\": \"land\"\n  },\n  \"halftrack\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.2,\n    \"handling\": 0.54,\n    \"speed\": 20.9333,\n    \"traction\": 2.3,\n    \"name\": \"Half-track\",\n    \"make\": \"Bravado\",\n    \"class\": 19,\n    \"seats\": 3,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 174666,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"handler\": {\n    \"acceleration\": 0.14,\n    \"braking\": 0.1,\n    \"handling\": 0.52,\n    \"speed\": 8.3333,\n    \"traction\": 1.85,\n    \"name\": \"Dock Handler\",\n    \"make\": \"\",\n    \"class\": 10,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"automobile\",\n    \"price\": 14549,\n    \"category\": \"land\"\n  },\n  \"hauler\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.8,\n    \"handling\": 0.54,\n    \"speed\": 28.6501,\n    \"traction\": 1.55,\n    \"name\": \"Hauler\",\n    \"make\": \"JoBuilt\",\n    \"class\": 20,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 48240,\n    \"category\": \"land\"\n  },\n  \"hauler2\": {\n    \"acceleration\": 0.32,\n    \"braking\": 0.85,\n    \"handling\": 0.7,\n    \"speed\": 41.9442,\n    \"traction\": 1.95,\n    \"name\": \"Hauler Custom\",\n    \"make\": \"JoBuilt\",\n    \"class\": 20,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 70102,\n    \"category\": \"land\"\n  },\n  \"havok\": {\n    \"acceleration\": 5.39,\n    \"braking\": 3.1212,\n    \"handling\": 5.39,\n    \"speed\": 57.9072,\n    \"traction\": 1.3,\n    \"name\": \"Havok\",\n    \"make\": \"Nagasaki\",\n    \"class\": 15,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"heli\",\n    \"price\": 6462756,\n    \"category\": \"air\"\n  },\n  \"hellion\": {\n    \"acceleration\": 0.25,\n    \"braking\": 0.3,\n    \"handling\": 0.63,\n    \"speed\": 40.3984,\n    \"traction\": 2,\n    \"name\": \"Hellion\",\n    \"make\": \"Annis\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 66525,\n    \"category\": \"land\"\n  },\n  \"hermes\": {\n    \"acceleration\": 0.285,\n    \"braking\": 0.775,\n    \"handling\": 0.665,\n    \"speed\": 41.2605,\n    \"traction\": 2.375,\n    \"name\": \"Hermes\",\n    \"make\": \"Albany\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 68776,\n    \"category\": \"land\"\n  },\n  \"hexer\": {\n    \"acceleration\": 0.26,\n    \"braking\": 1,\n    \"handling\": 0.64,\n    \"speed\": 43.1425,\n    \"traction\": 1.85,\n    \"name\": \"Hexer\",\n    \"make\": \"LCC\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 22521,\n    \"category\": \"land\"\n  },\n  \"hotknife\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.43,\n    \"handling\": 0.68,\n    \"speed\": 45.0454,\n    \"traction\": 1.85,\n    \"name\": \"Hotknife\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 74328,\n    \"category\": \"land\"\n  },\n  \"hotring\": {\n    \"acceleration\": 0.335,\n    \"braking\": 0.7,\n    \"handling\": 0.715,\n    \"speed\": 48.0775,\n    \"traction\": 2.55,\n    \"name\": \"Hotring Sabre\",\n    \"make\": \"Declasse\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 79724,\n    \"category\": \"land\"\n  },\n  \"howard\": {\n    \"acceleration\": 20.58,\n    \"braking\": 20.58,\n    \"handling\": 20.58,\n    \"speed\": 100,\n    \"traction\": 1.15,\n    \"name\": \"Howard NX-25\",\n    \"make\": \"Buckingham\",\n    \"class\": 16,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"plane\",\n    \"price\": 2587840,\n    \"category\": \"air\"\n  },\n  \"hunter\": {\n    \"acceleration\": 5.488,\n    \"braking\": 3.2135,\n    \"handling\": 5.488,\n    \"speed\": 58.5543,\n    \"traction\": 1.3,\n    \"name\": \"FH-1 Hunter\",\n    \"make\": \"\",\n    \"class\": 15,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"heli\",\n    \"price\": 32734709,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"huntley\": {\n    \"acceleration\": 0.265,\n    \"braking\": 0.55,\n    \"handling\": 0.645,\n    \"speed\": 45.3333,\n    \"traction\": 2.1,\n    \"name\": \"Huntley S\",\n    \"make\": \"Enus\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 74869,\n    \"category\": \"land\"\n  },\n  \"hustler\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.43,\n    \"handling\": 0.68,\n    \"speed\": 44.1528,\n    \"traction\": 1.95,\n    \"name\": \"Hustler\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 72900,\n    \"category\": \"land\"\n  },\n  \"hydra\": {\n    \"acceleration\": 8.82,\n    \"braking\": 9.6812,\n    \"handling\": 8.82,\n    \"speed\": 109.7643,\n    \"traction\": 1.15,\n    \"name\": \"Hydra\",\n    \"make\": \"Mammoth\",\n    \"class\": 16,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"plane\",\n    \"price\": 10966840,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"ignus\": {\n    \"acceleration\": 0.3835,\n    \"braking\": 1,\n    \"handling\": 0.7635,\n    \"speed\": 52.3653,\n    \"traction\": 2.7675,\n    \"name\": \"Ignus\",\n    \"make\": \"Pegassi\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 87219,\n    \"category\": \"land\"\n  },\n  \"imorgon\": {\n    \"acceleration\": 0.66,\n    \"braking\": 0.835,\n    \"handling\": 1.04,\n    \"speed\": 45.499,\n    \"traction\": 2.598,\n    \"name\": \"Imorgon\",\n    \"make\": \"Overflod\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 76854,\n    \"category\": \"land\"\n  },\n  \"impaler\": {\n    \"acceleration\": 0.31,\n    \"braking\": 0.6,\n    \"handling\": 0.69,\n    \"speed\": 45.0153,\n    \"traction\": 2.35,\n    \"name\": \"Impaler\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 74584,\n    \"category\": \"land\"\n  },\n  \"impaler2\": {\n    \"acceleration\": 0.38,\n    \"braking\": 0.7,\n    \"handling\": 0.76,\n    \"speed\": 50.7078,\n    \"traction\": 2.4,\n    \"name\": \"Apocalypse Impaler\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 84076,\n    \"category\": \"land\"\n  },\n  \"impaler3\": {\n    \"acceleration\": 0.38,\n    \"braking\": 0.7,\n    \"handling\": 0.76,\n    \"speed\": 50.7078,\n    \"traction\": 2.4,\n    \"name\": \"Future Shock Impaler\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 84076,\n    \"category\": \"land\"\n  },\n  \"impaler4\": {\n    \"acceleration\": 0.38,\n    \"braking\": 0.7,\n    \"handling\": 0.76,\n    \"speed\": 50.7078,\n    \"traction\": 2.4,\n    \"name\": \"Nightmare Impaler\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 84076,\n    \"category\": \"land\"\n  },\n  \"impaler5\": {\n    \"acceleration\": 0.2537,\n    \"braking\": 0.865,\n    \"handling\": 0.6338,\n    \"speed\": 47.5449,\n    \"traction\": 2.3,\n    \"name\": \"Impaler SZ\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 78875,\n    \"category\": \"land\"\n  },\n  \"impaler6\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.7,\n    \"handling\": 0.68,\n    \"speed\": 47.0182,\n    \"traction\": 2.135,\n    \"name\": \"Impaler LX\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 77917,\n    \"category\": \"land\"\n  },\n  \"imperator\": {\n    \"acceleration\": 0.365,\n    \"braking\": 0.5,\n    \"handling\": 0.745,\n    \"speed\": 48.5751,\n    \"traction\": 2.25,\n    \"name\": \"Apocalypse Imperator\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 80296,\n    \"category\": \"land\"\n  },\n  \"imperator2\": {\n    \"acceleration\": 0.365,\n    \"braking\": 0.5,\n    \"handling\": 0.745,\n    \"speed\": 48.5751,\n    \"traction\": 2.25,\n    \"name\": \"Future Shock Imperator\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 80296,\n    \"category\": \"land\"\n  },\n  \"imperator3\": {\n    \"acceleration\": 0.365,\n    \"braking\": 0.5,\n    \"handling\": 0.745,\n    \"speed\": 48.5751,\n    \"traction\": 2.25,\n    \"name\": \"Nightmare Imperator\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 80296,\n    \"category\": \"land\"\n  },\n  \"inductor\": {\n    \"acceleration\": 0.112,\n    \"braking\": 3.1,\n    \"handling\": 0.492,\n    \"speed\": 10.7824,\n    \"traction\": 2.05,\n    \"name\": \"Inductor\",\n    \"make\": \"\",\n    \"class\": 13,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bicycle\",\n    \"price\": 4345,\n    \"category\": \"land\"\n  },\n  \"inductor2\": {\n    \"acceleration\": 0.112,\n    \"braking\": 3.1,\n    \"handling\": 0.492,\n    \"speed\": 10.7824,\n    \"traction\": 2.05,\n    \"name\": \"Junk Energy Inductor\",\n    \"make\": \"\",\n    \"class\": 13,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bicycle\",\n    \"price\": 4345,\n    \"category\": \"land\"\n  },\n  \"infernus\": {\n    \"acceleration\": 0.34,\n    \"braking\": 0.5,\n    \"handling\": 0.72,\n    \"speed\": 49.1131,\n    \"traction\": 2.65,\n    \"name\": \"Infernus\",\n    \"make\": \"Pegassi\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 81076,\n    \"category\": \"land\"\n  },\n  \"infernus2\": {\n    \"acceleration\": 0.33,\n    \"braking\": 0.5,\n    \"handling\": 0.71,\n    \"speed\": 48.0533,\n    \"traction\": 2.635,\n    \"name\": \"Infernus Classic\",\n    \"make\": \"Pegassi\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 79349,\n    \"category\": \"land\"\n  },\n  \"ingot\": {\n    \"acceleration\": 0.14,\n    \"braking\": 0.6,\n    \"handling\": 0.52,\n    \"speed\": 32.0802,\n    \"traction\": 1.95,\n    \"name\": \"Ingot\",\n    \"make\": \"Vulcar\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 53344,\n    \"category\": \"land\"\n  },\n  \"innovation\": {\n    \"acceleration\": 0.32,\n    \"braking\": 1,\n    \"handling\": 0.7,\n    \"speed\": 45,\n    \"traction\": 1.9,\n    \"name\": \"Innovation\",\n    \"make\": \"LCC\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 23510,\n    \"category\": \"land\"\n  },\n  \"insurgent\": {\n    \"acceleration\": 0.24,\n    \"braking\": 0.6,\n    \"handling\": 0.62,\n    \"speed\": 35.4436,\n    \"traction\": 2,\n    \"name\": \"Insurgent Pick-Up\",\n    \"make\": \"HVY\",\n    \"class\": 9,\n    \"seats\": 9,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 295228,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"insurgent2\": {\n    \"acceleration\": 0.24,\n    \"braking\": 0.6,\n    \"handling\": 0.62,\n    \"speed\": 35.4436,\n    \"traction\": 2,\n    \"name\": \"Insurgent\",\n    \"make\": \"HVY\",\n    \"class\": 9,\n    \"seats\": 6,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 59045,\n    \"category\": \"land\"\n  },\n  \"insurgent3\": {\n    \"acceleration\": 0.24,\n    \"braking\": 0.6,\n    \"handling\": 0.62,\n    \"speed\": 35.4436,\n    \"traction\": 2,\n    \"name\": \"Insurgent Pick-Up Custom\",\n    \"make\": \"HVY\",\n    \"class\": 9,\n    \"seats\": 9,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 295228,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"intruder\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.9,\n    \"handling\": 0.58,\n    \"speed\": 39.3713,\n    \"traction\": 2.35,\n    \"name\": \"Intruder\",\n    \"make\": \"Karin\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 65682,\n    \"category\": \"land\"\n  },\n  \"issi2\": {\n    \"acceleration\": 0.23,\n    \"braking\": 0.6,\n    \"handling\": 0.61,\n    \"speed\": 41.9174,\n    \"traction\": 2.05,\n    \"name\": \"Issi\",\n    \"make\": \"Weeny\",\n    \"class\": 0,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 69371,\n    \"category\": \"land\"\n  },\n  \"issi3\": {\n    \"acceleration\": 0.26,\n    \"braking\": 0.3,\n    \"handling\": 0.64,\n    \"speed\": 39.7959,\n    \"traction\": 2,\n    \"name\": \"Issi Classic\",\n    \"make\": \"Weeny\",\n    \"class\": 0,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 65593,\n    \"category\": \"land\"\n  },\n  \"issi4\": {\n    \"acceleration\": 0.34,\n    \"braking\": 0.4,\n    \"handling\": 0.72,\n    \"speed\": 44.9375,\n    \"traction\": 2,\n    \"name\": \"Apocalypse Issi\",\n    \"make\": \"Weeny\",\n    \"class\": 0,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 74236,\n    \"category\": \"land\"\n  },\n  \"issi5\": {\n    \"acceleration\": 0.34,\n    \"braking\": 0.4,\n    \"handling\": 0.72,\n    \"speed\": 44.9375,\n    \"traction\": 2,\n    \"name\": \"Future Shock Issi\",\n    \"make\": \"Weeny\",\n    \"class\": 0,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 74236,\n    \"category\": \"land\"\n  },\n  \"issi6\": {\n    \"acceleration\": 0.34,\n    \"braking\": 0.4,\n    \"handling\": 0.72,\n    \"speed\": 44.9375,\n    \"traction\": 2,\n    \"name\": \"Nightmare Issi\",\n    \"make\": \"Weeny\",\n    \"class\": 0,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 74236,\n    \"category\": \"land\"\n  },\n  \"issi7\": {\n    \"acceleration\": 0.305,\n    \"braking\": 1,\n    \"handling\": 0.685,\n    \"speed\": 42.0375,\n    \"traction\": 2.55,\n    \"name\": \"Issi Sport\",\n    \"make\": \"Weeny\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 70444,\n    \"category\": \"land\"\n  },\n  \"issi8\": {\n    \"acceleration\": 0.3215,\n    \"braking\": 0.548,\n    \"handling\": 0.7415,\n    \"speed\": 48.2089,\n    \"traction\": 2.1495,\n    \"name\": \"Issi Rally\",\n    \"make\": \"Weeny\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 79711,\n    \"category\": \"land\"\n  },\n  \"italigtb\": {\n    \"acceleration\": 0.3365,\n    \"braking\": 1.1,\n    \"handling\": 0.7165,\n    \"speed\": 52.1595,\n    \"traction\": 2.5,\n    \"name\": \"Itali GTB\",\n    \"make\": \"Progen\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 86900,\n    \"category\": \"land\"\n  },\n  \"italigtb2\": {\n    \"acceleration\": 0.34,\n    \"braking\": 1.2,\n    \"handling\": 0.72,\n    \"speed\": 52.4821,\n    \"traction\": 2.55,\n    \"name\": \"Itali GTB Custom\",\n    \"make\": \"Progen\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 87587,\n    \"category\": \"land\"\n  },\n  \"italigto\": {\n    \"acceleration\": 0.4,\n    \"braking\": 1.1,\n    \"handling\": 0.78,\n    \"speed\": 52.3922,\n    \"traction\": 2.62,\n    \"name\": \"Itali GTO\",\n    \"make\": \"Grotti\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 87475,\n    \"category\": \"land\"\n  },\n  \"italirsx\": {\n    \"acceleration\": 0.4013,\n    \"braking\": 1.35,\n    \"handling\": 0.7813,\n    \"speed\": 52.2692,\n    \"traction\": 2.737,\n    \"name\": \"Itali RSX\",\n    \"make\": \"Grotti\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 87682,\n    \"category\": \"land\"\n  },\n  \"iwagen\": {\n    \"acceleration\": 0.2315,\n    \"braking\": 0.775,\n    \"handling\": 0.6115,\n    \"speed\": 33.3125,\n    \"traction\": 2.365,\n    \"name\": \"I-Wagen\",\n    \"make\": \"Obey\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 55888,\n    \"category\": \"land\"\n  },\n  \"jackal\": {\n    \"acceleration\": 0.22,\n    \"braking\": 0.9,\n    \"handling\": 0.6,\n    \"speed\": 45.9825,\n    \"traction\": 2.6,\n    \"name\": \"Jackal\",\n    \"make\": \"Ocelot\",\n    \"class\": 3,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 76324,\n    \"category\": \"land\"\n  },\n  \"jb700\": {\n    \"acceleration\": 0.26,\n    \"braking\": 0.6,\n    \"handling\": 0.64,\n    \"speed\": 50,\n    \"traction\": 2.15,\n    \"name\": \"JB 700\",\n    \"make\": \"Dewbauchee\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 82400,\n    \"category\": \"land\"\n  },\n  \"jb7002\": {\n    \"acceleration\": 0.26,\n    \"braking\": 0.6,\n    \"handling\": 0.64,\n    \"speed\": 50,\n    \"traction\": 2.15,\n    \"name\": \"JB 700W\",\n    \"make\": \"Dewbauchee\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 82400,\n    \"category\": \"land\"\n  },\n  \"jester\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.95,\n    \"handling\": 0.68,\n    \"speed\": 45.9981,\n    \"traction\": 2.55,\n    \"name\": \"Jester\",\n    \"make\": \"Dinka\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 76684,\n    \"category\": \"land\"\n  },\n  \"jester2\": {\n    \"acceleration\": 0.31,\n    \"braking\": 0.95,\n    \"handling\": 0.69,\n    \"speed\": 46.9034,\n    \"traction\": 2.57,\n    \"name\": \"Jester (Racecar)\",\n    \"make\": \"Dinka\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 78165,\n    \"category\": \"land\"\n  },\n  \"jester3\": {\n    \"acceleration\": 0.32,\n    \"braking\": 0.95,\n    \"handling\": 0.7,\n    \"speed\": 48.319,\n    \"traction\": 2.575,\n    \"name\": \"Jester Classic\",\n    \"make\": \"Dinka\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 80462,\n    \"category\": \"land\"\n  },\n  \"jester4\": {\n    \"acceleration\": 0.3291,\n    \"braking\": 0.85,\n    \"handling\": 0.7091,\n    \"speed\": 48.0367,\n    \"traction\": 2.59,\n    \"name\": \"Jester RR\",\n    \"make\": \"Dinka\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 79879,\n    \"category\": \"land\"\n  },\n  \"jester5\": {\n    \"acceleration\": 0.3291,\n    \"braking\": 0.85,\n    \"handling\": 0.7091,\n    \"speed\": 46.905,\n    \"traction\": 2.725,\n    \"name\": \"Jester RR Widebody\",\n    \"make\": \"Dinka\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 78069,\n    \"category\": \"land\"\n  },\n  \"jet\": {\n    \"acceleration\": 6.174,\n    \"braking\": 4.8714,\n    \"handling\": 6.174,\n    \"speed\": 78.9023,\n    \"traction\": 1.6,\n    \"name\": \"Jet\",\n    \"make\": \"\",\n    \"class\": 16,\n    \"seats\": 2,\n    \"doors\": 0,\n    \"type\": \"plane\",\n    \"price\": 1537947,\n    \"category\": \"air\"\n  },\n  \"jetmax\": {\n    \"acceleration\": 17,\n    \"braking\": 0.4,\n    \"handling\": 17.38,\n    \"speed\": 45,\n    \"traction\": 0,\n    \"name\": \"Jetmax\",\n    \"make\": \"Shitzu\",\n    \"class\": 14,\n    \"seats\": 2,\n    \"doors\": 0,\n    \"type\": \"boat\",\n    \"price\": 478680,\n    \"category\": \"sea\"\n  },\n  \"journey\": {\n    \"acceleration\": 0.13,\n    \"braking\": 0.25,\n    \"handling\": 0.51,\n    \"speed\": 32.1641,\n    \"traction\": 1.4,\n    \"name\": \"Journey\",\n    \"make\": \"Zirconium\",\n    \"class\": 12,\n    \"seats\": 6,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 52886,\n    \"category\": \"land\"\n  },\n  \"journey2\": {\n    \"acceleration\": 0.13,\n    \"braking\": 0.25,\n    \"handling\": 0.51,\n    \"speed\": 32.1641,\n    \"traction\": 1.4,\n    \"name\": \"Journey II\",\n    \"make\": \"Zirconium\",\n    \"class\": 12,\n    \"seats\": 6,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 52886,\n    \"category\": \"land\"\n  },\n  \"jubilee\": {\n    \"acceleration\": 0.2975,\n    \"braking\": 0.75,\n    \"handling\": 0.6775,\n    \"speed\": 42.7814,\n    \"traction\": 2.285,\n    \"name\": \"Jubilee\",\n    \"make\": \"Enus\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 71210,\n    \"category\": \"land\"\n  },\n  \"jugular\": {\n    \"acceleration\": 0.378,\n    \"braking\": 1.1,\n    \"handling\": 0.758,\n    \"speed\": 48.6466,\n    \"traction\": 2.62,\n    \"name\": \"Jugular\",\n    \"make\": \"Ocelot\",\n    \"class\": 6,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 81412,\n    \"category\": \"land\"\n  },\n  \"kalahari\": {\n    \"acceleration\": 0.26,\n    \"braking\": 1,\n    \"handling\": 0.64,\n    \"speed\": 35.004,\n    \"traction\": 1.78,\n    \"name\": \"Kalahari\",\n    \"make\": \"Canis\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 59046,\n    \"category\": \"land\"\n  },\n  \"kamacho\": {\n    \"acceleration\": 0.255,\n    \"braking\": 0.3,\n    \"handling\": 0.635,\n    \"speed\": 40.8822,\n    \"traction\": 2,\n    \"name\": \"Kamacho\",\n    \"make\": \"Canis\",\n    \"class\": 9,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 67315,\n    \"category\": \"land\"\n  },\n  \"kanjo\": {\n    \"acceleration\": 0.32,\n    \"braking\": 0.5,\n    \"handling\": 0.7,\n    \"speed\": 44.4042,\n    \"traction\": 1.97,\n    \"name\": \"Blista Kanjo\",\n    \"make\": \"Dinka\",\n    \"class\": 0,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 73478,\n    \"category\": \"land\"\n  },\n  \"kanjosj\": {\n    \"acceleration\": 0.315,\n    \"braking\": 0.45,\n    \"handling\": 0.695,\n    \"speed\": 44.6584,\n    \"traction\": 1.995,\n    \"name\": \"Kanjo SJ\",\n    \"make\": \"Dinka\",\n    \"class\": 3,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 73789,\n    \"category\": \"land\"\n  },\n  \"khamelion\": {\n    \"acceleration\": 0.15,\n    \"braking\": 0.9,\n    \"handling\": 0.53,\n    \"speed\": 31.7276,\n    \"traction\": 2.6,\n    \"name\": \"Khamelion\",\n    \"make\": \"Hijak\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 53292,\n    \"category\": \"land\"\n  },\n  \"khanjali\": {\n    \"acceleration\": 0.1,\n    \"braking\": 0.2,\n    \"handling\": 0.48,\n    \"speed\": 18.1221,\n    \"traction\": 2.55,\n    \"name\": \"TM-02 Khanjali\",\n    \"make\": \"\",\n    \"class\": 19,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 151216,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"komoda\": {\n    \"acceleration\": 0.367,\n    \"braking\": 0.95,\n    \"handling\": 0.747,\n    \"speed\": 49.8918,\n    \"traction\": 2.69,\n    \"name\": \"Komoda\",\n    \"make\": \"Lampadati\",\n    \"class\": 6,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 83129,\n    \"category\": \"land\"\n  },\n  \"kosatka\": {\n    \"acceleration\": 5.25,\n    \"braking\": 0.4,\n    \"handling\": 5.63,\n    \"speed\": 25,\n    \"traction\": 0,\n    \"name\": \"Kosatka\",\n    \"make\": \"RUNE\",\n    \"class\": 14,\n    \"seats\": 1,\n    \"doors\": 3,\n    \"type\": \"submarine\",\n    \"price\": 3990800,\n    \"category\": \"sea\",\n    \"weapons\": true\n  },\n  \"krieger\": {\n    \"acceleration\": 0.374,\n    \"braking\": 1.12,\n    \"handling\": 0.754,\n    \"speed\": 52.5741,\n    \"traction\": 2.782,\n    \"name\": \"Krieger\",\n    \"make\": \"Benefactor\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 87715,\n    \"category\": \"land\"\n  },\n  \"kuruma\": {\n    \"acceleration\": 0.31,\n    \"braking\": 0.5,\n    \"handling\": 0.69,\n    \"speed\": 46.9034,\n    \"traction\": 2.45,\n    \"name\": \"Kuruma\",\n    \"make\": \"Karin\",\n    \"class\": 6,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 77445,\n    \"category\": \"land\"\n  },\n  \"kuruma2\": {\n    \"acceleration\": 0.31,\n    \"braking\": 0.5,\n    \"handling\": 0.69,\n    \"speed\": 45.9285,\n    \"traction\": 2.25,\n    \"name\": \"Kuruma (Armored)\",\n    \"make\": \"Karin\",\n    \"class\": 6,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 75885,\n    \"category\": \"land\"\n  },\n  \"l35\": {\n    \"acceleration\": 0.236,\n    \"braking\": 0.32,\n    \"handling\": 0.616,\n    \"speed\": 39.0963,\n    \"traction\": 2.038,\n    \"name\": \"Walton L35\",\n    \"make\": \"Declasse\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 64429,\n    \"category\": \"land\"\n  },\n  \"landstalker\": {\n    \"acceleration\": 0.18,\n    \"braking\": 0.8,\n    \"handling\": 0.56,\n    \"speed\": 36.8308,\n    \"traction\": 2.1,\n    \"name\": \"Landstalker\",\n    \"make\": \"Dundreary\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 61393,\n    \"category\": \"land\"\n  },\n  \"landstalker2\": {\n    \"acceleration\": 0.19,\n    \"braking\": 0.8,\n    \"handling\": 0.57,\n    \"speed\": 37.6554,\n    \"traction\": 2.15,\n    \"name\": \"Landstalker XL\",\n    \"make\": \"Dundreary\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 62744,\n    \"category\": \"land\"\n  },\n  \"lazer\": {\n    \"acceleration\": 19.6,\n    \"braking\": 17.8923,\n    \"handling\": 19.6,\n    \"speed\": 91.2871,\n    \"traction\": 2.15,\n    \"name\": \"P-996 LAZER\",\n    \"make\": \"\",\n    \"class\": 16,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"plane\",\n    \"price\": 11870352,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"le7b\": {\n    \"acceleration\": 0.371,\n    \"braking\": 1.1,\n    \"handling\": 0.751,\n    \"speed\": 50.3563,\n    \"traction\": 2.68,\n    \"name\": \"RE-7B\",\n    \"make\": \"Annis\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 84125,\n    \"category\": \"land\"\n  },\n  \"lectro\": {\n    \"acceleration\": 0.28,\n    \"braking\": 1.2,\n    \"handling\": 0.66,\n    \"speed\": 43.2353,\n    \"traction\": 1.95,\n    \"name\": \"Lectro\",\n    \"make\": \"Principe\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 45375,\n    \"category\": \"land\"\n  },\n  \"lguard\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.8,\n    \"handling\": 0.58,\n    \"speed\": 37.5559,\n    \"traction\": 2.05,\n    \"name\": \"Lifeguard\",\n    \"make\": \"Declasse\",\n    \"class\": 18,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 62617,\n    \"category\": \"land\"\n  },\n  \"limo2\": {\n    \"acceleration\": 0.27,\n    \"braking\": 0.8,\n    \"handling\": 0.65,\n    \"speed\": 39.2704,\n    \"traction\": 2.175,\n    \"name\": \"Turreted Limo\",\n    \"make\": \"Benefactor\",\n    \"class\": 1,\n    \"seats\": 5,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 327923,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"lm87\": {\n    \"acceleration\": 0.3765,\n    \"braking\": 1.35,\n    \"handling\": 0.7565,\n    \"speed\": 50.3353,\n    \"traction\": 2.77,\n    \"name\": \"LM87\",\n    \"make\": \"Benefactor\",\n    \"class\": 7,\n    \"seats\": 1,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 84509,\n    \"category\": \"land\"\n  },\n  \"locust\": {\n    \"acceleration\": 0.334,\n    \"braking\": 1,\n    \"handling\": 0.714,\n    \"speed\": 48.8089,\n    \"traction\": 2.685,\n    \"name\": \"Locust\",\n    \"make\": \"Ocelot\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 81371,\n    \"category\": \"land\"\n  },\n  \"longfin\": {\n    \"acceleration\": 18,\n    \"braking\": 0.4,\n    \"handling\": 18.38,\n    \"speed\": 46.6667,\n    \"traction\": 0,\n    \"name\": \"Longfin\",\n    \"make\": \"Shitzu\",\n    \"class\": 14,\n    \"seats\": 4,\n    \"doors\": 0,\n    \"type\": \"boat\",\n    \"price\": 500680,\n    \"category\": \"sea\"\n  },\n  \"lurcher\": {\n    \"acceleration\": 0.29,\n    \"braking\": 0.8,\n    \"handling\": 0.67,\n    \"speed\": 47.1435,\n    \"traction\": 2.15,\n    \"name\": \"Lurcher\",\n    \"make\": \"Albany\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 78245,\n    \"category\": \"land\"\n  },\n  \"luxor\": {\n    \"acceleration\": 7.938,\n    \"braking\": 7.193,\n    \"handling\": 7.938,\n    \"speed\": 90.6145,\n    \"traction\": 1.15,\n    \"name\": \"Luxor\",\n    \"make\": \"Buckingham\",\n    \"class\": 16,\n    \"seats\": 10,\n    \"doors\": 1,\n    \"type\": \"plane\",\n    \"price\": 1818936,\n    \"category\": \"air\"\n  },\n  \"luxor2\": {\n    \"acceleration\": 8.036,\n    \"braking\": 7.3309,\n    \"handling\": 8.036,\n    \"speed\": 91.2252,\n    \"traction\": 1.15,\n    \"name\": \"Luxor Deluxe\",\n    \"make\": \"Buckingham\",\n    \"class\": 16,\n    \"seats\": 8,\n    \"doors\": 1,\n    \"type\": \"plane\",\n    \"price\": 1834049,\n    \"category\": \"air\"\n  },\n  \"lynx\": {\n    \"acceleration\": 0.315,\n    \"braking\": 1,\n    \"handling\": 0.695,\n    \"speed\": 49.0772,\n    \"traction\": 2.56,\n    \"name\": \"Lynx\",\n    \"make\": \"Ocelot\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 81739,\n    \"category\": \"land\"\n  },\n  \"mamba\": {\n    \"acceleration\": 0.34,\n    \"braking\": 0.5,\n    \"handling\": 0.72,\n    \"speed\": 49.3333,\n    \"traction\": 2.5,\n    \"name\": \"Mamba\",\n    \"make\": \"Declasse\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 81429,\n    \"category\": \"land\"\n  },\n  \"mammatus\": {\n    \"acceleration\": 4.9,\n    \"braking\": 3.399,\n    \"handling\": 4.9,\n    \"speed\": 69.3676,\n    \"traction\": 2.15,\n    \"name\": \"Mammatus\",\n    \"make\": \"\",\n    \"class\": 16,\n    \"seats\": 4,\n    \"doors\": 3,\n    \"type\": \"plane\",\n    \"price\": 1321065,\n    \"category\": \"air\"\n  },\n  \"manana\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.25,\n    \"handling\": 0.54,\n    \"speed\": 36.9472,\n    \"traction\": 1.95,\n    \"name\": \"Manana\",\n    \"make\": \"Albany\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 60635,\n    \"category\": \"land\"\n  },\n  \"manana2\": {\n    \"acceleration\": 0.24,\n    \"braking\": 0.275,\n    \"handling\": 0.62,\n    \"speed\": 43.563,\n    \"traction\": 1.98,\n    \"name\": \"Manana Custom\",\n    \"make\": \"Albany\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 71516,\n    \"category\": \"land\"\n  },\n  \"manchez\": {\n    \"acceleration\": 0.295,\n    \"braking\": 1.2,\n    \"handling\": 0.675,\n    \"speed\": 44.1064,\n    \"traction\": 2.15,\n    \"name\": \"Manchez\",\n    \"make\": \"Maibatsu\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 23138,\n    \"category\": \"land\"\n  },\n  \"manchez2\": {\n    \"acceleration\": 0.265,\n    \"braking\": 0.8,\n    \"handling\": 0.645,\n    \"speed\": 41.3801,\n    \"traction\": 2.12,\n    \"name\": \"Manchez Scout\",\n    \"make\": \"Maibatsu\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 21545,\n    \"category\": \"land\"\n  },\n  \"manchez3\": {\n    \"acceleration\": 0.272,\n    \"braking\": 0.8,\n    \"handling\": 0.652,\n    \"speed\": 41.5401,\n    \"traction\": 2.11,\n    \"name\": \"Manchez Scout C\",\n    \"make\": \"Maibatsu\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 21632,\n    \"category\": \"land\"\n  },\n  \"marquis\": {\n    \"acceleration\": 2.5,\n    \"braking\": 0.4,\n    \"handling\": 2.88,\n    \"speed\": 10,\n    \"traction\": 0,\n    \"name\": \"Marquis\",\n    \"make\": \"Dinka\",\n    \"class\": 14,\n    \"seats\": 4,\n    \"doors\": 0,\n    \"type\": \"boat\",\n    \"price\": 94680,\n    \"category\": \"sea\"\n  },\n  \"marshall\": {\n    \"acceleration\": 0.4,\n    \"braking\": 0.65,\n    \"handling\": 0.78,\n    \"speed\": 33.9677,\n    \"traction\": 2.25,\n    \"name\": \"Marshall\",\n    \"make\": \"Cheval\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 57276,\n    \"category\": \"land\"\n  },\n  \"massacro\": {\n    \"acceleration\": 0.364,\n    \"braking\": 0.9,\n    \"handling\": 0.744,\n    \"speed\": 50.4748,\n    \"traction\": 2.42,\n    \"name\": \"Massacro\",\n    \"make\": \"Dewbauchee\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 83972,\n    \"category\": \"land\"\n  },\n  \"massacro2\": {\n    \"acceleration\": 0.364,\n    \"braking\": 0.9,\n    \"handling\": 0.744,\n    \"speed\": 50.4748,\n    \"traction\": 2.43,\n    \"name\": \"Massacro (Racecar)\",\n    \"make\": \"Dewbauchee\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 83972,\n    \"category\": \"land\"\n  },\n  \"maverick\": {\n    \"acceleration\": 5.096,\n    \"braking\": 2.7553,\n    \"handling\": 5.096,\n    \"speed\": 54.0675,\n    \"traction\": 1.3,\n    \"name\": \"Maverick\",\n    \"make\": \"\",\n    \"class\": 15,\n    \"seats\": 4,\n    \"doors\": 2,\n    \"type\": \"heli\",\n    \"price\": 30156660,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"menacer\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.6,\n    \"handling\": 0.58,\n    \"speed\": 31.794,\n    \"traction\": 2,\n    \"name\": \"Menacer\",\n    \"make\": \"HVY\",\n    \"class\": 9,\n    \"seats\": 5,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 265392,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"mesa\": {\n    \"acceleration\": 0.17,\n    \"braking\": 0.3,\n    \"handling\": 0.55,\n    \"speed\": 34.6832,\n    \"traction\": 2,\n    \"name\": \"Mesa\",\n    \"make\": \"Canis\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 57125,\n    \"category\": \"land\"\n  },\n  \"mesa2\": {\n    \"acceleration\": 0.17,\n    \"braking\": 0.3,\n    \"handling\": 0.55,\n    \"speed\": 34.6832,\n    \"traction\": 2,\n    \"name\": \"Mesa\",\n    \"make\": \"Canis\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 57125,\n    \"category\": \"land\"\n  },\n  \"mesa3\": {\n    \"acceleration\": 0.17,\n    \"braking\": 0.3,\n    \"handling\": 0.55,\n    \"speed\": 34.6832,\n    \"traction\": 2,\n    \"name\": \"Mesa\",\n    \"make\": \"Canis\",\n    \"class\": 9,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 57125,\n    \"category\": \"land\"\n  },\n  \"metrotrain\": {\n    \"acceleration\": 0.2,\n    \"braking\": 5,\n    \"handling\": 0.58,\n    \"speed\": 26.6667,\n    \"traction\": 2.5,\n    \"name\": \"Freight Train\",\n    \"make\": \"\",\n    \"class\": 21,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"train\",\n    \"price\": 194680,\n    \"category\": \"land\"\n  },\n  \"michelli\": {\n    \"acceleration\": 0.2825,\n    \"braking\": 0.75,\n    \"handling\": 0.6625,\n    \"speed\": 44.5681,\n    \"traction\": 2.3,\n    \"name\": \"Michelli GT\",\n    \"make\": \"Lampadati\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 74020,\n    \"category\": \"land\"\n  },\n  \"microlight\": {\n    \"acceleration\": 13.72,\n    \"braking\": 4.1367,\n    \"handling\": 13.72,\n    \"speed\": 30.1511,\n    \"traction\": 2.15,\n    \"name\": \"Ultralight\",\n    \"make\": \"Nagasaki\",\n    \"class\": 16,\n    \"seats\": 1,\n    \"doors\": 0,\n    \"type\": \"plane\",\n    \"price\": 987644,\n    \"category\": \"air\"\n  },\n  \"miljet\": {\n    \"acceleration\": 8.134,\n    \"braking\": 7.4696,\n    \"handling\": 8.134,\n    \"speed\": 91.8322,\n    \"traction\": 1.5,\n    \"name\": \"Miljet\",\n    \"make\": \"Buckingham\",\n    \"class\": 16,\n    \"seats\": 16,\n    \"doors\": 1,\n    \"type\": \"plane\",\n    \"price\": 1849116,\n    \"category\": \"air\"\n  },\n  \"minitank\": {\n    \"acceleration\": 0.06,\n    \"braking\": 0.15,\n    \"handling\": 0.44,\n    \"speed\": 9.7297,\n    \"traction\": 2,\n    \"name\": \"Invade and Persuade Tank\",\n    \"make\": \"\",\n    \"class\": 19,\n    \"seats\": 1,\n    \"doors\": 0,\n    \"type\": \"automobile\",\n    \"price\": 124556,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"minivan\": {\n    \"acceleration\": 0.15,\n    \"braking\": 0.4,\n    \"handling\": 0.53,\n    \"speed\": 35.4017,\n    \"traction\": 1.9,\n    \"name\": \"Minivan\",\n    \"make\": \"Vapid\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 58370,\n    \"category\": \"land\"\n  },\n  \"minivan2\": {\n    \"acceleration\": 0.15,\n    \"braking\": 0.45,\n    \"handling\": 0.53,\n    \"speed\": 35.4017,\n    \"traction\": 1.925,\n    \"name\": \"Minivan Custom\",\n    \"make\": \"Vapid\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 58450,\n    \"category\": \"land\"\n  },\n  \"mixer\": {\n    \"acceleration\": 0.11,\n    \"braking\": 0.3,\n    \"handling\": 0.49,\n    \"speed\": 32.4021,\n    \"traction\": 1.6,\n    \"name\": \"Mixer\",\n    \"make\": \"HVY\",\n    \"class\": 10,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 53283,\n    \"category\": \"land\"\n  },\n  \"mixer2\": {\n    \"acceleration\": 0.11,\n    \"braking\": 0.3,\n    \"handling\": 0.49,\n    \"speed\": 32.4021,\n    \"traction\": 1.6,\n    \"name\": \"Mixer\",\n    \"make\": \"HVY\",\n    \"class\": 10,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 53283,\n    \"category\": \"land\"\n  },\n  \"mogul\": {\n    \"acceleration\": 5.88,\n    \"braking\": 4.5156,\n    \"handling\": 5.88,\n    \"speed\": 76.7957,\n    \"traction\": 2.15,\n    \"name\": \"Mogul\",\n    \"make\": \"Mammoth\",\n    \"class\": 16,\n    \"seats\": 3,\n    \"doors\": 3,\n    \"type\": \"plane\",\n    \"price\": 7445704,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"molotok\": {\n    \"acceleration\": 14.7,\n    \"braking\": 13.4192,\n    \"handling\": 14.7,\n    \"speed\": 91.2871,\n    \"traction\": 2.15,\n    \"name\": \"V-65 Molotok\",\n    \"make\": \"\",\n    \"class\": 16,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"plane\",\n    \"price\": 10728503,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"monroe\": {\n    \"acceleration\": 0.28,\n    \"braking\": 0.65,\n    \"handling\": 0.66,\n    \"speed\": 50,\n    \"traction\": 2.2,\n    \"name\": \"Monroe\",\n    \"make\": \"Pegassi\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 82544,\n    \"category\": \"land\"\n  },\n  \"monster\": {\n    \"acceleration\": 0.4,\n    \"braking\": 0.65,\n    \"handling\": 0.78,\n    \"speed\": 33.9677,\n    \"traction\": 2.25,\n    \"name\": \"Liberator\",\n    \"make\": \"Vapid\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 57276,\n    \"category\": \"land\"\n  },\n  \"monster3\": {\n    \"acceleration\": 0.41,\n    \"braking\": 0.65,\n    \"handling\": 0.79,\n    \"speed\": 38.3787,\n    \"traction\": 2.275,\n    \"name\": \"Apocalypse Sasquatch\",\n    \"make\": \"Bravado\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 64365,\n    \"category\": \"land\"\n  },\n  \"monster4\": {\n    \"acceleration\": 0.41,\n    \"braking\": 0.65,\n    \"handling\": 0.79,\n    \"speed\": 38.3787,\n    \"traction\": 2.275,\n    \"name\": \"Future Shock Sasquatch\",\n    \"make\": \"Bravado\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 64365,\n    \"category\": \"land\"\n  },\n  \"monster5\": {\n    \"acceleration\": 0.41,\n    \"braking\": 0.65,\n    \"handling\": 0.79,\n    \"speed\": 38.3787,\n    \"traction\": 2.275,\n    \"name\": \"Nightmare Sasquatch\",\n    \"make\": \"Bravado\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 64365,\n    \"category\": \"land\"\n  },\n  \"monstrociti\": {\n    \"acceleration\": 0.2735,\n    \"braking\": 0.369,\n    \"handling\": 0.7135,\n    \"speed\": 41.3981,\n    \"traction\": 2.16,\n    \"name\": \"MonstroCiti\",\n    \"make\": \"Maibatsu\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 68406,\n    \"category\": \"land\"\n  },\n  \"moonbeam\": {\n    \"acceleration\": 0.21,\n    \"braking\": 0.4,\n    \"handling\": 0.59,\n    \"speed\": 41.6667,\n    \"traction\": 2,\n    \"name\": \"Moonbeam\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 68586,\n    \"category\": \"land\"\n  },\n  \"moonbeam2\": {\n    \"acceleration\": 0.21,\n    \"braking\": 0.4,\n    \"handling\": 0.59,\n    \"speed\": 41.6667,\n    \"traction\": 2,\n    \"name\": \"Moonbeam Custom\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 68586,\n    \"category\": \"land\"\n  },\n  \"mower\": {\n    \"acceleration\": 0.05,\n    \"braking\": 0.5,\n    \"handling\": 0.43,\n    \"speed\": 6.6667,\n    \"traction\": 1.35,\n    \"name\": \"Lawn Mower\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"automobile\",\n    \"price\": 12234,\n    \"category\": \"land\"\n  },\n  \"mule\": {\n    \"acceleration\": 0.11,\n    \"braking\": 0.25,\n    \"handling\": 0.49,\n    \"speed\": 28.6961,\n    \"traction\": 1.5,\n    \"name\": \"Mule\",\n    \"make\": \"Maibatsu\",\n    \"class\": 20,\n    \"seats\": 6,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 47273,\n    \"category\": \"land\"\n  },\n  \"mule2\": {\n    \"acceleration\": 0.11,\n    \"braking\": 0.25,\n    \"handling\": 0.49,\n    \"speed\": 28.6961,\n    \"traction\": 1.5,\n    \"name\": \"Mule\",\n    \"make\": \"Maibatsu\",\n    \"class\": 20,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 47273,\n    \"category\": \"land\"\n  },\n  \"mule3\": {\n    \"acceleration\": 0.17,\n    \"braking\": 0.25,\n    \"handling\": 0.55,\n    \"speed\": 31.9047,\n    \"traction\": 1.5,\n    \"name\": \"Mule\",\n    \"make\": \"Maibatsu\",\n    \"class\": 20,\n    \"seats\": 6,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 52599,\n    \"category\": \"land\"\n  },\n  \"mule4\": {\n    \"acceleration\": 0.11,\n    \"braking\": 0.25,\n    \"handling\": 0.49,\n    \"speed\": 28.6961,\n    \"traction\": 1.5,\n    \"name\": \"Mule Custom\",\n    \"make\": \"Maibatsu\",\n    \"class\": 20,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 47273,\n    \"category\": \"land\"\n  },\n  \"mule5\": {\n    \"acceleration\": 0.17,\n    \"braking\": 0.25,\n    \"handling\": 0.55,\n    \"speed\": 31.9047,\n    \"traction\": 1.5,\n    \"name\": \"Mule\",\n    \"make\": \"Maibatsu\",\n    \"class\": 20,\n    \"seats\": 6,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 52599,\n    \"category\": \"land\"\n  },\n  \"nebula\": {\n    \"acceleration\": 0.24,\n    \"braking\": 0.5,\n    \"handling\": 0.62,\n    \"speed\": 37.9382,\n    \"traction\": 1.95,\n    \"name\": \"Nebula Turbo\",\n    \"make\": \"Vulcar\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 62877,\n    \"category\": \"land\"\n  },\n  \"nemesis\": {\n    \"acceleration\": 0.3,\n    \"braking\": 1.2,\n    \"handling\": 0.68,\n    \"speed\": 45.0454,\n    \"traction\": 1.95,\n    \"name\": \"Nemesis\",\n    \"make\": \"Principe\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 23612,\n    \"category\": \"land\"\n  },\n  \"neo\": {\n    \"acceleration\": 0.387,\n    \"braking\": 1.2,\n    \"handling\": 0.767,\n    \"speed\": 51.2066,\n    \"traction\": 2.62,\n    \"name\": \"Neo\",\n    \"make\": \"Vysser\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 85696,\n    \"category\": \"land\"\n  },\n  \"neon\": {\n    \"acceleration\": 0.2505,\n    \"braking\": 1.3,\n    \"handling\": 0.6305,\n    \"speed\": 38.9224,\n    \"traction\": 2.275,\n    \"name\": \"Neon\",\n    \"make\": \"Pfister\",\n    \"class\": 6,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 65765,\n    \"category\": \"land\"\n  },\n  \"nero\": {\n    \"acceleration\": 0.3375,\n    \"braking\": 1,\n    \"handling\": 0.7175,\n    \"speed\": 52.642,\n    \"traction\": 2.65,\n    \"name\": \"Nero\",\n    \"make\": \"Truffade\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 87515,\n    \"category\": \"land\"\n  },\n  \"nero2\": {\n    \"acceleration\": 0.3401,\n    \"braking\": 1.1,\n    \"handling\": 0.7201,\n    \"speed\": 52.879,\n    \"traction\": 2.675,\n    \"name\": \"Nero Custom\",\n    \"make\": \"Truffade\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 88062,\n    \"category\": \"land\"\n  },\n  \"nightblade\": {\n    \"acceleration\": 0.31,\n    \"braking\": 1.2,\n    \"handling\": 0.69,\n    \"speed\": 46.9034,\n    \"traction\": 1.95,\n    \"name\": \"Nightblade\",\n    \"make\": \"Western\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 24551,\n    \"category\": \"land\"\n  },\n  \"nightshade\": {\n    \"acceleration\": 0.25,\n    \"braking\": 0.6,\n    \"handling\": 0.63,\n    \"speed\": 40.3984,\n    \"traction\": 2.25,\n    \"name\": \"Nightshade\",\n    \"make\": \"Imponte\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 67005,\n    \"category\": \"land\"\n  },\n  \"nightshark\": {\n    \"acceleration\": 0.27,\n    \"braking\": 0.75,\n    \"handling\": 0.65,\n    \"speed\": 36.833,\n    \"traction\": 2.1,\n    \"name\": \"Nightshark\",\n    \"make\": \"HVY\",\n    \"class\": 9,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 308024,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"nimbus\": {\n    \"acceleration\": 8.134,\n    \"braking\": 7.6912,\n    \"handling\": 8.134,\n    \"speed\": 94.5562,\n    \"traction\": 1.15,\n    \"name\": \"Nimbus\",\n    \"make\": \"Buckingham\",\n    \"class\": 16,\n    \"seats\": 8,\n    \"doors\": 1,\n    \"type\": \"plane\",\n    \"price\": 1896246,\n    \"category\": \"air\"\n  },\n  \"ninef\": {\n    \"acceleration\": 0.33,\n    \"braking\": 1,\n    \"handling\": 0.71,\n    \"speed\": 48.6724,\n    \"traction\": 2.55,\n    \"name\": \"9F\",\n    \"make\": \"Obey\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 81139,\n    \"category\": \"land\"\n  },\n  \"ninef2\": {\n    \"acceleration\": 0.33,\n    \"braking\": 1,\n    \"handling\": 0.71,\n    \"speed\": 48.6724,\n    \"traction\": 2.55,\n    \"name\": \"9F Cabrio\",\n    \"make\": \"Obey\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 81139,\n    \"category\": \"land\"\n  },\n  \"niobe\": {\n    \"acceleration\": 0.3805,\n    \"braking\": 0.76,\n    \"handling\": 0.8405,\n    \"speed\": 50.7465,\n    \"traction\": 2.605,\n    \"name\": \"Niobe\",\n    \"make\": \"Ubermacht\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 84364,\n    \"category\": \"land\"\n  },\n  \"nokota\": {\n    \"acceleration\": 14.7,\n    \"braking\": 12.8928,\n    \"handling\": 14.7,\n    \"speed\": 87.7058,\n    \"traction\": 2.15,\n    \"name\": \"P-45 Nokota\",\n    \"make\": \"\",\n    \"class\": 16,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"plane\",\n    \"price\": 10399888,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"novak\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.8,\n    \"handling\": 0.68,\n    \"speed\": 47.0182,\n    \"traction\": 2.3,\n    \"name\": \"Novak\",\n    \"make\": \"Lampadati\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 78077,\n    \"category\": \"land\"\n  },\n  \"omnis\": {\n    \"acceleration\": 0.305,\n    \"braking\": 1,\n    \"handling\": 0.685,\n    \"speed\": 43.7374,\n    \"traction\": 2,\n    \"name\": \"Omnis\",\n    \"make\": \"Obey\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 73163,\n    \"category\": \"land\"\n  },\n  \"omnisegt\": {\n    \"acceleration\": 0.58,\n    \"braking\": 1,\n    \"handling\": 0.96,\n    \"speed\": 47.6944,\n    \"traction\": 2.595,\n    \"name\": \"Omnis e-GT\",\n    \"make\": \"Obey\",\n    \"class\": 6,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 80375,\n    \"category\": \"land\"\n  },\n  \"openwheel1\": {\n    \"acceleration\": 0.76,\n    \"braking\": 1.3,\n    \"handling\": 1.14,\n    \"speed\": 52.5277,\n    \"traction\": 3.2925,\n    \"name\": \"BR8\",\n    \"make\": \"Benefactor\",\n    \"class\": 22,\n    \"seats\": 1,\n    \"doors\": 0,\n    \"type\": \"automobile\",\n    \"price\": 178328,\n    \"category\": \"land\"\n  },\n  \"openwheel2\": {\n    \"acceleration\": 0.655,\n    \"braking\": 1.15,\n    \"handling\": 1.035,\n    \"speed\": 53.0537,\n    \"traction\": 3.08,\n    \"name\": \"DR1\",\n    \"make\": \"Declasse\",\n    \"class\": 22,\n    \"seats\": 1,\n    \"doors\": 0,\n    \"type\": \"automobile\",\n    \"price\": 178859,\n    \"category\": \"land\"\n  },\n  \"oppressor\": {\n    \"acceleration\": 0.4,\n    \"braking\": 1.2,\n    \"handling\": 0.78,\n    \"speed\": 48.4978,\n    \"traction\": 2.125,\n    \"name\": \"Oppressor\",\n    \"make\": \"Pegassi\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 381583,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"oppressor2\": {\n    \"acceleration\": 0.38,\n    \"braking\": 1.2,\n    \"handling\": 0.76,\n    \"speed\": 47.0927,\n    \"traction\": 2.1,\n    \"name\": \"Oppressor Mk II\",\n    \"make\": \"Pegassi\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 370745,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"oracle\": {\n    \"acceleration\": 0.26,\n    \"braking\": 0.9,\n    \"handling\": 0.64,\n    \"speed\": 45.1953,\n    \"traction\": 2.25,\n    \"name\": \"Oracle XS\",\n    \"make\": \"Ubermacht\",\n    \"class\": 3,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 75192,\n    \"category\": \"land\"\n  },\n  \"oracle2\": {\n    \"acceleration\": 0.27,\n    \"braking\": 0.9,\n    \"handling\": 0.65,\n    \"speed\": 46.2473,\n    \"traction\": 2.25,\n    \"name\": \"Oracle\",\n    \"make\": \"Ubermacht\",\n    \"class\": 3,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 76907,\n    \"category\": \"land\"\n  },\n  \"osiris\": {\n    \"acceleration\": 0.36,\n    \"braking\": 1.05,\n    \"handling\": 0.74,\n    \"speed\": 49.6559,\n    \"traction\": 2.66,\n    \"name\": \"Osiris\",\n    \"make\": \"Pegassi\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 82889,\n    \"category\": \"land\"\n  },\n  \"outlaw\": {\n    \"acceleration\": 0.475,\n    \"braking\": 0.6,\n    \"handling\": 0.855,\n    \"speed\": 36.1565,\n    \"traction\": 2.025,\n    \"name\": \"Outlaw\",\n    \"make\": \"Nagasaki\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 60938,\n    \"category\": \"land\"\n  },\n  \"packer\": {\n    \"acceleration\": 0.21,\n    \"braking\": 0.8,\n    \"handling\": 0.59,\n    \"speed\": 36.3465,\n    \"traction\": 1.55,\n    \"name\": \"Packer\",\n    \"make\": \"MTL\",\n    \"class\": 20,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 60714,\n    \"category\": \"land\"\n  },\n  \"panthere\": {\n    \"acceleration\": 0.3462,\n    \"braking\": 0.84,\n    \"handling\": 0.7262,\n    \"speed\": 49.5323,\n    \"traction\": 2.5814,\n    \"name\": \"Panthere\",\n    \"make\": \"Toundra\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 82311,\n    \"category\": \"land\"\n  },\n  \"panto\": {\n    \"acceleration\": 0.27,\n    \"braking\": 0.6,\n    \"handling\": 0.65,\n    \"speed\": 40.6987,\n    \"traction\": 1.97,\n    \"name\": \"Panto\",\n    \"make\": \"Benefactor\",\n    \"class\": 0,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 67549,\n    \"category\": \"land\"\n  },\n  \"paradise\": {\n    \"acceleration\": 0.17,\n    \"braking\": 0.4,\n    \"handling\": 0.55,\n    \"speed\": 38.4494,\n    \"traction\": 1.95,\n    \"name\": \"Paradise\",\n    \"make\": \"Bravado\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 63311,\n    \"category\": \"land\"\n  },\n  \"paragon\": {\n    \"acceleration\": 0.329,\n    \"braking\": 1,\n    \"handling\": 0.709,\n    \"speed\": 44.997,\n    \"traction\": 2.675,\n    \"name\": \"Paragon R\",\n    \"make\": \"Enus\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 75256,\n    \"category\": \"land\"\n  },\n  \"paragon2\": {\n    \"acceleration\": 0.3275,\n    \"braking\": 0.95,\n    \"handling\": 0.7075,\n    \"speed\": 44.828,\n    \"traction\": 2.675,\n    \"name\": \"Paragon R (Armored)\",\n    \"make\": \"Enus\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 374504,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"paragon3\": {\n    \"acceleration\": 0.33,\n    \"braking\": 1.1,\n    \"handling\": 0.71,\n    \"speed\": 47.4585,\n    \"traction\": 2.515,\n    \"name\": \"Paragon S\",\n    \"make\": \"Enus\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 79357,\n    \"category\": \"land\"\n  },\n  \"pariah\": {\n    \"acceleration\": 0.321,\n    \"braking\": 1,\n    \"handling\": 0.701,\n    \"speed\": 48.7328,\n    \"traction\": 2.625,\n    \"name\": \"Pariah\",\n    \"make\": \"Ocelot\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 81207,\n    \"category\": \"land\"\n  },\n  \"patriot\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.32,\n    \"handling\": 0.58,\n    \"speed\": 38.4289,\n    \"traction\": 1.7,\n    \"name\": \"Patriot\",\n    \"make\": \"Mammoth\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 63246,\n    \"category\": \"land\"\n  },\n  \"patriot2\": {\n    \"acceleration\": 0.18,\n    \"braking\": 0.32,\n    \"handling\": 0.56,\n    \"speed\": 35.9639,\n    \"traction\": 1.6,\n    \"name\": \"Patriot Stretch\",\n    \"make\": \"Mammoth\",\n    \"class\": 2,\n    \"seats\": 6,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 59238,\n    \"category\": \"land\"\n  },\n  \"patriot3\": {\n    \"acceleration\": 0.23,\n    \"braking\": 0.485,\n    \"handling\": 0.61,\n    \"speed\": 37.6763,\n    \"traction\": 1.985,\n    \"name\": \"Patriot Mil-Spec\",\n    \"make\": \"Mammoth\",\n    \"class\": 9,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 62402,\n    \"category\": \"land\"\n  },\n  \"patrolboat\": {\n    \"acceleration\": 15.5,\n    \"braking\": 0.4,\n    \"handling\": 15.88,\n    \"speed\": 40,\n    \"traction\": 0,\n    \"name\": \"Kurtz 31 Patrol Boat\",\n    \"make\": \"\",\n    \"class\": 14,\n    \"seats\": 4,\n    \"doors\": 0,\n    \"type\": \"boat\",\n    \"price\": 2153400,\n    \"category\": \"sea\",\n    \"weapons\": true\n  },\n  \"pbus\": {\n    \"acceleration\": 0.14,\n    \"braking\": 0.25,\n    \"handling\": 0.52,\n    \"speed\": 28.2361,\n    \"traction\": 1.35,\n    \"name\": \"Prison Bus\",\n    \"make\": \"\",\n    \"class\": 18,\n    \"seats\": 11,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 46633,\n    \"category\": \"land\"\n  },\n  \"pbus2\": {\n    \"acceleration\": 0.13,\n    \"braking\": 0.25,\n    \"handling\": 0.51,\n    \"speed\": 23.1177,\n    \"traction\": 1.15,\n    \"name\": \"Festival Bus\",\n    \"make\": \"\",\n    \"class\": 17,\n    \"seats\": 11,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 38412,\n    \"category\": \"land\"\n  },\n  \"pcj\": {\n    \"acceleration\": 0.26,\n    \"braking\": 1.3,\n    \"handling\": 0.64,\n    \"speed\": 39.7959,\n    \"traction\": 2.05,\n    \"name\": \"PCJ 600\",\n    \"make\": \"Shitzu\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 20997,\n    \"category\": \"land\"\n  },\n  \"penetrator\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.8,\n    \"handling\": 0.68,\n    \"speed\": 49.4194,\n    \"traction\": 2.58,\n    \"name\": \"Penetrator\",\n    \"make\": \"Ocelot\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 81919,\n    \"category\": \"land\"\n  },\n  \"penumbra\": {\n    \"acceleration\": 0.22,\n    \"braking\": 0.8,\n    \"handling\": 0.6,\n    \"speed\": 40.7799,\n    \"traction\": 2.25,\n    \"name\": \"Penumbra\",\n    \"make\": \"Maibatsu\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 67839,\n    \"category\": \"land\"\n  },\n  \"penumbra2\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.8,\n    \"handling\": 0.68,\n    \"speed\": 45.0454,\n    \"traction\": 2.35,\n    \"name\": \"Penumbra FF\",\n    \"make\": \"Maibatsu\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 74920,\n    \"category\": \"land\"\n  },\n  \"peyote\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.25,\n    \"handling\": 0.54,\n    \"speed\": 36.9472,\n    \"traction\": 1.85,\n    \"name\": \"Peyote\",\n    \"make\": \"Vapid\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 60635,\n    \"category\": \"land\"\n  },\n  \"peyote2\": {\n    \"acceleration\": 0.3445,\n    \"braking\": 0.9,\n    \"handling\": 0.7245,\n    \"speed\": 46.7033,\n    \"traction\": 2.26,\n    \"name\": \"Peyote Gasser\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 77875,\n    \"category\": \"land\"\n  },\n  \"peyote3\": {\n    \"acceleration\": 0.205,\n    \"braking\": 0.28,\n    \"handling\": 0.585,\n    \"speed\": 42.7741,\n    \"traction\": 1.98,\n    \"name\": \"Peyote Custom\",\n    \"make\": \"Vapid\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 70150,\n    \"category\": \"land\"\n  },\n  \"pfister811\": {\n    \"acceleration\": 0.356,\n    \"braking\": 1.12,\n    \"handling\": 0.736,\n    \"speed\": 53.1,\n    \"traction\": 2.688,\n    \"name\": \"811\",\n    \"make\": \"Pfister\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 88499,\n    \"category\": \"land\"\n  },\n  \"phantom\": {\n    \"acceleration\": 0.21,\n    \"braking\": 0.8,\n    \"handling\": 0.59,\n    \"speed\": 33.8106,\n    \"traction\": 1.65,\n    \"name\": \"Phantom\",\n    \"make\": \"JoBuilt\",\n    \"class\": 20,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 56656,\n    \"category\": \"land\"\n  },\n  \"phantom2\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.85,\n    \"handling\": 0.68,\n    \"speed\": 43.3141,\n    \"traction\": 1.95,\n    \"name\": \"Phantom Wedge\",\n    \"make\": \"JoBuilt\",\n    \"class\": 20,\n    \"seats\": 5,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 72230,\n    \"category\": \"land\"\n  },\n  \"phantom3\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.85,\n    \"handling\": 0.68,\n    \"speed\": 41.7777,\n    \"traction\": 2.05,\n    \"name\": \"Phantom Custom\",\n    \"make\": \"JoBuilt\",\n    \"class\": 20,\n    \"seats\": 5,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 69772,\n    \"category\": \"land\"\n  },\n  \"phantom4\": {\n    \"acceleration\": 0.21,\n    \"braking\": 0.8,\n    \"handling\": 0.59,\n    \"speed\": 33.8106,\n    \"traction\": 1.65,\n    \"name\": \"Phantom\",\n    \"make\": \"JoBuilt\",\n    \"class\": 20,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 56656,\n    \"category\": \"land\"\n  },\n  \"phoenix\": {\n    \"acceleration\": 0.28,\n    \"braking\": 0.8,\n    \"handling\": 0.66,\n    \"speed\": 47.2809,\n    \"traction\": 2.15,\n    \"name\": \"Phoenix\",\n    \"make\": \"Imponte\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 78433,\n    \"category\": \"land\"\n  },\n  \"picador\": {\n    \"acceleration\": 0.22,\n    \"braking\": 0.8,\n    \"handling\": 0.6,\n    \"speed\": 40.7799,\n    \"traction\": 2.05,\n    \"name\": \"Picador\",\n    \"make\": \"Cheval\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 67839,\n    \"category\": \"land\"\n  },\n  \"pigalle\": {\n    \"acceleration\": 0.265,\n    \"braking\": 0.85,\n    \"handling\": 0.645,\n    \"speed\": 49.6667,\n    \"traction\": 2.36,\n    \"name\": \"Pigalle\",\n    \"make\": \"Lampadati\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 82282,\n    \"category\": \"land\"\n  },\n  \"pipistrello\": {\n    \"acceleration\": 0.224,\n    \"braking\": 0.92,\n    \"handling\": 0.604,\n    \"speed\": 35.3852,\n    \"traction\": 2.75,\n    \"name\": \"Pipistrello\",\n    \"make\": \"Overflod\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 59413,\n    \"category\": \"land\"\n  },\n  \"pizzaboy\": {\n    \"acceleration\": 0.12,\n    \"braking\": 0.33,\n    \"handling\": 0.5,\n    \"speed\": 27.152,\n    \"traction\": 1.66,\n    \"name\": \"Pizza Boy\",\n    \"make\": \"Pegassi\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 14051,\n    \"category\": \"land\"\n  },\n  \"polcaracara\": {\n    \"acceleration\": 0.27,\n    \"braking\": 0.3,\n    \"handling\": 0.65,\n    \"speed\": 39.2704,\n    \"traction\": 2.05,\n    \"name\": \"Caracara Pursuit\",\n    \"make\": \"Vapid\",\n    \"class\": 18,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 64784,\n    \"category\": \"land\"\n  },\n  \"polcoquette4\": {\n    \"acceleration\": 0.32,\n    \"braking\": 0.6,\n    \"handling\": 0.7,\n    \"speed\": 48.8621,\n    \"traction\": 2.6,\n    \"name\": \"Coquette D10 Pursuit\",\n    \"make\": \"Invetero\",\n    \"class\": 18,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 80771,\n    \"category\": \"land\"\n  },\n  \"poldominator10\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.69,\n    \"handling\": 0.68,\n    \"speed\": 49.296,\n    \"traction\": 2.383,\n    \"name\": \"Dominator FX Interceptor\",\n    \"make\": \"Vapid\",\n    \"class\": 18,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 81545,\n    \"category\": \"land\"\n  },\n  \"poldorado\": {\n    \"acceleration\": 0.2168,\n    \"braking\": 0.5,\n    \"handling\": 0.5968,\n    \"speed\": 42.173,\n    \"traction\": 1.845,\n    \"name\": \"Dorado Cruiser\",\n    \"make\": \"Bravado\",\n    \"class\": 18,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 69578,\n    \"category\": \"land\"\n  },\n  \"polfaction2\": {\n    \"acceleration\": 0.28,\n    \"braking\": 0.8,\n    \"handling\": 0.66,\n    \"speed\": 46.6667,\n    \"traction\": 2.25,\n    \"name\": \"Outreach Faction\",\n    \"make\": \"Willard\",\n    \"class\": 18,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 77450,\n    \"category\": \"land\"\n  },\n  \"polgauntlet\": {\n    \"acceleration\": 0.362,\n    \"braking\": 0.9,\n    \"handling\": 0.742,\n    \"speed\": 49.1011,\n    \"traction\": 2.35,\n    \"name\": \"Gauntlet Interceptor\",\n    \"make\": \"Bravado\",\n    \"class\": 18,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 81768,\n    \"category\": \"land\"\n  },\n  \"polgreenwood\": {\n    \"acceleration\": 0.282,\n    \"braking\": 0.7,\n    \"handling\": 0.662,\n    \"speed\": 47.6667,\n    \"traction\": 2.3,\n    \"name\": \"Greenwood Cruiser\",\n    \"make\": \"Bravado\",\n    \"class\": 18,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 78897,\n    \"category\": \"land\"\n  },\n  \"police\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.9,\n    \"handling\": 0.58,\n    \"speed\": 42.7284,\n    \"traction\": 2.55,\n    \"name\": \"Police Cruiser\",\n    \"make\": \"\",\n    \"class\": 18,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 71053,\n    \"category\": \"land\"\n  },\n  \"police2\": {\n    \"acceleration\": 0.28,\n    \"braking\": 0.9,\n    \"handling\": 0.66,\n    \"speed\": 46.1566,\n    \"traction\": 2.4,\n    \"name\": \"Police Cruiser\",\n    \"make\": \"\",\n    \"class\": 18,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 76794,\n    \"category\": \"land\"\n  },\n  \"police3\": {\n    \"acceleration\": 0.3,\n    \"braking\": 1.2,\n    \"handling\": 0.68,\n    \"speed\": 48.1141,\n    \"traction\": 2.57,\n    \"name\": \"Police Cruiser\",\n    \"make\": \"\",\n    \"class\": 18,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 80470,\n    \"category\": \"land\"\n  },\n  \"police4\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.9,\n    \"handling\": 0.58,\n    \"speed\": 42.7284,\n    \"traction\": 2.55,\n    \"name\": \"Unmarked Cruiser\",\n    \"make\": \"Vapid\",\n    \"class\": 18,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 71053,\n    \"category\": \"land\"\n  },\n  \"police5\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.9,\n    \"handling\": 0.58,\n    \"speed\": 42.7284,\n    \"traction\": 2.55,\n    \"name\": \"Stanier LE Cruiser\",\n    \"make\": \"Vapid\",\n    \"class\": 18,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 71053,\n    \"category\": \"land\"\n  },\n  \"policeb\": {\n    \"acceleration\": 0.27,\n    \"braking\": 1.1,\n    \"handling\": 0.65,\n    \"speed\": 44.1369,\n    \"traction\": 1.9,\n    \"name\": \"Police Bike\",\n    \"make\": \"\",\n    \"class\": 18,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 23078,\n    \"category\": \"land\"\n  },\n  \"policeold1\": {\n    \"acceleration\": 0.18,\n    \"braking\": 0.8,\n    \"handling\": 0.56,\n    \"speed\": 35.1601,\n    \"traction\": 1.95,\n    \"name\": \"Police Rancher\",\n    \"make\": \"\",\n    \"class\": 18,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 58720,\n    \"category\": \"land\"\n  },\n  \"policeold2\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.9,\n    \"handling\": 0.58,\n    \"speed\": 42.7284,\n    \"traction\": 2.15,\n    \"name\": \"Police Roadcruiser\",\n    \"make\": \"\",\n    \"class\": 18,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 71053,\n    \"category\": \"land\"\n  },\n  \"policet\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.6,\n    \"handling\": 0.54,\n    \"speed\": 36.9472,\n    \"traction\": 1.95,\n    \"name\": \"Police Transporter\",\n    \"make\": \"\",\n    \"class\": 18,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 61195,\n    \"category\": \"land\"\n  },\n  \"policet3\": {\n    \"acceleration\": 0.195,\n    \"braking\": 0.6,\n    \"handling\": 0.575,\n    \"speed\": 42.0369,\n    \"traction\": 2,\n    \"name\": \"Burrito (Bail Enforcement)\",\n    \"make\": \"\",\n    \"class\": 18,\n    \"seats\": 6,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 69451,\n    \"category\": \"land\"\n  },\n  \"polimpaler5\": {\n    \"acceleration\": 0.2537,\n    \"braking\": 0.865,\n    \"handling\": 0.6338,\n    \"speed\": 47.5449,\n    \"traction\": 2.3,\n    \"name\": \"Impaler SZ Cruiser\",\n    \"make\": \"Declasse\",\n    \"class\": 18,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 78875,\n    \"category\": \"land\"\n  },\n  \"polimpaler6\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.7,\n    \"handling\": 0.68,\n    \"speed\": 47.0182,\n    \"traction\": 2.135,\n    \"name\": \"Impaler LX Cruiser\",\n    \"make\": \"Declasse\",\n    \"class\": 18,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 77917,\n    \"category\": \"land\"\n  },\n  \"polmav\": {\n    \"acceleration\": 5.194,\n    \"braking\": 2.9396,\n    \"handling\": 5.194,\n    \"speed\": 56.5962,\n    \"traction\": 1.3,\n    \"name\": \"Police Maverick\",\n    \"make\": \"\",\n    \"class\": 15,\n    \"seats\": 4,\n    \"doors\": 2,\n    \"type\": \"heli\",\n    \"price\": 31465710,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"polterminus\": {\n    \"acceleration\": 0.269,\n    \"braking\": 0.55,\n    \"handling\": 0.649,\n    \"speed\": 43.2138,\n    \"traction\": 2.1875,\n    \"name\": \"Terminus Patrol\",\n    \"make\": \"Canis\",\n    \"class\": 18,\n    \"seats\": 4,\n    \"doors\": 7,\n    \"type\": \"automobile\",\n    \"price\": 71490,\n    \"category\": \"land\"\n  },\n  \"pony\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.6,\n    \"handling\": 0.54,\n    \"speed\": 36.9472,\n    \"traction\": 1.95,\n    \"name\": \"Pony\",\n    \"make\": \"Brute\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 61195,\n    \"category\": \"land\"\n  },\n  \"pony2\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.6,\n    \"handling\": 0.54,\n    \"speed\": 36.9472,\n    \"traction\": 1.95,\n    \"name\": \"Pony\",\n    \"make\": \"Brute\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 61195,\n    \"category\": \"land\"\n  },\n  \"postlude\": {\n    \"acceleration\": 0.295,\n    \"braking\": 0.4,\n    \"handling\": 0.675,\n    \"speed\": 42.1823,\n    \"traction\": 1.985,\n    \"name\": \"Postlude\",\n    \"make\": \"Dinka\",\n    \"class\": 3,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 69683,\n    \"category\": \"land\"\n  },\n  \"pounder\": {\n    \"acceleration\": 0.14,\n    \"braking\": 0.25,\n    \"handling\": 0.52,\n    \"speed\": 33.8088,\n    \"traction\": 1.65,\n    \"name\": \"Pounder\",\n    \"make\": \"MTL\",\n    \"class\": 20,\n    \"seats\": 2,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 55550,\n    \"category\": \"land\"\n  },\n  \"pounder2\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.25,\n    \"handling\": 0.54,\n    \"speed\": 36.9472,\n    \"traction\": 1.5,\n    \"name\": \"Pounder Custom\",\n    \"make\": \"MTL\",\n    \"class\": 20,\n    \"seats\": 8,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 60635,\n    \"category\": \"land\"\n  },\n  \"powersurge\": {\n    \"acceleration\": 0.82,\n    \"braking\": 1.3,\n    \"handling\": 1.2,\n    \"speed\": 42.7333,\n    \"traction\": 2.365,\n    \"name\": \"Powersurge\",\n    \"make\": \"Western\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 23026,\n    \"category\": \"land\"\n  },\n  \"prairie\": {\n    \"acceleration\": 0.22,\n    \"braking\": 0.6,\n    \"handling\": 0.6,\n    \"speed\": 40.7799,\n    \"traction\": 1.95,\n    \"name\": \"Prairie\",\n    \"make\": \"Bollokan\",\n    \"class\": 0,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 67519,\n    \"category\": \"land\"\n  },\n  \"pranger\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.8,\n    \"handling\": 0.58,\n    \"speed\": 37.5559,\n    \"traction\": 2.15,\n    \"name\": \"Park Ranger\",\n    \"make\": \"Declasse\",\n    \"class\": 18,\n    \"seats\": 8,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 62617,\n    \"category\": \"land\"\n  },\n  \"predator\": {\n    \"acceleration\": 14,\n    \"braking\": 0.4,\n    \"handling\": 14.38,\n    \"speed\": 40,\n    \"traction\": 0,\n    \"name\": \"Police Predator\",\n    \"make\": \"\",\n    \"class\": 14,\n    \"seats\": 4,\n    \"doors\": 0,\n    \"type\": \"boat\",\n    \"price\": 2063399,\n    \"category\": \"sea\",\n    \"weapons\": true\n  },\n  \"premier\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.6,\n    \"handling\": 0.58,\n    \"speed\": 38.4289,\n    \"traction\": 2.1,\n    \"name\": \"Premier\",\n    \"make\": \"Declasse\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 63694,\n    \"category\": \"land\"\n  },\n  \"previon\": {\n    \"acceleration\": 0.3185,\n    \"braking\": 0.85,\n    \"handling\": 0.6985,\n    \"speed\": 47.0085,\n    \"traction\": 2.4865,\n    \"name\": \"Previon\",\n    \"make\": \"Karin\",\n    \"class\": 3,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 78200,\n    \"category\": \"land\"\n  },\n  \"primo\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.9,\n    \"handling\": 0.58,\n    \"speed\": 38.4289,\n    \"traction\": 2.35,\n    \"name\": \"Primo\",\n    \"make\": \"Albany\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 64174,\n    \"category\": \"land\"\n  },\n  \"primo2\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.9,\n    \"handling\": 0.58,\n    \"speed\": 38.4289,\n    \"traction\": 2.35,\n    \"name\": \"Primo Custom\",\n    \"make\": \"Albany\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 64174,\n    \"category\": \"land\"\n  },\n  \"proptrailer\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5132,\n    \"traction\": 3.3,\n    \"name\": \"NULL\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"trailer\",\n    \"price\": 5668,\n    \"category\": \"land\"\n  },\n  \"prototipo\": {\n    \"acceleration\": 0.375,\n    \"braking\": 1.1,\n    \"handling\": 0.755,\n    \"speed\": 53.0565,\n    \"traction\": 2.7,\n    \"name\": \"X80 Proto\",\n    \"make\": \"Grotti\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 88458,\n    \"category\": \"land\"\n  },\n  \"pyro\": {\n    \"acceleration\": 11.27,\n    \"braking\": 11.27,\n    \"handling\": 11.27,\n    \"speed\": 100,\n    \"traction\": 2.15,\n    \"name\": \"Pyro\",\n    \"make\": \"Buckingham\",\n    \"class\": 16,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"plane\",\n    \"price\": 10704800,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"r300\": {\n    \"acceleration\": 0.3288,\n    \"braking\": 0.78,\n    \"handling\": 0.7088,\n    \"speed\": 47.8497,\n    \"traction\": 2.495,\n    \"name\": \"300R\",\n    \"make\": \"Annis\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 79467,\n    \"category\": \"land\"\n  },\n  \"radi\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.8,\n    \"handling\": 0.58,\n    \"speed\": 39.3713,\n    \"traction\": 2.25,\n    \"name\": \"Radius\",\n    \"make\": \"Vapid\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 65522,\n    \"category\": \"land\"\n  },\n  \"raiden\": {\n    \"acceleration\": 0.245,\n    \"braking\": 1.3,\n    \"handling\": 0.625,\n    \"speed\": 38.0616,\n    \"traction\": 2.15,\n    \"name\": \"Raiden\",\n    \"make\": \"Coil\",\n    \"class\": 6,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 64370,\n    \"category\": \"land\"\n  },\n  \"raiju\": {\n    \"acceleration\": 21.56,\n    \"braking\": 22.417,\n    \"handling\": 21.56,\n    \"speed\": 103.975,\n    \"traction\": 1.15,\n    \"name\": \"F-160 Raiju\",\n    \"make\": \"\",\n    \"class\": 16,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"plane\",\n    \"price\": 13560960,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"raketrailer\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5132,\n    \"traction\": 1.3,\n    \"name\": \"Trailer\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 0,\n    \"type\": \"trailer\",\n    \"price\": 5668,\n    \"category\": \"land\"\n  },\n  \"rallytruck\": {\n    \"acceleration\": 0.33,\n    \"braking\": 0.6,\n    \"handling\": 0.71,\n    \"speed\": 40.7586,\n    \"traction\": 2.3,\n    \"name\": \"Dune\",\n    \"make\": \"MTL\",\n    \"class\": 17,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 67837,\n    \"category\": \"land\"\n  },\n  \"rancherxl\": {\n    \"acceleration\": 0.18,\n    \"braking\": 0.8,\n    \"handling\": 0.56,\n    \"speed\": 35.1601,\n    \"traction\": 1.95,\n    \"name\": \"Rancher XL\",\n    \"make\": \"Declasse\",\n    \"class\": 9,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 58720,\n    \"category\": \"land\"\n  },\n  \"rancherxl2\": {\n    \"acceleration\": 0.18,\n    \"braking\": 0.8,\n    \"handling\": 0.56,\n    \"speed\": 35.1601,\n    \"traction\": 1.95,\n    \"name\": \"Rancher XL\",\n    \"make\": \"Declasse\",\n    \"class\": 9,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 58720,\n    \"category\": \"land\"\n  },\n  \"rapidgt\": {\n    \"acceleration\": 0.36,\n    \"braking\": 1,\n    \"handling\": 0.74,\n    \"speed\": 50.1498,\n    \"traction\": 2.45,\n    \"name\": \"Rapid GT\",\n    \"make\": \"Dewbauchee\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 83599,\n    \"category\": \"land\"\n  },\n  \"rapidgt2\": {\n    \"acceleration\": 0.36,\n    \"braking\": 1,\n    \"handling\": 0.74,\n    \"speed\": 50.1498,\n    \"traction\": 2.45,\n    \"name\": \"Rapid GT\",\n    \"make\": \"Dewbauchee\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 83599,\n    \"category\": \"land\"\n  },\n  \"rapidgt3\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.5,\n    \"handling\": 0.68,\n    \"speed\": 47.1242,\n    \"traction\": 2.6,\n    \"name\": \"Rapid GT Classic\",\n    \"make\": \"Dewbauchee\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 77766,\n    \"category\": \"land\"\n  },\n  \"raptor\": {\n    \"acceleration\": 0.295,\n    \"braking\": 1.2,\n    \"handling\": 0.675,\n    \"speed\": 42.8873,\n    \"traction\": 2.6,\n    \"name\": \"Raptor\",\n    \"make\": \"BF\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 0,\n    \"type\": \"automobile\",\n    \"price\": 72091,\n    \"category\": \"land\"\n  },\n  \"ratbike\": {\n    \"acceleration\": 0.215,\n    \"braking\": 1.2,\n    \"handling\": 0.595,\n    \"speed\": 36.8722,\n    \"traction\": 1.65,\n    \"name\": \"Rat Bike\",\n    \"make\": \"Western\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 19441,\n    \"category\": \"land\"\n  },\n  \"ratel\": {\n    \"acceleration\": 0.342,\n    \"braking\": 0.32,\n    \"handling\": 0.722,\n    \"speed\": 43.8756,\n    \"traction\": 2.098,\n    \"name\": \"Ratel\",\n    \"make\": \"Vapid\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 72415,\n    \"category\": \"land\"\n  },\n  \"ratloader\": {\n    \"acceleration\": 0.22,\n    \"braking\": 0.4,\n    \"handling\": 0.6,\n    \"speed\": 37.392,\n    \"traction\": 1.65,\n    \"name\": \"Rat-Loader\",\n    \"make\": \"\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 61779,\n    \"category\": \"land\"\n  },\n  \"ratloader2\": {\n    \"acceleration\": 0.24,\n    \"braking\": 0.7,\n    \"handling\": 0.62,\n    \"speed\": 39.4166,\n    \"traction\": 1.75,\n    \"name\": \"Rat-Truck\",\n    \"make\": \"Bravado\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 65562,\n    \"category\": \"land\"\n  },\n  \"rcbandito\": {\n    \"acceleration\": 0.14,\n    \"braking\": 0.8,\n    \"handling\": 0.52,\n    \"speed\": 26.3718,\n    \"traction\": 2.95,\n    \"name\": \"RC Bandito\",\n    \"make\": \"\",\n    \"class\": 9,\n    \"seats\": 1,\n    \"doors\": 0,\n    \"type\": \"automobile\",\n    \"price\": 44530,\n    \"category\": \"land\"\n  },\n  \"reaper\": {\n    \"acceleration\": 0.365,\n    \"braking\": 1.1,\n    \"handling\": 0.745,\n    \"speed\": 49.6593,\n    \"traction\": 2.67,\n    \"name\": \"Reaper\",\n    \"make\": \"Pegassi\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 82990,\n    \"category\": \"land\"\n  },\n  \"rebel\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.6,\n    \"handling\": 0.58,\n    \"speed\": 38.4289,\n    \"traction\": 2.05,\n    \"name\": \"Rusty Rebel\",\n    \"make\": \"Karin\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 63694,\n    \"category\": \"land\"\n  },\n  \"rebel2\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.6,\n    \"handling\": 0.58,\n    \"speed\": 38.4289,\n    \"traction\": 2.05,\n    \"name\": \"Rebel\",\n    \"make\": \"Karin\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 63694,\n    \"category\": \"land\"\n  },\n  \"rebla\": {\n    \"acceleration\": 0.335,\n    \"braking\": 0.85,\n    \"handling\": 0.715,\n    \"speed\": 46.5645,\n    \"traction\": 2.195,\n    \"name\": \"Rebla GTS\",\n    \"make\": \"Ubermacht\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 77543,\n    \"category\": \"land\"\n  },\n  \"reever\": {\n    \"acceleration\": 0.4085,\n    \"braking\": 1.3,\n    \"handling\": 0.7885,\n    \"speed\": 50.0416,\n    \"traction\": 2.2,\n    \"name\": \"Reever\",\n    \"make\": \"Western\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 26269,\n    \"category\": \"land\"\n  },\n  \"regina\": {\n    \"acceleration\": 0.14,\n    \"braking\": 0.6,\n    \"handling\": 0.52,\n    \"speed\": 30.6132,\n    \"traction\": 1.9,\n    \"name\": \"Regina\",\n    \"make\": \"Dundreary\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 50997,\n    \"category\": \"land\"\n  },\n  \"remus\": {\n    \"acceleration\": 0.327,\n    \"braking\": 0.9,\n    \"handling\": 0.707,\n    \"speed\": 47.0123,\n    \"traction\": 2.685,\n    \"name\": \"Remus\",\n    \"make\": \"Annis\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 78314,\n    \"category\": \"land\"\n  },\n  \"rentalbus\": {\n    \"acceleration\": 0.12,\n    \"braking\": 0.25,\n    \"handling\": 0.5,\n    \"speed\": 25.5809,\n    \"traction\": 1.55,\n    \"name\": \"Rental Shuttle Bus\",\n    \"make\": \"\",\n    \"class\": 17,\n    \"seats\": 10,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 42321,\n    \"category\": \"land\"\n  },\n  \"retinue\": {\n    \"acceleration\": 0.2275,\n    \"braking\": 0.7,\n    \"handling\": 0.6075,\n    \"speed\": 42.6766,\n    \"traction\": 2.05,\n    \"name\": \"Retinue\",\n    \"make\": \"Vapid\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 70738,\n    \"category\": \"land\"\n  },\n  \"retinue2\": {\n    \"acceleration\": 0.2775,\n    \"braking\": 0.72,\n    \"handling\": 0.6575,\n    \"speed\": 45.9073,\n    \"traction\": 2.05,\n    \"name\": \"Retinue Mk II\",\n    \"make\": \"Vapid\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 76099,\n    \"category\": \"land\"\n  },\n  \"revolter\": {\n    \"acceleration\": 0.35,\n    \"braking\": 0.8,\n    \"handling\": 0.73,\n    \"speed\": 44.915,\n    \"traction\": 2.25,\n    \"name\": \"Revolter\",\n    \"make\": \"Ubermacht\",\n    \"class\": 6,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 74872,\n    \"category\": \"land\"\n  },\n  \"rhapsody\": {\n    \"acceleration\": 0.23,\n    \"braking\": 0.6,\n    \"handling\": 0.61,\n    \"speed\": 41.3257,\n    \"traction\": 2.05,\n    \"name\": \"Rhapsody\",\n    \"make\": \"Declasse\",\n    \"class\": 0,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 68425,\n    \"category\": \"land\"\n  },\n  \"rhinehart\": {\n    \"acceleration\": 0.339,\n    \"braking\": 0.885,\n    \"handling\": 0.719,\n    \"speed\": 46.9796,\n    \"traction\": 2.285,\n    \"name\": \"Rhinehart\",\n    \"make\": \"Ubermacht\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 78276,\n    \"category\": \"land\"\n  },\n  \"rhino\": {\n    \"acceleration\": 0.11,\n    \"braking\": 0.2,\n    \"handling\": 0.49,\n    \"speed\": 18.3333,\n    \"traction\": 2.5,\n    \"name\": \"Rhino Tank\",\n    \"make\": \"\",\n    \"class\": 19,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"automobile\",\n    \"price\": 153066,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"riata\": {\n    \"acceleration\": 0.25,\n    \"braking\": 0.3,\n    \"handling\": 0.63,\n    \"speed\": 40.3984,\n    \"traction\": 2.05,\n    \"name\": \"Riata\",\n    \"make\": \"Vapid\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 66525,\n    \"category\": \"land\"\n  },\n  \"riot\": {\n    \"acceleration\": 0.12,\n    \"braking\": 0.25,\n    \"handling\": 0.5,\n    \"speed\": 34.4979,\n    \"traction\": 1.65,\n    \"name\": \"Police Riot\",\n    \"make\": \"\",\n    \"class\": 18,\n    \"seats\": 8,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 56588,\n    \"category\": \"land\"\n  },\n  \"riot2\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.3,\n    \"handling\": 0.54,\n    \"speed\": 35.9341,\n    \"traction\": 1.75,\n    \"name\": \"RCV\",\n    \"make\": \"\",\n    \"class\": 18,\n    \"seats\": 6,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 295472,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"ripley\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.2,\n    \"handling\": 0.54,\n    \"speed\": 23.3333,\n    \"traction\": 1.35,\n    \"name\": \"Ripley\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 38773,\n    \"category\": \"land\"\n  },\n  \"rocoto\": {\n    \"acceleration\": 0.19,\n    \"braking\": 0.25,\n    \"handling\": 0.57,\n    \"speed\": 41.3372,\n    \"traction\": 2.1,\n    \"name\": \"Rocoto\",\n    \"make\": \"Obey\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 67755,\n    \"category\": \"land\"\n  },\n  \"rogue\": {\n    \"acceleration\": 9.8,\n    \"braking\": 9.8,\n    \"handling\": 9.8,\n    \"speed\": 100,\n    \"traction\": 2.15,\n    \"name\": \"Rogue\",\n    \"make\": \"Western\",\n    \"class\": 16,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"plane\",\n    \"price\": 2070400,\n    \"category\": \"air\"\n  },\n  \"romero\": {\n    \"acceleration\": 0.15,\n    \"braking\": 0.5,\n    \"handling\": 0.53,\n    \"speed\": 32.0112,\n    \"traction\": 1.95,\n    \"name\": \"Romero Hearse\",\n    \"make\": \"Chariot\",\n    \"class\": 1,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 53105,\n    \"category\": \"land\"\n  },\n  \"rrocket\": {\n    \"acceleration\": 0.382,\n    \"braking\": 1,\n    \"handling\": 0.762,\n    \"speed\": 41.6183,\n    \"traction\": 2.1,\n    \"name\": \"Rampant Rocket\",\n    \"make\": \"Western\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 0,\n    \"type\": \"quadbike\",\n    \"price\": 48138,\n    \"category\": \"land\"\n  },\n  \"rt3000\": {\n    \"acceleration\": 0.312,\n    \"braking\": 1,\n    \"handling\": 0.692,\n    \"speed\": 48.1314,\n    \"traction\": 2.58,\n    \"name\": \"RT3000\",\n    \"make\": \"Dinka\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 80216,\n    \"category\": \"land\"\n  },\n  \"rubble\": {\n    \"acceleration\": 0.14,\n    \"braking\": 0.25,\n    \"handling\": 0.52,\n    \"speed\": 33.3333,\n    \"traction\": 1.6,\n    \"name\": \"Rubble\",\n    \"make\": \"JoBuilt\",\n    \"class\": 10,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 54789,\n    \"category\": \"land\"\n  },\n  \"ruffian\": {\n    \"acceleration\": 0.34,\n    \"braking\": 1.1,\n    \"handling\": 0.72,\n    \"speed\": 46.6667,\n    \"traction\": 1.95,\n    \"name\": \"Ruffian\",\n    \"make\": \"Pegassi\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 24413,\n    \"category\": \"land\"\n  },\n  \"ruiner\": {\n    \"acceleration\": 0.28,\n    \"braking\": 0.8,\n    \"handling\": 0.66,\n    \"speed\": 48.3333,\n    \"traction\": 2.2,\n    \"name\": \"Ruiner\",\n    \"make\": \"Imponte\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 80117,\n    \"category\": \"land\"\n  },\n  \"ruiner2\": {\n    \"acceleration\": 0.33,\n    \"braking\": 1,\n    \"handling\": 0.71,\n    \"speed\": 49.7632,\n    \"traction\": 2.1,\n    \"name\": \"Ruiner 2000\",\n    \"make\": \"Imponte\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 932457,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"ruiner3\": {\n    \"acceleration\": 0.28,\n    \"braking\": 0.8,\n    \"handling\": 0.66,\n    \"speed\": 48.3333,\n    \"traction\": 2.2,\n    \"name\": \"Ruiner\",\n    \"make\": \"Imponte\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 0,\n    \"type\": \"automobile\",\n    \"price\": 80117,\n    \"category\": \"land\"\n  },\n  \"ruiner4\": {\n    \"acceleration\": 0.3085,\n    \"braking\": 0.82,\n    \"handling\": 0.6885,\n    \"speed\": 48.4697,\n    \"traction\": 2.36,\n    \"name\": \"Ruiner ZZ-8\",\n    \"make\": \"Imponte\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 80458,\n    \"category\": \"land\"\n  },\n  \"rumpo\": {\n    \"acceleration\": 0.17,\n    \"braking\": 0.4,\n    \"handling\": 0.55,\n    \"speed\": 38.4494,\n    \"traction\": 1.95,\n    \"name\": \"Rumpo\",\n    \"make\": \"Bravado\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 63311,\n    \"category\": \"land\"\n  },\n  \"rumpo2\": {\n    \"acceleration\": 0.17,\n    \"braking\": 0.4,\n    \"handling\": 0.55,\n    \"speed\": 38.4494,\n    \"traction\": 1.95,\n    \"name\": \"Rumpo\",\n    \"make\": \"Bravado\",\n    \"class\": 12,\n    \"seats\": 2,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 63311,\n    \"category\": \"land\"\n  },\n  \"rumpo3\": {\n    \"acceleration\": 0.18,\n    \"braking\": 0.3,\n    \"handling\": 0.56,\n    \"speed\": 35.9639,\n    \"traction\": 2,\n    \"name\": \"Rumpo Custom\",\n    \"make\": \"Bravado\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 59206,\n    \"category\": \"land\"\n  },\n  \"ruston\": {\n    \"acceleration\": 0.325,\n    \"braking\": 1.2,\n    \"handling\": 0.705,\n    \"speed\": 46.7483,\n    \"traction\": 2.6,\n    \"name\": \"Ruston\",\n    \"make\": \"Hijak\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 78365,\n    \"category\": \"land\"\n  },\n  \"s80\": {\n    \"acceleration\": 0.3725,\n    \"braking\": 1.25,\n    \"handling\": 0.7525,\n    \"speed\": 49.6302,\n    \"traction\": 2.77,\n    \"name\": \"S80RR\",\n    \"make\": \"Annis\",\n    \"class\": 7,\n    \"seats\": 1,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 83208,\n    \"category\": \"land\"\n  },\n  \"sabregt\": {\n    \"acceleration\": 0.28,\n    \"braking\": 0.8,\n    \"handling\": 0.66,\n    \"speed\": 46.6667,\n    \"traction\": 2.25,\n    \"name\": \"Sabre Turbo\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 77450,\n    \"category\": \"land\"\n  },\n  \"sabregt2\": {\n    \"acceleration\": 0.282,\n    \"braking\": 0.82,\n    \"handling\": 0.662,\n    \"speed\": 46.6667,\n    \"traction\": 2.26,\n    \"name\": \"Sabre Turbo Custom\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 77489,\n    \"category\": \"land\"\n  },\n  \"sadler\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.6,\n    \"handling\": 0.58,\n    \"speed\": 37.5559,\n    \"traction\": 2.05,\n    \"name\": \"Sadler\",\n    \"make\": \"Vapid\",\n    \"class\": 11,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 62297,\n    \"category\": \"land\"\n  },\n  \"sadler2\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.6,\n    \"handling\": 0.58,\n    \"speed\": 37.5559,\n    \"traction\": 2.05,\n    \"name\": \"Sadler\",\n    \"make\": \"Vapid\",\n    \"class\": 11,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 62297,\n    \"category\": \"land\"\n  },\n  \"sanchez\": {\n    \"acceleration\": 0.28,\n    \"braking\": 1.1,\n    \"handling\": 0.66,\n    \"speed\": 39.3333,\n    \"traction\": 2.15,\n    \"name\": \"Sanchez (livery)\",\n    \"make\": \"Maibatsu\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 20686,\n    \"category\": \"land\"\n  },\n  \"sanchez2\": {\n    \"acceleration\": 0.28,\n    \"braking\": 1.1,\n    \"handling\": 0.66,\n    \"speed\": 39.3333,\n    \"traction\": 2.15,\n    \"name\": \"Sanchez\",\n    \"make\": \"Maibatsu\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 20686,\n    \"category\": \"land\"\n  },\n  \"sanctus\": {\n    \"acceleration\": 0.405,\n    \"braking\": 1,\n    \"handling\": 0.785,\n    \"speed\": 46.5123,\n    \"traction\": 1.95,\n    \"name\": \"Sanctus\",\n    \"make\": \"LCC\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 24351,\n    \"category\": \"land\"\n  },\n  \"sandking\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.6,\n    \"handling\": 0.58,\n    \"speed\": 38.4289,\n    \"traction\": 2,\n    \"name\": \"Sandking XL\",\n    \"make\": \"Vapid\",\n    \"class\": 9,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 63694,\n    \"category\": \"land\"\n  },\n  \"sandking2\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.6,\n    \"handling\": 0.58,\n    \"speed\": 38.4289,\n    \"traction\": 2,\n    \"name\": \"Sandking SWB\",\n    \"make\": \"Vapid\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 63694,\n    \"category\": \"land\"\n  },\n  \"savage\": {\n    \"acceleration\": 4.5864,\n    \"braking\": 2.9901,\n    \"handling\": 4.5864,\n    \"speed\": 65.1953,\n    \"traction\": 1.3,\n    \"name\": \"Savage\",\n    \"make\": \"\",\n    \"class\": 15,\n    \"seats\": 4,\n    \"doors\": 2,\n    \"type\": \"heli\",\n    \"price\": 34811190,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"savestra\": {\n    \"acceleration\": 0.2375,\n    \"braking\": 0.7,\n    \"handling\": 0.6175,\n    \"speed\": 43.8312,\n    \"traction\": 2.05,\n    \"name\": \"Savestra\",\n    \"make\": \"Annis\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 72617,\n    \"category\": \"land\"\n  },\n  \"sc1\": {\n    \"acceleration\": 0.31,\n    \"braking\": 1.12,\n    \"handling\": 0.69,\n    \"speed\": 47.4162,\n    \"traction\": 2.65,\n    \"name\": \"SC1\",\n    \"make\": \"Ubermacht\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 79257,\n    \"category\": \"land\"\n  },\n  \"scarab\": {\n    \"acceleration\": 0.1,\n    \"braking\": 0.7,\n    \"handling\": 0.48,\n    \"speed\": 23.5477,\n    \"traction\": 2.25,\n    \"name\": \"Apocalypse Scarab\",\n    \"make\": \"HVY\",\n    \"class\": 19,\n    \"seats\": 4,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 39724,\n    \"category\": \"land\"\n  },\n  \"scarab2\": {\n    \"acceleration\": 0.1,\n    \"braking\": 0.7,\n    \"handling\": 0.48,\n    \"speed\": 23.5477,\n    \"traction\": 2.25,\n    \"name\": \"Future Shock Scarab\",\n    \"make\": \"HVY\",\n    \"class\": 19,\n    \"seats\": 4,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 39724,\n    \"category\": \"land\"\n  },\n  \"scarab3\": {\n    \"acceleration\": 0.1,\n    \"braking\": 0.7,\n    \"handling\": 0.48,\n    \"speed\": 23.5477,\n    \"traction\": 2.25,\n    \"name\": \"Nightmare Scarab\",\n    \"make\": \"HVY\",\n    \"class\": 19,\n    \"seats\": 4,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 39724,\n    \"category\": \"land\"\n  },\n  \"schafter2\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.9,\n    \"handling\": 0.58,\n    \"speed\": 39.3713,\n    \"traction\": 2.55,\n    \"name\": \"Schafter\",\n    \"make\": \"Benefactor\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 65682,\n    \"category\": \"land\"\n  },\n  \"schafter3\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.95,\n    \"handling\": 0.68,\n    \"speed\": 50,\n    \"traction\": 2.55,\n    \"name\": \"Schafter V12\",\n    \"make\": \"Benefactor\",\n    \"class\": 6,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 83088,\n    \"category\": \"land\"\n  },\n  \"schafter4\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.85,\n    \"handling\": 0.58,\n    \"speed\": 39.3713,\n    \"traction\": 2.55,\n    \"name\": \"Schafter LWB\",\n    \"make\": \"Benefactor\",\n    \"class\": 6,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 65602,\n    \"category\": \"land\"\n  },\n  \"schafter5\": {\n    \"acceleration\": 0.29,\n    \"braking\": 0.92,\n    \"handling\": 0.67,\n    \"speed\": 50,\n    \"traction\": 2.55,\n    \"name\": \"Schafter V12 (Armored)\",\n    \"make\": \"Benefactor\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 83008,\n    \"category\": \"land\"\n  },\n  \"schafter6\": {\n    \"acceleration\": 0.185,\n    \"braking\": 0.82,\n    \"handling\": 0.565,\n    \"speed\": 37.4779,\n    \"traction\": 2.55,\n    \"name\": \"Schafter LWB (Armored)\",\n    \"make\": \"Benefactor\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 62476,\n    \"category\": \"land\"\n  },\n  \"schlagen\": {\n    \"acceleration\": 0.37,\n    \"braking\": 0.8,\n    \"handling\": 0.75,\n    \"speed\": 52.0606,\n    \"traction\": 2.5,\n    \"name\": \"Schlagen GT\",\n    \"make\": \"Benefactor\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 86368,\n    \"category\": \"land\"\n  },\n  \"schwarzer\": {\n    \"acceleration\": 0.29,\n    \"braking\": 0.9,\n    \"handling\": 0.67,\n    \"speed\": 48.2968,\n    \"traction\": 2.3,\n    \"name\": \"Schwartzer\",\n    \"make\": \"Benefactor\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 80250,\n    \"category\": \"land\"\n  },\n  \"scorcher\": {\n    \"acceleration\": 0.17,\n    \"braking\": 2.8,\n    \"handling\": 0.55,\n    \"speed\": 15.03,\n    \"traction\": 2.05,\n    \"name\": \"Scorcher\",\n    \"make\": \"\",\n    \"class\": 13,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bicycle\",\n    \"price\": 2782,\n    \"category\": \"land\"\n  },\n  \"scramjet\": {\n    \"acceleration\": 0.4,\n    \"braking\": 0.95,\n    \"handling\": 0.78,\n    \"speed\": 49.3536,\n    \"traction\": 2.7,\n    \"name\": \"Scramjet\",\n    \"make\": \"Declasse\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 1853409,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"scrap\": {\n    \"acceleration\": 0.13,\n    \"braking\": 0.25,\n    \"handling\": 0.51,\n    \"speed\": 32.1641,\n    \"traction\": 1.6,\n    \"name\": \"Scrap Truck\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 52886,\n    \"category\": \"land\"\n  },\n  \"seabreeze\": {\n    \"acceleration\": 20.09,\n    \"braking\": 16.4034,\n    \"handling\": 20.09,\n    \"speed\": 81.6497,\n    \"traction\": 2.15,\n    \"name\": \"Seabreeze\",\n    \"make\": \"Western\",\n    \"class\": 16,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"plane\",\n    \"price\": 2211729,\n    \"category\": \"air\"\n  },\n  \"seashark\": {\n    \"acceleration\": 12.5,\n    \"braking\": 0.4,\n    \"handling\": 12.88,\n    \"speed\": 43.3333,\n    \"traction\": 0,\n    \"name\": \"Seashark\",\n    \"make\": \"Speedophile\",\n    \"class\": 14,\n    \"seats\": 2,\n    \"doors\": 0,\n    \"type\": \"boat\",\n    \"price\": 414679,\n    \"category\": \"sea\"\n  },\n  \"seashark2\": {\n    \"acceleration\": 12.5,\n    \"braking\": 0.4,\n    \"handling\": 12.88,\n    \"speed\": 43.3333,\n    \"traction\": 0,\n    \"name\": \"Seashark\",\n    \"make\": \"Speedophile\",\n    \"class\": 14,\n    \"seats\": 2,\n    \"doors\": 0,\n    \"type\": \"boat\",\n    \"price\": 414679,\n    \"category\": \"sea\"\n  },\n  \"seashark3\": {\n    \"acceleration\": 12.5,\n    \"braking\": 0.4,\n    \"handling\": 12.88,\n    \"speed\": 43.3333,\n    \"traction\": 0,\n    \"name\": \"Seashark\",\n    \"make\": \"Speedophile\",\n    \"class\": 14,\n    \"seats\": 2,\n    \"doors\": 0,\n    \"type\": \"boat\",\n    \"price\": 414679,\n    \"category\": \"sea\"\n  },\n  \"seasparrow\": {\n    \"acceleration\": 5.194,\n    \"braking\": 2.9396,\n    \"handling\": 5.194,\n    \"speed\": 56.5962,\n    \"traction\": 1.3,\n    \"name\": \"Sea Sparrow\",\n    \"make\": \"\",\n    \"class\": 15,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"heli\",\n    \"price\": 6293142,\n    \"category\": \"air\"\n  },\n  \"seasparrow2\": {\n    \"acceleration\": 6.223,\n    \"braking\": 4.3221,\n    \"handling\": 6.223,\n    \"speed\": 69.4544,\n    \"traction\": 1.3,\n    \"name\": \"Sparrow\",\n    \"make\": \"\",\n    \"class\": 15,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"heli\",\n    \"price\": 7760025,\n    \"category\": \"air\"\n  },\n  \"seasparrow3\": {\n    \"acceleration\": 6.223,\n    \"braking\": 4.3221,\n    \"handling\": 6.223,\n    \"speed\": 69.4544,\n    \"traction\": 1.3,\n    \"name\": \"Sparrow\",\n    \"make\": \"\",\n    \"class\": 15,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"heli\",\n    \"price\": 7760025,\n    \"category\": \"air\"\n  },\n  \"seminole\": {\n    \"acceleration\": 0.18,\n    \"braking\": 0.8,\n    \"handling\": 0.56,\n    \"speed\": 36.8308,\n    \"traction\": 2.05,\n    \"name\": \"Seminole\",\n    \"make\": \"Canis\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 61393,\n    \"category\": \"land\"\n  },\n  \"seminole2\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.8,\n    \"handling\": 0.58,\n    \"speed\": 38.9854,\n    \"traction\": 2,\n    \"name\": \"Seminole Frontier\",\n    \"make\": \"Canis\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 64904,\n    \"category\": \"land\"\n  },\n  \"sentinel\": {\n    \"acceleration\": 0.21,\n    \"braking\": 0.9,\n    \"handling\": 0.64,\n    \"speed\": 45.4909,\n    \"traction\": 2.45,\n    \"name\": \"Sentinel XS\",\n    \"make\": \"Ubermacht\",\n    \"class\": 3,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 75585,\n    \"category\": \"land\"\n  },\n  \"sentinel2\": {\n    \"acceleration\": 0.21,\n    \"braking\": 0.9,\n    \"handling\": 0.64,\n    \"speed\": 45.4909,\n    \"traction\": 2.45,\n    \"name\": \"Sentinel\",\n    \"make\": \"Ubermacht\",\n    \"class\": 3,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 75585,\n    \"category\": \"land\"\n  },\n  \"sentinel3\": {\n    \"acceleration\": 0.265,\n    \"braking\": 0.8,\n    \"handling\": 0.645,\n    \"speed\": 44.644,\n    \"traction\": 2.25,\n    \"name\": \"Sentinel Classic\",\n    \"make\": \"Ubermacht\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 74166,\n    \"category\": \"land\"\n  },\n  \"sentinel4\": {\n    \"acceleration\": 0.295,\n    \"braking\": 0.88,\n    \"handling\": 0.675,\n    \"speed\": 47.5188,\n    \"traction\": 2.295,\n    \"name\": \"Sentinel Classic Widebody\",\n    \"make\": \"Ubermacht\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 78990,\n    \"category\": \"land\"\n  },\n  \"serrano\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.4,\n    \"handling\": 0.58,\n    \"speed\": 40.3933,\n    \"traction\": 2.1,\n    \"name\": \"Serrano\",\n    \"make\": \"Benefactor\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 66517,\n    \"category\": \"land\"\n  },\n  \"seven70\": {\n    \"acceleration\": 0.335,\n    \"braking\": 1,\n    \"handling\": 0.715,\n    \"speed\": 50.9092,\n    \"traction\": 2.56,\n    \"name\": \"Seven-70\",\n    \"make\": \"Dewbauchee\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 84734,\n    \"category\": \"land\"\n  },\n  \"shamal\": {\n    \"acceleration\": 7.938,\n    \"braking\": 7.193,\n    \"handling\": 7.938,\n    \"speed\": 90.6145,\n    \"traction\": 1.15,\n    \"name\": \"Shamal\",\n    \"make\": \"Buckingham\",\n    \"class\": 16,\n    \"seats\": 10,\n    \"doors\": 1,\n    \"type\": \"plane\",\n    \"price\": 1818936,\n    \"category\": \"air\"\n  },\n  \"sheava\": {\n    \"acceleration\": 0.33,\n    \"braking\": 1,\n    \"handling\": 0.71,\n    \"speed\": 48.6724,\n    \"traction\": 2.65,\n    \"name\": \"ETR1\",\n    \"make\": \"Emperor\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 81139,\n    \"category\": \"land\"\n  },\n  \"sheriff\": {\n    \"acceleration\": 0.24,\n    \"braking\": 0.6,\n    \"handling\": 0.62,\n    \"speed\": 43.0315,\n    \"traction\": 2.25,\n    \"name\": \"Sheriff Cruiser\",\n    \"make\": \"\",\n    \"class\": 18,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 71186,\n    \"category\": \"land\"\n  },\n  \"sheriff2\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.8,\n    \"handling\": 0.58,\n    \"speed\": 37.5559,\n    \"traction\": 2.15,\n    \"name\": \"Sheriff SUV\",\n    \"make\": \"\",\n    \"class\": 18,\n    \"seats\": 8,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 62617,\n    \"category\": \"land\"\n  },\n  \"shinobi\": {\n    \"acceleration\": 0.3625,\n    \"braking\": 1.25,\n    \"handling\": 0.7425,\n    \"speed\": 52.1333,\n    \"traction\": 2.3,\n    \"name\": \"Shinobi\",\n    \"make\": \"Nagasaki\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 27244,\n    \"category\": \"land\"\n  },\n  \"shotaro\": {\n    \"acceleration\": 0.4,\n    \"braking\": 1.4,\n    \"handling\": 0.78,\n    \"speed\": 51.2182,\n    \"traction\": 2.7,\n    \"name\": \"Shotaro\",\n    \"make\": \"Nagasaki\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 26899,\n    \"category\": \"land\"\n  },\n  \"skylift\": {\n    \"acceleration\": 4.704,\n    \"braking\": 2.2547,\n    \"handling\": 4.704,\n    \"speed\": 47.9315,\n    \"traction\": 1.3,\n    \"name\": \"Skylift\",\n    \"make\": \"\",\n    \"class\": 15,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"heli\",\n    \"price\": 5363478,\n    \"category\": \"air\"\n  },\n  \"slamtruck\": {\n    \"acceleration\": 0.225,\n    \"braking\": 0.6,\n    \"handling\": 0.605,\n    \"speed\": 37.9062,\n    \"traction\": 1.71,\n    \"name\": \"Slamtruck\",\n    \"make\": \"Vapid\",\n    \"class\": 11,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 62937,\n    \"category\": \"land\"\n  },\n  \"slamvan\": {\n    \"acceleration\": 0.245,\n    \"braking\": 0.6,\n    \"handling\": 0.625,\n    \"speed\": 39.9099,\n    \"traction\": 1.65,\n    \"name\": \"Slamvan\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 66207,\n    \"category\": \"land\"\n  },\n  \"slamvan2\": {\n    \"acceleration\": 0.25,\n    \"braking\": 0.7,\n    \"handling\": 0.63,\n    \"speed\": 40.3984,\n    \"traction\": 1.85,\n    \"name\": \"Lost Slamvan\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 67165,\n    \"category\": \"land\"\n  },\n  \"slamvan3\": {\n    \"acceleration\": 0.25,\n    \"braking\": 0.6,\n    \"handling\": 0.63,\n    \"speed\": 40.3984,\n    \"traction\": 2.35,\n    \"name\": \"Slamvan Custom\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 67005,\n    \"category\": \"land\"\n  },\n  \"slamvan4\": {\n    \"acceleration\": 0.27,\n    \"braking\": 0.4,\n    \"handling\": 0.65,\n    \"speed\": 41.478,\n    \"traction\": 1.85,\n    \"name\": \"Apocalypse Slamvan\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 68476,\n    \"category\": \"land\"\n  },\n  \"slamvan5\": {\n    \"acceleration\": 0.27,\n    \"braking\": 0.4,\n    \"handling\": 0.65,\n    \"speed\": 41.478,\n    \"traction\": 1.85,\n    \"name\": \"Future Shock Slamvan\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 68476,\n    \"category\": \"land\"\n  },\n  \"slamvan6\": {\n    \"acceleration\": 0.27,\n    \"braking\": 0.4,\n    \"handling\": 0.65,\n    \"speed\": 41.478,\n    \"traction\": 1.85,\n    \"name\": \"Nightmare Slamvan\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 68476,\n    \"category\": \"land\"\n  },\n  \"sm722\": {\n    \"acceleration\": 0.358,\n    \"braking\": 0.85,\n    \"handling\": 0.738,\n    \"speed\": 48.2165,\n    \"traction\": 2.508,\n    \"name\": \"SM722\",\n    \"make\": \"Benefactor\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 80260,\n    \"category\": \"land\"\n  },\n  \"sovereign\": {\n    \"acceleration\": 0.27,\n    \"braking\": 1.1,\n    \"handling\": 0.65,\n    \"speed\": 44.1369,\n    \"traction\": 1.9,\n    \"name\": \"Sovereign\",\n    \"make\": \"Western\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 23078,\n    \"category\": \"land\"\n  },\n  \"specter\": {\n    \"acceleration\": 0.32,\n    \"braking\": 1,\n    \"handling\": 0.7,\n    \"speed\": 48.6425,\n    \"traction\": 2.62,\n    \"name\": \"Specter\",\n    \"make\": \"Dewbauchee\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 81060,\n    \"category\": \"land\"\n  },\n  \"specter2\": {\n    \"acceleration\": 0.33,\n    \"braking\": 1.1,\n    \"handling\": 0.71,\n    \"speed\": 49.3176,\n    \"traction\": 2.67,\n    \"name\": \"Specter Custom\",\n    \"make\": \"Dewbauchee\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 82332,\n    \"category\": \"land\"\n  },\n  \"speeder\": {\n    \"acceleration\": 16,\n    \"braking\": 0.4,\n    \"handling\": 16.38,\n    \"speed\": 44.3333,\n    \"traction\": 0,\n    \"name\": \"Speeder\",\n    \"make\": \"Pegassi\",\n    \"class\": 14,\n    \"seats\": 4,\n    \"doors\": 0,\n    \"type\": \"boat\",\n    \"price\": 462679,\n    \"category\": \"sea\"\n  },\n  \"speeder2\": {\n    \"acceleration\": 16,\n    \"braking\": 0.4,\n    \"handling\": 16.38,\n    \"speed\": 44.3333,\n    \"traction\": 0,\n    \"name\": \"Speeder\",\n    \"make\": \"Pegassi\",\n    \"class\": 14,\n    \"seats\": 4,\n    \"doors\": 0,\n    \"type\": \"boat\",\n    \"price\": 462679,\n    \"category\": \"sea\"\n  },\n  \"speedo\": {\n    \"acceleration\": 0.18,\n    \"braking\": 0.6,\n    \"handling\": 0.56,\n    \"speed\": 39.9117,\n    \"traction\": 1.8,\n    \"name\": \"Speedo\",\n    \"make\": \"Vapid\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 66002,\n    \"category\": \"land\"\n  },\n  \"speedo2\": {\n    \"acceleration\": 0.18,\n    \"braking\": 0.6,\n    \"handling\": 0.56,\n    \"speed\": 39.9117,\n    \"traction\": 1.8,\n    \"name\": \"Clown Van\",\n    \"make\": \"Vapid\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 66002,\n    \"category\": \"land\"\n  },\n  \"speedo4\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.65,\n    \"handling\": 0.58,\n    \"speed\": 42.7284,\n    \"traction\": 1.9,\n    \"name\": \"Speedo Custom\",\n    \"make\": \"Vapid\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 70653,\n    \"category\": \"land\"\n  },\n  \"speedo5\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.65,\n    \"handling\": 0.58,\n    \"speed\": 42.7284,\n    \"traction\": 1.9,\n    \"name\": \"Speedo Custom\",\n    \"make\": \"Vapid\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 70653,\n    \"category\": \"land\"\n  },\n  \"squaddie\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.315,\n    \"handling\": 0.58,\n    \"speed\": 38.4289,\n    \"traction\": 1.9,\n    \"name\": \"Squaddie\",\n    \"make\": \"Mammoth\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 63238,\n    \"category\": \"land\"\n  },\n  \"squalo\": {\n    \"acceleration\": 11.5,\n    \"braking\": 0.4,\n    \"handling\": 11.88,\n    \"speed\": 36.6667,\n    \"traction\": 0,\n    \"name\": \"Squalo\",\n    \"make\": \"Shitzu\",\n    \"class\": 14,\n    \"seats\": 2,\n    \"doors\": 0,\n    \"type\": \"boat\",\n    \"price\": 362680,\n    \"category\": \"sea\"\n  },\n  \"stafford\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.45,\n    \"handling\": 0.58,\n    \"speed\": 38.0719,\n    \"traction\": 2,\n    \"name\": \"Stafford\",\n    \"make\": \"Enus\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 7,\n    \"type\": \"automobile\",\n    \"price\": 62883,\n    \"category\": \"land\"\n  },\n  \"stalion\": {\n    \"acceleration\": 0.29,\n    \"braking\": 0.7,\n    \"handling\": 0.67,\n    \"speed\": 45.0781,\n    \"traction\": 2.25,\n    \"name\": \"Stallion\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 74780,\n    \"category\": \"land\"\n  },\n  \"stalion2\": {\n    \"acceleration\": 0.31,\n    \"braking\": 0.7,\n    \"handling\": 0.69,\n    \"speed\": 47.7326,\n    \"traction\": 2.25,\n    \"name\": \"Burger Shot Stallion\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 79092,\n    \"category\": \"land\"\n  },\n  \"stanier\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.9,\n    \"handling\": 0.58,\n    \"speed\": 42.7284,\n    \"traction\": 2.45,\n    \"name\": \"Stanier\",\n    \"make\": \"Vapid\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 71053,\n    \"category\": \"land\"\n  },\n  \"starling\": {\n    \"acceleration\": 12.25,\n    \"braking\": 10.7188,\n    \"handling\": 12.25,\n    \"speed\": 87.5,\n    \"traction\": 1.15,\n    \"name\": \"LF-22 Starling\",\n    \"make\": \"\",\n    \"class\": 16,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"plane\",\n    \"price\": 29452512,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"stinger\": {\n    \"acceleration\": 0.26,\n    \"braking\": 0.6,\n    \"handling\": 0.64,\n    \"speed\": 45.1953,\n    \"traction\": 2.15,\n    \"name\": \"Stinger\",\n    \"make\": \"Grotti\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 74712,\n    \"category\": \"land\"\n  },\n  \"stingergt\": {\n    \"acceleration\": 0.26,\n    \"braking\": 0.6,\n    \"handling\": 0.64,\n    \"speed\": 45.1953,\n    \"traction\": 2.15,\n    \"name\": \"Stinger GT\",\n    \"make\": \"Grotti\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 74712,\n    \"category\": \"land\"\n  },\n  \"stingertt\": {\n    \"acceleration\": 0.398,\n    \"braking\": 0.98,\n    \"handling\": 0.858,\n    \"speed\": 52.2722,\n    \"traction\": 2.6165,\n    \"name\": \"Itali GTO Stinger TT\",\n    \"make\": \"Grotti\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 87213,\n    \"category\": \"land\"\n  },\n  \"stockade\": {\n    \"acceleration\": 0.12,\n    \"braking\": 0.25,\n    \"handling\": 0.5,\n    \"speed\": 34.4979,\n    \"traction\": 1.65,\n    \"name\": \"Stockade\",\n    \"make\": \"Brute\",\n    \"class\": 20,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 56588,\n    \"category\": \"land\"\n  },\n  \"stockade3\": {\n    \"acceleration\": 0.12,\n    \"braking\": 0.25,\n    \"handling\": 0.5,\n    \"speed\": 34.4979,\n    \"traction\": 1.65,\n    \"name\": \"Stockade\",\n    \"make\": \"Brute\",\n    \"class\": 20,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 56588,\n    \"category\": \"land\"\n  },\n  \"stratum\": {\n    \"acceleration\": 0.21,\n    \"braking\": 0.6,\n    \"handling\": 0.59,\n    \"speed\": 41.6589,\n    \"traction\": 2.2,\n    \"name\": \"Stratum\",\n    \"make\": \"Zirconium\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 68894,\n    \"category\": \"land\"\n  },\n  \"streamer216\": {\n    \"acceleration\": 7.84,\n    \"braking\": 6.013,\n    \"handling\": 7.84,\n    \"speed\": 76.6965,\n    \"traction\": 2.15,\n    \"name\": \"Streamer216\",\n    \"make\": \"Mammoth\",\n    \"class\": 16,\n    \"seats\": 4,\n    \"doors\": 3,\n    \"type\": \"plane\",\n    \"price\": 1574232,\n    \"category\": \"air\"\n  },\n  \"streiter\": {\n    \"acceleration\": 0.2125,\n    \"braking\": 0.8,\n    \"handling\": 0.5925,\n    \"speed\": 42.8978,\n    \"traction\": 2.08,\n    \"name\": \"Streiter\",\n    \"make\": \"Benefactor\",\n    \"class\": 6,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 71204,\n    \"category\": \"land\"\n  },\n  \"stretch\": {\n    \"acceleration\": 0.17,\n    \"braking\": 0.8,\n    \"handling\": 0.55,\n    \"speed\": 38.4494,\n    \"traction\": 1.85,\n    \"name\": \"Stretch\",\n    \"make\": \"Dundreary\",\n    \"class\": 1,\n    \"seats\": 6,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 63951,\n    \"category\": \"land\"\n  },\n  \"strikeforce\": {\n    \"acceleration\": 15.68,\n    \"braking\": 11.0874,\n    \"handling\": 15.68,\n    \"speed\": 70.7107,\n    \"traction\": 2.15,\n    \"name\": \"B-11 Strikeforce\",\n    \"make\": \"\",\n    \"class\": 16,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"plane\",\n    \"price\": 9052648,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"stromberg\": {\n    \"acceleration\": 0.29,\n    \"braking\": 1,\n    \"handling\": 0.67,\n    \"speed\": 45.8691,\n    \"traction\": 2.5,\n    \"name\": \"Stromberg\",\n    \"make\": \"Ocelot\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"submarinecar\",\n    \"price\": 6217783,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"stryder\": {\n    \"acceleration\": 0.36,\n    \"braking\": 1.2,\n    \"handling\": 0.74,\n    \"speed\": 42.2187,\n    \"traction\": 2.45,\n    \"name\": \"Stryder\",\n    \"make\": \"Nagasaki\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 0,\n    \"type\": \"quadbike\",\n    \"price\": 48970,\n    \"category\": \"land\"\n  },\n  \"stunt\": {\n    \"acceleration\": 9.8,\n    \"braking\": 7.7476,\n    \"handling\": 9.8,\n    \"speed\": 79.0569,\n    \"traction\": 1.15,\n    \"name\": \"Mallard\",\n    \"make\": \"\",\n    \"class\": 16,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"plane\",\n    \"price\": 1702472,\n    \"category\": \"air\"\n  },\n  \"submersible\": {\n    \"acceleration\": 8,\n    \"braking\": 0.4,\n    \"handling\": 8.38,\n    \"speed\": 25,\n    \"traction\": 0,\n    \"name\": \"Submersible\",\n    \"make\": \"\",\n    \"class\": 14,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"submarine\",\n    \"price\": 919160,\n    \"category\": \"sea\"\n  },\n  \"submersible2\": {\n    \"acceleration\": 10,\n    \"braking\": 0.4,\n    \"handling\": 10.38,\n    \"speed\": 25,\n    \"traction\": 0,\n    \"name\": \"Kraken\",\n    \"make\": \"\",\n    \"class\": 14,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"submarine\",\n    \"price\": 1007160,\n    \"category\": \"sea\"\n  },\n  \"sugoi\": {\n    \"acceleration\": 0.31,\n    \"braking\": 0.85,\n    \"handling\": 0.69,\n    \"speed\": 45.1933,\n    \"traction\": 2.49,\n    \"name\": \"Sugoi\",\n    \"make\": \"Dinka\",\n    \"class\": 6,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 75269,\n    \"category\": \"land\"\n  },\n  \"sultan\": {\n    \"acceleration\": 0.26,\n    \"braking\": 0.4,\n    \"handling\": 0.64,\n    \"speed\": 45.1953,\n    \"traction\": 2.35,\n    \"name\": \"Sultan\",\n    \"make\": \"Karin\",\n    \"class\": 6,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 74392,\n    \"category\": \"land\"\n  },\n  \"sultan2\": {\n    \"acceleration\": 0.33,\n    \"braking\": 0.5,\n    \"handling\": 0.71,\n    \"speed\": 46.7006,\n    \"traction\": 2.495,\n    \"name\": \"Sultan Classic\",\n    \"make\": \"Karin\",\n    \"class\": 6,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 77184,\n    \"category\": \"land\"\n  },\n  \"sultan3\": {\n    \"acceleration\": 0.3385,\n    \"braking\": 0.52,\n    \"handling\": 0.7185,\n    \"speed\": 47.2149,\n    \"traction\": 2.485,\n    \"name\": \"Sultan RS Classic\",\n    \"make\": \"Karin\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 78067,\n    \"category\": \"land\"\n  },\n  \"sultanrs\": {\n    \"acceleration\": 0.33,\n    \"braking\": 1,\n    \"handling\": 0.71,\n    \"speed\": 49.3333,\n    \"traction\": 2.5,\n    \"name\": \"Sultan RS\",\n    \"make\": \"Karin\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 82197,\n    \"category\": \"land\"\n  },\n  \"suntrap\": {\n    \"acceleration\": 11.5,\n    \"braking\": 0.4,\n    \"handling\": 11.88,\n    \"speed\": 36.6667,\n    \"traction\": 0,\n    \"name\": \"Suntrap\",\n    \"make\": \"Shitzu\",\n    \"class\": 14,\n    \"seats\": 4,\n    \"doors\": 0,\n    \"type\": \"boat\",\n    \"price\": 362680,\n    \"category\": \"sea\"\n  },\n  \"superd\": {\n    \"acceleration\": 0.26,\n    \"braking\": 0.6,\n    \"handling\": 0.64,\n    \"speed\": 45.1953,\n    \"traction\": 2.1,\n    \"name\": \"Super Diamond\",\n    \"make\": \"Enus\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 74712,\n    \"category\": \"land\"\n  },\n  \"supervolito\": {\n    \"acceleration\": 5.635,\n    \"braking\": 3.4919,\n    \"handling\": 5.635,\n    \"speed\": 61.9686,\n    \"traction\": 1.3,\n    \"name\": \"SuperVolito\",\n    \"make\": \"Buckingham\",\n    \"class\": 15,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"heli\",\n    \"price\": 6905745,\n    \"category\": \"air\"\n  },\n  \"supervolito2\": {\n    \"acceleration\": 5.635,\n    \"braking\": 3.4919,\n    \"handling\": 5.635,\n    \"speed\": 61.9686,\n    \"traction\": 1.3,\n    \"name\": \"SuperVolito Carbon\",\n    \"make\": \"Buckingham\",\n    \"class\": 15,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"heli\",\n    \"price\": 6905745,\n    \"category\": \"air\"\n  },\n  \"surano\": {\n    \"acceleration\": 0.34,\n    \"braking\": 1,\n    \"handling\": 0.72,\n    \"speed\": 50.422,\n    \"traction\": 2.55,\n    \"name\": \"Surano\",\n    \"make\": \"Benefactor\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 83971,\n    \"category\": \"land\"\n  },\n  \"surfer\": {\n    \"acceleration\": 0.1,\n    \"braking\": 0.3,\n    \"handling\": 0.48,\n    \"speed\": 20.6859,\n    \"traction\": 1.55,\n    \"name\": \"Surfer\",\n    \"make\": \"BF\",\n    \"class\": 12,\n    \"seats\": 2,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 34505,\n    \"category\": \"land\"\n  },\n  \"surfer2\": {\n    \"acceleration\": 0.1,\n    \"braking\": 0.3,\n    \"handling\": 0.48,\n    \"speed\": 20.6859,\n    \"traction\": 1.55,\n    \"name\": \"Surfer\",\n    \"make\": \"BF\",\n    \"class\": 12,\n    \"seats\": 2,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 34505,\n    \"category\": \"land\"\n  },\n  \"surfer3\": {\n    \"acceleration\": 0.1,\n    \"braking\": 0.3,\n    \"handling\": 0.48,\n    \"speed\": 20.6859,\n    \"traction\": 1.55,\n    \"name\": \"Surfer Custom\",\n    \"make\": \"BF\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 34505,\n    \"category\": \"land\"\n  },\n  \"surge\": {\n    \"acceleration\": 0.1,\n    \"braking\": 0.6,\n    \"handling\": 0.48,\n    \"speed\": 24.1987,\n    \"traction\": 2.15,\n    \"name\": \"Surge\",\n    \"make\": \"Cheval\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 40605,\n    \"category\": \"land\"\n  },\n  \"swift\": {\n    \"acceleration\": 5.439,\n    \"braking\": 3.1672,\n    \"handling\": 5.439,\n    \"speed\": 58.2314,\n    \"traction\": 1.3,\n    \"name\": \"Swift\",\n    \"make\": \"Buckingham\",\n    \"class\": 15,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"heli\",\n    \"price\": 6504894,\n    \"category\": \"air\"\n  },\n  \"swift2\": {\n    \"acceleration\": 5.537,\n    \"braking\": 3.2599,\n    \"handling\": 5.537,\n    \"speed\": 58.8757,\n    \"traction\": 1.3,\n    \"name\": \"Swift Deluxe\",\n    \"make\": \"Buckingham\",\n    \"class\": 15,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"heli\",\n    \"price\": 6588863,\n    \"category\": \"air\"\n  },\n  \"swinger\": {\n    \"acceleration\": 0.39,\n    \"braking\": 0.995,\n    \"handling\": 0.77,\n    \"speed\": 48.6413,\n    \"traction\": 2.4,\n    \"name\": \"Swinger\",\n    \"make\": \"Ocelot\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 81274,\n    \"category\": \"land\"\n  },\n  \"t20\": {\n    \"acceleration\": 0.365,\n    \"braking\": 1.1,\n    \"handling\": 0.745,\n    \"speed\": 49.6793,\n    \"traction\": 2.68,\n    \"name\": \"T20\",\n    \"make\": \"Progen\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 83022,\n    \"category\": \"land\"\n  },\n  \"taco\": {\n    \"acceleration\": 0.11,\n    \"braking\": 0.25,\n    \"handling\": 0.49,\n    \"speed\": 28.6961,\n    \"traction\": 1.55,\n    \"name\": \"Taco Van\",\n    \"make\": \"\",\n    \"class\": 12,\n    \"seats\": 1,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 47273,\n    \"category\": \"land\"\n  },\n  \"tahoma\": {\n    \"acceleration\": 0.298,\n    \"braking\": 0.625,\n    \"handling\": 0.678,\n    \"speed\": 43.5549,\n    \"traction\": 2.308,\n    \"name\": \"Tahoma Coupe\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 72249,\n    \"category\": \"land\"\n  },\n  \"tailgater\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.9,\n    \"handling\": 0.58,\n    \"speed\": 38.4289,\n    \"traction\": 2.55,\n    \"name\": \"Tailgater\",\n    \"make\": \"Obey\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 64174,\n    \"category\": \"land\"\n  },\n  \"tailgater2\": {\n    \"acceleration\": 0.2775,\n    \"braking\": 0.88,\n    \"handling\": 0.6575,\n    \"speed\": 46.567,\n    \"traction\": 2.595,\n    \"name\": \"Tailgater S\",\n    \"make\": \"Obey\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 77411,\n    \"category\": \"land\"\n  },\n  \"taipan\": {\n    \"acceleration\": 0.357,\n    \"braking\": 1,\n    \"handling\": 0.737,\n    \"speed\": 53.8669,\n    \"traction\": 2.65,\n    \"name\": \"Taipan\",\n    \"make\": \"Cheval\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 89537,\n    \"category\": \"land\"\n  },\n  \"tampa\": {\n    \"acceleration\": 0.27,\n    \"braking\": 0.8,\n    \"handling\": 0.65,\n    \"speed\": 42.3068,\n    \"traction\": 2.25,\n    \"name\": \"Tampa\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 70442,\n    \"category\": \"land\"\n  },\n  \"tampa2\": {\n    \"acceleration\": 0.33,\n    \"braking\": 0.5,\n    \"handling\": 0.71,\n    \"speed\": 45.8049,\n    \"traction\": 2.25,\n    \"name\": \"Drift Tampa\",\n    \"make\": \"Declasse\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 75751,\n    \"category\": \"land\"\n  },\n  \"tampa3\": {\n    \"acceleration\": 0.33,\n    \"braking\": 0.5,\n    \"handling\": 0.71,\n    \"speed\": 45.8049,\n    \"traction\": 2.25,\n    \"name\": \"Weaponized Tampa\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 378759,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"tanker\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5051,\n    \"traction\": 1.8,\n    \"name\": \"Trailer\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 0,\n    \"type\": \"trailer\",\n    \"price\": 5749,\n    \"category\": \"land\"\n  },\n  \"tanker2\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5051,\n    \"traction\": 1.8,\n    \"name\": \"NULL\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 0,\n    \"type\": \"trailer\",\n    \"price\": 5749,\n    \"category\": \"land\"\n  },\n  \"tankercar\": {\n    \"acceleration\": 0.2,\n    \"braking\": 5,\n    \"handling\": 0.58,\n    \"speed\": 26.6667,\n    \"traction\": 2.5,\n    \"name\": \"Freight Train\",\n    \"make\": \"\",\n    \"class\": 21,\n    \"seats\": 2,\n    \"doors\": 0,\n    \"type\": \"train\",\n    \"price\": 194680,\n    \"category\": \"land\"\n  },\n  \"taxi\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.9,\n    \"handling\": 0.58,\n    \"speed\": 42.7284,\n    \"traction\": 2.55,\n    \"name\": \"Taxi\",\n    \"make\": \"\",\n    \"class\": 17,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 71053,\n    \"category\": \"land\"\n  },\n  \"technical\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.7,\n    \"handling\": 0.58,\n    \"speed\": 38.4289,\n    \"traction\": 2.13,\n    \"name\": \"Technical\",\n    \"make\": \"Karin\",\n    \"class\": 9,\n    \"seats\": 3,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 319271,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"technical2\": {\n    \"acceleration\": 0.25,\n    \"braking\": 0.7,\n    \"handling\": 0.63,\n    \"speed\": 39.6139,\n    \"traction\": 2.13,\n    \"name\": \"Technical Aqua\",\n    \"make\": \"Karin\",\n    \"class\": 9,\n    \"seats\": 3,\n    \"doors\": 3,\n    \"type\": \"amphibious_automobile\",\n    \"price\": 1318204,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"technical3\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.7,\n    \"handling\": 0.58,\n    \"speed\": 38.4289,\n    \"traction\": 2.13,\n    \"name\": \"Technical Custom\",\n    \"make\": \"Karin\",\n    \"class\": 9,\n    \"seats\": 3,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 319271,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"tempesta\": {\n    \"acceleration\": 0.36,\n    \"braking\": 1,\n    \"handling\": 0.74,\n    \"speed\": 49.1378,\n    \"traction\": 2.65,\n    \"name\": \"Tempesta\",\n    \"make\": \"Pegassi\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 81980,\n    \"category\": \"land\"\n  },\n  \"tenf\": {\n    \"acceleration\": 0.3545,\n    \"braking\": 1.1,\n    \"handling\": 0.7345,\n    \"speed\": 49.1413,\n    \"traction\": 2.68,\n    \"name\": \"10F\",\n    \"make\": \"Obey\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 82128,\n    \"category\": \"land\"\n  },\n  \"tenf2\": {\n    \"acceleration\": 0.356,\n    \"braking\": 1.15,\n    \"handling\": 0.736,\n    \"speed\": 49.4641,\n    \"traction\": 2.69,\n    \"name\": \"10F Widebody\",\n    \"make\": \"Obey\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 82729,\n    \"category\": \"land\"\n  },\n  \"terbyte\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.25,\n    \"handling\": 0.54,\n    \"speed\": 30.7185,\n    \"traction\": 1.95,\n    \"name\": \"Terrorbyte\",\n    \"make\": \"Benefactor\",\n    \"class\": 20,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 253348,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"terminus\": {\n    \"acceleration\": 0.269,\n    \"braking\": 0.55,\n    \"handling\": 0.649,\n    \"speed\": 43.2138,\n    \"traction\": 2.1875,\n    \"name\": \"Terminus\",\n    \"make\": \"Canis\",\n    \"class\": 9,\n    \"seats\": 4,\n    \"doors\": 7,\n    \"type\": \"automobile\",\n    \"price\": 71490,\n    \"category\": \"land\"\n  },\n  \"tezeract\": {\n    \"acceleration\": 0.1375,\n    \"braking\": 1.2,\n    \"handling\": 0.5175,\n    \"speed\": 45.8515,\n    \"traction\": 2.6,\n    \"name\": \"Tezeract\",\n    \"make\": \"Pegassi\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 76330,\n    \"category\": \"land\"\n  },\n  \"thrax\": {\n    \"acceleration\": 0.34,\n    \"braking\": 1.2,\n    \"handling\": 0.72,\n    \"speed\": 50.1961,\n    \"traction\": 2.72,\n    \"name\": \"Thrax\",\n    \"make\": \"Truffade\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 83929,\n    \"category\": \"land\"\n  },\n  \"thrust\": {\n    \"acceleration\": 0.265,\n    \"braking\": 1.5,\n    \"handling\": 0.645,\n    \"speed\": 49.3205,\n    \"traction\": 1.98,\n    \"name\": \"Thrust\",\n    \"make\": \"Dinka\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 25865,\n    \"category\": \"land\"\n  },\n  \"thruster\": {\n    \"acceleration\": 6.86,\n    \"braking\": 3.9472,\n    \"handling\": 6.86,\n    \"speed\": 57.5399,\n    \"traction\": 1.3,\n    \"name\": \"Thruster\",\n    \"make\": \"Mammoth\",\n    \"class\": 19,\n    \"seats\": 1,\n    \"doors\": 0,\n    \"type\": \"heli\",\n    \"price\": 6768639,\n    \"category\": \"air\"\n  },\n  \"tigon\": {\n    \"acceleration\": 0.3795,\n    \"braking\": 1.12,\n    \"handling\": 0.7595,\n    \"speed\": 51.7179,\n    \"traction\": 2.781,\n    \"name\": \"Tigon\",\n    \"make\": \"Lampadati\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 86363,\n    \"category\": \"land\"\n  },\n  \"tiptruck\": {\n    \"acceleration\": 0.11,\n    \"braking\": 0.25,\n    \"handling\": 0.49,\n    \"speed\": 28.6961,\n    \"traction\": 1.6,\n    \"name\": \"Tipper\",\n    \"make\": \"Brute\",\n    \"class\": 10,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 47273,\n    \"category\": \"land\"\n  },\n  \"tiptruck2\": {\n    \"acceleration\": 0.11,\n    \"braking\": 0.25,\n    \"handling\": 0.49,\n    \"speed\": 28.6961,\n    \"traction\": 1.6,\n    \"name\": \"Tipper\",\n    \"make\": \"\",\n    \"class\": 10,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 47273,\n    \"category\": \"land\"\n  },\n  \"titan\": {\n    \"acceleration\": 6.076,\n    \"braking\": 4.7518,\n    \"handling\": 6.076,\n    \"speed\": 78.2058,\n    \"traction\": 0.85,\n    \"name\": \"Titan\",\n    \"make\": \"\",\n    \"class\": 16,\n    \"seats\": 10,\n    \"doors\": 2,\n    \"type\": \"plane\",\n    \"price\": 1521753,\n    \"category\": \"air\"\n  },\n  \"titan2\": {\n    \"acceleration\": 6.125,\n    \"braking\": 4.8942,\n    \"handling\": 6.125,\n    \"speed\": 79.9059,\n    \"traction\": 0.85,\n    \"name\": \"Titan 250 D\",\n    \"make\": \"Eberhard\",\n    \"class\": 16,\n    \"seats\": 16,\n    \"doors\": 4,\n    \"type\": \"plane\",\n    \"price\": 7764008,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"toreador\": {\n    \"acceleration\": 0.3,\n    \"braking\": 1,\n    \"handling\": 0.68,\n    \"speed\": 46.997,\n    \"traction\": 2.45,\n    \"name\": \"Toreador\",\n    \"make\": \"Pegassi\",\n    \"class\": 5,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"submarinecar\",\n    \"price\": 19101030,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"torero\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.5,\n    \"handling\": 0.68,\n    \"speed\": 47.556,\n    \"traction\": 2.6,\n    \"name\": \"Torero\",\n    \"make\": \"Pegassi\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 78457,\n    \"category\": \"land\"\n  },\n  \"torero2\": {\n    \"acceleration\": 0.385,\n    \"braking\": 1.15,\n    \"handling\": 0.765,\n    \"speed\": 52.4177,\n    \"traction\": 2.7695,\n    \"name\": \"Torero XO\",\n    \"make\": \"Pegassi\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 87548,\n    \"category\": \"land\"\n  },\n  \"tornado\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.25,\n    \"handling\": 0.54,\n    \"speed\": 36.9472,\n    \"traction\": 1.8,\n    \"name\": \"Tornado\",\n    \"make\": \"Declasse\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 60635,\n    \"category\": \"land\"\n  },\n  \"tornado2\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.25,\n    \"handling\": 0.54,\n    \"speed\": 36.9472,\n    \"traction\": 1.8,\n    \"name\": \"Tornado\",\n    \"make\": \"Declasse\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 60635,\n    \"category\": \"land\"\n  },\n  \"tornado3\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.25,\n    \"handling\": 0.54,\n    \"speed\": 36.9472,\n    \"traction\": 1.8,\n    \"name\": \"Tornado\",\n    \"make\": \"Declasse\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 60635,\n    \"category\": \"land\"\n  },\n  \"tornado4\": {\n    \"acceleration\": 0.16,\n    \"braking\": 0.25,\n    \"handling\": 0.54,\n    \"speed\": 36.9472,\n    \"traction\": 1.8,\n    \"name\": \"Tornado\",\n    \"make\": \"Declasse\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 60635,\n    \"category\": \"land\"\n  },\n  \"tornado5\": {\n    \"acceleration\": 0.161,\n    \"braking\": 0.255,\n    \"handling\": 0.541,\n    \"speed\": 37.0993,\n    \"traction\": 1.85,\n    \"name\": \"Tornado Custom\",\n    \"make\": \"Declasse\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 60890,\n    \"category\": \"land\"\n  },\n  \"tornado6\": {\n    \"acceleration\": 0.28,\n    \"braking\": 0.25,\n    \"handling\": 0.66,\n    \"speed\": 40.1205,\n    \"traction\": 2,\n    \"name\": \"Tornado Rat Rod\",\n    \"make\": \"Declasse\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 66096,\n    \"category\": \"land\"\n  },\n  \"toro\": {\n    \"acceleration\": 18,\n    \"braking\": 0.4,\n    \"handling\": 18.38,\n    \"speed\": 44.3333,\n    \"traction\": 0,\n    \"name\": \"Toro\",\n    \"make\": \"Lampadati\",\n    \"class\": 14,\n    \"seats\": 4,\n    \"doors\": 0,\n    \"type\": \"boat\",\n    \"price\": 486679,\n    \"category\": \"sea\"\n  },\n  \"toro2\": {\n    \"acceleration\": 18,\n    \"braking\": 0.4,\n    \"handling\": 18.38,\n    \"speed\": 44.3333,\n    \"traction\": 0,\n    \"name\": \"Toro\",\n    \"make\": \"Lampadati\",\n    \"class\": 14,\n    \"seats\": 4,\n    \"doors\": 0,\n    \"type\": \"boat\",\n    \"price\": 486679,\n    \"category\": \"sea\"\n  },\n  \"toros\": {\n    \"acceleration\": 0.32,\n    \"braking\": 0.8,\n    \"handling\": 0.7,\n    \"speed\": 48.8621,\n    \"traction\": 2.3,\n    \"name\": \"Toros\",\n    \"make\": \"Pegassi\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 81091,\n    \"category\": \"land\"\n  },\n  \"tourbus\": {\n    \"acceleration\": 0.12,\n    \"braking\": 0.25,\n    \"handling\": 0.5,\n    \"speed\": 25.5809,\n    \"traction\": 1.55,\n    \"name\": \"Tour Bus\",\n    \"make\": \"\",\n    \"class\": 17,\n    \"seats\": 10,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 42321,\n    \"category\": \"land\"\n  },\n  \"towtruck\": {\n    \"acceleration\": 0.15,\n    \"braking\": 0.25,\n    \"handling\": 0.53,\n    \"speed\": 35,\n    \"traction\": 1.6,\n    \"name\": \"Tow Truck\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 57488,\n    \"category\": \"land\"\n  },\n  \"towtruck2\": {\n    \"acceleration\": 0.15,\n    \"braking\": 0.25,\n    \"handling\": 0.53,\n    \"speed\": 33.3333,\n    \"traction\": 1.45,\n    \"name\": \"Tow Truck\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 54821,\n    \"category\": \"land\"\n  },\n  \"towtruck3\": {\n    \"acceleration\": 0.175,\n    \"braking\": 0.25,\n    \"handling\": 0.555,\n    \"speed\": 38.3333,\n    \"traction\": 1.6,\n    \"name\": \"Tow Truck\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 62901,\n    \"category\": \"land\"\n  },\n  \"towtruck4\": {\n    \"acceleration\": 0.175,\n    \"braking\": 0.25,\n    \"handling\": 0.555,\n    \"speed\": 38.3333,\n    \"traction\": 1.6,\n    \"name\": \"Tow Truck\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 62901,\n    \"category\": \"land\"\n  },\n  \"tr2\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5051,\n    \"traction\": 1.8,\n    \"name\": \"Trailer\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 2,\n    \"type\": \"trailer\",\n    \"price\": 5749,\n    \"category\": \"land\"\n  },\n  \"tr3\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5051,\n    \"traction\": 1.8,\n    \"name\": \"Trailer\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 1,\n    \"type\": \"trailer\",\n    \"price\": 5749,\n    \"category\": \"land\"\n  },\n  \"tr4\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5051,\n    \"traction\": 1.8,\n    \"name\": \"Trailer\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 2,\n    \"type\": \"trailer\",\n    \"price\": 5749,\n    \"category\": \"land\"\n  },\n  \"tractor\": {\n    \"acceleration\": 0.08,\n    \"braking\": 0.3,\n    \"handling\": 0.46,\n    \"speed\": 13.3333,\n    \"traction\": 1.2,\n    \"name\": \"Tractor\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 1,\n    \"doors\": 0,\n    \"type\": \"automobile\",\n    \"price\": 22677,\n    \"category\": \"land\"\n  },\n  \"tractor2\": {\n    \"acceleration\": 0.15,\n    \"braking\": 0.3,\n    \"handling\": 0.53,\n    \"speed\": 14.4594,\n    \"traction\": 1.7,\n    \"name\": \"Fieldmaster\",\n    \"make\": \"Stanley\",\n    \"class\": 11,\n    \"seats\": 1,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 24703,\n    \"category\": \"land\"\n  },\n  \"tractor3\": {\n    \"acceleration\": 0.15,\n    \"braking\": 0.3,\n    \"handling\": 0.53,\n    \"speed\": 14.4594,\n    \"traction\": 1.7,\n    \"name\": \"Fieldmaster\",\n    \"make\": \"Stanley\",\n    \"class\": 11,\n    \"seats\": 1,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 24703,\n    \"category\": \"land\"\n  },\n  \"trailerlarge\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5132,\n    \"traction\": 3.3,\n    \"name\": \"Mobile Operations Center\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 3,\n    \"doors\": 1,\n    \"type\": \"trailer\",\n    \"price\": 28340,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"trailerlogs\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5051,\n    \"traction\": 1.8,\n    \"name\": \"Trailer\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 0,\n    \"type\": \"trailer\",\n    \"price\": 5749,\n    \"category\": \"land\"\n  },\n  \"trailers\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5132,\n    \"traction\": 3.3,\n    \"name\": \"Trailer\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 0,\n    \"type\": \"trailer\",\n    \"price\": 5668,\n    \"category\": \"land\"\n  },\n  \"trailers2\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5132,\n    \"traction\": 3.3,\n    \"name\": \"Trailer\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 2,\n    \"type\": \"trailer\",\n    \"price\": 5668,\n    \"category\": \"land\"\n  },\n  \"trailers3\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5132,\n    \"traction\": 3.3,\n    \"name\": \"Trailer\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 1,\n    \"type\": \"trailer\",\n    \"price\": 5668,\n    \"category\": \"land\"\n  },\n  \"trailers4\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5132,\n    \"traction\": 3.3,\n    \"name\": \"Trailer\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 0,\n    \"type\": \"trailer\",\n    \"price\": 5668,\n    \"category\": \"land\"\n  },\n  \"trailers5\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5132,\n    \"traction\": 3.3,\n    \"name\": \"Trailer\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 2,\n    \"type\": \"trailer\",\n    \"price\": 5668,\n    \"category\": \"land\"\n  },\n  \"trailersmall\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5132,\n    \"traction\": 1.8,\n    \"name\": \"Trailer\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 0,\n    \"type\": \"trailer\",\n    \"price\": 5668,\n    \"category\": \"land\"\n  },\n  \"trailersmall2\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5132,\n    \"traction\": 3.7,\n    \"name\": \"Anti-Aircraft Trailer\",\n    \"make\": \"Vom Feuer\",\n    \"class\": 19,\n    \"seats\": 1,\n    \"doors\": 0,\n    \"type\": \"trailer\",\n    \"price\": 28340,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"trash\": {\n    \"acceleration\": 0.13,\n    \"braking\": 0.3,\n    \"handling\": 0.51,\n    \"speed\": 36.5224,\n    \"traction\": 1.55,\n    \"name\": \"Trashmaster\",\n    \"make\": \"\",\n    \"class\": 17,\n    \"seats\": 4,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 59939,\n    \"category\": \"land\"\n  },\n  \"trash2\": {\n    \"acceleration\": 0.13,\n    \"braking\": 0.3,\n    \"handling\": 0.51,\n    \"speed\": 36.5224,\n    \"traction\": 1.55,\n    \"name\": \"Trashmaster\",\n    \"make\": \"\",\n    \"class\": 17,\n    \"seats\": 4,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 59939,\n    \"category\": \"land\"\n  },\n  \"trflat\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5132,\n    \"traction\": 3.3,\n    \"name\": \"Trailer\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 0,\n    \"type\": \"trailer\",\n    \"price\": 5668,\n    \"category\": \"land\"\n  },\n  \"tribike\": {\n    \"acceleration\": 0.135,\n    \"braking\": 2.5,\n    \"handling\": 0.515,\n    \"speed\": 21,\n    \"traction\": 1.85,\n    \"name\": \"Whippet Race Bike\",\n    \"make\": \"\",\n    \"class\": 13,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bicycle\",\n    \"price\": 3622,\n    \"category\": \"land\"\n  },\n  \"tribike2\": {\n    \"acceleration\": 0.135,\n    \"braking\": 2.5,\n    \"handling\": 0.515,\n    \"speed\": 21,\n    \"traction\": 1.85,\n    \"name\": \"Endurex Race Bike\",\n    \"make\": \"\",\n    \"class\": 13,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bicycle\",\n    \"price\": 3622,\n    \"category\": \"land\"\n  },\n  \"tribike3\": {\n    \"acceleration\": 0.135,\n    \"braking\": 2.5,\n    \"handling\": 0.515,\n    \"speed\": 21,\n    \"traction\": 1.85,\n    \"name\": \"Tri-Cycles Race Bike\",\n    \"make\": \"\",\n    \"class\": 13,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bicycle\",\n    \"price\": 3622,\n    \"category\": \"land\"\n  },\n  \"trophytruck\": {\n    \"acceleration\": 0.339,\n    \"braking\": 0.3,\n    \"handling\": 0.719,\n    \"speed\": 43.3667,\n    \"traction\": 2.5,\n    \"name\": \"Trophy Truck\",\n    \"make\": \"Vapid\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 71559,\n    \"category\": \"land\"\n  },\n  \"trophytruck2\": {\n    \"acceleration\": 0.339,\n    \"braking\": 0.3,\n    \"handling\": 0.719,\n    \"speed\": 43.3667,\n    \"traction\": 2.5,\n    \"name\": \"Desert Raid\",\n    \"make\": \"Vapid\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 71559,\n    \"category\": \"land\"\n  },\n  \"tropic\": {\n    \"acceleration\": 13,\n    \"braking\": 0.4,\n    \"handling\": 13.38,\n    \"speed\": 38.3333,\n    \"traction\": 0,\n    \"name\": \"Tropic\",\n    \"make\": \"Shitzu\",\n    \"class\": 14,\n    \"seats\": 4,\n    \"doors\": 0,\n    \"type\": \"boat\",\n    \"price\": 390679,\n    \"category\": \"sea\"\n  },\n  \"tropic2\": {\n    \"acceleration\": 13,\n    \"braking\": 0.4,\n    \"handling\": 13.38,\n    \"speed\": 38.3333,\n    \"traction\": 0,\n    \"name\": \"Tropic\",\n    \"make\": \"Shitzu\",\n    \"class\": 14,\n    \"seats\": 4,\n    \"doors\": 0,\n    \"type\": \"boat\",\n    \"price\": 390679,\n    \"category\": \"sea\"\n  },\n  \"tropos\": {\n    \"acceleration\": 0.225,\n    \"braking\": 0.7,\n    \"handling\": 0.605,\n    \"speed\": 42.9329,\n    \"traction\": 2.05,\n    \"name\": \"Tropos Rallye\",\n    \"make\": \"Lampadati\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 71140,\n    \"category\": \"land\"\n  },\n  \"tug\": {\n    \"acceleration\": 2.2,\n    \"braking\": 0.4,\n    \"handling\": 2.58,\n    \"speed\": 6,\n    \"traction\": 0,\n    \"name\": \"Tug\",\n    \"make\": \"\",\n    \"class\": 14,\n    \"seats\": 1,\n    \"doors\": 0,\n    \"type\": \"boat\",\n    \"price\": 67080,\n    \"category\": \"sea\"\n  },\n  \"tula\": {\n    \"acceleration\": 4.9,\n    \"braking\": 3.399,\n    \"handling\": 4.9,\n    \"speed\": 69.3676,\n    \"traction\": 2.15,\n    \"name\": \"Tula\",\n    \"make\": \"Mammoth\",\n    \"class\": 16,\n    \"seats\": 5,\n    \"doors\": 2,\n    \"type\": \"plane\",\n    \"price\": 6605327,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"tulip\": {\n    \"acceleration\": 0.32,\n    \"braking\": 0.5,\n    \"handling\": 0.7,\n    \"speed\": 48.8621,\n    \"traction\": 2.25,\n    \"name\": \"Tulip\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 80611,\n    \"category\": \"land\"\n  },\n  \"tulip2\": {\n    \"acceleration\": 0.3153,\n    \"braking\": 0.68,\n    \"handling\": 0.6953,\n    \"speed\": 45.0262,\n    \"traction\": 2.33,\n    \"name\": \"Tulip M-100\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 74746,\n    \"category\": \"land\"\n  },\n  \"turismo2\": {\n    \"acceleration\": 0.34,\n    \"braking\": 0.5,\n    \"handling\": 0.77,\n    \"speed\": 49.5374,\n    \"traction\": 2.65,\n    \"name\": \"Turismo Classic\",\n    \"make\": \"Grotti\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 81835,\n    \"category\": \"land\"\n  },\n  \"turismo3\": {\n    \"acceleration\": 0.374,\n    \"braking\": 1.185,\n    \"handling\": 0.754,\n    \"speed\": 49.9028,\n    \"traction\": 2.764,\n    \"name\": \"Turismo Omaggio\",\n    \"make\": \"Grotti\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 83545,\n    \"category\": \"land\"\n  },\n  \"turismor\": {\n    \"acceleration\": 0.353,\n    \"braking\": 1.2,\n    \"handling\": 0.733,\n    \"speed\": 51.0911,\n    \"traction\": 2.64,\n    \"name\": \"Turismo R\",\n    \"make\": \"Grotti\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 85403,\n    \"category\": \"land\"\n  },\n  \"tvtrailer\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5132,\n    \"traction\": 3.3,\n    \"name\": \"Trailer\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 2,\n    \"type\": \"trailer\",\n    \"price\": 5668,\n    \"category\": \"land\"\n  },\n  \"tvtrailer2\": {\n    \"acceleration\": 0,\n    \"braking\": 0.7,\n    \"handling\": 0.38,\n    \"speed\": -0.5132,\n    \"traction\": 3.3,\n    \"name\": \"Trailer\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 0,\n    \"doors\": 2,\n    \"type\": \"trailer\",\n    \"price\": 5668,\n    \"category\": \"land\"\n  },\n  \"tyrant\": {\n    \"acceleration\": 0.34,\n    \"braking\": 1,\n    \"handling\": 0.72,\n    \"speed\": 53.1411,\n    \"traction\": 2.75,\n    \"name\": \"Tyrant\",\n    \"make\": \"Overflod\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 88321,\n    \"category\": \"land\"\n  },\n  \"tyrus\": {\n    \"acceleration\": 0.371,\n    \"braking\": 1.2,\n    \"handling\": 0.751,\n    \"speed\": 50.3972,\n    \"traction\": 2.685,\n    \"name\": \"Tyrus\",\n    \"make\": \"Progen\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 84350,\n    \"category\": \"land\"\n  },\n  \"uranus\": {\n    \"acceleration\": 0.3245,\n    \"braking\": 0.48,\n    \"handling\": 0.7045,\n    \"speed\": 47.8313,\n    \"traction\": 2.54,\n    \"name\": \"Uranus LozSpeed\",\n    \"make\": \"Vapid\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 78944,\n    \"category\": \"land\"\n  },\n  \"utillitruck\": {\n    \"acceleration\": 0.12,\n    \"braking\": 0.25,\n    \"handling\": 0.5,\n    \"speed\": 30.462,\n    \"traction\": 1.6,\n    \"name\": \"Utility Truck\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 50131,\n    \"category\": \"land\"\n  },\n  \"utillitruck2\": {\n    \"acceleration\": 0.12,\n    \"braking\": 0.25,\n    \"handling\": 0.5,\n    \"speed\": 30.462,\n    \"traction\": 1.6,\n    \"name\": \"Utility Truck\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 50131,\n    \"category\": \"land\"\n  },\n  \"utillitruck3\": {\n    \"acceleration\": 0.12,\n    \"braking\": 0.25,\n    \"handling\": 0.5,\n    \"speed\": 30.462,\n    \"traction\": 1.6,\n    \"name\": \"Utility Truck\",\n    \"make\": \"\",\n    \"class\": 11,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 50131,\n    \"category\": \"land\"\n  },\n  \"vacca\": {\n    \"acceleration\": 0.3,\n    \"braking\": 1,\n    \"handling\": 0.68,\n    \"speed\": 50.3117,\n    \"traction\": 2.6,\n    \"name\": \"Vacca\",\n    \"make\": \"Pegassi\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 83666,\n    \"category\": \"land\"\n  },\n  \"vader\": {\n    \"acceleration\": 0.27,\n    \"braking\": 1.1,\n    \"handling\": 0.65,\n    \"speed\": 42.3068,\n    \"traction\": 1.9,\n    \"name\": \"Vader\",\n    \"make\": \"Shitzu\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 22163,\n    \"category\": \"land\"\n  },\n  \"vagner\": {\n    \"acceleration\": 0.37,\n    \"braking\": 1.12,\n    \"handling\": 0.75,\n    \"speed\": 52.6405,\n    \"traction\": 2.76,\n    \"name\": \"Vagner\",\n    \"make\": \"Dewbauchee\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 87808,\n    \"category\": \"land\"\n  },\n  \"vagrant\": {\n    \"acceleration\": 0.3325,\n    \"braking\": 0.625,\n    \"handling\": 0.7125,\n    \"speed\": 46.8151,\n    \"traction\": 2.35,\n    \"name\": \"Vagrant\",\n    \"make\": \"Maxwell\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 77576,\n    \"category\": \"land\"\n  },\n  \"valkyrie\": {\n    \"acceleration\": 5.194,\n    \"braking\": 2.8425,\n    \"handling\": 5.194,\n    \"speed\": 54.7262,\n    \"traction\": 1.6,\n    \"name\": \"Valkyrie\",\n    \"make\": \"\",\n    \"class\": 15,\n    \"seats\": 4,\n    \"doors\": 2,\n    \"type\": \"heli\",\n    \"price\": 30580515,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"valkyrie2\": {\n    \"acceleration\": 5.194,\n    \"braking\": 2.8425,\n    \"handling\": 5.194,\n    \"speed\": 54.7262,\n    \"traction\": 1.6,\n    \"name\": \"Valkyrie MOD.0\",\n    \"make\": \"\",\n    \"class\": 15,\n    \"seats\": 4,\n    \"doors\": 2,\n    \"type\": \"heli\",\n    \"price\": 30580515,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"vamos\": {\n    \"acceleration\": 0.33,\n    \"braking\": 0.5,\n    \"handling\": 0.71,\n    \"speed\": 45.8049,\n    \"traction\": 2.25,\n    \"name\": \"Vamos\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 75751,\n    \"category\": \"land\"\n  },\n  \"vectre\": {\n    \"acceleration\": 0.324,\n    \"braking\": 0.6,\n    \"handling\": 0.704,\n    \"speed\": 44.1236,\n    \"traction\": 2.635,\n    \"name\": \"Vectre\",\n    \"make\": \"Emperor\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 73202,\n    \"category\": \"land\"\n  },\n  \"velum\": {\n    \"acceleration\": 5.586,\n    \"braking\": 4.1692,\n    \"handling\": 5.586,\n    \"speed\": 74.6362,\n    \"traction\": 2.15,\n    \"name\": \"Velum\",\n    \"make\": \"\",\n    \"class\": 16,\n    \"seats\": 4,\n    \"doors\": 2,\n    \"type\": \"plane\",\n    \"price\": 1439638,\n    \"category\": \"air\"\n  },\n  \"velum2\": {\n    \"acceleration\": 5.586,\n    \"braking\": 4.1692,\n    \"handling\": 5.586,\n    \"speed\": 74.6362,\n    \"traction\": 2.15,\n    \"name\": \"Velum 5-Seater\",\n    \"make\": \"\",\n    \"class\": 16,\n    \"seats\": 5,\n    \"doors\": 3,\n    \"type\": \"plane\",\n    \"price\": 1439638,\n    \"category\": \"air\"\n  },\n  \"verlierer2\": {\n    \"acceleration\": 0.335,\n    \"braking\": 1,\n    \"handling\": 0.715,\n    \"speed\": 50,\n    \"traction\": 2.43,\n    \"name\": \"Verlierer\",\n    \"make\": \"Bravado\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 83280,\n    \"category\": \"land\"\n  },\n  \"verus\": {\n    \"acceleration\": 0.135,\n    \"braking\": 0.26,\n    \"handling\": 0.515,\n    \"speed\": 26.6342,\n    \"traction\": 2.1,\n    \"name\": \"Verus\",\n    \"make\": \"Dinka\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 0,\n    \"type\": \"quadbike\",\n    \"price\": 30298,\n    \"category\": \"land\"\n  },\n  \"vestra\": {\n    \"acceleration\": 9.016,\n    \"braking\": 8.7581,\n    \"handling\": 9.016,\n    \"speed\": 97.1397,\n    \"traction\": 1.15,\n    \"name\": \"Vestra\",\n    \"make\": \"Buckingham\",\n    \"class\": 16,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"plane\",\n    \"price\": 1982876,\n    \"category\": \"air\"\n  },\n  \"vetir\": {\n    \"acceleration\": 0.11,\n    \"braking\": 0.3,\n    \"handling\": 0.49,\n    \"speed\": 23.3676,\n    \"traction\": 1.52,\n    \"name\": \"Vetir\",\n    \"make\": \"\",\n    \"class\": 19,\n    \"seats\": 10,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 38828,\n    \"category\": \"land\"\n  },\n  \"veto\": {\n    \"acceleration\": 0.45,\n    \"braking\": 0.35,\n    \"handling\": 0.83,\n    \"speed\": 25,\n    \"traction\": 2.85,\n    \"name\": \"Veto Classic\",\n    \"make\": \"Dinka\",\n    \"class\": 6,\n    \"seats\": 1,\n    \"doors\": 0,\n    \"type\": \"automobile\",\n    \"price\": 42608,\n    \"category\": \"land\"\n  },\n  \"veto2\": {\n    \"acceleration\": 0.4275,\n    \"braking\": 0.4,\n    \"handling\": 0.8075,\n    \"speed\": 26.6667,\n    \"traction\": 2.925,\n    \"name\": \"Veto Modern\",\n    \"make\": \"Dinka\",\n    \"class\": 6,\n    \"seats\": 1,\n    \"doors\": 0,\n    \"type\": \"automobile\",\n    \"price\": 45282,\n    \"category\": \"land\"\n  },\n  \"vigero\": {\n    \"acceleration\": 0.29,\n    \"braking\": 0.8,\n    \"handling\": 0.67,\n    \"speed\": 46.6667,\n    \"traction\": 2.05,\n    \"name\": \"Vigero\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 77482,\n    \"category\": \"land\"\n  },\n  \"vigero2\": {\n    \"acceleration\": 0.3645,\n    \"braking\": 0.95,\n    \"handling\": 0.8245,\n    \"speed\": 49.201,\n    \"traction\": 2.585,\n    \"name\": \"Vigero ZX\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 82144,\n    \"category\": \"land\"\n  },\n  \"vigero3\": {\n    \"acceleration\": 0.3645,\n    \"braking\": 0.95,\n    \"handling\": 0.8245,\n    \"speed\": 49.0273,\n    \"traction\": 2.585,\n    \"name\": \"Vigero ZX Convertible\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 81866,\n    \"category\": \"land\"\n  },\n  \"vigilante\": {\n    \"acceleration\": 0.375,\n    \"braking\": 1.02,\n    \"handling\": 0.755,\n    \"speed\": 52.2429,\n    \"traction\": 2.775,\n    \"name\": \"Vigilante\",\n    \"make\": \"\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 1305429,\n    \"category\": \"land\",\n    \"weapons\": true\n  },\n  \"vindicator\": {\n    \"acceleration\": 0.263,\n    \"braking\": 1.52,\n    \"handling\": 0.643,\n    \"speed\": 49.3333,\n    \"traction\": 1.98,\n    \"name\": \"Vindicator\",\n    \"make\": \"Dinka\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 51759,\n    \"category\": \"land\"\n  },\n  \"virgo\": {\n    \"acceleration\": 0.21,\n    \"braking\": 0.7,\n    \"handling\": 0.59,\n    \"speed\": 36.3465,\n    \"traction\": 2.05,\n    \"name\": \"Virgo\",\n    \"make\": \"Albany\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 60554,\n    \"category\": \"land\"\n  },\n  \"virgo2\": {\n    \"acceleration\": 0.211,\n    \"braking\": 0.72,\n    \"handling\": 0.591,\n    \"speed\": 36.4521,\n    \"traction\": 2.1,\n    \"name\": \"Virgo Classic Custom\",\n    \"make\": \"Dundreary\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 60758,\n    \"category\": \"land\"\n  },\n  \"virgo3\": {\n    \"acceleration\": 0.21,\n    \"braking\": 0.7,\n    \"handling\": 0.59,\n    \"speed\": 36.3465,\n    \"traction\": 2.05,\n    \"name\": \"Virgo Classic\",\n    \"make\": \"Dundreary\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 60554,\n    \"category\": \"land\"\n  },\n  \"virtue\": {\n    \"acceleration\": 0.3418,\n    \"braking\": 1.28,\n    \"handling\": 0.7218,\n    \"speed\": 45.3958,\n    \"traction\": 2.588,\n    \"name\": \"Virtue\",\n    \"make\": \"Ocelot\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 76383,\n    \"category\": \"land\"\n  },\n  \"viseris\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.8,\n    \"handling\": 0.68,\n    \"speed\": 47.1242,\n    \"traction\": 2.3,\n    \"name\": \"Viseris\",\n    \"make\": \"Lampadati\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 78246,\n    \"category\": \"land\"\n  },\n  \"visione\": {\n    \"acceleration\": 0.355,\n    \"braking\": 1.02,\n    \"handling\": 0.735,\n    \"speed\": 51.3756,\n    \"traction\": 2.75,\n    \"name\": \"Visione\",\n    \"make\": \"Grotti\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 85576,\n    \"category\": \"land\"\n  },\n  \"vivanite\": {\n    \"acceleration\": 0.1095,\n    \"braking\": 0.78,\n    \"handling\": 0.5895,\n    \"speed\": 27.48,\n    \"traction\": 2.1785,\n    \"name\": \"Vivanite\",\n    \"make\": \"Karin\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 46334,\n    \"category\": \"land\"\n  },\n  \"volatol\": {\n    \"acceleration\": 6.37,\n    \"braking\": 5.1138,\n    \"handling\": 6.37,\n    \"speed\": 80.2793,\n    \"traction\": 2.15,\n    \"name\": \"Volatol\",\n    \"make\": \"\",\n    \"class\": 16,\n    \"seats\": 4,\n    \"doors\": 1,\n    \"type\": \"plane\",\n    \"price\": 7850648,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"volatus\": {\n    \"acceleration\": 5.39,\n    \"braking\": 3.1931,\n    \"handling\": 5.39,\n    \"speed\": 59.2404,\n    \"traction\": 1.3,\n    \"name\": \"Volatus\",\n    \"make\": \"Buckingham\",\n    \"class\": 15,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"heli\",\n    \"price\": 6589215,\n    \"category\": \"air\"\n  },\n  \"voltic\": {\n    \"acceleration\": 0.18,\n    \"braking\": 1,\n    \"handling\": 0.56,\n    \"speed\": 35.9639,\n    \"traction\": 2.53,\n    \"name\": \"Voltic\",\n    \"make\": \"Coil\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 60326,\n    \"category\": \"land\"\n  },\n  \"voltic2\": {\n    \"acceleration\": 0.18,\n    \"braking\": 1,\n    \"handling\": 0.56,\n    \"speed\": 35.9639,\n    \"traction\": 2.53,\n    \"name\": \"Rocket Voltic\",\n    \"make\": \"Coil\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 180978,\n    \"category\": \"land\"\n  },\n  \"voodoo\": {\n    \"acceleration\": 0.18,\n    \"braking\": 0.7,\n    \"handling\": 0.56,\n    \"speed\": 39.9117,\n    \"traction\": 1.85,\n    \"name\": \"Voodoo Custom\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 66162,\n    \"category\": \"land\"\n  },\n  \"voodoo2\": {\n    \"acceleration\": 0.17,\n    \"braking\": 0.25,\n    \"handling\": 0.55,\n    \"speed\": 38.4494,\n    \"traction\": 1.85,\n    \"name\": \"Voodoo\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 63071,\n    \"category\": \"land\"\n  },\n  \"vorschlaghammer\": {\n    \"acceleration\": 0.265,\n    \"braking\": 0.625,\n    \"handling\": 0.645,\n    \"speed\": 43.4501,\n    \"traction\": 2.065,\n    \"name\": \"Vorschlaghammer\",\n    \"make\": \"Benefactor\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 71976,\n    \"category\": \"land\"\n  },\n  \"vortex\": {\n    \"acceleration\": 0.4025,\n    \"braking\": 1.2,\n    \"handling\": 0.7825,\n    \"speed\": 48.8391,\n    \"traction\": 2.15,\n    \"name\": \"Vortex\",\n    \"make\": \"Pegassi\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 25612,\n    \"category\": \"land\"\n  },\n  \"vstr\": {\n    \"acceleration\": 0.379,\n    \"braking\": 0.625,\n    \"handling\": 0.759,\n    \"speed\": 48.0182,\n    \"traction\": 2.58,\n    \"name\": \"V-STR\",\n    \"make\": \"Albany\",\n    \"class\": 6,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 79649,\n    \"category\": \"land\"\n  },\n  \"warrener\": {\n    \"acceleration\": 0.245,\n    \"braking\": 0.95,\n    \"handling\": 0.625,\n    \"speed\": 38.4094,\n    \"traction\": 2.16,\n    \"name\": \"Warrener\",\n    \"make\": \"Vulcar\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 64367,\n    \"category\": \"land\"\n  },\n  \"warrener2\": {\n    \"acceleration\": 0.265,\n    \"braking\": 0.95,\n    \"handling\": 0.645,\n    \"speed\": 40.2494,\n    \"traction\": 2.16,\n    \"name\": \"Warrener HKR\",\n    \"make\": \"Vulcar\",\n    \"class\": 1,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 67375,\n    \"category\": \"land\"\n  },\n  \"washington\": {\n    \"acceleration\": 0.2,\n    \"braking\": 0.9,\n    \"handling\": 0.58,\n    \"speed\": 42.7284,\n    \"traction\": 2.45,\n    \"name\": \"Washington\",\n    \"make\": \"Albany\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 71053,\n    \"category\": \"land\"\n  },\n  \"wastelander\": {\n    \"acceleration\": 0.33,\n    \"braking\": 0.6,\n    \"handling\": 0.71,\n    \"speed\": 40.7586,\n    \"traction\": 2.3,\n    \"name\": \"Wastelander\",\n    \"make\": \"MTL\",\n    \"class\": 17,\n    \"seats\": 6,\n    \"doors\": 0,\n    \"type\": \"automobile\",\n    \"price\": 67837,\n    \"category\": \"land\"\n  },\n  \"weevil\": {\n    \"acceleration\": 0.188,\n    \"braking\": 0.26,\n    \"handling\": 0.568,\n    \"speed\": 32.7237,\n    \"traction\": 1.78,\n    \"name\": \"Weevil\",\n    \"make\": \"BF\",\n    \"class\": 0,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 53983,\n    \"category\": \"land\"\n  },\n  \"weevil2\": {\n    \"acceleration\": 0.3375,\n    \"braking\": 0.775,\n    \"handling\": 0.7175,\n    \"speed\": 50.5455,\n    \"traction\": 2.1075,\n    \"name\": \"Weevil Custom\",\n    \"make\": \"BF\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 83800,\n    \"category\": \"land\"\n  },\n  \"windsor\": {\n    \"acceleration\": 0.28,\n    \"braking\": 0.7,\n    \"handling\": 0.66,\n    \"speed\": 47.9991,\n    \"traction\": 2.2,\n    \"name\": \"Windsor\",\n    \"make\": \"Enus\",\n    \"class\": 3,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 79422,\n    \"category\": \"land\"\n  },\n  \"windsor2\": {\n    \"acceleration\": 0.279,\n    \"braking\": 0.7,\n    \"handling\": 0.659,\n    \"speed\": 47.8947,\n    \"traction\": 2.2,\n    \"name\": \"Windsor Drop\",\n    \"make\": \"Enus\",\n    \"class\": 3,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 79252,\n    \"category\": \"land\"\n  },\n  \"winky\": {\n    \"acceleration\": 0.15,\n    \"braking\": 0.26,\n    \"handling\": 0.53,\n    \"speed\": 30,\n    \"traction\": 1.85,\n    \"name\": \"Winky\",\n    \"make\": \"Vapid\",\n    \"class\": 9,\n    \"seats\": 3,\n    \"doors\": 1,\n    \"type\": \"automobile\",\n    \"price\": 49504,\n    \"category\": \"land\"\n  },\n  \"wolfsbane\": {\n    \"acceleration\": 0.215,\n    \"braking\": 1.2,\n    \"handling\": 0.595,\n    \"speed\": 36.8722,\n    \"traction\": 1.65,\n    \"name\": \"Wolfsbane\",\n    \"make\": \"Western\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 19441,\n    \"category\": \"land\"\n  },\n  \"xa21\": {\n    \"acceleration\": 0.364,\n    \"braking\": 1.1,\n    \"handling\": 0.744,\n    \"speed\": 49.5999,\n    \"traction\": 2.68,\n    \"name\": \"XA-21\",\n    \"make\": \"Ocelot\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 82892,\n    \"category\": \"land\"\n  },\n  \"xls\": {\n    \"acceleration\": 0.26,\n    \"braking\": 0.58,\n    \"handling\": 0.64,\n    \"speed\": 44,\n    \"traction\": 2,\n    \"name\": \"XLS\",\n    \"make\": \"Benefactor\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 72768,\n    \"category\": \"land\"\n  },\n  \"xls2\": {\n    \"acceleration\": 0.265,\n    \"braking\": 0.59,\n    \"handling\": 0.645,\n    \"speed\": 44,\n    \"traction\": 2.05,\n    \"name\": \"XLS (Armored)\",\n    \"make\": \"Benefactor\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 72800,\n    \"category\": \"land\"\n  },\n  \"yosemite\": {\n    \"acceleration\": 0.285,\n    \"braking\": 0.75,\n    \"handling\": 0.665,\n    \"speed\": 41.6363,\n    \"traction\": 2.375,\n    \"name\": \"Yosemite\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 69338,\n    \"category\": \"land\"\n  },\n  \"yosemite1500\": {\n    \"acceleration\": 0.2335,\n    \"braking\": 0.53,\n    \"handling\": 0.6135,\n    \"speed\": 42.8304,\n    \"traction\": 2,\n    \"name\": \"Yosemite 1500\",\n    \"make\": \"Declasse\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 70731,\n    \"category\": \"land\"\n  },\n  \"yosemite2\": {\n    \"acceleration\": 0.395,\n    \"braking\": 0.85,\n    \"handling\": 0.775,\n    \"speed\": 44.3373,\n    \"traction\": 2.625,\n    \"name\": \"Drift Yosemite\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 74171,\n    \"category\": \"land\"\n  },\n  \"yosemite3\": {\n    \"acceleration\": 0.275,\n    \"braking\": 0.48,\n    \"handling\": 0.655,\n    \"speed\": 40.4001,\n    \"traction\": 2.1,\n    \"name\": \"Yosemite Rancher\",\n    \"make\": \"Declasse\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 66896,\n    \"category\": \"land\"\n  },\n  \"youga\": {\n    \"acceleration\": 0.14,\n    \"braking\": 0.3,\n    \"handling\": 0.52,\n    \"speed\": 33.8088,\n    \"traction\": 1.8,\n    \"name\": \"Youga\",\n    \"make\": \"Bravado\",\n    \"class\": 12,\n    \"seats\": 2,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 55630,\n    \"category\": \"land\"\n  },\n  \"youga2\": {\n    \"acceleration\": 0.14,\n    \"braking\": 0.3,\n    \"handling\": 0.52,\n    \"speed\": 33.8088,\n    \"traction\": 1.8,\n    \"name\": \"Youga Classic\",\n    \"make\": \"Bravado\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 55630,\n    \"category\": \"land\"\n  },\n  \"youga3\": {\n    \"acceleration\": 0.17,\n    \"braking\": 0.3,\n    \"handling\": 0.55,\n    \"speed\": 38.4494,\n    \"traction\": 1.95,\n    \"name\": \"Youga Classic 4x4\",\n    \"make\": \"Bravado\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 5,\n    \"type\": \"automobile\",\n    \"price\": 63151,\n    \"category\": \"land\"\n  },\n  \"youga4\": {\n    \"acceleration\": 0.158,\n    \"braking\": 0.32,\n    \"handling\": 0.538,\n    \"speed\": 36.6417,\n    \"traction\": 1.8,\n    \"name\": \"Youga Custom\",\n    \"make\": \"Vapid\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 60252,\n    \"category\": \"land\"\n  },\n  \"youga5\": {\n    \"acceleration\": 0.158,\n    \"braking\": 0.32,\n    \"handling\": 0.538,\n    \"speed\": 36.6417,\n    \"traction\": 1.8,\n    \"name\": \"Youga Custom\",\n    \"make\": \"Vapid\",\n    \"class\": 12,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 60252,\n    \"category\": \"land\"\n  },\n  \"z190\": {\n    \"acceleration\": 0.27,\n    \"braking\": 0.95,\n    \"handling\": 0.65,\n    \"speed\": 43.9424,\n    \"traction\": 2.3,\n    \"name\": \"190z\",\n    \"make\": \"Karin\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 73299,\n    \"category\": \"land\"\n  },\n  \"zeno\": {\n    \"acceleration\": 0.388,\n    \"braking\": 1.2,\n    \"handling\": 0.768,\n    \"speed\": 53.6449,\n    \"traction\": 2.75,\n    \"name\": \"Zeno\",\n    \"make\": \"Overflod\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 89601,\n    \"category\": \"land\"\n  },\n  \"zentorno\": {\n    \"acceleration\": 0.354,\n    \"braking\": 1,\n    \"handling\": 0.734,\n    \"speed\": 49.659,\n    \"traction\": 2.65,\n    \"name\": \"Zentorno\",\n    \"make\": \"Pegassi\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 82795,\n    \"category\": \"land\"\n  },\n  \"zhaba\": {\n    \"acceleration\": 0.18,\n    \"braking\": 0.8,\n    \"handling\": 0.56,\n    \"speed\": 30.3041,\n    \"traction\": 1.9,\n    \"name\": \"Zhaba\",\n    \"make\": \"RUNE\",\n    \"class\": 9,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"amphibious_automobile\",\n    \"price\": 203802,\n    \"category\": \"land\"\n  },\n  \"zion\": {\n    \"acceleration\": 0.22,\n    \"braking\": 0.9,\n    \"handling\": 0.6,\n    \"speed\": 46.8751,\n    \"traction\": 2.6,\n    \"name\": \"Zion\",\n    \"make\": \"Ubermacht\",\n    \"class\": 3,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 77752,\n    \"category\": \"land\"\n  },\n  \"zion2\": {\n    \"acceleration\": 0.22,\n    \"braking\": 0.9,\n    \"handling\": 0.6,\n    \"speed\": 46.8751,\n    \"traction\": 2.6,\n    \"name\": \"Zion Cabrio\",\n    \"make\": \"Ubermacht\",\n    \"class\": 3,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 77752,\n    \"category\": \"land\"\n  },\n  \"zion3\": {\n    \"acceleration\": 0.305,\n    \"braking\": 0.85,\n    \"handling\": 0.685,\n    \"speed\": 44.5858,\n    \"traction\": 2.35,\n    \"name\": \"Zion Classic\",\n    \"make\": \"Ubermacht\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 74281,\n    \"category\": \"land\"\n  },\n  \"zombiea\": {\n    \"acceleration\": 0.29,\n    \"braking\": 0.8,\n    \"handling\": 0.67,\n    \"speed\": 44.6053,\n    \"traction\": 1.875,\n    \"name\": \"Zombie Bobber\",\n    \"make\": \"Western\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 23182,\n    \"category\": \"land\"\n  },\n  \"zombieb\": {\n    \"acceleration\": 0.29,\n    \"braking\": 0.8,\n    \"handling\": 0.67,\n    \"speed\": 44.6053,\n    \"traction\": 1.875,\n    \"name\": \"Zombie Chopper\",\n    \"make\": \"Western\",\n    \"class\": 8,\n    \"seats\": 2,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 23182,\n    \"category\": \"land\"\n  },\n  \"zorrusso\": {\n    \"acceleration\": 0.3745,\n    \"braking\": 1.2,\n    \"handling\": 0.7545,\n    \"speed\": 50.8958,\n    \"traction\": 2.728,\n    \"name\": \"Zorrusso\",\n    \"make\": \"Pegassi\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 85159,\n    \"category\": \"land\"\n  },\n  \"zr350\": {\n    \"acceleration\": 0.33,\n    \"braking\": 0.85,\n    \"handling\": 0.71,\n    \"speed\": 48.0938,\n    \"traction\": 2.485,\n    \"name\": \"ZR350\",\n    \"make\": \"Annis\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 79974,\n    \"category\": \"land\"\n  },\n  \"zr380\": {\n    \"acceleration\": 0.35,\n    \"braking\": 0.8,\n    \"handling\": 0.73,\n    \"speed\": 50.39,\n    \"traction\": 2.5,\n    \"name\": \"Apocalypse ZR380\",\n    \"make\": \"Annis\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 83632,\n    \"category\": \"land\"\n  },\n  \"zr3802\": {\n    \"acceleration\": 0.35,\n    \"braking\": 0.8,\n    \"handling\": 0.73,\n    \"speed\": 50.39,\n    \"traction\": 2.5,\n    \"name\": \"Future Shock ZR380\",\n    \"make\": \"Annis\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 83632,\n    \"category\": \"land\"\n  },\n  \"zr3803\": {\n    \"acceleration\": 0.35,\n    \"braking\": 0.8,\n    \"handling\": 0.73,\n    \"speed\": 50.39,\n    \"traction\": 2.5,\n    \"name\": \"Nightmare ZR380\",\n    \"make\": \"Annis\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 83632,\n    \"category\": \"land\"\n  },\n  \"ztype\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.7,\n    \"handling\": 0.68,\n    \"speed\": 51.3333,\n    \"traction\": 2.3,\n    \"name\": \"Z-Type\",\n    \"make\": \"Truffade\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 84821,\n    \"category\": \"land\"\n  },\n  \"hardy\": {\n    \"acceleration\": 0.28,\n    \"braking\": 0.75,\n    \"handling\": 0.65,\n    \"speed\": 42.0,\n    \"traction\": 2.1,\n    \"name\": \"Hardy\",\n    \"make\": \"Annis\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 85000,\n    \"category\": \"land\"\n  },\n  \"drifthardy\": {\n    \"acceleration\": 0.28,\n    \"braking\": 0.75,\n    \"handling\": 0.65,\n    \"speed\": 42.0,\n    \"traction\": 2.1,\n    \"name\": \"Hardy Drift\",\n    \"make\": \"Annis\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 85000,\n    \"category\": \"land\"\n  },\n  \"minimus\": {\n    \"acceleration\": 0.29,\n    \"braking\": 0.78,\n    \"handling\": 0.67,\n    \"speed\": 43.5,\n    \"traction\": 2.2,\n    \"name\": \"Minimus\",\n    \"make\": \"Annis\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 120000,\n    \"category\": \"land\"\n  },\n  \"tampa4\": {\n    \"acceleration\": 0.33,\n    \"braking\": 0.9,\n    \"handling\": 0.72,\n    \"speed\": 48.0,\n    \"traction\": 2.6,\n    \"name\": \"Tampa GT\",\n    \"make\": \"Declasse\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 1850000,\n    \"category\": \"land\"\n  },\n  \"l352\": {\n    \"acceleration\": 0.21,\n    \"braking\": 0.6,\n    \"handling\": 0.58,\n    \"speed\": 38.0,\n    \"traction\": 2.3,\n    \"name\": \"Walton L35 Stock\",\n    \"make\": \"Declasse\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 650000,\n    \"category\": \"land\"\n  },\n  \"driftl352\": {\n    \"acceleration\": 0.25,\n    \"braking\": 0.65,\n    \"handling\": 0.7,\n    \"speed\": 40.0,\n    \"traction\": 2.5,\n    \"name\": \"Drift Walton L35\",\n    \"make\": \"Declasse\",\n    \"class\": 9,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 950000,\n    \"category\": \"land\"\n  },\n  \"rapidgt4\": {\n    \"acceleration\": 0.35,\n    \"braking\": 1.0,\n    \"handling\": 0.75,\n    \"speed\": 49.5,\n    \"traction\": 2.65,\n    \"name\": \"Rapid GT X\",\n    \"make\": \"Dewbauchee\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 1600000,\n    \"category\": \"land\"\n  },\n  \"cheetah3\": {\n    \"acceleration\": 0.34,\n    \"braking\": 0.95,\n    \"handling\": 0.73,\n    \"speed\": 49.0,\n    \"traction\": 2.55,\n    \"name\": \"LSCM Cheetah Classic\",\n    \"make\": \"Grotti\",\n    \"class\": 5,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 1300000,\n    \"category\": \"land\"\n  },\n  \"everon3\": {\n    \"acceleration\": 0.27,\n    \"braking\": 0.7,\n    \"handling\": 0.63,\n    \"speed\": 41.0,\n    \"traction\": 2.4,\n    \"name\": \"Everon RS\",\n    \"make\": \"Karin\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 1500000,\n    \"category\": \"land\"\n  },\n  \"woodlander\": {\n    \"acceleration\": 0.26,\n    \"braking\": 0.68,\n    \"handling\": 0.62,\n    \"speed\": 40.5,\n    \"traction\": 2.35,\n    \"name\": \"Woodlander\",\n    \"make\": \"Karin\",\n    \"class\": 2,\n    \"seats\": 4,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 1350000,\n    \"category\": \"land\"\n  },\n  \"suzume\": {\n    \"acceleration\": 0.39,\n    \"braking\": 1.2,\n    \"handling\": 0.8,\n    \"speed\": 53.0,\n    \"traction\": 2.8,\n    \"name\": \"Suzume\",\n    \"make\": \"Överflöd\",\n    \"class\": 7,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 2800000,\n    \"category\": \"land\"\n  },\n  \"sentinel5\": {\n    \"acceleration\": 0.31,\n    \"braking\": 0.9,\n    \"handling\": 0.7,\n    \"speed\": 47.0,\n    \"traction\": 2.5,\n    \"name\": \"Sentinel GTS\",\n    \"make\": \"Übermacht\",\n    \"class\": 6,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 1950000,\n    \"category\": \"land\"\n  },\n  \"policeb2\": {\n    \"acceleration\": 0.32,\n    \"braking\": 1.3,\n    \"handling\": 0.7,\n    \"speed\": 45.0,\n    \"traction\": 2.0,\n    \"name\": \"Police Bike\",\n    \"make\": \"Western\",\n    \"class\": 8,\n    \"seats\": 1,\n    \"doors\": 1,\n    \"type\": \"bike\",\n    \"price\": 200000,\n    \"category\": \"land\"\n  },\n  \"stockade4\": {\n    \"acceleration\": 0.15,\n    \"braking\": 0.4,\n    \"handling\": 0.55,\n    \"speed\": 35.0,\n    \"traction\": 1.8,\n    \"name\": \"Bobcat Security Stockade\",\n    \"make\": \"Brute\",\n    \"class\": 20,\n    \"seats\": 2,\n    \"doors\": 2,\n    \"type\": \"automobile\",\n    \"price\": 800000,\n    \"category\": \"land\"\n  },\n  \"maverick2\": {\n    \"acceleration\": 5.096,\n    \"braking\": 2.7553,\n    \"handling\": 5.096,\n    \"speed\": 54.0675,\n    \"traction\": 1.3,\n    \"name\": \"Maverick\",\n    \"make\": \"\",\n    \"class\": 15,\n    \"seats\": 4,\n    \"doors\": 2,\n    \"type\": \"heli\",\n    \"price\": 30156660,\n    \"category\": \"air\",\n    \"weapons\": true\n  },\n  \"flatbed2\": {\n    \"acceleration\": 0.14,\n    \"braking\": 0.25,\n    \"handling\": 0.52,\n    \"speed\": 28.2361,\n    \"traction\": 1.65,\n    \"name\": \"Flatbed\",\n    \"make\": \"MTL\",\n    \"class\": 10,\n    \"seats\": 2,\n    \"doors\": 3,\n    \"type\": \"automobile\",\n    \"price\": 46633,\n    \"category\": \"land\"\n  },\n  \"driftdominator10\": {\n    \"acceleration\": 0.3,\n    \"braking\": 0.69,\n    \"handling\": 0.68,\n    \"speed\": 49.296,\n    \"traction\": 2.383,\n    \"name\": \"Dominator FX Drift\",\n    \"make\": \"Vapid\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 81545,\n    \"category\": \"land\"\n  },\n  \"driftgauntlet4\": {\n    \"acceleration\": 0.36,\n    \"braking\": 0.9,\n    \"handling\": 0.74,\n    \"speed\": 48.6553,\n    \"traction\": 2.35,\n    \"name\": \"Gauntlet Hellfire Drift\",\n    \"make\": \"Bravado\",\n    \"class\": 4,\n    \"seats\": 2,\n    \"doors\": 4,\n    \"type\": \"automobile\",\n    \"price\": 81048,\n    \"category\": \"land\"\n  },\n  \"driftchavosv6\": {\n    \"acceleration\": 0.274,\n    \"braking\": 0.69,\n    \"handling\": 0.654,\n    \"speed\": 46.6629,\n    \"traction\": 2.554,\n    \"name\": \"Chavos V6 Drift\",\n    \"make\": \"Dinka\",\n    \"class\": 1,\n    \"seats\": 4,\n    \"doors\": 6,\n    \"type\": \"automobile\",\n    \"price\": 77249,\n    \"category\": \"land\"\n  }\n}\n"
  },
  {
    "path": "common/index.ts",
    "content": "import { checkDependency } from \"@overextended/ox_lib/\";\nimport type { OxGroupPermissions } from \"types\";\n\nif (!checkDependency(\"ox_lib\", \"3.24.0\", true)) throw new Error(\"Failed dependency check.\");\n\nexport function LoadDataFile(file: string) {\n  return JSON.parse(LoadResourceFile(\"ox_core\", `/common/data/${file}.json`));\n}\n\nexport function GetGroupPermissions(groupName: string): OxGroupPermissions {\n  return GlobalState[`group.${groupName}:permissions`] || {};\n}\n\nconsole.info = (...args: any[]) => console.log(`^3${args.join(\"\\t\")}^0`);\n\nDEV: console.info(`Resource ${GetCurrentResourceName()} is running in development mode!`);\n\nimport \"./vehicles\";\n\nexports(\"GetGroupPermissions\", GetGroupPermissions);\n"
  },
  {
    "path": "common/locales.ts",
    "content": "import { locale, type FlattenObjectKeys } from \"@overextended/ox_lib\";\n\ntype Locales = FlattenObjectKeys<typeof import(\"../locales/en.json\")>;\n\nexport default <T extends Locales>(str: T, ...args: any[]) => locale(str, ...args) as string;\n"
  },
  {
    "path": "common/tsconfig.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"composite\": true,\n    \"paths\": {\n      \"types\": [\"../types\"]\n    }\n  },\n  \"include\": [\"./\", \"../types\", \"../locales/en.json\"]\n}\n"
  },
  {
    "path": "common/vehicles.ts",
    "content": "import { LoadDataFile } from './';\nimport type { Dict, VehicleCategories, VehicleData, VehicleStats, Vehicles } from 'types';\n\nconst vehicles: Dict<VehicleData> = LoadDataFile('vehicles');\nconst vehicleStats = LoadDataFile('vehicleStats');\n\nexport function GetTopVehicleStats(): Record<VehicleCategories, VehicleStats>;\nexport function GetTopVehicleStats(category: VehicleCategories): VehicleStats;\n\nexport function GetTopVehicleStats(category?: VehicleCategories) {\n  return category ? (vehicleStats as any)[category] : vehicleStats;\n}\n\nexport function GetVehicleData(): Vehicles;\nexport function GetVehicleData<T extends string>(filter: T): VehicleData;\nexport function GetVehicleData<T extends string[]>(\n  filter: T,\n): {\n  [K in T[number]]: VehicleData; // this could be better\n};\n\nexport function GetVehicleData(filter?: void | string | string[]) {\n  if (!filter) return vehicles;\n\n  if (typeof filter === 'string') return vehicles[filter];\n\n  if (Array.isArray(filter)) {\n    const obj: Record<string, any> = {};\n\n    filter.forEach((name) => {\n      const vehicle = vehicles[name];\n\n      if (vehicle) obj[name] = vehicle;\n    });\n\n    return obj;\n  }\n}\n\n/**\n * Remap vehicle types to their net types.\n * https://github.com/citizenfx/fivem/commit/1e266a2ca5c04eb96c090de67508a3475d35d6da\n */\nexport function GetVehicleNetworkType(modelName: string) {\n  const vehicleType = vehicles[modelName]?.type;\n\n  switch (vehicleType) {\n    case 'bicycle':\n      return 'bike';\n    case 'blimp':\n      return 'heli';\n    case 'quadbike':\n    case 'amphibious_quadbike':\n    case 'amphibious_automobile':\n    case 'submarinecar':\n      return 'automobile';\n    default:\n      return vehicleType;\n  }\n}\n\nexports('GetTopVehicleStats', GetTopVehicleStats);\nexports('GetVehicleData', GetVehicleData);\nexports('GetVehicleNetworkType', GetVehicleNetworkType);\n"
  },
  {
    "path": "lib/client/index.ts",
    "content": "import { Ox as OxCore, type OxCommon } from 'lib';\n\ninterface OxClient extends OxCommon {}\n\nexport const Ox = OxCore as OxClient;\n\nexport * from './player';\n"
  },
  {
    "path": "lib/client/init.lua",
    "content": "require 'lib.client.player'\n"
  },
  {
    "path": "lib/client/player.lua",
    "content": "---@diagnostic disable: redundant-parameter\n---@class OxPlayerClient : OxClass\nlocal OxPlayer = lib.class('OxPlayer')\n\n-- Support for `player.method` rather than self (:) syntax\nfunction OxPlayer:__index(index)\n    local value = OxPlayer[index] --[[@as any]]\n\n    if type(value) == 'function' then\n        self[index] = value == OxPlayer.__call and function(...)\n            return value(self, index, ...)\n        end or function(...)\n            return value(self, ...)\n        end\n\n        return self[index]\n    end\n\n    return value\nend\n\nfunction OxPlayer:constructor()\n    pcall(function()\n        local data = exports.ox_core.GetPlayer()\n\n        self.userId = data.userId\n        self.charId = data.charId\n        self.stateId = data.stateId\n    end)\n\n    self.state = LocalPlayer.state\nend\n\nfunction OxPlayer:__call(...)\n    return exports.ox_core:CallPlayer(...)\nend\n\nfunction OxPlayer:__tostring()\n    return string.format('{\\n  \"userId\": %s\\n  \"charId\": %s\\n  \"stateId\": %s\\n}',\n        self.userId, self.charId, self.stateId)\nend\n\nlocal getters = {}\n\nfunction OxPlayer:on(key, callback)\n    self.get(key)\n\n    AddEventHandler(('ox:player:%s'):format(key), function(data)\n        if GetInvokingResource() == 'ox_core' and source == '' then\n            callback(data)\n        end\n    end)\nend\n\nfunction OxPlayer:get(key)\n    if not self.charId then return end\n\n    if not getters[key] then\n        getters[key] = true\n\n        self.on(key, function(data) self[key] = data end)\n        self[key] = OxPlayer:__call('get', key);\n    end\n\n    return self[key]\nend\n\nfunction OxPlayer:getCoords()\n    return GetEntityCoords(cache.ped);\nend\n\nfunction OxPlayer:getGroup(filter)\n    local result = OxPlayer:__call('getGroup', filter)\n\n    if type(result) == 'table' then\n        return table.unpack(result)\n    end\n\n    return result\nend\n\nfunction OxPlayer:getGroupByType(type)\n    local result = OxPlayer:__call('getGroupByType', type)\n\n    if result then\n        return table.unpack(result)\n    end\nend\n\n---@class OxClient\nlocal Ox = Ox\n\nlocal player = OxPlayer:new()\n\nfunction Ox.GetPlayer()\n    return player\nend\n\nlocal function getMethods()\n    for method in pairs(exports.ox_core:GetPlayerCalls()) do\n        if not rawget(OxPlayer, method) then OxPlayer[method] = OxPlayer.__call end\n    end\nend\n\n-- Prevent errors if resource starts before ox_core (generally during development)\nif not pcall(getMethods) then CreateThread(getMethods) end\n\nAddEventHandler('ox:playerLoaded', function(data)\n    if player.charId then return end\n\n    for k, v in pairs(data) do player[k] = v end\nend)\n\nAddEventHandler('ox:playerLogout', function()\n    table.wipe(player)\nend)\n"
  },
  {
    "path": "lib/client/player.ts",
    "content": "import { cache } from \"@overextended/ox_lib/client\";\nimport type { OxPlayer } from \"client/player\";\nimport type { Dict } from \"types\";\n\nclass PlayerInterface {\n  public userId: number;\n  public charId?: number;\n  public stateId?: string;\n  [key: string]: any;\n\n  constructor() {\n    try {\n      const { userId, charId, stateId } = exports.ox_core.GetPlayer();\n      this.userId = userId;\n      this.charId = charId;\n      this.stateId = stateId;\n    } catch (e) {}\n\n    this.state = LocalPlayer.state;\n\n    this.constructor.prototype.toString = () => {\n      return JSON.stringify(this, null, 2);\n    };\n\n    const getMethods = async () => {\n      Object.keys(exports.ox_core.GetPlayerCalls()).forEach((method: string) => {\n        if (!this.constructor.prototype[method])\n          this.constructor.prototype[method] = (...args: any[]) => exports.ox_core.CallPlayer(method, ...args);\n      });\n    };\n\n    // Prevent errors if resource starts before ox_core (generally during development)\n    getMethods().catch(() => setImmediate(getMethods));\n  }\n\n  /**\n   * Registers an event handler which will be triggered when the specified player data is updated.\n   */\n  on(key: string, callback: (data: unknown) => void) {\n    this.get(key);\n\n    on(`ox:player:${key}`, (data: unknown) => {\n      if (GetInvokingResource() == \"ox_core\" && (source as any) === \"\") callback(data);\n    });\n  }\n\n  /**\n   * Returns player data for the specified key. The data is cached and kept updated for future calls.\n   */\n  get(key: string) {\n    if (!this.charId) return;\n\n    if (!(key in this)) {\n      this[key] = exports.ox_core.CallPlayer(\"get\", key) ?? null;\n      this.on(key, (data: unknown) => (this[key] = data));\n    }\n\n    return this[key];\n  }\n\n  getCoords() {\n    return GetEntityCoords(cache.ped);\n  }\n}\n\nexport type OxPlayer = typeof OxPlayer & PlayerInterface;\n\nconst player = new PlayerInterface() as OxPlayer;\n\nexport function GetPlayer() {\n  return player;\n}\n\non(\"ox:playerLoaded\", (data: Dict<any>) => {\n  if (player.charId) return;\n\n  for (const key in data) player[key] = data[key];\n});\n\non(\"ox:playerLogout\", () => {\n  for (const key in player) delete player[key];\n});\n"
  },
  {
    "path": "lib/index.ts",
    "content": "import type { GetTopVehicleStats, GetVehicleData, GetVehicleNetworkType } from 'common/vehicles';\nimport type { OxGroup } from 'types';\n\nexport type * from 'types';\n\nexport interface OxCommon {\n  [key: string]: (...args: any[]) => any;\n  GetTopVehicleStats: typeof GetTopVehicleStats;\n  GetVehicleData: typeof GetVehicleData;\n  GetVehicleNetworkType: typeof GetVehicleNetworkType;\n}\n\nexport const Ox = exports.ox_core as OxCommon;\n\nexport function GetGroup(name: string): OxGroup {\n  return GlobalState[`group.${name}`];\n}\n"
  },
  {
    "path": "lib/init.lua",
    "content": "if Ox then return Ox end\n\nif not lib then\n    if GetResourceState('ox_lib') ~= 'started' then\n        error('ox_lib must be started before this resource.', 0)\n    end\n\n    local chunk = LoadResourceFile('ox_lib', 'init.lua')\n\n    if not chunk then\n        error('failed to load resource file @ox_lib/init.lua', 0)\n    end\n\n    load(chunk, '@@ox_lib/init.lua', 't')()\nend\n\n---@type OxCommon\nOx = setmetatable({}, {\n    __index = function(self, index)\n        self[index] = function(...)\n            return exports.ox_core[index](nil, ...)\n        end\n\n        return self[index]\n    end\n})\n\nrequire(('@ox_core.lib.%s.init'):format(lib.context))\n\nfunction Ox.GetGroup(name)\n    return GlobalState['group.' .. name]\nend\n\nreturn Ox\n"
  },
  {
    "path": "lib/server/account.lua",
    "content": "---@diagnostic disable: redundant-parameter\n---@class OxAccountServer : OxClass\nlocal OxAccount = lib.class('OxAccount')\n\nfunction OxAccount:__index(index)\n    local value = OxAccount[index] --[[@as any]]\n\n    if type(value) == 'function' then\n        self[index] = value == OxAccount.__call and function(...)\n            return value(self, index, ...)\n        end or function(...)\n            return value(self, ...)\n        end\n\n        return self[index]\n    end\n\n    return value\nend\n\nfunction OxAccount:constructor(data)\n    for k, v in pairs(data) do\n        self[k] = v\n    end\nend\n\nfunction OxAccount:__call(...)\n    return exports.ox_core:CallAccount(self.accountId, ...)\nend\n\nfunction OxAccount:__tostring()\n    return json.encode(self, { indent = true })\nend\n\nfor method in pairs(exports.ox_core:GetAccountCalls() or {}) do\n    if not rawget(OxAccount, method) then OxAccount[method] = OxAccount.__call end\nend\n\nlocal function CreateAccountInstance(account)\n    if not account then return end\n\n    return OxAccount:new(account)\nend\n\n---@class OxServer\nlocal Ox = Ox\n\nfunction Ox.GetAccount(accountId)\n    local account = exports.ox_core:GetAccount(accountId)\n    return CreateAccountInstance(account)\nend\n\nfunction Ox.GetCharacterAccount(charId)\n    local account = exports.ox_core:GetCharacterAccount(charId)\n    return CreateAccountInstance(account)\nend\n\nfunction Ox.GetGroupAccount(groupName)\n    local account = exports.ox_core:GetGroupAccount(groupName)\n    return CreateAccountInstance(account)\nend\n\nfunction Ox.CreateAccount(owner, label)\n    local account = exports.ox_core:CreateAccount(owner, label)\n    return CreateAccountInstance(account)\nend\n"
  },
  {
    "path": "lib/server/account.ts",
    "content": "import type { OxAccount as _OxAccount } from 'server/accounts/class';\n\nclass AccountInterface {\n  constructor(public accountId: number) {}\n}\n\nObject.keys(exports.ox_core.GetAccountCalls()).forEach((method: string) => {\n  (AccountInterface.prototype as any)[method] = function (...args: any[]) {\n    return exports.ox_core.CallAccount(this.accountId, method, ...args);\n  };\n});\n\nAccountInterface.prototype.toString = function () {\n  return JSON.stringify(this, null, 2);\n};\n\nexport type OxAccount = _OxAccount & AccountInterface;\n\nfunction CreateAccountInstance(account?: _OxAccount) {\n  if (!account) return;\n\n  return new AccountInterface(account.accountId) as OxAccount;\n}\n\nexport async function GetAccount(accountId: number) {\n  const account = await exports.ox_core.GetAccount(accountId);\n  return CreateAccountInstance(account);\n}\n\nexport async function GetCharacterAccount(charId: number | string) {\n  const account = await exports.ox_core.GetCharacterAccount(charId);\n  return CreateAccountInstance(account);\n}\n\nexport async function GetGroupAccount(groupName: string) {\n  const account = await exports.ox_core.GetGroupAccount(groupName);\n  return CreateAccountInstance(account);\n}\n\nexport async function CreateAccount(owner: number | string, label: string) {\n  const account = await exports.ox_core.CreateAccount(owner, label);\n  return CreateAccountInstance(account);\n}\n"
  },
  {
    "path": "lib/server/index.ts",
    "content": "import type { OxVehicle } from 'server/vehicle/class';\nimport type { PayAccountInvoice, DeleteAccountInvoice } from 'server/accounts';\nimport type { OxPlayer } from 'server/player/class';\nimport type { BanUser, GetCharIdFromStateId, GetLicense, GetLicenses, UnbanUser } from 'server/player/db';\nimport type {\n  CreateGroup,\n  DeleteGroup,\n  GetGroupsByType,\n  RemoveGroupPermission,\n  SetGroupPermission,\n} from 'server/groups';\nimport { Ox as OxCore, type OxCommon } from 'lib';\n\ninterface OxServer extends OxCommon {\n  SaveAllPlayers: typeof OxPlayer.saveAll;\n  SaveAllVehicles: typeof OxVehicle.saveAll;\n  GetCharIdFromStateId: typeof GetCharIdFromStateId;\n  GenerateVehicleVin: (model: string) => Promise<string>;\n  GenerateVehiclePlate: typeof OxVehicle.generatePlate;\n  SetGroupPermission: typeof SetGroupPermission;\n  RemoveGroupPermission: typeof RemoveGroupPermission;\n  PayAccountInvoice: typeof PayAccountInvoice;\n  DeleteAccountInvoice: typeof DeleteAccountInvoice;\n  GetGroupsByType: typeof GetGroupsByType;\n  CreateGroup: typeof CreateGroup;\n  DeleteGroup: typeof DeleteGroup;\n  GetLicenses: typeof GetLicenses;\n  GetLicense: typeof GetLicense;\n  BanUser: typeof BanUser;\n  UnbanUser: typeof UnbanUser;\n}\n\nexport const Ox = OxCore as OxServer;\n\nexport * from './player';\nexport * from './vehicle';\nexport * from './account';\n"
  },
  {
    "path": "lib/server/init.lua",
    "content": "require 'lib.server.player'\nrequire 'lib.server.vehicle'\nrequire 'lib.server.account'\n"
  },
  {
    "path": "lib/server/player.lua",
    "content": "---@diagnostic disable: redundant-parameter\n---@class OxPlayerServer : OxClass\nlocal OxPlayer = lib.class('OxPlayer')\n\nfunction OxPlayer:__index(index)\n    local value = OxPlayer[index] --[[@as any]]\n\n    if type(value) == 'function' then\n        self[index] = value == OxPlayer.__call and function(...)\n            return value(self, index, ...)\n        end or function(...)\n            return value(self, ...)\n        end\n\n        return self[index]\n    end\n\n    return value\nend\n\nfunction OxPlayer:constructor(data)\n    for k, v in pairs(data) do\n        self[k] = v\n    end\nend\n\nfunction OxPlayer:__call(...)\n    return exports.ox_core:CallPlayer(self.source, ...)\nend\n\nfunction OxPlayer:__tostring()\n    return string.format('{\\n  \"source\": %s\\n  \"userId\": %s\\n  \"identifier\": %s\\n  \"username\": %s\\n}', self.source,\n        self.userId, self.identifier, self.username)\nend\n\nfunction OxPlayer:getCoords()\n    return GetEntityCoords(self.ped);\nend\n\nfunction OxPlayer:getState()\n    return Player(self.source).state;\nend\n\nfunction OxPlayer:getGroup(filter)\n    local result = OxPlayer.__call(self, 'getGroup', filter)\n\n    if type(result) == 'table' then\n        return table.unpack(result)\n    end\n\n    return result\nend\n\nfunction OxPlayer:getAccount()\n    return self.charId and Ox.GetCharacterAccount(self.charId) or nil\nend\n\nfunction OxPlayer:getGroupByType(type)\n    local result = OxPlayer.__call(self, 'getGroupByType', type)\n\n    if result then\n        return table.unpack(result)\n    end\nend\n\nfor method in pairs(exports.ox_core:GetPlayerCalls() or {}) do\n    if not rawget(OxPlayer, method) then OxPlayer[method] = OxPlayer.__call end\nend\n\nlocal function CreatePlayerInstance(player)\n    if not player then return end;\n\n    return OxPlayer:new(player)\nend\n\n---@class OxServer\nlocal Ox = Ox\n\nfunction Ox.GetPlayer(playerId)\n    return CreatePlayerInstance(exports.ox_core:GetPlayer(playerId))\nend\n\nfunction Ox.GetPlayerFromUserId(userId)\n    return CreatePlayerInstance(exports.ox_core:GetPlayerFromUserId(userId))\nend\n\nfunction Ox.GetPlayerFromCharId(charId)\n    return CreatePlayerInstance(exports.ox_core:GetPlayerFromCharId(charId))\nend\n\nfunction Ox.GetPlayers(filter)\n    local players = exports.ox_core:GetPlayers(filter)\n\n    for i = 1, #players do\n        players[i] = CreatePlayerInstance(players[i])\n    end\n\n    return players\nend\n\nfunction Ox.GetPlayerFromFilter(filter)\n    return CreatePlayerInstance(exports.ox_core:GetPlayerFromFilter(filter))\nend\n"
  },
  {
    "path": "lib/server/player.ts",
    "content": "import type { OxPlayer as _OxPlayer } from 'server/player/class';\nimport type { Dict } from 'types';\nimport { GetCharacterAccount } from './account';\n\nclass PlayerInterface {\n  public state: StateBagInterface;\n\n  constructor(\n    public source: number,\n    public userId: number,\n    public charId: number | undefined,\n    public stateId: string | undefined,\n    public username: string,\n    public identifier: string,\n    public ped: number,\n  ) {\n    this.source = source;\n    this.userId = userId;\n    this.charId = charId;\n    this.stateId = stateId;\n    this.username = username;\n    this.identifier = identifier;\n    this.ped = ped;\n  }\n\n  getCoords() {\n    return GetEntityCoords(this.ped);\n  }\n\n  getState() {\n    return Player(source).state;\n  }\n\n  async getAccount() {\n    return this.charId ? GetCharacterAccount(this.charId) : null;\n  }\n}\n\nObject.keys(exports.ox_core.GetPlayerCalls()).forEach((method: string) => {\n  (PlayerInterface.prototype as any)[method] = function (...args: any[]) {\n    return exports.ox_core.CallPlayer(this.source, method, ...args);\n  };\n});\n\nPlayerInterface.prototype.toString = function () {\n  return JSON.stringify(this, null, 2);\n};\n\nexport type OxPlayer = _OxPlayer & PlayerInterface;\n\nfunction CreatePlayerInstance(player?: _OxPlayer) {\n  if (!player) return;\n\n  return new PlayerInterface(\n    player.source as number,\n    player.userId,\n    player.charId,\n    player.stateId,\n    player.username,\n    player.identifier,\n    player.ped,\n  ) as OxPlayer;\n}\n\nexport function GetPlayer(playerId: string | number) {\n  return CreatePlayerInstance(exports.ox_core.GetPlayer(playerId));\n}\n\nexport function GetPlayerFromUserId(userId: number) {\n  return CreatePlayerInstance(exports.ox_core.GetPlayerFromUserId(userId));\n}\n\nexport function GetPlayerFromCharId(charId: number) {\n  return CreatePlayerInstance(exports.ox_core.GetPlayerFromCharId(charId));\n}\n\nexport function GetPlayers(filter?: Dict<any>): OxPlayer[] {\n  const players = exports.ox_core.GetPlayers(filter);\n\n  for (const id in players) players[id] = CreatePlayerInstance(players[id]);\n\n  return players;\n}\n\nexport function GetPlayerFromFilter(filter: Dict<any>) {\n  return CreatePlayerInstance(exports.ox_core.GetPlayerFromFilter(filter));\n}\n"
  },
  {
    "path": "lib/server/vehicle.lua",
    "content": "---@diagnostic disable: redundant-parameter\n---@class OxVehicleServer : OxClass\nlocal OxVehicle = lib.class('OxVehicle')\n\nfunction OxVehicle:__index(index)\n    local value = OxVehicle[index] --[[@as any]]\n\n    if type(value) == 'function' then\n        self[index] = value == OxVehicle.__call and function(...)\n            return value(self, index, ...)\n        end or function(...)\n            return value(self, ...)\n        end\n\n        return self[index]\n    end\n\n    return value\nend\n\nfunction OxVehicle:constructor(data)\n    for k, v in pairs(data) do\n        self[k] = v\n    end\nend\n\nfunction OxVehicle:__call(...)\n    return exports.ox_core:CallVehicle(self.vin, ...)\nend\n\nfunction OxVehicle:__tostring()\n    return json.encode(self, { indent = true})\nend\n\nfunction OxVehicle:getCoords()\n    return GetEntityCoords(self.entity);\nend\n\nfunction OxVehicle:getState()\n    return Entity(self.entity).state;\nend\n\nfor method in pairs(exports.ox_core:GetVehicleCalls() or {}) do\n    if not rawget(OxVehicle, method) then OxVehicle[method] = OxVehicle.__call end\nend\n\nlocal function CreateVehicleInstance(vehicle)\n    if not vehicle then return end;\n\n    return OxVehicle:new(vehicle)\nend\n\n---@class OxServer\nlocal Ox = Ox\n\nfunction Ox.GetVehicle(handle)\n    return type(handle) == 'string' and Ox.GetVehicleFromVin(handle) or Ox.GetVehicleFromEntity(handle)\nend\n\nfunction Ox.GetVehicleFromEntity(entityId)\n    return CreateVehicleInstance(exports.ox_core:GetVehicleFromEntity(entityId))\nend\n\nfunction Ox.GetVehicleFromNetId(netId)\n    return CreateVehicleInstance(exports.ox_core:GetVehicleFromNetId(netId))\nend\n\nfunction Ox.GetVehicleFromVin(vin)\n    return CreateVehicleInstance(exports.ox_core:GetVehicleFromVin(vin))\nend\n\nfunction Ox.GetVehicles(filter)\n    local vehicles = exports.ox_core:GetVehicles(filter)\n\n    for i = 1, #vehicles do\n        vehicles[i] = CreateVehicleInstance(vehicles[i])\n    end\n\n    return vehicles\nend\n\nfunction Ox.GetVehicleFromFilter(filter)\n    return CreateVehicleInstance(exports.ox_core:GetVehicleFromFilter(filter))\nend\n\nfunction Ox.CreateVehicle(data, coords, heading)\n    return CreateVehicleInstance(exports.ox_core:CreateVehicle(data, coords, heading));\nend\n\nfunction Ox.SpawnVehicle(dbId, coords, heading)\n    return CreateVehicleInstance(exports.ox_core:SpawnVehicle(dbId, coords, heading));\nend\n"
  },
  {
    "path": "lib/server/vehicle.ts",
    "content": "import type { OxVehicle as _OxVehicle } from 'server/vehicle/class';\nimport type { CreateVehicleData } from 'server/vehicle';\nimport type { VehicleRow } from 'server/vehicle/db';\nimport { Dict } from 'types';\n\nclass VehicleInterface {\n  constructor(\n    public entity: number | undefined,\n    public netId: number | undefined,\n    public script: string,\n    public plate: string,\n    public model: string,\n    public make: string,\n    public id?: number,\n    public vin?: string,\n    public owner?: number,\n    public group?: string,\n  ) {\n    this.entity = entity;\n    this.netId = netId;\n    this.script = script;\n    this.plate = plate;\n    this.model = model;\n    this.make = make;\n    this.id = id;\n    this.vin = vin;\n    this.owner = owner;\n    this.group = group;\n  }\n\n  getCoords() {\n    return this.entity ? GetEntityCoords(this.entity) : null;\n  }\n\n  getState() {\n    return this.entity ? Entity(this.entity).state : null;\n  }\n}\n\nObject.keys(exports.ox_core.GetVehicleCalls()).forEach((method: string) => {\n  (VehicleInterface.prototype as any)[method] = function (...args: any[]) {\n    return exports.ox_core.CallVehicle(this.vin, method, ...args);\n  };\n});\n\nVehicleInterface.prototype.toString = function () {\n  return JSON.stringify(this, null, 2);\n};\n\nexport type OxVehicle = _OxVehicle & VehicleInterface;\n\nfunction CreateVehicleInstance(vehicle: _OxVehicle) {\n  if (!vehicle) return;\n\n  return new VehicleInterface(\n    vehicle.entity,\n    vehicle.netId,\n    vehicle.script,\n    vehicle.plate,\n    vehicle.model,\n    vehicle.make,\n    vehicle.id,\n    vehicle.vin,\n    vehicle.owner,\n    vehicle.group,\n  ) as OxVehicle;\n}\n\nexport function GetVehicle(entityId: number): OxVehicle;\nexport function GetVehicle(vin: string): OxVehicle;\nexport function GetVehicle(handle: number | string) {\n  return typeof handle === 'string' ? GetVehicleFromVin(handle) : GetVehicleFromEntity(handle);\n}\n\nexport function GetVehicleFromEntity(entityId: number) {\n  return CreateVehicleInstance(exports.ox_core.GetVehicleFromEntity(entityId));\n}\n\nexport function GetVehicleFromNetId(netId: number) {\n  return CreateVehicleInstance(exports.ox_core.GetVehicleFromNetId(netId));\n}\n\nexport function GetVehicleFromVin(vin: string) {\n  return CreateVehicleInstance(exports.ox_core.GetVehicleFromVin(vin));\n}\n\nexport function GetVehicles(filter?: Dict<any>): OxVehicle[] {\n  const vehicles = exports.ox_core.GetVehicles(filter);\n\n  for (const id in vehicles) vehicles[id] = CreateVehicleInstance(vehicles[id]);\n\n  return vehicles;\n}\n\nexport function GetVehicleFromFilter(filter: Dict<any>) {\n  return CreateVehicleInstance(exports.ox_core.GetVehicleFromFilter(filter));\n}\n\nexport async function CreateVehicle(\n  data: string | (CreateVehicleData & Partial<VehicleRow>),\n  coords?: number | number[] | { x: number; y: number; z: number },\n  heading?: number,\n) {\n  return CreateVehicleInstance(await exports.ox_core.CreateVehicle(data, coords, heading));\n}\n\nexport async function SpawnVehicle(\n  dbId: number,\n  coords: number | number[] | { x: number; y: number; z: number },\n  heading?: number,\n) {\n  return CreateVehicleInstance(await exports.ox_core.SpawnVehicle(dbId, coords, heading));\n}\n"
  },
  {
    "path": "lib/tsconfig.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"emitDeclarationOnly\": false,\n    \"composite\": true\n  },\n  \"include\": [\"./\", \"../types/\"],\n  \"references\": [{ \"path\": \"../client\" }, { \"path\": \"../server\" }]\n}\n"
  },
  {
    "path": "locales/ar.json",
    "content": "{\n  \"create_character\": \"إنشاء شخصية جديدة\",\n  \"firstname\": \"الاسم الأول\",\n  \"lastname\": \"اسم العائلة\",\n  \"gender\": \"الجنس\",\n  \"male\": \"ذكر\",\n  \"female\": \"أنثى\",\n  \"non_binary\": \"غير ثنائي\",\n  \"date_of_birth\": \"تاريخ الميلاد\",\n  \"withdraw\": \"سحب\",\n  \"deposit\": \"إيداع\",\n  \"transfer\": \"تحويل بنكي\",\n  \"invoice_payment\": \"دفع الفاتورة\",\n  \"hours\": \"ساعات\",\n  \"minutes\": \"دقائق\",\n  \"seconds\": \"ثوانٍ\",\n  \"ban_indefinite\": \"هذا الحظر ليس له مدة انتهاء.\",\n  \"ban_expires_in\": \"ينتهي الحظر خلال %s ${hours}، %s ${minutes}، و %s ${seconds}.\",\n  \"ban_notice\": \"⚠️ لقد تم حظرك من هذا الخادم! ⚠️\\nتاريخ الحظر: %s\\nالسبب: %s\\n\\n%s\",\n  \"userid_is_active\": \"معرّف المستخدم الخاص بك (%s) نشط بالفعل.\",\n  \"no_license\": \"تعذر علينا التحقق من رخصة لعبتك.\",\n  \"server_restarting\": \"الخادم على وشك إعادة التشغيل. لا يمكنك الانضمام في الوقت الحالي.\"\n}\n"
  },
  {
    "path": "locales/bg.json",
    "content": "{\n  \"create_character\": \"Създай нов герой\",\n  \"firstname\": \"Име\",\n  \"lastname\": \"Фамилия\",\n  \"gender\": \"Пол\",\n  \"male\": \"Мъж\",\n  \"female\": \"Жена\",\n  \"non_binary\": \"Небинарен\",\n  \"date_of_birth\": \"Дата на раждане\",\n  \"withdraw\": \"Теглене\",\n  \"deposit\": \"Депозит\",\n  \"transfer\": \"Банков превод\",\n  \"invoice_payment\": \"Плащане на фактура\"\n}\n"
  },
  {
    "path": "locales/cs.json",
    "content": "{\n  \"create_character\": \"Vytvořit novou postavu\",\n  \"firstname\": \"Jméno\",\n  \"lastname\": \"Příjmení\",\n  \"gender\": \"Pohlaví\",\n  \"male\": \"Muž\",\n  \"female\": \"Žena\",\n  \"non_binary\": \"Nebinární\",\n  \"date_of_birth\": \"Datum narození\",\n  \"withdraw\": \"Výběr\",\n  \"deposit\": \"Vklad\",\n  \"transfer\": \"Bankovní převod\",\n  \"invoice_payment\": \"Úhrada faktury\"\n}\n"
  },
  {
    "path": "locales/da.json",
    "content": "{\n  \"create_character\": \"Opret en ny karakter\",\n  \"firstname\": \"Fornavn\",\n  \"lastname\": \"Efternavn\",\n  \"gender\": \"Køn\",\n  \"male\": \"Mand\",\n  \"female\": \"Kvinde\",\n  \"non_binary\": \"Ikke-binær\",\n  \"date_of_birth\": \"Fødselsdato\",\n  \"withdraw\": \"Hæv\",\n  \"deposit\": \"Indsæt\",\n  \"transfer\": \"Bankoverførsel\",\n  \"invoice_payment\": \"Fakturabetaling\"\n}\n"
  },
  {
    "path": "locales/de.json",
    "content": "{\n  \"create_character\": \"Einen neuen Charakter erstellen\",\n  \"firstname\": \"Vorname\",\n  \"lastname\": \"Nachname\",\n  \"gender\": \"Geschlecht\",\n  \"male\": \"Männlich\",\n  \"female\": \"Weiblich\",\n  \"non_binary\": \"Nicht-binär\",\n  \"date_of_birth\": \"Geburtsdatum\",\n  \"withdraw\": \"Abheben\",\n  \"deposit\": \"Einzahlen\",\n  \"transfer\": \"Banküberweisung\",\n  \"invoice_payment\": \"Rechnungszahlung\",\n  \"hours\": \"Stunden\",\n  \"minutes\": \"Minuten\",\n  \"seconds\": \"Sekunden\",\n  \"ban_indefinite\": \"Dieses Verbot läuft nicht ab.\",\n  \"ban_expires_in\": \"Das Verbot läuft in %s ${hours}, %s ${minutes} und %s ${seconds} ab.\",\n  \"ban_notice\": \"⚠️ Du wurdest von diesem Server gebannt! ⚠️\\nVerbot erteilt: %s\\nGrund: %s\\n\\n%s\",\n  \"userid_is_active\": \"Deine Benutzer-ID (%s) ist bereits aktiv.\",\n  \"no_license\": \"Wir konnten deine Spiel-Lizenz nicht verifizieren.\",\n  \"server_restarting\": \"Der Server wird neu gestartet. Du kannst dich derzeit nicht verbinden.\"\n}\n"
  },
  {
    "path": "locales/en.json",
    "content": "{\n  \"create_character\": \"Create a new character\",\n  \"firstname\": \"First name\",\n  \"lastname\": \"Last name\",\n  \"gender\": \"Gender\",\n  \"male\": \"Male\",\n  \"female\": \"Female\",\n  \"non_binary\": \"Non-Binary\",\n  \"date_of_birth\": \"Date of birth\",\n  \"withdraw\": \"Withdraw\",\n  \"deposit\": \"Deposit\",\n  \"transfer\": \"Bank transfer\",\n  \"invoice_payment\": \"Invoice payment\",\n  \"hours\": \"hours\",\n  \"minutes\": \"minutes\",\n  \"seconds\": \"seconds\",\n  \"ban_indefinite\": \"This ban will not expire.\",\n  \"ban_expires_in\": \"Ban expires in %s ${hours}, %s ${minutes}, and %s ${seconds}.\",\n  \"ban_notice\": \"⚠️ You have been banned from this server! ⚠️\\nBan issued: %s\\nReason: %s\\n\\n%s\",\n  \"userid_is_active\": \"Your userId (%s), is already active.\",\n  \"no_license\": \"We were unable to verify your game license.\",\n  \"server_restarting\": \"The server is about to restart. You cannot join at this time.\"\n}\n"
  },
  {
    "path": "locales/es.json",
    "content": "{\n  \"create_character\": \"Crear un nuevo personaje\",\n  \"firstname\": \"Nombre\",\n  \"lastname\": \"Apellido\",\n  \"gender\": \"Género\",\n  \"male\": \"Hombre\",\n  \"female\": \"Mujer\",\n  \"non_binary\": \"No binario\",\n  \"date_of_birth\": \"Fecha de nacimiento\",\n  \"withdraw\": \"Retirar\",\n  \"deposit\": \"Depositar\",\n  \"transfer\": \"Transferencia bancaria\",\n  \"invoice_payment\": \"Pago de factura\",\n  \"hours\": \"horas\",\n  \"minutes\": \"minutos\",\n  \"seconds\": \"segundos\",\n  \"ban_indefinite\": \"Este baneo es indefinido.\",\n  \"ban_expires_in\": \"El baneo expira en %s ${hours}, %s ${minutes}, y %s ${seconds}.\",\n  \"ban_notice\": \"⚠️ Has sido baneado de este servidor! ⚠️\\nBaneado el: %s\\nRazón: %s\\n\\n%s\",\n  \"userid_is_active\": \"Tu userId (%s), ya está activo.\",\n  \"no_license\": \"No pudimos verificar tu licencia de juego.\",\n  \"server_restarting\": \"El servidor está a punto de reiniciar. No puedes unirte en estos momentos.\"\n}\n"
  },
  {
    "path": "locales/et.json",
    "content": "{\n  \"create_character\": \"Loo uus karakter\",\n  \"firstname\": \"Eesnimi\",\n  \"lastname\": \"Perekonnanimi\",\n  \"gender\": \"Sugu\",\n  \"male\": \"Mees\",\n  \"female\": \"Naine\",\n  \"non_binary\": \"Mittebinaarne\",\n  \"date_of_birth\": \"Sünnikuupäev\",\n  \"withdraw\": \"Väljamakse\",\n  \"deposit\": \"Sissemakse\",\n  \"transfer\": \"Pangaülekanne\",\n  \"invoice_payment\": \"Arve tasumine\"\n}\n"
  },
  {
    "path": "locales/fr.json",
    "content": "{\n  \"create_character\": \"Créer un personnage\",\n  \"firstname\": \"Prénom\",\n  \"lastname\": \"Nom\",\n  \"gender\": \"Sexe\",\n  \"male\": \"Homme\",\n  \"female\": \"Femme\",\n  \"non_binary\": \"Non-Binaire\",\n  \"date_of_birth\": \"Date de naissance\",\n  \"withdraw\": \"Retrait\",\n  \"deposit\": \"Dépôt\",\n  \"transfer\": \"Virement\",\n  \"invoice_payment\": \"Facture\",\n  \"hours\": \"heures\",\n  \"minutes\": \"minutes\",\n  \"seconds\": \"secondes\",\n  \"ban_indefinite\": \"Ce ban n'expirera pas.\",\n  \"ban_expires_in\": \"Ce ban expire dans %s ${hours}, %s ${minutes}, et %s ${seconds}.\",\n  \"ban_notice\": \"⚠️ Vous avez été banni de ce serveur ! ⚠️\\nBanni le : %s\\nRaison : %s\\n\\n%s\",\n  \"userid_is_active\": \"Votre userId (%s), est déjà actif.\",\n  \"no_license\": \"Nous n'avons pas pu vérifier votre licence de jeu.\",\n  \"server_restarting\": \"Le serveur est en train de redémarrer. Vous ne pouvez pas vous connecter pour le moment.\"\n}"
  },
  {
    "path": "locales/hu.json",
    "content": "{\n    \"create_character\": \"Új karakter létrehozása\",\n    \"firstname\": \"Keresztnév\",\n    \"lastname\": \"Vezetéknév\",\n    \"gender\": \"Neme\",\n    \"male\": \"Férfi\",\n    \"female\": \"Nő\",\n    \"non_binary\": \"Nem-bináris\",\n    \"date_of_birth\": \"Születési dátum\",\n    \"withdraw\": \"Felvevés\",\n    \"deposit\": \"Befizetés\",\n    \"transfer\": \"Banki átutalás\",\n    \"invoice_payment\": \"Számla kifizetése\",\n    \"hours\": \"Óra\",\n    \"minutes\": \"Perc\",\n    \"seconds\": \"Másodperc\",\n    \"ban_indefinite\": \"Ez a kitiltás nem fog lejárni.\",\n    \"ban_expires_in\": \"A tiltás le fog járni %s ${hours}, %s ${minutes}, és %s ${seconds} múlva.\",\n    \"ban_notice\": \"⚠️ Ki lettél tiltva erről a szerverről! ⚠️\\nEkkor: %s\\nIndok: %s\\n\\n%s\",\n    \"userid_is_active\": \"A te userId-d (%s), éppen használatban van.\",\n    \"no_license\": \"Nem bírtuk ellenőrizni a játék liszenszedet.\",\n    \"server_restarting\": \"A szerver mindjárt újra indul. Ezalatt az idő alatt nem lehet csatlakozni.\"\n  }\n  "
  },
  {
    "path": "locales/it.json",
    "content": "{\n    \"create_character\": \"Crea un nuovo personaggio\",\n    \"firstname\": \"Nome\",\n    \"lastname\": \"Cognome\",\n    \"gender\": \"Genere\",\n    \"male\": \"Maschio\",\n    \"female\": \"Femmina\",\n    \"non_binary\": \"Non-Binario\",\n    \"date_of_birth\": \"Data di nascita\",\n    \"withdraw\": \"Preleva\",\n    \"deposit\": \"Deposita\",\n    \"transfer\": \"Bonifico bancario\",\n    \"invoice_payment\": \"Pagamento fattura\"\n}\n"
  },
  {
    "path": "locales/jp.json",
    "content": "{\n  \"create_character\": \"新しいキャラクターを作成\",\n  \"firstname\": \"名前\",\n  \"lastname\": \"苗字\",\n  \"gender\": \"性別\",\n  \"male\": \"男性\",\n  \"female\": \"女性\",\n  \"non_binary\": \"ノンバイナリー\",\n  \"date_of_birth\": \"生年月日\",\n  \"withdraw\": \"引き出し\",\n  \"deposit\": \"預金\",\n  \"transfer\": \"銀行振込\",\n  \"invoice_payment\": \"請求書の支払い\"\n}\n"
  },
  {
    "path": "locales/lt.json",
    "content": "{\n  \"create_character\": \"Sukurti naują veikėją\",\n  \"firstname\": \"Vardas\",\n  \"lastname\": \"Pavardė\",\n  \"gender\": \"Lytis\",\n  \"male\": \"Vyras\",\n  \"female\": \"Moteris\",\n  \"non_binary\": \"Nebinarinis lytiškumas\",\n  \"date_of_birth\": \"Gimimo data\",\n  \"withdraw\": \"Išėmimas\",\n  \"deposit\": \"Įmokėjimas\",\n  \"transfer\": \"Banko pervedimas\",\n  \"invoice_payment\": \"Sąskaitos apmokėjimas\",\n  \"hours\": \"valandos\",\n  \"minutes\": \"minutes\",\n  \"seconds\": \"sekundes\",\n  \"ban_indefinite\": \"Šis užblokavimas niekada nesibaigs.\",\n  \"ban_expires_in\": \"Užblokavimas baigsis už %s ${hours}, %s ${minutes}, ir %s ${seconds}.\",\n  \"ban_notice\": \"⚠️ Jūs buvote užblokuotas iš šito serverio! ⚠️\\nAtsakingas asmuo: %s\\nKodėl: %s\\n\\n%s\",\n  \"userid_is_active\": \"Jūsų userId (%s), yra jau aktyvus.\",\n  \"no_license\": \"Negalėjome patvirtinti jūsų žaidimo licenzijos.\",\n  \"server_restarting\": \"Serveris restartuojasi. Negalima dabar prisijungti.\"\n}\n"
  },
  {
    "path": "locales/nl.json",
    "content": "{\r\n  \"create_character\": \"Maak een nieuw karakter\",\r\n  \"firstname\": \"Voornaam\",\r\n  \"lastname\": \"Achternaam\",\r\n  \"gender\": \"Geslacht\",\r\n  \"male\": \"Man\",\r\n  \"female\": \"Vrouw\",\r\n  \"non_binary\": \"Non-binair\",\r\n  \"date_of_birth\": \"Geboortedatum\",\r\n  \"withdraw\": \"Opnemen\",\r\n  \"deposit\": \"Storten\",\r\n  \"transfer\": \"Overschrijving\",\r\n  \"invoice_payment\": \"Factuurbetaling\"\r\n}\r\n"
  },
  {
    "path": "locales/no.json",
    "content": "{\n  \"create_character\": \"Opprett ny karakter\",\n  \"firstname\": \"Fornavn\",\n  \"lastname\": \"Etternavn\",\n  \"gender\": \"Kjønn\",\n  \"male\": \"Mann\",\n  \"female\": \"Kvinne\",\n  \"non_binary\": \"Ikke-binær\",\n  \"date_of_birth\": \"Fødselsdato\",\n  \"withdraw\": \"Ta ut\",\n  \"deposit\": \"Sett inn\",\n  \"transfer\": \"Bankoverføring\",\n  \"invoice_payment\": \"Fakturabetaling\",\n  \"hours\": \"timer\",\n  \"minutes\": \"minutter\",\n  \"seconds\": \"sekunder\",\n  \"ban_indefinite\": \"Denne utestengelsen utløper ikke.\",\n  \"ban_expires_in\": \"Utestengelsen utløper om %s ${hours}, %s ${minutes} og %s ${seconds}.\",\n  \"ban_notice\": \"⚠️ Du er utestengt fra denne serveren! ⚠️\\nUtestengt: %s\\nÅrsak: %s\\n\\n%s\",\n  \"userid_is_active\": \"Din bruker (%s) er allerede aktiv.\",\n  \"no_license\": \"Vi kunne ikke verifisere spill-lisensen din.\",\n  \"server_restarting\": \"Serveren er i ferd med å starte på nytt. Du kan ikke koble til nå.\"\n}\n"
  },
  {
    "path": "locales/pl.json",
    "content": "{\n    \"create_character\": \"Stwórz nową postać\",\n    \"firstname\": \"Imię\",\n    \"lastname\": \"Nazwisko\",\n    \"gender\": \"Płeć\",\n    \"male\": \"Mężczyzna\",\n    \"female\": \"Kobieta\",\n    \"non_binary\": \"Niebinarny/a\",\n    \"date_of_birth\": \"Data urodzenia\",\n    \"withdraw\": \"Wypłać\",\n    \"deposit\": \"Wpłać\",\n    \"transfer\": \"Przelew Bankowy\",\n    \"invoice_payment\": \"Opłata Faktury\"\n}"
  },
  {
    "path": "locales/ro.json",
    "content": "{\n  \"create_character\": \"Creează un nou caracter\",\n  \"firstname\": \"Prenume\",\n  \"lastname\": \"Nume\",\n  \"gender\": \"Gen\",\n  \"male\": \"Masculin\",\n  \"female\": \"Feminin\",\n  \"non_binary\": \"Non-Binar\",\n  \"date_of_birth\": \"Dată de naștere\",\n  \"withdraw\": \"Retragere\",\n  \"deposit\": \"Depunere\",\n  \"transfer\": \"Transfer bancar\",\n  \"invoice_payment\": \"Plată factură\",\n  \"hours\": \"ore\",\n  \"minutes\": \"minute\",\n  \"seconds\": \"secunde\",\n  \"ban_indefinite\": \"Acest ban nu va expira.\",\n  \"ban_expires_in\": \"Banul expiră în %s ${hours}, %s ${minutes}, și %s ${seconds}.\",\n  \"ban_notice\": \"⚠️ Ai fost banat de pe server! ⚠️\\nBan emis la: %s\\nMotiv: %s\\n\\n%s\",\n  \"userid_is_active\": \"ID-ul tău de utilizator (%s), este deja activ.\",\n  \"no_license\": \"Nu am putut să-ți verificăm licența jocului tău.\",\n  \"server_restarting\": \"Serverul este pe cale să se repornească. Nu poți să te conectezi în acest moment.\"\n}\n"
  },
  {
    "path": "locales/ru.json",
    "content": "{\n    \"create_character\": \"Создать нового персонажа\",\n    \"firstname\": \"Имя\",\n    \"lastname\": \"Фамилия\",\n    \"gender\": \"Пол\",\n    \"male\": \"Мужской\",\n    \"female\": \"Женский\",\n    \"non_binary\": \"Небинарный\",\n    \"date_of_birth\": \"Дата рождения\",\n    \"withdraw\": \"Вывести\",\n    \"deposit\": \"Внести\",\n    \"transfer\": \"Банковский перевод\",\n    \"invoice_payment\": \"Оплата по счету\"\n}"
  },
  {
    "path": "locales/sk.json",
    "content": "{\n    \"create_character\": \"Vytvoriť novú postavu\",\n    \"firstname\": \"Meno\",\n    \"lastname\": \"Priezvisko\",\n    \"gender\": \"Pohlavie\",\n    \"male\": \"Muž\",\n    \"female\": \"Žena\",\n    \"non_binary\": \"Ne-binárne\",\n    \"date_of_birth\": \"Dátum narodenia\",\n    \"withdraw\": \"Výber\",\n    \"deposit\": \"Vklad\",\n    \"transfer\": \"Bankový prevod\",\n    \"invoice_payment\": \"Úhrada faktúry\"\n}"
  },
  {
    "path": "locales/tr.json",
    "content": "{\n  \"create_character\": \"Yeni bir karakter oluştur\",\n  \"firstname\": \"Ad\",\n  \"lastname\": \"Soyad\",\n  \"gender\": \"Cinsiyet\",\n  \"male\": \"Erkek\",\n  \"female\": \"Kadın\",\n  \"non_binary\": \"İkili Olmayan\",\n  \"date_of_birth\": \"Doğum Tarihi\",\n  \"withdraw\": \"Para çek\",\n  \"deposit\": \"Para yatır\",\n  \"transfer\": \"Banka transferi\",\n  \"invoice_payment\": \"Fatura ödemesi\",\n  \"hours\": \"saat\",\n  \"minutes\": \"dakika\",\n  \"seconds\": \"saniye\",\n  \"ban_indefinite\": \"Bu yasak süresizdir.\",\n  \"ban_expires_in\": \"Yasağın süresi %s ${hours}, %s ${minutes} ve %s ${seconds} sonra sona erecek.\",\n  \"ban_notice\": \"⚠️ Bu sunucudan yasaklandın! ⚠️\\nYasak tarihi: %s\\nSebep: %s\\n\\n%s\",\n  \"userid_is_active\": \"Kullanıcı ID'niz (%s) zaten aktif.\",\n  \"no_license\": \"Oyun lisansınızı doğrulayamadık.\",\n  \"server_restarting\": \"Sunucu yeniden başlatılmak üzere. Bu anda katılamazsınız.\"\n}\n"
  },
  {
    "path": "locales/zh-cn.json",
    "content": "{\n  \"create_character\": \"创建新角色\",\n  \"firstname\": \"名字\",\n  \"lastname\": \"姓氏\",\n  \"gender\": \"性别\",\n  \"male\": \"男\",\n  \"female\": \"女\",\n  \"non_binary\": \"非二元性别\",\n  \"date_of_birth\": \"出生日期\",\n  \"withdraw\": \"取款\",\n  \"deposit\": \"存款\",\n  \"transfer\": \"银行转账\",\n  \"invoice_payment\": \"账单付款\"\n}"
  },
  {
    "path": "locales/zh-tw.json",
    "content": "{\n  \"create_character\": \"創建新角色\",\n  \"firstname\": \"名字\",\n  \"lastname\": \"姓氏\",\n  \"gender\": \"性別\",\n  \"male\": \"男\",\n  \"female\": \"女\",\n  \"non_binary\": \"非二元性別\",\n  \"date_of_birth\": \"出生日期\",\n  \"withdraw\": \"取款\",\n  \"deposit\": \"存款\",\n  \"transfer\": \"銀行轉賬\",\n  \"invoice_payment\": \"賬單付款\"\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"@overextended/ox_core\",\n  \"author\": \"Overextended\",\n  \"version\": \"1.5.10\",\n  \"license\": \"LGPL-3.0-or-later\",\n  \"description\": \"A modern FiveM framework.\",\n  \"type\": \"module\",\n  \"files\": [\n    \"./tsconfig.json\",\n    \"./package/**/*.js\",\n    \"./package/**/*.d.ts\"\n  ],\n  \"exports\": {\n    \".\": \"./package/lib/index.js\",\n    \"./client\": \"./package/lib/client/index.js\",\n    \"./server\": \"./package/lib/server/index.js\"\n  },\n  \"scripts\": {\n    \"build\": \"bun run build.js\",\n    \"watch\": \"bun run build.js --watch\",\n    \"format\": \"bun run biome format --write\",\n    \"lint\": \"bun run biome lint --write\"\n  },\n  \"keywords\": [\n    \"fivem\",\n    \"ox_core\",\n    \"ox\",\n    \"overextended\",\n    \"overextended\"\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/overextended/ox_core.git\"\n  },\n  \"bugs\": \"https://github.com/overextended/ox_core/issues\",\n  \"devDependencies\": {\n    \"@citizenfx/client\": \"latest\",\n    \"@citizenfx/server\": \"latest\",\n    \"@overextended/fx-utils\": \"^0.0.6\",\n    \"@types/node\": \"^22.13.10\",\n    \"esbuild\": \"^0.23.1\",\n    \"tsc-alias\": \"^1.8.11\",\n    \"typescript\": \"^5.8.2\"\n  },\n  \"dependencies\": {\n    \"@biomejs/biome\": \"^1.9.4\",\n    \"@nativewrappers/fivem\": \"^0.0.86\",\n    \"@nativewrappers/server\": \"^0.0.86\",\n    \"@overextended/ox_lib\": \"^3.32.6\",\n    \"mariadb\": \"^3.4.1\"\n  },\n  \"engines\": {\n    \"node\": \">=22.9.0\"\n  }\n}"
  },
  {
    "path": "server/accounts/class.ts",
    "content": "import { ClassInterface } from 'classInterface';\nimport { OxPlayer } from 'player/class';\nimport { GetCharIdFromStateId } from 'player/db';\nimport type { Dict, OxAccountMetadata, OxAccountRole, OxAccountPermissions, OxCreateInvoice } from 'types';\nimport {\n  SelectAccount,\n  UpdateBalance,\n  PerformTransaction,\n  DepositMoney,\n  WithdrawMoney,\n  DeleteAccount,\n  SelectAccountRole,\n  UpdateAccountAccess,\n  SetAccountType,\n  CreateInvoice,\n} from './db';\nimport { CanPerformAction } from './roles';\n\ninterface UpdateAccountBalance {\n  amount: number;\n  message?: string;\n}\n\ninterface RemoveAccountBalance extends UpdateAccountBalance {\n  overdraw?: boolean;\n}\n\ninterface TransferAccountBalance {\n  toId: number;\n  amount: number;\n  overdraw?: boolean;\n  message?: string;\n  note?: string;\n  actorId?: number;\n}\n\nexport class OxAccount extends ClassInterface {\n  protected static members: Dict<OxAccount> = {};\n\n  static async get(accountId: number) {\n    if (accountId in this.members) this.members[accountId];\n\n    const validAccount = await SelectAccount(accountId);\n\n    if (!validAccount) throw new Error(`No account exists with accountId ${accountId}.`);\n\n    return new OxAccount(accountId);\n  }\n\n  static getAll() {\n    return this.members;\n  }\n\n  constructor(public accountId: number) {\n    super();\n    OxAccount.add(accountId, this);\n  }\n\n  /**\n   * Get the value of specific key(s) from account metadata.\n   */\n  async get<T extends keyof OxAccountMetadata>(key: T): Promise<OxAccountMetadata[T]>;\n  async get<T extends keyof OxAccountMetadata>(keys: T[]): Promise<Pick<OxAccountMetadata, T>>;\n  async get<T extends keyof OxAccountMetadata>(\n    keys: T | T[],\n  ): Promise<OxAccountMetadata[T] | Pick<OxAccountMetadata, T> | null> {\n    const metadata = await SelectAccount(this.accountId);\n\n    if (!metadata) return null;\n\n    if (Array.isArray(keys))\n      return keys.reduce(\n        (acc, key) => {\n          acc[key] = metadata[key];\n          return acc;\n        },\n        {} as Pick<OxAccountMetadata, T>,\n      );\n\n    return metadata[keys];\n  }\n\n  /**\n   * Add funds to the account.\n   */\n  async addBalance({ amount, message }: UpdateAccountBalance) {\n    return UpdateBalance(this.accountId, amount, 'add', false, message);\n  }\n\n  /**\n   * Remove funds from the account.\n   */\n  async removeBalance({ amount, overdraw = false, message }: RemoveAccountBalance) {\n    return UpdateBalance(this.accountId, amount, 'remove', overdraw, message);\n  }\n\n  /**\n   * Transfer funds to another account.\n   */\n  async transferBalance({ toId, amount, overdraw = false, message, note, actorId }: TransferAccountBalance) {\n    return PerformTransaction(this.accountId, toId, amount, overdraw, message, note, actorId);\n  }\n\n  /**\n   * Deposit money into the account.\n   */\n  async depositMoney(playerId: number, amount: number, message?: string, note?: string) {\n    return DepositMoney(playerId, this.accountId, amount, message, note);\n  }\n\n  /**\n   * Withdraw money from the account.\n   */\n  async withdrawMoney(playerId: number, amount: number, message?: string, note?: string) {\n    return WithdrawMoney(playerId, this.accountId, amount, message, note);\n  }\n\n  /**\n   * Mark the account as deleted. It can no longer be accessed, but remains in the database.\n   */\n  async deleteAccount() {\n    return DeleteAccount(this.accountId);\n  }\n\n  /**\n   * Get the account access role of a character by charId or stateId.\n   */\n  async getCharacterRole(id: number | string) {\n    const charId = typeof id === 'string' ? await GetCharIdFromStateId(id) : id;\n    return charId ? SelectAccountRole(this.accountId, charId) : null;\n  }\n\n  /**\n   * Set the account access role of a character by charId or stateId.\n   */\n  async setCharacterRole(id: number | string, role?: OxAccountRole) {\n    const charId = typeof id === 'string' ? await GetCharIdFromStateId(id) : id;\n    return charId && UpdateAccountAccess(this.accountId, charId, role);\n  }\n\n  /**\n   * Checks if a player's active character has permission to perform an action on the account.\n   */\n  async playerHasPermission(playerId: number, permission: keyof OxAccountPermissions) {\n    const player = OxPlayer.get(playerId);\n\n    if (!player?.charId) return false;\n\n    const role = await this.getCharacterRole(player.charId);\n    return await CanPerformAction(player, this.accountId, role, permission);\n  }\n\n  /**\n   * Set the account as shared, allowing permissions to be assigned to other characters.\n   */\n  async setShared() {\n    return SetAccountType(this.accountId, 'shared');\n  }\n\n  /**\n   * Create an unpaid invoice on the account.\n   */\n  async createInvoice(data: Omit<OxCreateInvoice, 'fromAccount'>) {\n    const invoice = {\n      fromAccount: this.accountId,\n      ...data,\n    };\n\n    return await CreateInvoice(invoice);\n  }\n}\n\nOxAccount.init();\n"
  },
  {
    "path": "server/accounts/db.ts",
    "content": "import { getRandomInt } from \"@overextended/ox_lib\";\nimport { OxAccount } from \"accounts/class\";\nimport { type Connection, GetConnection, db } from \"db\";\nimport { OxPlayer } from \"player/class\";\nimport type { OxAccountMetadata, OxAccountRole, OxAccountUserMetadata, OxCreateInvoice } from \"types\";\nimport locales from \"../../common/locales\";\nimport { CanPerformAction } from \"./roles\";\n\nconst addBalance = \"UPDATE accounts SET balance = balance + ? WHERE id = ?\";\nconst removeBalance = \"UPDATE accounts SET balance = balance - ? WHERE id = ?\";\nconst safeRemoveBalance = `${removeBalance} AND (balance - ?) >= 0`;\nconst addTransaction =\n  \"INSERT INTO accounts_transactions (actorId, fromId, toId, amount, message, note, fromBalance, toBalance) VALUES (?, ?, ?, ?, ?, ?, ?, ?)\";\nconst getBalance = \"SELECT balance FROM accounts WHERE id = ?\";\nconst doesAccountExist = \"SELECT 1 FROM accounts WHERE id = ?\";\n\nasync function GenerateAccountId(conn: Connection) {\n  const date = new Date();\n  const year = date.getFullYear().toString().slice(-2);\n  const month = (\"0\" + (date.getMonth() + 1)).slice(-2);\n  const baseId = Number(year + month) * 1e3;\n\n  while (true) {\n    const accountId = getRandomInt(10, 99) * 1e7 + baseId + getRandomInt(0, 9999);\n    const existingId = await conn.scalar<number>(doesAccountExist, [accountId]);\n\n    if (!existingId) return accountId;\n  }\n}\n\nexport async function UpdateBalance(\n  accountId: number,\n  amount: number,\n  action: \"add\" | \"remove\",\n  overdraw: boolean,\n  message?: string,\n  note?: string,\n  actorId?: number,\n): Promise<{ success: boolean; message?: string }> {\n  amount = Number.parseInt(String(amount));\n\n  if (isNaN(amount)) return { success: false, message: \"amount_not_number\" };\n\n  if (amount <= 0) return { success: false, message: \"invalid_amount\" };\n\n  using conn = await GetConnection();\n  const balance = await conn.scalar<number>(getBalance, [accountId]);\n\n  if (balance === null)\n    return {\n      success: false,\n      message: \"no_balance\",\n    };\n\n  const addAction = action === \"add\";\n  const success = addAction\n    ? await conn.update(addBalance, [amount, accountId])\n    : await conn.update(overdraw ? removeBalance : safeRemoveBalance, [amount, accountId, amount]);\n  if (!success)\n    return {\n      success: false,\n      message: \"insufficient_balance\",\n    };\n\n  !message && (message = locales(action === \"add\" ? \"deposit\" : \"withdraw\"));\n\n  const didUpdate =\n    (await conn.update(addTransaction, [\n      actorId || null,\n      addAction ? null : accountId,\n      addAction ? accountId : null,\n      amount,\n      message,\n      note,\n      addAction ? null : balance - amount,\n      addAction ? balance + amount : null,\n    ])) === 1;\n\n  if (!didUpdate)\n    return {\n      success: false,\n      message: \"something_went_wrong\",\n    };\n\n  emit(\"ox:updatedBalance\", { accountId, amount, action });\n\n  return { success: true };\n}\n\nexport async function PerformTransaction(\n  fromId: number,\n  toId: number,\n  amount: number,\n  overdraw: boolean,\n  message?: string,\n  note?: string,\n  actorId?: number,\n): Promise<{ success: boolean; message?: string }> {\n  amount = Number.parseInt(String(amount));\n\n  if (isNaN(amount)) return { success: false, message: \"amount_not_number\" };\n\n  if (amount <= 0) return { success: false, message: \"invalid_amount\" };\n\n  using conn = await GetConnection();\n\n  const fromBalance = await conn.scalar<number>(getBalance, [fromId]);\n  const toBalance = await conn.scalar<number>(getBalance, [toId]);\n\n  if (fromBalance === null || toBalance === null) return { success: false, message: \"no_balance\" };\n\n  await conn.beginTransaction();\n\n  try {\n    const query = overdraw ? removeBalance : safeRemoveBalance;\n    const values = [amount, fromId];\n\n    if (!overdraw) values.push(amount);\n\n    const removedBalance = await conn.update(query, values);\n    const addedBalance = removedBalance && (await conn.update(addBalance, [amount, toId]));\n\n    if (addedBalance) {\n      await conn.execute(addTransaction, [\n        actorId,\n        fromId,\n        toId,\n        amount,\n        message ?? locales(\"transfer\"),\n        note,\n        fromBalance - amount,\n        toBalance + amount,\n      ]);\n\n      emit(\"ox:transferredMoney\", { fromId, toId, amount });\n\n      return { success: true };\n    }\n  } catch (e) {\n    console.error(`Failed to transfer $${amount} from account<${fromId}> to account<${toId}>`);\n    console.log(e);\n  }\n\n  conn.rollback();\n\n  return { success: false, message: \"something_went_wrong\" };\n}\n\nexport async function SelectAccounts(column: \"owner\" | \"group\" | \"id\", id: number | string) {\n  return db.execute<OxAccountMetadata>(`SELECT * FROM accounts WHERE \\`${column}\\` = ?`, [id]);\n}\n\nexport async function SelectDefaultAccountId(column: \"owner\" | \"group\" | \"id\", id: number | string) {\n  return await db.column<number>(`SELECT id FROM accounts WHERE \\`${column}\\` = ? AND isDefault = 1`, [id]);\n}\n\nexport async function SelectAccount(id: number) {\n  return db.single(await SelectAccounts(\"id\", id));\n}\n\nexport async function IsAccountIdAvailable(id: number) {\n  return !(await db.exists(doesAccountExist, [id]));\n}\n\nexport async function CreateNewAccount(owner: string | number, label: string, isDefault?: boolean) {\n  using conn = await GetConnection();\n\n  const accountId = await GenerateAccountId(conn);\n  const column = typeof owner === \"string\" ? \"group\" : \"owner\";\n  const result = await conn.update(\n    `INSERT INTO accounts (id, label, \\`${column}\\`, type, isDefault) VALUES (?, ?, ?, ?, ?)`,\n    [accountId, label, owner, column === \"group\" ? \"group\" : \"personal\", isDefault || 0],\n  );\n\n  if (result && column === \"owner\")\n    conn.execute(\"INSERT INTO accounts_access (accountId, charId, role) VALUE (?, ?, ?)\", [accountId, owner, \"owner\"]);\n\n  return accountId;\n}\n\nexport async function DeleteAccount(accountId: number): Promise<{ success: boolean; message?: string }> {\n  const success = await db.update(`UPDATE accounts SET \\`type\\` = 'inactive' WHERE id = ?`, [accountId]);\n\n  if (!success)\n    return {\n      success: false,\n      message: \"something_went_wrong\",\n    };\n\n  return { success: true };\n}\n\nconst selectAccountRole = \"SELECT role FROM accounts_access WHERE accountId = ? AND charId = ?\";\n\nexport function SelectAccountRole(accountId: number, charId: number) {\n  return db.column<OxAccountUserMetadata[\"role\"]>(selectAccountRole, [accountId, charId]);\n}\n\nexport async function DepositMoney(\n  playerId: number,\n  accountId: number,\n  amount: number,\n  message?: string,\n  note?: string,\n): Promise<{ success: boolean; message?: string }> {\n  amount = Number.parseInt(String(amount));\n\n  if (isNaN(amount)) return { success: false, message: \"amount_not_number\" };\n\n  if (amount <= 0) return { success: false, message: \"invalid_amount\" };\n\n  const player = OxPlayer.get(playerId);\n\n  if (!player?.charId)\n    return {\n      success: false,\n      message: \"no_charid\",\n    };\n\n  const money = exports.ox_inventory.GetItemCount(playerId, \"money\");\n\n  if (amount > money) return { success: false, message: \"insufficient_funds\" };\n\n  using conn = await GetConnection();\n  const balance = await conn.scalar<number>(getBalance, [accountId]);\n\n  if (balance === null) return { success: false, message: \"no_balance\" };\n\n  const role = await conn.scalar<OxAccountRole>(selectAccountRole, [accountId, player.charId]);\n\n  if (!(await CanPerformAction(player, accountId, role, \"deposit\"))) return { success: false, message: \"no_access\" };\n\n  await conn.beginTransaction();\n\n  const affectedRows = await conn.update(addBalance, [amount, accountId]);\n\n  if (!affectedRows || !exports.ox_inventory.RemoveItem(playerId, \"money\", amount)) {\n    conn.rollback();\n    return {\n      success: false,\n      message: \"something_went_wrong\",\n    };\n  }\n\n  await conn.execute(addTransaction, [\n    player.charId,\n    null,\n    accountId,\n    amount,\n    message ?? locales(\"deposit\"),\n    note,\n    null,\n    balance + amount,\n  ]);\n\n  emit(\"ox:depositedMoney\", { playerId, accountId, amount });\n\n  return {\n    success: true,\n  };\n}\n\nexport async function WithdrawMoney(\n  playerId: number,\n  accountId: number,\n  amount: number,\n  message?: string,\n  note?: string,\n): Promise<{ success: boolean; message?: string }> {\n  amount = Number.parseInt(String(amount));\n\n  if (isNaN(amount)) return { success: false, message: \"amount_not_number\" };\n\n  if (amount <= 0) return { success: false, message: \"invalid_amount\" };\n\n  const player = OxPlayer.get(playerId);\n\n  if (!player?.charId) return { success: false, message: \"no_charId\" };\n\n  using conn = await GetConnection();\n  const role = await conn.scalar<OxAccountRole>(selectAccountRole, [accountId, player.charId]);\n\n  if (!(await CanPerformAction(player, accountId, role, \"withdraw\"))) return { success: false, message: \"no_access\" };\n\n  const balance = await conn.scalar<number>(getBalance, [accountId]);\n\n  if (balance === null) return { success: false, message: \"no_balance\" };\n\n  await conn.beginTransaction();\n\n  const affectedRows = await conn.update(safeRemoveBalance, [amount, accountId, amount]);\n\n  if (!affectedRows || !exports.ox_inventory.AddItem(playerId, \"money\", amount)) {\n    conn.rollback();\n    return {\n      success: false,\n      message: \"something_went_wrong\",\n    };\n  }\n\n  await conn.execute(addTransaction, [\n    player.charId,\n    accountId,\n    null,\n    amount,\n    message ?? locales(\"withdraw\"),\n    note,\n    balance - amount,\n    null,\n  ]);\n\n  emit(\"ox:withdrewMoney\", { playerId, accountId, amount });\n\n  return { success: true };\n}\n\nexport async function UpdateAccountAccess(\n  accountId: number,\n  id: number,\n  role?: string,\n): Promise<{ success: boolean; message?: string }> {\n  if (!role) {\n    const success = await db.update(\"DELETE FROM accounts_access WHERE accountId = ? AND charId = ?\", [accountId, id]);\n\n    if (!success) return { success: false, message: \"something_went_wrong\" };\n\n    return { success: true };\n  }\n\n  const success = await db.update(\n    \"INSERT INTO accounts_access (accountId, charId, role) VALUE (?, ?, ?) ON DUPLICATE KEY UPDATE role = VALUES(role)\",\n    [accountId, id, role],\n  );\n\n  if (!success) return { success: false, message: \"something_went_wrong\" };\n\n  return { success: true };\n}\n\nexport async function UpdateInvoice(\n  invoiceId: number,\n  charId: number,\n): Promise<{ success: boolean; message?: string }> {\n  const player = OxPlayer.getFromCharId(charId);\n\n  if (!player?.charId) return { success: false, message: \"no_charId\" };\n\n  const invoice = await db.row<{ amount: number; payerId?: number; fromAccount: number; toAccount: number }>(\n    \"SELECT * FROM `accounts_invoices` WHERE `id` = ?\",\n    [invoiceId],\n  );\n\n  if (!invoice) return { success: false, message: \"no_invoice\" };\n\n  if (invoice.payerId) return { success: false, message: \"invoice_paid\" };\n\n  const account = await OxAccount.get(invoice.toAccount);\n  const hasPermission = await account?.playerHasPermission(player.source as number, \"payInvoice\");\n\n  if (!hasPermission) return { success: false, message: \"no_permission\" };\n\n  const updateReceiver = await UpdateBalance(\n    invoice.toAccount,\n    invoice.amount,\n    \"remove\",\n    false,\n    locales(\"invoice_payment\"),\n    undefined,\n    charId,\n  );\n\n  if (!updateReceiver.success) return { success: false, message: \"no_balance\" };\n\n  const updateSender = await UpdateBalance(\n    invoice.fromAccount,\n    invoice.amount,\n    \"add\",\n    false,\n    locales(\"invoice_payment\"),\n    undefined,\n    charId,\n  );\n\n  if (!updateSender.success) return { success: false, message: \"no_balance\" };\n\n  const invoiceUpdated = await db.update(\"UPDATE `accounts_invoices` SET `payerId` = ?, `paidAt` = ? WHERE `id` = ?\", [\n    player.charId,\n    new Date(),\n    invoiceId,\n  ]);\n\n  if (!invoiceUpdated)\n    return {\n      success: false,\n      message: \"invoice_not_updated\",\n    };\n\n  invoice.payerId = charId;\n\n  emit(\"ox:invoicePaid\", invoice);\n\n  return {\n    success: true,\n  };\n}\n\nexport async function CreateInvoice({\n  actorId,\n  fromAccount,\n  toAccount,\n  amount,\n  message,\n  dueDate,\n}: OxCreateInvoice): Promise<{ success: boolean; message?: string }> {\n  if (isNaN(amount)) return { success: false, message: \"amount_not_number\" };\n\n  if (amount <= 0) return { success: false, message: \"invalid_amount\" };\n\n  if (actorId) {\n    const player = OxPlayer.getFromCharId(actorId);\n\n    if (!player?.charId) return { success: false, message: \"no_charid\" };\n\n    const account = await OxAccount.get(fromAccount);\n    const hasPermission = await account?.playerHasPermission(player.source as number, \"sendInvoice\");\n\n    if (!hasPermission) return { success: false, message: \"no_permission\" };\n  }\n\n  const targetAccount = await OxAccount.get(toAccount);\n\n  if (!targetAccount) return { success: false, message: \"no_target_account\" };\n\n  const success = await db.insert(\n    \"INSERT INTO accounts_invoices (`actorId`, `fromAccount`, `toAccount`, `amount`, `message`, `dueDate`) VALUES (?, ?, ?, ?, ?, ?)\",\n    [actorId, fromAccount, toAccount, amount, message, dueDate],\n  );\n\n  if (!success) return { success: false, message: \"invoice_insert_error\" };\n\n  return { success: true };\n}\n\nexport async function DeleteInvoice(invoiceId: number): Promise<{ success: boolean; message?: string }> {\n  const success = await db.update(\"DELETE FROM `accounts_invoices` WHERE `id` = ?\", [invoiceId]);\n\n  if (!success) return { success: false, message: \"invoice_delete_error\" };\n\n  return { success: true };\n}\n\nexport async function SetAccountType(accountId: number, type: string): Promise<{ success: boolean; message?: string }> {\n  const success = await db.update(\"UPDATE `accounts` SET `type` = ? WHERE `id` = ?\", [type, accountId]);\n\n  if (!success) return { success: false, message: \"update_account_error\" };\n\n  return { success: true };\n}\n"
  },
  {
    "path": "server/accounts/index.ts",
    "content": "import { CreateNewAccount, SelectDefaultAccountId, UpdateInvoice, DeleteInvoice } from './db';\nimport { GetCharIdFromStateId } from 'player/db';\nimport { OxAccount } from './class';\n\nsetInterval(() => {\n  const accounts = OxAccount.getAll();\n\n  for (const accountId in accounts) {\n    const account = accounts[accountId];\n\n    OxAccount.remove(account.accountId);\n  }\n}, 60000);\n\n/**\n * Return the default account for a character.\n * @param id The charId or stateId used to identify the character.\n */\nexport async function GetCharacterAccount(id: number | string) {\n  const charId = typeof id === 'string' ? await GetCharIdFromStateId(id) : id;\n  const accountId = charId && (await SelectDefaultAccountId('owner', charId));\n  return accountId ? OxAccount.get(accountId) : null;\n}\n\n/**\n * Return the default account for a group.\n */\nexport async function GetGroupAccount(groupName: string) {\n  const accountId = await SelectDefaultAccountId('group', groupName);\n  return accountId ? OxAccount.get(accountId) : null;\n}\n\nexport async function CreateAccount(owner: number | string, label: string) {\n  const accountId = await CreateNewAccount(owner, label);\n  return OxAccount.get(accountId);\n}\n\nexport function PayAccountInvoice(invoiceId: number, charId: number) {\n  return UpdateInvoice(invoiceId, charId);\n}\n\nexport function DeleteAccountInvoice(invoiceId: number) {\n  return DeleteInvoice(invoiceId);\n}\n\nexports('GetCharacterAccount', GetCharacterAccount);\nexports('GetGroupAccount', GetGroupAccount);\nexports('CreateAccount', CreateAccount);\nexports('PayAccountInvoice', PayAccountInvoice);\nexports('DeleteAccountInvoice', DeleteAccountInvoice);\n"
  },
  {
    "path": "server/accounts/roles.ts",
    "content": "import { db } from 'db';\nimport type { OxAccountPermissions, OxAccountRole } from 'types';\nimport { SelectAccount } from './db';\nimport { GetGroup } from 'groups';\nimport type { OxPlayer } from 'player/class';\n\ntype OxAccountMetadataRow = OxAccountPermissions & { id?: number; name?: OxAccountRole };\n\nconst accountRoles = {} as Record<string, OxAccountPermissions>;\n\nconst blacklistedGroupActions = {\n  addUser: true,\n  removeUser: true,\n  manageUser: true,\n  transferOwnership: true,\n  manageAccount: true,\n  closeAccount: true,\n} as Record<keyof OxAccountPermissions, true>;\n\nexport function CheckRolePermission(roleName: OxAccountRole | null, permission: keyof OxAccountPermissions) {\n  if (!roleName) return;\n\n  return accountRoles?.[roleName.toLowerCase()]?.[permission];\n}\n\nexport async function CanPerformAction(\n  player: OxPlayer,\n  accountId: number,\n  role: OxAccountRole | null,\n  action: keyof OxAccountPermissions,\n) {\n  if (CheckRolePermission(role, action)) return true;\n\n  const groupName = (await SelectAccount(accountId))?.group;\n\n  if (groupName) {\n    if (action in blacklistedGroupActions) return false;\n\n    const group = GetGroup(groupName);\n    const groupRole = group.accountRoles[player.getGroup(groupName)];\n\n    if (CheckRolePermission(groupRole, action)) return true;\n  }\n\n  return false;\n}\n\nasync function LoadRoles() {\n  const roles = await db.execute<OxAccountMetadataRow>('SELECT * FROM account_roles');\n\n  if (!roles[0]) return;\n\n  roles.forEach((role) => {\n    const roleName = (role.name as string).toLowerCase() as OxAccountRole;\n    delete role.name;\n    delete role.id;\n\n    accountRoles[roleName] = role;\n    GlobalState[`accountRole.${roleName}`] = role;\n  });\n\n  GlobalState['accountRoles'] = Object.keys(accountRoles);\n}\n\nsetImmediate(LoadRoles);\n"
  },
  {
    "path": "server/bridge/index.ts",
    "content": "import './npwd';\nimport './ox_inventory';\n"
  },
  {
    "path": "server/bridge/npwd.ts",
    "content": "import { OnPlayerLoaded, OnPlayerLogout } from '../player/events';\n\nSetConvar('npwd:useResourceIntegration', 'true');\nSetConvar(\n  'npwd:database',\n  JSON.stringify({\n    playerTable: 'characters',\n    identifierColumn: 'charId',\n    phoneNumberColumn: 'phoneNumber',\n  }),\n);\n\nOnPlayerLoaded('npwd', (player) => {\n  exports.npwd.newPlayer({\n    source: player.source,\n    identifier: player.charId,\n    phoneNumber: player.get('phoneNumber'),\n    firstname: player.get('firstName'),\n    lastname: player.get('lastName'),\n  });\n});\n\nOnPlayerLogout((player) => exports.npwd.unloadPlayer(player.source));\n\nexport function GeneratePhoneNumber() {\n  try {\n    return exports.npwd.generatePhoneNumber();\n  } catch (e) {}\n}\n"
  },
  {
    "path": "server/bridge/ox_inventory.ts",
    "content": "import { OnPlayerLoaded } from '../player/events';\n\nSetConvarReplicated('inventory:framework', 'ox');\nSetConvarReplicated('inventory:trimplate ', 'false');\n\nOnPlayerLoaded('ox_inventory', (player) => {\n  exports.ox_inventory.setPlayerInventory({\n    source: player.source,\n    identifier: player.charId,\n    name: `${player.get('firstName')} ${player.get('lastName')}`,\n    sex: player.get('gender'),\n    dateofbirth: player.get('dateOfBirth'),\n    groups: {},\n  });\n});\n"
  },
  {
    "path": "server/classInterface.ts",
    "content": "import type { Dict } from 'types';\n\nexport class ClassInterface {\n  protected static members: Dict<any>;\n  protected static keys?: Dict<Dict<any>>;\n  protected static callableMethods: Dict<true>;\n\n  static isCallValid(method: string, id: string | number, member: any) {\n    if (!member) return console.error(`cannot call method ${method} on ${this.name}<${id}> (invalid id)`);\n\n    if (!member[method])\n      return console.error(`cannot call method ${method} on ${this.name}<${id}> (method does not exist)`);\n\n    if (!this.callableMethods[method])\n      return console.error(`cannot call method ${method} on ${this.name}<${id}> (method is not exported)`);\n\n    return true;\n  }\n\n  /** Exports several class methods and makes non-private methods callable from external resources. */\n  static init() {\n    const classMethods = Object.getOwnPropertyNames(this.prototype);\n\n    if (classMethods) {\n      this.callableMethods = {};\n\n      classMethods.forEach((method) => {\n        if (method !== 'constructor') this.callableMethods[method] = true;\n      });\n    }\n\n    const name = this.name;\n    const expName = this.name.replace('Ox', '');\n\n    // e.g. exports.ox_core.GetPlayer\n    exports(`Get${expName}`, (id: string | number) => this.get(id));\n\n    // e.g. exports.ox_core.GetPlayerCalls\n    exports(`Get${expName}Calls`, () => this.callableMethods);\n\n    // e.g. exports.ox_core.CallPlayer\n    exports(`Call${expName}`, (id: string | number, method: string, ...args: any[]) => {\n      // Maintain backwards compatibility with OxVehicle indexed by entityId..\n      const member = expName === 'Vehicle' && typeof id === 'number' ? this.keys?.entity[id] : this.get(id);\n\n      if (member instanceof Promise) {\n        return member.then((resolvedMember) => {\n          if (!this.isCallValid(method, id, resolvedMember)) return;\n\n          return resolvedMember.call(method, ...args);\n        });\n      }\n\n      if (!this.isCallValid(method, id, member)) return;\n\n      return member.call(method, ...args);\n    });\n\n    DEV: console.info(`Instantiated ClassInterface<${name}> and exports`);\n\n    return this;\n  }\n\n  call(method: string, ...args: any) {\n    return (this as any)[method](...args);\n  }\n\n  /** Get a member of the class by its id. */\n  static get(id: string | number) {\n    return this.members[id];\n  }\n\n  /** Get all members of the class. */\n  static getAll() {\n    return this.members;\n  }\n\n  /** Adds a new member of the class to its registries. */\n  static add(id: string | number, member: any) {\n    if (this.members[id]) return false;\n\n    this.members[id] = member;\n\n    if (this.keys) {\n      Object.entries(this.keys).forEach(([key, obj]) => {\n        if (member[key]) {\n          obj[member[key]] = member;\n        }\n      });\n    }\n\n    return true;\n  }\n\n  /** Removes a member of the class from its registries. */\n  static remove(id: string | number) {\n    const member = this.members[id];\n\n    if (!member) return false;\n\n    if (this.keys) {\n      Object.entries(this.keys).forEach(([key, obj]) => {\n        if (member[key]) {\n          delete obj[member[key]];\n        }\n      });\n    }\n\n    delete this.members[id];\n\n    return true;\n  }\n}\n"
  },
  {
    "path": "server/commands.ts",
    "content": "import { addCommand } from \"@overextended/ox_lib/server\";\nimport { OxPlayer } from \"player/class\";\nimport { OxVehicle } from \"vehicle/class\";\n\naddCommand(\n  \"saveall\",\n  async () => {\n    OxPlayer.saveAll();\n    OxVehicle.saveAll();\n  },\n  {\n    help: \"Saves all players and vehicles to the database.\",\n    restricted: \"group.admin\",\n  },\n);\n"
  },
  {
    "path": "server/config.ts",
    "content": "import { DEBUG } from 'config';\n\nexport * from '../common/config';\n\nexport const CREATE_DEFAULT_ACCOUNT = GetConvarInt('ox:createDefaultAccount', 1) === 1;\n\nif (DEBUG) SetConvar('ox:callbackTimeout', '1200000');\n"
  },
  {
    "path": "server/db/config.ts",
    "content": "import type { PoolConfig } from 'mariadb';\nimport type { Dict } from 'types';\n\nexport function GetConfig(): PoolConfig {\n  const connectionString = GetConvar('mysql_connection_string', 'mysql://root@localhost').replace(\n    'mysql://',\n    'mariadb://',\n  );\n\n  function parseUri() {\n    const splitMatchGroups = connectionString.match(\n      /^(?:([^:\\/?#.]+):)?(?:\\/\\/(?:([^\\/?#]*)@)?([\\w\\d\\-\\u0100-\\uffff.%]*)(?::([0-9]+))?)?([^?#]+)?(?:\\?([^#]*))?$/,\n    ) as RegExpMatchArray;\n\n    if (!splitMatchGroups) throw new Error(`mysql_connection_string structure was invalid (${connectionString})`);\n\n    const authTarget = splitMatchGroups[2] ? splitMatchGroups[2].split(':') : [];\n\n    return {\n      user: authTarget[0] || undefined,\n      password: authTarget[1] || undefined,\n      host: splitMatchGroups[3],\n      port: Number.parseInt(splitMatchGroups[4]),\n      database: splitMatchGroups[5].replace(/^\\/+/, ''),\n      ...(splitMatchGroups[6] &&\n        splitMatchGroups[6].split('&').reduce<Dict<string>>((connectionInfo, parameter) => {\n          const [key, value] = parameter.split('=');\n          connectionInfo[key] = value;\n          return connectionInfo;\n        }, {})),\n    };\n  }\n\n  const options: any = connectionString.includes('mariadb://')\n    ? parseUri()\n    : connectionString\n        .replace(/(?:host(?:name)|ip|server|data\\s?source|addr(?:ess)?)=/gi, 'host=')\n        .replace(/(?:user\\s?(?:id|name)?|uid)=/gi, 'user=')\n        .replace(/(?:pwd|pass)=/gi, 'password=')\n        .replace(/(?:db)=/gi, 'database=')\n        .split(';')\n        .reduce((connectionInfo: any, parameter: any) => {\n          const [key, value] = parameter.split('=');\n          if (key) connectionInfo[key] = value;\n          return connectionInfo;\n        }, {});\n\n  if (typeof options.ssl === 'string') {\n    try {\n      options.ssl = JSON.parse(options.ssl);\n    } catch (err) {\n      console.log(`^3Failed to parse ssl in configuration (${err})!^0`);\n    }\n  }\n\n  return {\n    connectTimeout: 60000,\n    connectionLimit: 5,\n    acquireTimeout: 30000,\n    ...options,\n    namedPlaceholders: false,\n    multipleStatements: true,\n    dateStrings: true,\n    insertIdAsNumber: true,\n    decimalAsNumber: true,\n    autoJsonMap: true,\n    jsonStrings: false,\n  };\n}\n"
  },
  {
    "path": "server/db/index.ts",
    "content": "import { waitFor } from \"@overextended/ox_lib\";\nimport { pool } from \"./pool\";\nimport type { Dict } from \"types\";\nimport type { PoolConnection, QueryOptions } from \"mariadb\";\n\n(Symbol as any).dispose ??= Symbol(\"Symbol.dispose\");\n\nexport interface MySqlRow<T = string | number | boolean | Dict<any> | undefined> {\n  [column: string]: T;\n}\n\nexport interface OkPacket {\n  affectedRows: number;\n  insertId: number;\n  warningStatus: any;\n}\n\nfunction getScalar<T>(resp: T[] | null) {\n  if (resp && resp[0]) for (const key in resp[0]) return resp[0][key] as T;\n  return null;\n}\n\nfunction getRow<T>(resp: T[] | null) {\n  return resp ? resp[0] : null;\n}\n\nexport class Connection {\n  public transaction?: boolean;\n\n  constructor(public connection: PoolConnection) {}\n\n  async execute<T = MySqlRow[] & OkPacket>(query: string | QueryOptions, values?: any[]) {\n    return (await this.connection.execute(query, values)) as T;\n  }\n\n  async query<T = MySqlRow[] & OkPacket>(query: string | QueryOptions, values?: any[]) {\n    return (await this.connection.query(query, values)) as T;\n  }\n\n  async scalar<T>(query: string | QueryOptions, values?: any[]) {\n    return getScalar(await this.execute<T[]>(query, values)) as T | null;\n  }\n\n  async row<T>(query: string | QueryOptions, values?: any[]) {\n    return getRow(await this.execute<T[]>(query, values)) as T | null;\n  }\n\n  async insert(query: string | QueryOptions, values?: any[]) {\n    return (await this.execute<OkPacket>(query, values))?.insertId;\n  }\n\n  async update(query: string | QueryOptions, values?: any[]) {\n    return (await this.execute<OkPacket>(query, values))?.affectedRows;\n  }\n\n  batch(query: string | QueryOptions, values?: any[]) {\n    return this.connection.batch(query, values);\n  }\n\n  beginTransaction() {\n    this.transaction = true;\n    return this.connection.beginTransaction();\n  }\n\n  rollback() {\n    delete this.transaction;\n    return this.connection.rollback();\n  }\n\n  commit() {\n    delete this.transaction;\n    return this.connection.commit();\n  }\n\n  [Symbol.dispose]() {\n    if (this.transaction) this.commit();\n    this.connection.release();\n  }\n}\n\nexport async function GetConnection() {\n  while (!pool) {\n    await waitFor(() => pool, \"Failed to acquire database connection.\", 30000);\n  }\n\n  return new Connection(await pool.getConnection());\n}\n\nexport const db = {\n  async query<T>(query: string | QueryOptions, values?: any[]) {\n    using conn = await GetConnection();\n    return conn.query<T extends OkPacket ? OkPacket : T[]>(query, values);\n  },\n  async execute<T>(query: string | QueryOptions, values?: any[]) {\n    using conn = await GetConnection();\n    return conn.execute<T extends OkPacket ? OkPacket : T[]>(query, values);\n  },\n  async column<T>(query: string | QueryOptions, values?: any[]) {\n    return db.scalar(await db.execute<T[]>(query, values)) as T | null;\n  },\n  async exists<T>(query: string | QueryOptions, values?: any[]) {\n    return (db.scalar(await db.execute<T[]>(query, values)) as T) === 1;\n  },\n  async row<T>(query: string | QueryOptions, values?: any[]) {\n    return db.single(await db.execute<T[]>(query, values)) as T | null;\n  },\n  async insert(query: string | QueryOptions, values?: any[]) {\n    return (await db.execute<OkPacket>(query, values))?.insertId;\n  },\n  async update(query: string | QueryOptions, values?: any[]) {\n    return (await db.execute<OkPacket>(query, values))?.affectedRows;\n  },\n  batch(query: string | QueryOptions, values?: any[]) {\n    return pool.batch(query, values);\n  },\n  scalar<T>(resp: T[] | null) {\n    if (resp && resp[0]) for (const key in resp[0]) return resp[0][key] as T;\n    return null;\n  },\n  single<T>(resp: T[] | null) {\n    return resp ? resp[0] : null;\n  },\n};\n"
  },
  {
    "path": "server/db/pool.ts",
    "content": "import { createPool } from 'mariadb';\nimport { GetConfig } from './config';\nimport type { Pool } from 'mariadb';\nimport schema from './schema';\n\nexport let pool: Pool;\n\nsetImmediate(async () => {\n  const config = GetConfig();\n\n  try {\n    const dbPool = createPool(config);\n    const conn = await dbPool.getConnection();\n    const info = conn.info!; // when would info be null? i'm sure we'll find out eventually!\n    const version = info.serverVersion;\n    const recommendedDb =\n      'Install MariaDB 11.4+ for the best experience.\\n- https://mariadb.com/kb/en/changes-improvements-in-mariadb-11-4/';\n\n    conn.release();\n\n    if (!version.mariaDb) return console.error(`MySQL ${version?.raw} is not supported. ${recommendedDb}`);\n\n    if (!info.hasMinVersion(11, 4, 0)) return console.error(`${version.raw} is not supported. ${recommendedDb}`);\n\n    console.log(`${`^5[${version.raw}]`} ^2Database server connection established!^0`);\n\n    await schema(dbPool);\n\n    pool = dbPool;\n  } catch (err) {\n    console.log(\n      `^3Unable to establish a connection to the database (${err.code})!\\n^1Error ${err.errno}: ${err.message}^0`,\n    );\n\n    if (config.password) config.password = '******';\n\n    console.log(config);\n  }\n});\n"
  },
  {
    "path": "server/db/schema.ts",
    "content": "import { Pool } from 'mariadb';\n\n/**\n * Validate some database settings, tables, etc. and add anything missing (e.g. version changes).\n */\nexport default async function (pool: Pool) {\n  await pool.query(`CREATE TABLE IF NOT EXISTS user_tokens (\n    userId INT UNSIGNED NOT NULL,\n    token VARCHAR(50) NOT NULL,\n    PRIMARY KEY (userId, token),\n    INDEX token (token),\n    CONSTRAINT FK_user_tokens_users FOREIGN KEY (userId) REFERENCES users (userId) ON UPDATE CASCADE ON DELETE CASCADE\n  )`);\n\n  await pool.query(`CREATE TABLE IF NOT EXISTS banned_users (\n    userId INT UNSIGNED NOT NULL,\n    banned_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n    unban_at TIMESTAMP DEFAULT NULL,\n    reason VARCHAR(255),\n    PRIMARY KEY (userId),\n    CONSTRAINT FK_banned_users_users FOREIGN KEY (userId) REFERENCES users (userId) ON UPDATE CASCADE ON DELETE CASCADE\n  )`);\n}\n"
  },
  {
    "path": "server/groups/db.ts",
    "content": "import { GetConnection, db } from 'db';\nimport type { UpsertResult } from 'mariadb';\nimport type { DbGroup } from 'types';\n\nexport function SelectGroups() {\n  return db.query<DbGroup>(`\n    SELECT \n      ox_groups.*,\n      JSON_OBJECTAGG(ox_group_grades.grade, ox_group_grades.accountRole) AS accountRoles,\n      JSON_ARRAYAGG(ox_group_grades.label ORDER BY ox_group_grades.grade) AS grades\n    FROM \n        ox_groups\n    JOIN \n        ox_group_grades\n    ON\n        ox_groups.name = ox_group_grades.group\n    GROUP BY \n        ox_groups.name;\n  `);\n}\n\nexport async function InsertGroup({ name, label, type, colour, hasAccount, grades, accountRoles }: DbGroup) {\n  using conn = await GetConnection();\n  await conn.beginTransaction();\n\n  const insertedGroup = await conn.update(\n    'INSERT IGNORE INTO `ox_groups` (`name`, `label`, `type`, `colour`, `hasAccount`) VALUES (?, ?, ?, ?, ?)',\n    [name, label, type, colour, hasAccount],\n  );\n\n  if (!insertedGroup) return true;\n\n  const insertedGrades = (await conn.batch(\n    'INSERT INTO `ox_group_grades` (`group`, `grade`, `label`, `accountRole`) VALUES (?, ?, ?, ?)',\n    grades.map((gradeLabel, index) => [name, index + 1, gradeLabel, accountRoles[index + 1]]),\n  )) as UpsertResult;\n\n  return insertedGrades.affectedRows > 0;\n}\n\nexport function RemoveGroup(groupName: string) {\n  return db.update('DELETE FROM `ox_groups` WHERE name = ?', [groupName]);\n}\n\nexport async function AddCharacterGroup(charId: number, name: string, grade: number) {\n  return (\n    (await db.update('INSERT INTO character_groups (charId, name, grade) VALUES (?, ?, ?)', [charId, name, grade])) ===\n    1\n  );\n}\n\nexport async function UpdateCharacterGroup(charId: number, name: string, grade: number) {\n  return (\n    (await db.update('UPDATE character_groups SET grade = ? WHERE charId = ? AND name = ?', [grade, charId, name])) ===\n    1\n  );\n}\n\nexport async function RemoveCharacterGroup(charId: number, name: string) {\n  return (await db.update('DELETE FROM character_groups WHERE charId = ? AND name = ?', [charId, name])) === 1;\n}\n\nexport function GetCharacterGroups(charId: number) {\n  return db.execute<{ name: string; grade: number; isActive: boolean }>(\n    'SELECT name, grade, isActive FROM character_groups WHERE charId = ?',\n    [charId],\n  );\n}\n\nexport async function SetActiveGroup(charId: number, groupName?: string) {\n  using conn = await GetConnection();\n  const params: [number, string?] = [charId];\n\n  conn.execute('UPDATE character_groups SET isActive = 0 WHERE charId = ? AND isActive = 1', params);\n\n  if (groupName) {\n    params.push(groupName);\n    conn.execute('UPDATE character_groups SET isActive = 1 WHERE charId = ? AND name = ?', params);\n  }\n}\n"
  },
  {
    "path": "server/groups/index.ts",
    "content": "import { addAce, addCommand, addPrincipal, removeAce, removePrincipal } from \"@overextended/ox_lib/server\";\nimport { InsertGroup, RemoveGroup, SelectGroups } from \"./db\";\nimport { OxPlayer } from \"player/class\";\nimport type { Dict, OxGroup, DbGroup, CreateGroupProperties, OxAccountRole } from \"types\";\nimport { GetGroupPermissions } from \"../../common\";\nimport { GetGroupAccount } from \"accounts\";\nimport { CreateNewAccount } from \"accounts/db\";\n\nconst groups: Dict<OxGroup> = {};\nGlobalState.groups = [];\n\nexport function GetGroup(name: string) {\n  return groups[name];\n}\n\nexport function GetGroupsByType(type: string) {\n  return Object.values(groups).reduce((acc, group) => {\n    if (group.type === type) acc.push(group.name);\n    return acc;\n  }, [] as string[]);\n}\n\nexport function GetGroupActivePlayers(groupName: string) {\n  const group = groups[groupName];\n\n  return group ? [...group.activePlayers] : [];\n}\n\nexport function GetGroupActivePlayersByType(type: string) {\n  return Object.values(groups).reduce((acc, group) => {\n    if (group.type === type) {\n      acc.push(...group.activePlayers);\n    }\n    return acc;\n  }, [] as number[]);\n}\n\nexport function SetGroupPermission(groupName: string, grade: number, permission: string, value: \"allow\" | \"deny\") {\n  const permissions = GetGroupPermissions(groupName);\n\n  if (!permissions[grade]) permissions[grade] = {};\n\n  permissions[grade][permission] = value === \"allow\" ? true : false;\n  GlobalState[`group.${groupName}:permissions`] = permissions;\n}\n\nexport function RemoveGroupPermission(groupName: string, grade: number, permission: string) {\n  const permissions = GetGroupPermissions(groupName);\n\n  if (!permissions[grade]) return;\n\n  delete permissions[grade][permission];\n  GlobalState[`group.${groupName}:permissions`] = permissions;\n}\n\nfunction SetupGroup(data: DbGroup) {\n  const group: OxGroup = {\n    ...data,\n    principal: `group.${data.name}`,\n    hasAccount: Boolean(data.hasAccount),\n  };\n\n  GlobalState[group.principal] = group;\n  GlobalState[`${group.name}:count`] = 0;\n  GlobalState[`${group.name}:activeCount`] = 0;\n\n  group.activePlayers = new Set();\n\n  groups[group.name] = group;\n  group.grades = group.grades.reduce(\n    (acc, value, index) => {\n      acc[index + 1] = value;\n      return acc;\n    },\n    {} as Record<number, string>,\n  ) as any;\n\n  let parent = group.principal;\n\n  for (const i in group.grades) {\n    const child = `${group.principal}:${i}`;\n\n    if (!IsPrincipalAceAllowed(child, child)) {\n      addAce(child, child, true);\n      addPrincipal(child, parent);\n    }\n\n    parent = child;\n  }\n\n  if (group.hasAccount) {\n    GetGroupAccount(group.name).then((account) => {\n      if (!account) CreateNewAccount(group.name, group.label, true);\n    });\n  }\n\n  DEV: console.info(`Instantiated OxGroup<${group.name}>`);\n\n  return group;\n}\n\n// @todo more data validation and error handling\nexport async function CreateGroup(data: CreateGroupProperties) {\n  if (groups[data.name]) throw new Error(`Cannot create OxGroup<${data.name}> (group already exists with that name)`);\n\n  const grades = data.grades.map((grade) => grade.label);\n  const accountRoles = data.grades.reduce((acc, grade, index) => {\n    if (grade.accountRole) acc[index + 1] = grade.accountRole;\n    return acc;\n  }, {} as Dict<OxAccountRole>);\n\n  const group: DbGroup = {\n    ...data,\n    grades: grades,\n    accountRoles: accountRoles,\n    hasAccount: data.hasAccount ?? false,\n    activePlayers: new Set(),\n  };\n\n  const response = await InsertGroup(group);\n\n  if (response) {\n    SetupGroup(group);\n    GlobalState.groups = [...GlobalState.groups, data.name];\n  }\n}\n\nexport async function DeleteGroup(groupName: string) {\n  const deleted = await RemoveGroup(groupName);\n  const group = deleted && groups[groupName];\n\n  if (!group) throw new Error(`Cannot delete OxGroup<${groupName}> (no group exists with that name)`);\n\n  let parent = group.principal;\n\n  removeAce(parent, parent, true);\n\n  for (const i in group.grades) {\n    const child = `${group.principal}:${i}`;\n\n    removeAce(child, child, true);\n    removePrincipal(child, parent);\n\n    parent = child;\n  }\n\n  const players = OxPlayer.getAll({\n    groups: groupName,\n  });\n\n  for (const id in players) {\n    const player = players[id];\n\n    player.setGroup(groupName, 0, true);\n  }\n\n  GlobalState[group.principal] = null;\n  GlobalState[`${group.name}:count`] = null;\n  GlobalState[`${group.name}:activeCount`] = null;\n  GlobalState.groups = GlobalState.groups.filter((name: string) => name !== groupName);\n  delete groups[group.name];\n}\n\nasync function LoadGroups() {\n  const dbGroups = await SelectGroups();\n  GlobalState.groups = dbGroups.map((group) => SetupGroup(group).name);\n}\n\nsetImmediate(LoadGroups);\n\naddCommand(\"reloadgroups\", LoadGroups, {\n  help: \"Reload groups from the database.\",\n  restricted: \"group.admin\",\n});\n\naddCommand<{ target: string; group: string; grade?: number }>(\n  \"setgroup\",\n  async (playerId, args, raw) => {\n    const player = OxPlayer.get(args.target);\n\n    player?.setGroup(args.group, args.grade || 0);\n  },\n  {\n    help: `Update a player's grade for a group.`,\n    restricted: \"group.admin\",\n    params: [\n      { name: \"target\", paramType: \"playerId\" },\n      { name: \"group\", paramType: \"string\" },\n      {\n        name: \"grade\",\n        paramType: \"number\",\n        help: \"The new grade to set. Set to 0 or omit to remove the group.\",\n        optional: true,\n      },\n    ],\n  },\n);\n\nexports(\"GetGroupsByType\", GetGroupsByType);\nexports(\"SetGroupPermission\", SetGroupPermission);\nexports(\"RemoveGroupPermission\", RemoveGroupPermission);\nexports(\"CreateGroup\", CreateGroup);\nexports(\"DeleteGroup\", DeleteGroup);\nexports(\"GetGroupActivePlayers\", GetGroupActivePlayers);\nexports(\"GetGroupActivePlayersByType\", GetGroupActivePlayersByType);\n"
  },
  {
    "path": "server/index.ts",
    "content": "export * from \"../common\";\nimport \"./bridge\";\nimport \"player\";\nimport \"utils\";\nimport \"accounts\";\nimport \"vehicle\";\nimport { versionCheck } from \"@overextended/ox_lib/server\";\nimport { DEBUG } from \"config\";\n\nif (!DEBUG) {\n  versionCheck(\"overextended/ox_core\");\n}\n"
  },
  {
    "path": "server/player/class.ts",
    "content": "import { ClassInterface } from \"classInterface\";\nimport {\n  AddCharacterLicense,\n  CreateCharacter,\n  DeleteCharacter,\n  GetCharacterLicenses,\n  GetCharacterMetadata,\n  GetCharacters,\n  IsStateIdAvailable,\n  RemoveCharacterLicense,\n  SaveCharacterData,\n  UpdateCharacterLicense,\n} from \"./db\";\nimport { getRandomChar, getRandomInt } from \"@overextended/ox_lib\";\nimport { GetGroup, GetGroupsByType } from \"groups\";\nimport { GeneratePhoneNumber } from \"bridge/npwd\";\nimport { Statuses } from \"./status\";\nimport { addPrincipal, removePrincipal } from \"@overextended/ox_lib/server\";\nimport {\n  AddCharacterGroup,\n  GetCharacterGroups,\n  RemoveCharacterGroup,\n  UpdateCharacterGroup,\n  SetActiveGroup,\n} from \"groups/db\";\nimport { PayAccountInvoice } from \"accounts\";\nimport type { Character, Dict, NewCharacter, PlayerMetadata, OxGroup, CharacterLicense, BanDetails } from \"types\";\nimport { GetGroupPermissions } from \"../../common\";\nimport { Licenses } from \"./license\";\nimport { CHARACTER_SLOTS } from \"config\";\nimport locales from \"../../common/locales\";\n\nexport class OxPlayer extends ClassInterface {\n  source: number | string;\n  userId: number;\n  charId?: number;\n  stateId?: string;\n  username: string;\n  identifier: string;\n  ped: number;\n  #characters: Character[];\n  #metadata: Dict<any>;\n  #statuses: Dict<number>;\n  #groups: Dict<number>;\n  #licenses: Dict<CharacterLicense>;\n\n  protected static members: Dict<OxPlayer> = {};\n  protected static keys: Dict<Dict<OxPlayer>> = {\n    userId: {},\n    charId: {},\n  };\n\n  /** Get an instance of OxPlayer with the matching playerId. */\n  static get(id: string | number) {\n    return this.members[id];\n  }\n\n  /** Get an instance of OxPlayer with the matching userId. */\n  static getFromUserId(id: number) {\n    return this.keys.userId[id];\n  }\n\n  /** Get an instance of OxPlayer with the matching charId. */\n  static getFromCharId(id: number) {\n    return this.keys.charId[id];\n  }\n\n  static formatBanReason(ban: BanDetails) {\n    const unbanTime = ban.unban_at ? new Date(ban.unban_at) : null;\n    let timeRemainingMessage;\n\n    if (unbanTime) {\n      const timeRemaining = +unbanTime - Date.now();\n      const hours = Math.floor(timeRemaining / (1000 * 60 * 60));\n      const minutes = Math.floor((timeRemaining % (1000 * 60 * 60)) / (1000 * 60));\n      const seconds = Math.floor((timeRemaining % (1000 * 60)) / 1000);\n\n      timeRemainingMessage = locales(\"ban_expires_in\", hours, minutes, seconds);\n    } else timeRemainingMessage = locales(\"ban_indefinite\");\n\n    return locales(\"ban_notice\", new Date(ban.banned_at).toLocaleString(), ban.reason, timeRemainingMessage);\n  }\n\n  /** Compares player fields and metadata to a filter, returning the player if all values match. */\n  private filter(criteria: Dict<any>) {\n    const { groups, ...filter } = criteria;\n\n    if (groups && !this.getGroup(groups)) return;\n\n    for (const key in filter) {\n      const value = filter[key];\n\n      if (this[key as keyof OxPlayer] !== value && this.#metadata[key] !== value) return;\n    }\n\n    return this;\n  }\n\n  /** Get an instance of OxPlayer with that matches the filter. */\n  static getFromFilter(filter: Dict<any>) {\n    for (const id in this.members) {\n      const player = this.members[id].filter(filter);\n      if (player) return player;\n    }\n  }\n\n  /** Gets all instances of OxPlayer, optionally comparing against a filter. */\n  static getAll(filter?: Dict<any>, asArray?: false): Dict<OxPlayer>;\n  static getAll(filter?: Dict<any>, asArray?: true): OxPlayer[];\n  static getAll(filter?: Dict<any>, asArray = false): Dict<OxPlayer> | OxPlayer[] {\n    if (!filter) return asArray ? Object.values(this.members) : this.members;\n\n    const obj: Dict<OxPlayer> = {};\n\n    for (const id in this.members) {\n      const player = this.members[id].filter(filter);\n      if (player) obj[id] = player;\n    }\n\n    return asArray ? Object.values(obj) : obj;\n  }\n\n  /** Saves all players to the database, and optionally kicks them from the server. */\n  static saveAll(kickWithReason?: string) {\n    const parameters = [];\n\n    for (const id in this.members) {\n      const player = this.members[id];\n\n      if (player.charId) {\n        parameters.push(player.#getSaveData());\n      }\n\n      if (kickWithReason) {\n        delete player.charId;\n        DropPlayer(player.source as string, kickWithReason);\n      }\n    }\n\n    DEV: console.info(`Saving ${parameters.length} players to the database.`);\n\n    if (parameters.length > 0) {\n      SaveCharacterData(parameters, true);\n      emit(\"ox:savedPlayers\", parameters.length);\n    }\n  }\n\n  constructor(source: number) {\n    super();\n    this.source = source;\n    this.#characters = [];\n    this.#metadata = {};\n    this.#statuses = {};\n    this.#groups = {};\n    this.#licenses = {};\n  }\n\n  /** Triggers an event on the player's client. */\n  emit(eventName: string, ...args: any[]) {\n    emitNet(eventName, this.source, ...args);\n  }\n\n  /** Stores a value in the active character's metadata. */\n  set<K extends string>(\n    key: K | keyof PlayerMetadata,\n    value: K extends keyof PlayerMetadata ? PlayerMetadata[K] : any,\n    replicated?: boolean,\n  ): void;\n  set(key: string, value: any, replicated?: boolean) {\n    this.#metadata[key] = value;\n\n    if (replicated) this.emit(\"ox:setPlayerData\", key, value);\n  }\n\n  /** Gets a value stored in active character's metadata. */\n  get<K extends string>(key: K | keyof PlayerMetadata): K extends keyof PlayerMetadata ? PlayerMetadata[K] : any {\n    return this.#metadata[key];\n  }\n\n  async payInvoice(invoiceId: number) {\n    if (!this.charId) return;\n    return await PayAccountInvoice(invoiceId, this.charId);\n  }\n\n  setActiveGroup(groupName?: string, temp?: boolean) {\n    if (!this.charId || (groupName && !(groupName in this.#groups))) return false;\n\n    const currentActiveGroup = this.get(\"activeGroup\");\n\n    if (currentActiveGroup) {\n      GlobalState[`${currentActiveGroup}:activeCount`] -= 1;\n\n      const group = GetGroup(currentActiveGroup);\n      group.activePlayers.delete(+this.source);\n    }\n\n    if (groupName) {\n      GlobalState[`${groupName}:activeCount`] += 1;\n\n      const group = GetGroup(groupName);\n      group.activePlayers.add(+this.source);\n    }\n\n    SetActiveGroup(this.charId, temp ? undefined : groupName);\n    this.set(\"activeGroup\", groupName, true);\n    emit(\"ox:setActiveGroup\", this.source, groupName, currentActiveGroup);\n\n    return true;\n  }\n\n  /** Sets the active character's grade in a group. If the grade is 0 they will be removed from the group. */\n  async setGroup(groupName: string, grade = 0, force = false) {\n    if (!this.charId) return false;\n\n    const group = GetGroup(groupName);\n\n    if (!group) return console.warn(`Failed to set OxPlayer<${this.userId}> ${groupName}:${grade} (invalid group)`);\n\n    const currentGrade = this.#groups[groupName];\n\n    if (currentGrade === grade) return;\n\n    if (!grade) {\n      if (!currentGrade) return;\n      if (!force && !(await RemoveCharacterGroup(this.charId, group.name))) return;\n\n      this.#removeGroup(group, currentGrade, true);\n\n      if (this.get(\"activeGroup\") === groupName) this.set(\"activeGroup\", undefined, true);\n    } else {\n      if (!group.grades[grade] && grade > 0)\n        return console.warn(`Failed to set OxPlayer<${this.userId}> ${group.name}:${grade} (invalid grade)`);\n\n      if (currentGrade) {\n        if (!(await UpdateCharacterGroup(this.charId, group.name, grade))) return;\n\n        this.#removeGroup(group, currentGrade, false);\n        this.#addGroup(group, grade);\n      } else {\n        const relatedGroups = group.type && GetGroupsByType(group.type);\n\n        if (\n          relatedGroups &&\n          relatedGroups.some((name) => {\n            return name in this.#groups;\n          })\n        )\n          return console.warn(\n            `Failed to set OxPlayer<${this.userId}> ${group.name}:${grade} (already has group of type '${group.type}')`,\n          );\n\n        if (!(await AddCharacterGroup(this.charId, group.name, grade))) return;\n\n        this.#addGroup(group, grade);\n      }\n    }\n\n    emit(\"ox:setGroup\", this.source, group.name, grade ? grade : null);\n    this.emit(\"ox:setGroup\", group.name, grade ? grade : null);\n\n    return true;\n  }\n\n  /** Returns the current grade of a given group name, or the first matched name and grade in the filter. */\n  getGroup(filter: string): number;\n  getGroup(filter: string[] | Record<string, number>): [string, number] | [];\n  getGroup(filter: string | string[] | Record<string, number>) {\n    if (typeof filter === \"string\") {\n      return this.#groups[filter];\n    }\n\n    if (Array.isArray(filter)) {\n      for (const name of filter) {\n        const grade = this.#groups[name];\n        if (grade) return [name, grade];\n      }\n    } else if (typeof filter === \"object\") {\n      for (const [name, requiredGrade] of Object.entries(filter)) {\n        const grade = this.#groups[name];\n        if (grade && (requiredGrade as number) <= grade) {\n          return [name, grade];\n        }\n      }\n    }\n  }\n\n  getGroupByType(type: string) {\n    return this.getGroup(GetGroupsByType(type));\n  }\n\n  getGroups() {\n    return this.#groups;\n  }\n\n  hasPermission(permission: string): boolean {\n    const matchResult = permission.match(/^group\\.([^.]+)\\.(.*)/);\n    const groupName = matchResult?.[1];\n    permission = matchResult?.[2] ?? permission;\n\n    if (groupName) {\n      const grade = this.#groups[groupName];\n\n      if (!grade) return false;\n\n      const permissions = GetGroupPermissions(groupName);\n\n      for (let g = grade; g > 0; g--) {\n        const value = permissions[g] && permissions[g][permission];\n\n        if (value !== undefined) return value;\n      }\n    }\n\n    return false;\n  }\n\n  /** Sets the value of a status. */\n  setStatus(statusName: string, value = Statuses[statusName].default) {\n    if (Statuses[statusName] === undefined) return;\n\n    const newValue = value < 0 ? 0 : value > 100 ? 100 : Number.parseFloat(value.toPrecision(8));\n    this.#statuses[statusName] = newValue;\n\n    this.emit(\"ox:setPlayerStatus\", statusName, newValue, true);\n\n    return true;\n  }\n\n  /** Returns the current value of a status. */\n  getStatus(statusName: string) {\n    return this.#statuses[statusName];\n  }\n\n  /** Returns an object containing all status names and their values. */\n  getStatuses() {\n    return this.#statuses;\n  }\n\n  /** Increases the status's value by the given amount. */\n  addStatus(statusName: string, value: number) {\n    if (this.#statuses[statusName] === undefined) return;\n\n    let newValue = this.#statuses[statusName] + value;\n    newValue = newValue < 0 ? 0 : newValue > 100 ? 100 : Number.parseFloat(newValue.toPrecision(8));\n\n    this.#statuses[statusName] = newValue;\n    this.emit(\"ox:setPlayerStatus\", statusName, newValue);\n\n    return true;\n  }\n\n  /** Reduces the status's value by the given amount. */\n  removeStatus(statusName: string, value: number) {\n    if (this.#statuses[statusName] === undefined) return;\n\n    let newValue = this.#statuses[statusName] - value;\n    newValue = newValue < 0 ? 0 : newValue > 100 ? 100 : Number.parseFloat(newValue.toPrecision(8));\n\n    this.#statuses[statusName] = newValue;\n    this.emit(\"ox:setPlayerStatus\", statusName, newValue);\n\n    return true;\n  }\n\n  getLicense(licenseName: string) {\n    return this.#licenses[licenseName];\n  }\n\n  getLicenses() {\n    return this.#licenses;\n  }\n\n  async addLicense(licenseName: string) {\n    if (!this.charId || this.#licenses[licenseName] || !Licenses[licenseName]) return false;\n\n    const license = {\n      issued: Date.now(),\n    };\n\n    if (!(await AddCharacterLicense(this.charId, licenseName, license))) return false;\n\n    this.#licenses[licenseName] = license;\n\n    emit(\"ox:licenseAdded\", this.source, licenseName);\n    this.emit(\"ox:licenseAdded\", licenseName);\n\n    return true;\n  }\n\n  async removeLicense(licenseName: string) {\n    if (!this.charId || !(await RemoveCharacterLicense(this.charId, licenseName))) return false;\n\n    delete this.#licenses[licenseName];\n\n    emit(\"ox:licenseRemoved\", this.source, licenseName);\n    this.emit(\"ox:licenseRemoved\", licenseName);\n\n    return true;\n  }\n\n  async updateLicense(licenseName: string, key: string, value: any) {\n    if (!this.charId) return false;\n\n    const license = this.#licenses[licenseName];\n\n    if (!license || key === \"issued\") return false;\n\n    if (!(await UpdateCharacterLicense(this.charId, licenseName, key, value))) return false;\n\n    value == null ? delete license[key] : (license[key] = value);\n\n    return true;\n  }\n\n  /** Returns an array of values to be saved in the database. */\n  #getSaveData() {\n    return [\n      ...GetEntityCoords(this.ped),\n      GetEntityHeading(this.ped),\n      Player(this.source).state.isDead || false,\n      GetEntityHealth(this.ped),\n      GetPedArmour(this.ped),\n      JSON.stringify(this.#statuses || {}),\n      this.charId,\n    ];\n  }\n\n  /** Adds the active character to the group and sets permissions. */\n  #addGroup(group: string | OxGroup, grade: number) {\n    const groupName = typeof group === \"string\" ? group : group.name;\n    group = GetGroup(groupName);\n\n    if (!group) return console.warn(`Failed to add group '${groupName}' to OxPlayer<${this.userId}> (invalid group)`);\n\n    addPrincipal(this.source as string, `${group.principal}:${grade}`);\n    DEV: console.info(`Added OxPlayer<${this.userId}> to group '${group.name}' as grade ${grade}.`);\n\n    this.#groups[group.name] = grade;\n    GlobalState[`${group.name}:count`] += 1;\n  }\n\n  /** Removes the active character from the group and sets permissions. */\n  #removeGroup(group: string | OxGroup, grade: number, canRemoveActiveCount = false) {\n    const groupName = typeof group === \"string\" ? group : group.name;\n    group = GetGroup(groupName);\n\n    if (!group)\n      return console.warn(`Failed to remove group '${groupName}' from OxPlayer<${this.userId}> (invalid group)`);\n\n    removePrincipal(this.source as string, `${group.principal}:${grade}`);\n    DEV: console.info(`Removed OxPlayer<${this.userId}> from group '${group.name}'.`);\n\n    delete this.#groups[group.name];\n    GlobalState[`${group.name}:count`] -= 1;\n\n    if (canRemoveActiveCount && group.name === this.get(\"activeGroup\")) {\n      GlobalState[`${group.name}:activeCount`] -= 1;\n      group.activePlayers.delete(+this.source);\n    }\n  }\n\n  /** Saves the active character to the database. */\n  save() {\n    if (this.charId) return SaveCharacterData(this.#getSaveData());\n  }\n\n  /** Adds the player to the player registry and starts character selection. */\n  async setAsJoined() {\n    if (!OxPlayer.getFromUserId(this.userId)) {\n      OxPlayer.add(this.source, this);\n      Player(this.source).state.set(\"userId\", this.userId, true);\n    }\n\n    DEV: console.info(`Starting character selection for OxPlayer<${this.userId}>`);\n\n    this.emit(\"ox:startCharacterSelect\", this.userId, await this.#getCharacters());\n  }\n\n  /** Returns an array of all characters owned by the player, excluding soft-deleted characters. */\n  async #getCharacters() {\n    this.#characters = await GetCharacters(this.userId);\n    return this.#characters;\n  }\n\n  /**\n   * Clears data for the active character. If the player is still connected then transition them to character selection.\n   * @param dropped If the player has been dropped from the server.\n   * @param save If character data should be saved to the database (defaults to true).\n   */\n  async logout(save = true, dropped = false) {\n    if (!this.charId) return;\n\n    for (const name in this.#groups) this.#removeGroup(name, this.#groups[name], true);\n\n    emit(\"ox:playerLogout\", this.source, this.userId, this.charId);\n\n    if (save) await this.save();\n\n    if (dropped) return;\n\n    delete OxPlayer.keys.charId[this.charId];\n    delete this.charId;\n\n    this.emit(\"ox:startCharacterSelect\", this.userId, await this.#getCharacters());\n  }\n\n  /** Creates a stateId for a newly created character. */\n  async #generateStateId() {\n    const arr = [];\n\n    while (true) {\n      for (let i = 0; i < 2; i++) arr[i] = getRandomChar();\n      for (let i = 2; i < 6; i++) arr[i] = getRandomInt();\n\n      const stateId = arr.join(\"\");\n\n      if (await IsStateIdAvailable(stateId)) return stateId;\n    }\n  }\n\n  /** Registers a new character for the player. */\n  async createCharacter(data: NewCharacter) {\n    if (this.charId || this.#characters.length >= CHARACTER_SLOTS) return;\n\n    const stateId = await this.#generateStateId();\n    const phoneNumber = await GeneratePhoneNumber();\n\n    const character: Character = {\n      firstName: data.firstName,\n      lastName: data.lastName,\n      stateId: stateId,\n      charId: await CreateCharacter(\n        this.userId,\n        stateId,\n        data.firstName,\n        data.lastName,\n        data.gender,\n        data.date,\n        phoneNumber,\n      ),\n      isNew: true,\n      gender: data.gender,\n    };\n\n    this.#characters.push(character);\n    emit(\"ox:createdCharacter\", this.source, this.userId, character.charId);\n\n    return this.#characters.length - 1;\n  }\n\n  /** Returns the current index for a character with the given charId. */\n  #getCharacterSlotFromId(charId: number) {\n    if (this.charId) return -1;\n\n    return this.#characters.findIndex((character) => {\n      return character.charId === charId;\n    });\n  }\n\n  /** Loads and sets the player's active character. */\n  async setActiveCharacter(data: number | NewCharacter) {\n    if (this.charId) return;\n\n    const characterSlot =\n      typeof data === \"object\" ? await this.createCharacter(data) : this.#getCharacterSlotFromId(data);\n\n    if (characterSlot == null) return;\n\n    const character = this.#characters[characterSlot];\n\n    this.#characters.length = 0;\n    this.charId = character.charId;\n    this.stateId = character.stateId;\n    this.ped = GetPlayerPed(this.source as string);\n\n    const metadata = await GetCharacterMetadata(character.charId);\n\n    if (!metadata) return;\n\n    const statuses = metadata.statuses || this.#statuses;\n    const { isDead, gender, dateOfBirth, phoneNumber, health, armour } = metadata;\n    const groups = await GetCharacterGroups(this.charId);\n    const licenses = await GetCharacterLicenses(this.charId);\n    const activeGroup = groups.find((group) => group.isActive)?.name;\n\n    character.health = isDead ? 0 : health;\n    character.armour = armour;\n\n    groups.forEach(({ name, grade }) => this.#addGroup(name, grade));\n    licenses.forEach(({ name, data }) => (this.#licenses[name] = data));\n\n    for (const name in Statuses) this.setStatus(name, statuses[name]);\n\n    this.emit(\"ox:setActiveCharacter\", character, this.#groups);\n\n    // Values stored in metadata and synced to client.\n    this.set(\"name\", `${character.firstName} ${character.lastName}`, true);\n    this.set(\"firstName\", character.firstName, true);\n    this.set(\"lastName\", character.lastName, true);\n    this.set(\"gender\", gender, true);\n    this.set(\"dateOfBirth\", dateOfBirth, true);\n    this.set(\"phoneNumber\", phoneNumber, true);\n    this.set(\"activeGroup\", activeGroup, true);\n\n    if (activeGroup) {\n      GlobalState[`${activeGroup}:activeCount`] += 1;\n\n      const group = GetGroup(activeGroup);\n      group.activePlayers.add(+this.source);\n    }\n\n    DEV: console.info(`Restored OxPlayer<${this.userId}> previous active group: ${activeGroup}`);\n\n    OxPlayer.keys.charId[character.charId] = this;\n\n    /**\n     * @todo Player metadata can ideally be handled with statebags, but requires security features.\n     * Rejection of client-set values is a must-have.\n     * \"Private\" states only visible to the owner would be :chefskiss:\n     * https://github.com/citizenfx/fivem/pull/2257 - state bag filters\n     * https://github.com/citizenfx/fivem/pull/2257 - state bag write policies\n     */\n    const state = Player(this.source).state;\n    state.set(\"isDead\", isDead === 1, true);\n\n    DEV: console.info(`OxPlayer<${this.userId}> loaded character ${this.get(\"name\")} (${this.charId})`);\n\n    emit(\"ox:playerLoaded\", this.source, this.userId, character.charId);\n\n    return character;\n  }\n\n  /** Deletes a character with the given charId if it's owned by the player. */\n  async deleteCharacter(charId: number) {\n    const isActive = this.charId === charId;\n\n    if (this.charId && !isActive) return;\n\n    const characterSlot = isActive ? 0 : this.#getCharacterSlotFromId(charId);\n\n    if (characterSlot === -1) return;\n\n    if (await DeleteCharacter(charId)) {\n      if (isActive) this.logout(false);\n      else this.#characters.splice(characterSlot, 1);\n\n      emit(\"ox:deletedCharacter\", this.source, this.userId, charId);\n\n      DEV: console.info(`Deleted character ${charId} for OxPlayer<${this.userId}>`);\n      return true;\n    }\n  }\n}\n\nOxPlayer.init();\n\nexports(\"SaveAllPlayers\", (arg: any) => OxPlayer.saveAll(arg));\nexports(\"GetPlayerFromUserId\", (arg: any) => OxPlayer.getFromUserId(arg));\nexports(\"GetPlayerFromCharId\", (arg: any) => OxPlayer.getFromCharId(arg));\nexports(\"GetPlayerFromFilter\", (arg: any) => OxPlayer.getFromFilter(arg));\nexports(\"GetPlayers\", (arg: any) => OxPlayer.getAll(arg, true));\n"
  },
  {
    "path": "server/player/commands.ts",
    "content": "import { addCommand } from \"@overextended/ox_lib/server\";\nimport { OxPlayer } from \"player/class\";\n\n// NOTE: These commands are intended for development purposes.\n\naddCommand(\"logout\", async (playerId) => OxPlayer.get(playerId).logout(true), {\n  help: \"Logout and return to character selection.\",\n  restricted: \"group.admin\",\n});\n\naddCommand(\n  \"deletechar\",\n  async (playerId) => {\n    const player = OxPlayer.get(playerId);\n\n    if (!player.charId) return;\n\n    player.deleteCharacter(player.charId);\n  },\n  {\n    help: \"Hard delete your current character (cannot be reversed).\",\n    restricted: \"group.admin\",\n  },\n);\n\naddCommand(\n  \"charinfo\",\n  async (playerId) => {\n    const player = OxPlayer.get(playerId);\n    console.log(`${player.get(\"firstName\")} ${player.get(\"lastName\")} (${player.charId}) - ${player.stateId}`);\n  },\n  {\n    help: \"Display basic character information.\",\n  },\n);\n"
  },
  {
    "path": "server/player/db.ts",
    "content": "import type { Character, Dict, OxStatus, CharacterLicense, OxLicense, BanDetails } from 'types';\nimport { CHARACTER_SLOTS } from '../../common/config';\nimport { db } from '../db';\nimport { OxPlayer } from './class';\n\nexport function GetUserIdFromIdentifier(identifier: string, offset?: number) {\n  return db.column<number>('SELECT userId FROM users WHERE license2 = ? LIMIT ?, 1', [identifier, offset || 0]);\n}\n\nexport function CreateUser(username: string, { license2, steam, fivem, discord }: Dict<string>) {\n  return db.insert('INSERT INTO users (username, license2, steam, fivem, discord) VALUES (?, ?, ?, ?, ?)', [\n    username,\n    license2,\n    steam,\n    fivem,\n    discord,\n  ]);\n}\n\nexport async function IsStateIdAvailable(stateId: string) {\n  return !(await db.exists('SELECT 1 FROM characters WHERE stateId = ?', [stateId]));\n}\n\nexport function CreateCharacter(\n  userId: number,\n  stateId: string,\n  firstName: string,\n  lastName: string,\n  gender: string,\n  date: number,\n  phoneNumber?: number,\n) {\n  return db.insert(\n    'INSERT INTO characters (userId, stateId, firstName, lastName, gender, dateOfBirth, phoneNumber) VALUES (?, ?, ?, ?, ?, ?, ?)',\n    [userId, stateId, firstName, lastName, gender, new Date(Number(date)), phoneNumber],\n  );\n}\n\nexport function GetCharacters(userId: number) {\n  return db.execute<Character>(\n    'SELECT charId, stateId, firstName, lastName, gender, x, y, z, heading, DATE_FORMAT(lastPlayed, \"%d/%m/%Y\") AS lastPlayed FROM characters WHERE userId = ? AND deleted IS NULL LIMIT ?',\n    [userId, CHARACTER_SLOTS],\n  );\n}\n\nexport function SaveCharacterData(values: any[] | any[][], batch?: boolean) {\n  const query =\n    'UPDATE characters SET x = ?, y = ?, z = ?, heading = ?, isDead = ?, lastPlayed = CURRENT_TIMESTAMP(), health = ?, armour = ?, statuses = ? WHERE charId = ?';\n\n  return batch ? db.batch(query, values) : db.update(query, values);\n}\n\nexport async function DeleteCharacter(charId: number) {\n  return (await db.update('UPDATE characters SET deleted = curdate() WHERE charId = ?', [charId])) === 1;\n}\n\nexport function GetCharacterMetadata(charId: number) {\n  return db.row<{\n    isDead: number;\n    gender: string;\n    dateOfBirth: string;\n    phoneNumber: string;\n    health: number;\n    armour: number;\n    statuses: Dict<number>;\n  }>(\n    'SELECT isDead, gender, DATE_FORMAT(dateOfBirth, \"%d/%m/%Y\") AS dateOfBirth, phoneNumber, health, armour, statuses FROM characters WHERE charId = ?',\n    [charId],\n  );\n}\n\nexport function GetStatuses() {\n  return db.query<OxStatus>('SELECT name, `default`, onTick FROM ox_statuses');\n}\n\nexport function GetLicenses() {\n  return db.query<Dict<OxLicense>>('SELECT name, label FROM ox_licenses');\n}\n\nexport function GetLicense(name: string) {\n  return db.row<OxLicense>('SELECT name, label FROM ox_licenses WHERE name = ?', [name]);\n}\n\nexport function GetCharacterLicenses(charId: number) {\n  return db.query<{ name: string; data: CharacterLicense }>(\n    'SELECT name, data FROM character_licenses WHERE charId = ?',\n    [charId],\n  );\n}\n\nexport function AddCharacterLicense(charId: number, name: string, data: CharacterLicense) {\n  return db.update('INSERT INTO character_licenses (charId, name, data) VALUES (?, ?, ?)', [\n    charId,\n    name,\n    JSON.stringify(data),\n  ]);\n}\n\nexport function RemoveCharacterLicense(charId: number, name: string) {\n  return db.update('DELETE FROM character_licenses WHERE charId = ? AND name = ?', [charId, name]);\n}\n\nexport function UpdateCharacterLicense(charId: number, name: string, key: string, value: any) {\n  const params = [`$.${key}`, name, charId];\n\n  if (value == null)\n    return db.update('UPDATE character_licenses SET data = JSON_REMOVE(data, ?) WHERE name = ? AND charId = ?', params);\n\n  params.splice(1, 0, value);\n\n  return db.update('UPDATE character_licenses SET data = JSON_SET(data, ?, ?) WHERE name = ? AND charId = ?', params);\n}\n\nexport function GetCharIdFromStateId(stateId: string) {\n  return db.column<number>('SELECT charId FROM characters WHERE stateId = ?', [stateId]);\n}\n\nexport async function UpdateUserTokens(userId: number, tokens: string[]) {\n  if (tokens.length === 0) return;\n\n  const parameters = tokens.map((token) => [userId, token]);\n\n  await db.batch('INSERT IGNORE INTO user_tokens (userId, token) VALUES (?, ?)', parameters);\n}\n\nexport async function IsUserBanned(userId: number): Promise<BanDetails | undefined> {\n  const banDetails = await db.query<BanDetails>(\n    `SELECT bu.reason, bu.banned_at, bu.unban_at, bu.userId, ut.token\n       FROM user_tokens ut\n       JOIN banned_users bu ON ut.userId = bu.userId\n       WHERE ut.userId = ?\n       GROUP BY bu.userId`,\n    [userId],\n  );\n\n  if (!banDetails?.[0]) return;\n\n  const currentDate = new Date();\n  const expiredBans = banDetails.filter((ban) => ban.unban_at && new Date(ban.unban_at) <= currentDate);\n\n  if (expiredBans.length > 0) {\n    await db.query(`DELETE FROM banned_users WHERE userId IN (?)`, [expiredBans.map((ban) => ban.userId)]);\n    return;\n  }\n\n  return banDetails[0];\n}\n\nexport async function BanUser(userId: number, reason?: string, hours?: number) {\n  const success = await db.update(\n    'INSERT INTO banned_users (userId, banned_at, unban_at, reason) VALUES (?, NOW(), DATE_ADD(NOW(), INTERVAL ? HOUR), ?)',\n    [userId, hours, reason],\n  );\n\n  if (!success) {\n    console.error(`Failed to ban ${userId}`);\n    return false;\n  }\n\n  const playerId = OxPlayer.getFromUserId(userId)?.source as string;\n\n  if (playerId) {\n    const banned_at = Date.now();\n    const unban_at = banned_at + (hours ? hours * 60 * 60 * 1000 : 0);\n\n    DropPlayer(playerId, OxPlayer.formatBanReason({ userId, banned_at, unban_at, reason }));\n  }\n\n  return true;\n}\n\nexport async function UnbanUser(userId: number) {\n  const success = await db.update('DELETE FROM banned_users WHERE userId = ?', [userId]);\n\n  return success;\n}\n"
  },
  {
    "path": "server/player/events.ts",
    "content": "import { onClientCallback } from \"@overextended/ox_lib/server\";\nimport { OxPlayer } from \"./class\";\nimport { sleep } from \"@overextended/ox_lib\";\nimport { db } from \"db\";\nimport { Statuses } from \"./status\";\nimport { CreateNewAccount } from \"accounts/db\";\nimport type { Dict, NewCharacter, OxStatus } from \"types\";\nimport { CREATE_DEFAULT_ACCOUNT } from \"config\";\nimport \"./license\";\n\nconst playerLoadEvents: Dict<Function> = {};\nconst playerLogoutEvents: Function[] = [];\n\n/** Triggers a callback when a player is fully loaded, or when the resource starts.  */\nexport function OnPlayerLoaded(resource: string, cb: (player: OxPlayer) => void) {\n  playerLoadEvents[resource] = cb;\n}\n\n/** Triggers a callback when a player logs out. */\nexport function OnPlayerLogout(cb: (player: OxPlayer) => void) {\n  playerLogoutEvents.push(cb);\n}\n\non(\"ox:playerLoaded\", (playerId: string | number) => {\n  for (const resource in playerLoadEvents) {\n    const player = OxPlayer.get(playerId);\n\n    if (player.charId)\n      try {\n        playerLoadEvents[resource](player);\n      } catch (e) {\n        DEV: console.info(e.message);\n      }\n  }\n});\n\non(\"onServerResourceStart\", async (resource: string) => {\n  const event = playerLoadEvents[resource];\n\n  if (!event) return;\n\n  await sleep(1000);\n\n  const players = OxPlayer.getAll();\n\n  for (const id in players) {\n    const player = players[id];\n\n    if (player.charId)\n      try {\n        event(player);\n      } catch (e) {\n        DEV: console.info(e.message);\n      }\n  }\n});\n\non(\"ox:playerLogout\", (playerId: number) => {\n  const player = OxPlayer.get(playerId);\n\n  if (player.charId)\n    for (const i in playerLogoutEvents)\n      try {\n        playerLogoutEvents[i](player);\n      } catch (e) {\n        DEV: console.info(e.message);\n      }\n});\n\non(\"onResourceStop\", (resource: string) => {\n  if (resource !== \"ox_core\") return;\n\n  const players = OxPlayer.getAll();\n\n  for (const id in players) {\n    const player = players[id];\n\n    if (player.charId) emit(\"ox:playerLogout\", player.source, player.userId, player.charId);\n  }\n});\n\nonNet(\"ox:setActiveCharacter\", async (data: number | NewCharacter) => {\n  const player = OxPlayer.get(source);\n\n  if (!player) return;\n\n  return await player.setActiveCharacter(data);\n});\n\nonClientCallback(\"ox:deleteCharacter\", async (playerId, charId: number) => {\n  const player = OxPlayer.get(playerId);\n\n  if (!player) return;\n\n  return await player.deleteCharacter(charId);\n});\n\non(\"ox:createdCharacter\", async (playerId: number, userId: number, charId: number) => {\n  db.execute(\"INSERT INTO character_inventory (charId) VALUES (?)\", [charId]);\n\n  if (CREATE_DEFAULT_ACCOUNT) CreateNewAccount(charId, \"Personal\", true);\n});\n\nonNet(\"ox:updateStatuses\", async (data: Dict<OxStatus>) => {\n  const player = OxPlayer.get(source);\n\n  if (!player) return;\n\n  for (const name in data) {\n    const status = Statuses[name];\n    const value = data[name];\n\n    if (status && typeof value === \"number\") {\n      player.setStatus(name, value);\n    }\n  }\n});\n\nonClientCallback(\"ox:setActiveGroup\", (playerId, groupName: string) => {\n  const player = OxPlayer.get(playerId);\n\n  if (!player) return false;\n\n  return player.setActiveGroup(groupName);\n});\n\nonClientCallback(\"ox:getLicense\", (playerId, licenseName: string, target?: number) => {\n  const player = OxPlayer.get(target || playerId);\n\n  if (player) return licenseName ? player.getLicense(licenseName) : player.getLicenses();\n});\n\non(\"txAdmin:events:playerHealed\", ({ target, author }: { target: number; author: string }) => {\n  if (target === -1) {\n    const players = OxPlayer.getAll();\n\n    for (const id in players) {\n      const state = Player(id).state;\n\n      state.set(\"isDead\", false, true);\n    }\n  } else {\n    const state = Player(target).state;\n\n    state.set(\"isDead\", false, true);\n  }\n});\n"
  },
  {
    "path": "server/player/index.ts",
    "content": "import './loading';\nimport './events';\nimport './commands';\nimport { OxPlayer } from './class';\nimport { BanUser, GetCharIdFromStateId, UnbanUser } from './db';\n\n/**\n * Sets an interval to save every 10 minutes.\n * @todo Consider performance on servers with a high player-count.\n * Multiple staggered saves may improve load.\n */\nsetInterval(() => OxPlayer.saveAll(), 600000);\n\nexports('GetCharIdFromStateId', GetCharIdFromStateId);\nexports('BanUser', BanUser);\nexports('UnbanUser', UnbanUser);\n"
  },
  {
    "path": "server/player/license.ts",
    "content": "import { addCommand } from \"@overextended/ox_lib/server\";\nimport type { Dict, OxLicense } from \"types\";\nimport { GetLicense, GetLicenses } from \"./db\";\n\nexport const Licenses: Dict<OxLicense> = {};\n\nasync function LoadLicenses() {\n  const rows = await GetLicenses();\n\n  if (!rows[0]) return;\n\n  for (let i = 0; i < rows.length; i++) {\n    const license = rows[i];\n    const name = license.name as string;\n    delete license.name;\n\n    Licenses[name] = license;\n    GlobalState[`license.${name}`] = license;\n  }\n}\n\nsetImmediate(LoadLicenses);\n\naddCommand(\"reloadlicenses\", LoadLicenses, {\n  help: \"Reload licenses from the database.\",\n  restricted: \"group.admin\",\n});\n\nexports(\"GetLicenses\", GetLicenses);\nexports(\"GetLicense\", GetLicense);\n"
  },
  {
    "path": "server/player/loading.ts",
    "content": "import { OxPlayer } from 'player/class';\nimport { CreateUser, GetUserIdFromIdentifier, IsUserBanned, UpdateUserTokens } from './db';\nimport { GetIdentifiers, GetPlayerLicense } from 'utils';\nimport { DEBUG, SV_LAN } from '../config';\nimport type { Dict } from 'types';\nimport locales from '../../common/locales';\n\nconst connectingPlayers: Dict<OxPlayer> = {};\n\n/** Loads existing data for the player, or inserts new data into the database. */\nasync function loadPlayer(playerId: number) {\n  let player: OxPlayer | undefined;\n\n  try {\n    if (serverLockdown) return serverLockdown;\n\n    player = new OxPlayer(playerId);\n    const license = SV_LAN ? 'fayoum' : GetPlayerLicense(playerId);\n\n    if (!license) return locales('no_license');\n\n    const identifier = license.substring(license.indexOf(':') + 1);\n    let userId: number;\n\n    userId = (await GetUserIdFromIdentifier(identifier)) ?? 0;\n\n    if (userId && OxPlayer.getFromUserId(userId)) {\n      const kickReason = locales('userid_is_active', userId);\n\n      if (!DEBUG) return kickReason;\n\n      userId = (await GetUserIdFromIdentifier(identifier, 1)) ?? 0;\n      if (userId && OxPlayer.getFromUserId(userId)) return kickReason;\n    }\n\n    const tokens = getPlayerTokens(playerId);\n    await UpdateUserTokens(userId, tokens);\n\n    const ban = await IsUserBanned(userId);\n\n    if (ban) {\n      return OxPlayer.formatBanReason(ban);\n    }\n\n    player.username = GetPlayerName(player.source as string);\n    player.userId = userId ? userId : await CreateUser(player.username, GetIdentifiers(playerId));\n    player.identifier = identifier;\n\n    DEV: console.info(`Loaded player data for OxPlayer<${player.userId}>`);\n\n    return player;\n  } catch (err) {\n    console.error('Error loading player:', err);\n\n    if (player?.userId) {\n      try {\n        OxPlayer.remove(player.source);\n      } catch (cleanupErr) {\n        console.error('Error during cleanup:', cleanupErr);\n      }\n    }\n\n    return err.message;\n  }\n}\n\nlet serverLockdown: string;\n\nsetInterval(() => {\n  for (const tempId in connectingPlayers) {\n    if (!DoesPlayerExist(tempId)) delete connectingPlayers[tempId];\n  }\n}, 10000);\n\non('txAdmin:events:serverShuttingDown', () => {\n  serverLockdown = locales('server_restarting');\n  OxPlayer.saveAll(serverLockdown);\n});\n\non('playerConnecting', async (username: string, _: any, deferrals: any) => {\n  const tempId = source;\n\n  deferrals.defer();\n\n  if (serverLockdown) return deferrals.done(serverLockdown);\n\n  const player = await loadPlayer(tempId);\n\n  if (!(player instanceof OxPlayer)) return deferrals.done(player || 'Failed to load player.');\n\n  connectingPlayers[tempId] = player;\n\n  deferrals.done();\n});\n\non('playerJoining', async (tempId: string) => {\n  if (serverLockdown) return DropPlayer(source.toString(), serverLockdown);\n\n  const player = connectingPlayers[tempId];\n\n  if (!player) return;\n\n  delete connectingPlayers[tempId];\n  connectingPlayers[source] = player;\n  player.source = source;\n\n  DEV: console.info(`Assigned id ${source} to OxPlayer<${player.userId}>`);\n});\n\nonNet('ox:playerJoined', async () => {\n  const playerSrc = source;\n  const player = connectingPlayers[playerSrc] || (await loadPlayer(playerSrc));\n  delete connectingPlayers[playerSrc];\n\n  if (!(player instanceof OxPlayer)) return DropPlayer(playerSrc.toString(), player || 'Failed to load player.');\n\n  player.setAsJoined();\n});\n\non('playerDropped', () => {\n  const player = OxPlayer.get(source);\n\n  if (!player) return;\n\n  player.logout(true, true);\n  OxPlayer.remove(player.source);\n\n  DEV: console.info(`Dropped OxPlayer<${player.userId}>`);\n});\n\nRegisterCommand(\n  'saveplayers',\n  () => {\n    OxPlayer.saveAll();\n  },\n  true,\n);\n"
  },
  {
    "path": "server/player/status.ts",
    "content": "import { addCommand } from \"@overextended/ox_lib/server\";\nimport { GetStatuses } from \"./db\";\nimport { OxPlayer } from \"./class\";\nimport type { Dict, OxStatus } from \"types\";\n\nexport const Statuses: Dict<OxStatus> = {};\n\nasync function LoadStatuses() {\n  const rows = await GetStatuses();\n\n  if (!rows[0]) return;\n\n  const players = OxPlayer.getAll();\n\n  for (let i = 0; i < rows.length; i++) {\n    const status = rows[i];\n\n    for (const id in players) {\n      const player = players[id];\n      const value = player.charId && player.getStatus(status.name);\n\n      if (!value || value > 100) player.setStatus(status.name, status.default);\n    }\n\n    Statuses[status.name] = status;\n    GlobalState[`status.${status.name}`] = status;\n  }\n}\n\nsetImmediate(LoadStatuses);\n\naddCommand(\"reloadstatuses\", LoadStatuses, {\n  help: \"Reload statuses from the database.\",\n  restricted: \"group.admin\",\n});\n"
  },
  {
    "path": "server/tsconfig.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"types\": [\"@citizenfx/server\"],\n    \"composite\": true,\n    \"paths\": {\n      \"types\": [\"../types\"]\n    }\n  },\n  \"include\": [\"./\", \"../types\", \"../common/\", \"../locales/en.json\"]\n}\n"
  },
  {
    "path": "server/utils.ts",
    "content": "import { SV_LAN } from 'config';\nimport type { Dict } from 'types';\n\nexport function GetPlayerLicense(playerId: number | string) {\n  return (\n    GetPlayerIdentifierByType(playerId as string, 'license2') ||\n    GetPlayerIdentifierByType(playerId as string, 'license')\n  );\n}\n\nexport function GetIdentifiers(playerId: number | string) {\n  const identifiers: Dict<string> = {};\n  playerId = playerId.toString();\n\n  for (let index = 0; index < GetNumPlayerIdentifiers(playerId); index++) {\n    const [prefix, identifier] = GetPlayerIdentifier(playerId, index).split(':');\n\n    if (prefix !== 'ip') identifiers[prefix] = identifier;\n  }\n\n  if (!identifiers.license2) {\n    identifiers.license2 = SV_LAN ? 'fayoum' : identifiers.license;\n\n    if (!identifiers.license2) throw new Error(`No license2 found for user [${playerId}] ${GetPlayerName(playerId)}`);\n  }\n\n  return identifiers;\n}\n"
  },
  {
    "path": "server/vehicle/class.ts",
    "content": "import { ClassInterface } from \"classInterface\";\nimport { DeleteVehicle, IsPlateAvailable, IsVinAvailable, SaveVehicleData, SetVehicleColumn } from \"./db\";\nimport {\n  getRandomString,\n  getRandomAlphanumeric,\n  getRandomChar,\n  getRandomInt,\n  type VehicleProperties,\n} from \"@overextended/ox_lib\";\nimport { PLATE_PATTERN } from \"../../common/config\";\nimport type { Dict, VehicleData } from \"types\";\nimport { GetVehicleData, GetVehicleNetworkType } from \"../../common/vehicles\";\nimport { setVehicleProperties } from \"@overextended/ox_lib/server\";\nimport { Vector3 } from \"@nativewrappers/server\";\nimport { SpawnVehicle } from \"vehicle\";\n\nexport type Vec3 = number[] | { x: number; y: number; z: number } | { buffer: any };\n\nconst setEntityOrphanMode = typeof SetEntityOrphanMode !== \"undefined\" ? SetEntityOrphanMode : () => {};\n\nexport class OxVehicle extends ClassInterface {\n  script: string;\n  plate: string;\n  model: string;\n  make: string;\n  id?: number;\n  vin: string;\n  owner?: number;\n  group?: string;\n  entity?: number;\n  netId?: number;\n  #metadata: Dict<any>;\n  #properties: Partial<VehicleProperties>;\n  #stored: string | null;\n\n  protected static members: Dict<OxVehicle> = {};\n  protected static keys: Dict<Dict<OxVehicle>> = {\n    id: {},\n    netId: {},\n    entity: {},\n  };\n\n  static spawn(model: string, coords: Vector3, heading?: number) {\n    const entityId = CreateVehicleServerSetter(\n      model,\n      GetVehicleNetworkType(model),\n      coords.x,\n      coords.y,\n      coords.z,\n      heading || 0,\n    );\n\n    setEntityOrphanMode(entityId, 2);\n\n    return entityId;\n  }\n\n  /** Get an instance of OxVehicle with the matching vin. */\n  static get(vin: string) {\n    const vehicle = this.members[vin];\n\n    if (vehicle) return vehicle;\n\n    return SpawnVehicle(vin);\n  }\n\n  /** Get an instance of OxVehicle with the matching vehicleId. */\n  static getFromVehicleId(vehicleId: number) {\n    return this.keys.id[vehicleId];\n  }\n\n  /** Get an instance of OxVehicle with the matching netId. */\n  static getFromNetId(id: number) {\n    return this.keys.netId[id];\n  }\n\n  /** Get an instance of OxVehicle with the matching entityId. */\n  static getFromEntity(entityId: number) {\n    return this.keys.entity[entityId];\n  }\n\n  /** Compares vehicle fields and metadata to a filter, returning the vehicle if all values match. */\n  private filter(criteria: Dict<any>) {\n    for (const key in criteria) {\n      const value = criteria[key];\n\n      if (this[key as keyof OxVehicle] !== value && this.#metadata[key] !== value) return;\n    }\n\n    return this;\n  }\n\n  /** Get an instance of OxVehicle that matches the filter. */\n  static getFromFilter(filter: Dict<any>) {\n    for (const id in this.members) {\n      const vehicle = this.members[id].filter(filter);\n      if (vehicle) return vehicle;\n    }\n  }\n\n  /** Gets all instances of OxVehicle, optionally comparing against a filter. */\n  static getAll(filter?: Dict<any>, asArray?: false): Dict<OxVehicle>;\n  static getAll(filter?: Dict<any>, asArray?: true): OxVehicle[];\n  static getAll(filter?: Dict<any>, asArray = false): Dict<OxVehicle> | OxVehicle[] {\n    if (!filter) return asArray ? Object.values(this.members) : this.members;\n\n    const obj: Dict<OxVehicle> = {};\n\n    for (const id in this.members) {\n      const vehicle = this.members[id].filter(filter);\n      if (vehicle) obj[id] = vehicle;\n    }\n\n    return asArray ? Object.values(obj) : obj;\n  }\n\n  static async generateVin({ make, name }: VehicleData, isOwned = true) {\n    if (!name) throw new Error(\"generateVin received invalid VehicleData (invalid model)\");\n\n    const arr = [\n      getRandomInt(),\n      make ? make.slice(0, 2).toUpperCase() : \"OX\",\n      name.slice(0, 2).toUpperCase(),\n      null,\n      null,\n      Math.floor(Date.now() / 1000),\n    ];\n\n    let vin: string;\n\n    while (true) {\n      arr[3] = getRandomAlphanumeric();\n      arr[4] = getRandomChar();\n      vin = arr.join(\"\");\n\n      if (!isOwned || (await IsVinAvailable(vin))) break;\n    }\n\n    return isOwned ? vin : `T${vin}`;\n  }\n\n  static async generatePlate(pattern: string = PLATE_PATTERN) {\n    while (true) {\n      const plate = getRandomString(pattern);\n\n      if (await IsPlateAvailable(plate)) return plate;\n    }\n  }\n\n  static saveAll(resource?: string) {\n    if (resource === \"ox_core\") resource = \"\";\n\n    const parameters = [];\n\n    for (const id in this.members) {\n      const vehicle = this.members[id];\n\n      if (!resource || resource === vehicle.script) {\n        if (vehicle.owner || vehicle.group) {\n          vehicle.#stored = \"impound\";\n          parameters.push(vehicle.#getSaveData());\n        }\n\n        vehicle.remove();\n      }\n    }\n\n    DEV: console.info(`Saving ${parameters.length} vehicles to the database.`);\n\n    if (parameters.length > 0) {\n      SaveVehicleData(parameters, true);\n      emit(\"ox:savedVehicles\", parameters.length);\n    }\n  }\n\n  constructor(\n    vin: string,\n    script: string,\n    plate: string,\n    model: string,\n    make: string,\n    stored: string | null,\n    metadata: Dict<any>,\n    properties: Partial<VehicleProperties>,\n    id?: number,\n    owner?: number,\n    group?: string,\n  ) {\n    super();\n    this.script = script;\n    this.plate = plate;\n    this.model = model;\n    this.make = make;\n    this.id = id;\n    this.vin = vin;\n    this.owner = owner;\n    this.group = group;\n    this.#properties = properties;\n    this.#metadata = metadata || {};\n    this.#stored = stored;\n\n    OxVehicle.add(this.vin, this);\n  }\n\n  /** Stores a value in the vehicle's metadata. */\n  set(key: string, value: any) {\n    this.#metadata[key] = value;\n  }\n\n  /** Gets a value stored in vehicle's metadata. */\n  get(key: string) {\n    return this.#metadata[key];\n  }\n\n  getState() {\n    return this.entity ? Entity(this.entity).state : null;\n  }\n\n  getStored() {\n    return this.#stored;\n  }\n\n  getProperties() {\n    return this.#properties;\n  }\n\n  #getSaveData() {\n    if (!this.id) return;\n\n    return [this.#stored, JSON.stringify({ ...this.#metadata, properties: this.#properties }), this.id];\n  }\n\n  save() {\n    const saveData = this.#getSaveData();\n    return saveData && SaveVehicleData(saveData);\n  }\n\n  despawn(save?: boolean) {\n    if (!this.entity) return;\n\n    emit(\"ox:despawnVehicle\", this.entity, this.id);\n\n    const saveData = save && this.#getSaveData();\n    if (saveData) SaveVehicleData(saveData);\n    if (DoesEntityExist(this.entity)) DeleteEntity(this.entity);\n  }\n\n  delete() {\n    if (this.id) DeleteVehicle(this.id);\n\n    this.despawn(false);\n    OxVehicle.remove(this.vin);\n  }\n\n  remove() {\n    this.despawn(true);\n    OxVehicle.remove(this.vin);\n  }\n\n  setStored(value: string | null, despawn?: boolean) {\n    this.#stored = value;\n\n    if (despawn) return this.remove();\n\n    SetVehicleColumn(this.id, \"stored\", value);\n  }\n\n  setOwner(charId?: number) {\n    if (this.owner === charId) return;\n\n    charId ? (this.owner = charId) : delete this.owner;\n\n    SetVehicleColumn(this.id, \"owner\", this.owner);\n  }\n\n  setGroup(group?: string) {\n    if (this.group === group) return;\n\n    group ? (this.group = group) : delete this.group;\n\n    SetVehicleColumn(this.id, \"group\", this.group);\n  }\n\n  setPlate(plate: string) {\n    if (this.plate === plate) return;\n\n    this.plate = plate.length > 8 ? plate.substring(0, 8) : plate.padEnd(8);\n\n    SetVehicleColumn(this.id, \"plate\", this.plate);\n  }\n\n  setProperties(properties: Partial<VehicleProperties>, apply?: boolean) {\n    if (!this.entity) return;\n\n    this.#properties = typeof properties === \"string\" ? JSON.parse(properties) : properties;\n\n    if (apply) setVehicleProperties(this.entity, this.#properties);\n  }\n\n  respawn(coords?: Vec3, rotation: Vector3 | number = 0): number | null {\n    const hasEntity = !!this.entity && DoesEntityExist(this.entity);\n\n    if (!coords && hasEntity) {\n      coords = GetEntityCoords(this.entity as number);\n    } else if (coords) {\n      coords = Vector3.fromObject(coords);\n    }\n\n    if (!coords) return null;\n\n    rotation =\n      typeof rotation === \"number\"\n        ? rotation\n        : Vector3.fromObject(rotation || hasEntity ? GetEntityRotation(this.entity as number) : null);\n\n    // Clean up existing entity and registry entries before spawning new one\n    if (hasEntity) {\n      emit(\"ox:despawnVehicle\", this.entity, this.id);\n      DeleteEntity(this.entity as number);\n    }\n\n    // Remove from registry before creating new entity to avoid conflicts\n    OxVehicle.remove(this.vin);\n\n    // Create new entity\n    this.entity = OxVehicle.spawn(this.model, coords as Vector3, typeof rotation === \"number\" ? rotation : 0);\n    this.netId = NetworkGetNetworkIdFromEntity(this.entity);\n\n    if (typeof rotation !== \"number\") SetEntityRotation(this.entity, rotation.x, rotation.y, rotation.z, 2, false);\n\n    // Re-add to registry after successful spawn\n    OxVehicle.add(this.vin, this);\n    SetVehicleNumberPlateText(this.entity, this.#properties.plate || this.plate);\n    setVehicleProperties(this.entity, this.#properties);\n    emit(\"ox:spawnedVehicle\", this.entity, this.id);\n\n    const state = this.getState();\n\n    if (state) state.set(\"initVehicle\", true, true);\n\n    return this.entity;\n  }\n}\n\nOxVehicle.init();\n\nexports(\"SaveAllVehicles\", (arg: any) => OxVehicle.saveAll(arg));\nexports(\"GetVehicleFromNetId\", (arg: any) => OxVehicle.getFromNetId(arg));\nexports(\"GetVehicleFromVin\", (arg: any) => OxVehicle.get(arg));\nexports(\"GetVehicleFromEntity\", (arg: any) => OxVehicle.getFromEntity(arg));\nexports(\"GetVehicleFromFilter\", (arg: any) => OxVehicle.getFromFilter(arg));\nexports(\"GetVehicles\", (arg: any) => OxVehicle.getAll(arg, true));\nexports(\"GenerateVehicleVin\", (model: string) => OxVehicle.generateVin(GetVehicleData(model)));\nexports(\"GenerateVehiclePlate\", (pattern?: string) => OxVehicle.generatePlate(pattern));\n"
  },
  {
    "path": "server/vehicle/commands.ts",
    "content": "import { addCommand, triggerClientCallback } from \"@overextended/ox_lib/server\";\nimport { OxVehicle } from \"./class\";\nimport { sleep } from \"@overextended/ox_lib\";\nimport { CreateVehicle } from \"vehicle\";\nimport { OxPlayer } from \"player/class\";\n\nexport function DeleteCurrentVehicle(ped: number) {\n  const entity = GetVehiclePedIsIn(ped, false);\n\n  if (!entity) return;\n\n  const vehicle = OxVehicle.getFromEntity(entity);\n\n  if (!vehicle) return DeleteEntity(entity);\n\n  vehicle.setStored(\"impound\", true);\n  vehicle.remove();\n}\n\naddCommand<{ model: string; owner?: number }>(\n  \"car\",\n  async (playerId, args, raw) => {\n    const ped = playerId && GetPlayerPed(playerId as any);\n\n    if (!ped) return;\n\n    const player = args.owner ? OxPlayer.get(args.owner) : null;\n    const data = {\n      model: args.model,\n      owner: player?.charId || undefined,\n    };\n\n    const vehicle = await CreateVehicle(data, GetEntityCoords(ped), GetEntityHeading(ped));\n\n    if (!vehicle.entity) return vehicle.remove();\n\n    DeleteCurrentVehicle(ped);\n    await sleep(200);\n    SetPedIntoVehicle(ped, vehicle.entity, -1);\n  },\n  {\n    help: \"Spawn a vehicle with the given model.\",\n    params: [\n      { name: \"model\", paramType: \"string\", help: \"The vehicle archetype.\" },\n      {\n        name: \"owner\",\n        paramType: \"playerId\",\n        help: \"Create a persistent vehicle owned by the target's active character.\",\n        optional: true,\n      },\n    ],\n    restricted: \"group.admin\",\n  },\n);\n\naddCommand<{ radius?: number; owned?: string }>(\n  \"dv\",\n  async (playerId, args, raw) => {\n    const ped = GetPlayerPed(playerId as any);\n\n    if (!args.radius) return DeleteCurrentVehicle(ped);\n\n    const vehicles = await triggerClientCallback<number[]>(\"ox:getNearbyVehicles\", playerId, args.radius);\n\n    if (!vehicles) return;\n\n    vehicles.forEach((netId) => {\n      const vehicle = OxVehicle.getFromNetId(netId);\n\n      if (!vehicle) DeleteEntity(NetworkGetEntityFromNetworkId(netId));\n      else if (args.owned) {\n        vehicle.setStored(\"impound\", true);\n        vehicle.remove();\n      }\n    });\n  },\n  {\n    help: \"Deletes your current vehicle, or any vehicles within range.\",\n    params: [\n      { name: \"radius\", paramType: \"number\", help: \"The radius to despawn vehicles (defaults to 2).\", optional: true },\n      { name: \"owned\", help: \"Include player-owned vehicles.\", optional: true },\n    ],\n    restricted: \"group.admin\",\n  },\n);\n"
  },
  {
    "path": "server/vehicle/db.ts",
    "content": "import { db } from \"../db\";\nimport type { VehicleProperties } from \"@overextended/ox_lib\";\nimport { DEFAULT_VEHICLE_STORE } from \"config\";\n\nexport type VehicleRow = {\n  id: number;\n  owner?: number;\n  group?: string;\n  plate: string;\n  vin: string;\n  model: string;\n  data: { properties: Partial<VehicleProperties>; [key: string]: any };\n};\n\nif (DEFAULT_VEHICLE_STORE)\n  setImmediate(() => db.query(\"UPDATE vehicles SET `stored` = ? WHERE `stored` IS NULL\", [DEFAULT_VEHICLE_STORE]));\n\nexport async function IsPlateAvailable(plate: string) {\n  return !(await db.exists(\"SELECT 1 FROM vehicles WHERE plate = ?\", [plate]));\n}\n\nexport async function IsVinAvailable(plate: string) {\n  return !(await db.exists(\"SELECT 1 FROM vehicles WHERE vin = ?\", [plate]));\n}\n\nexport async function GetStoredVehicleFromId(id: number | string, column = \"id\") {\n  const row = await db.row<VehicleRow>(\n    `SELECT id, owner, \\`group\\`, plate, vin, model, data FROM vehicles WHERE ${column} = ? AND \\`stored\\` IS NOT NULL`,\n    [id],\n  );\n\n  if (row && typeof row.data === \"string\") {\n    console.warn(\n      \"vehicle.data was selected from the database as a string rather than JSON.\\nLet us know if this warning occurred..\",\n    );\n    row.data = JSON.parse(row.data);\n  }\n\n  return row;\n}\n\nexport async function SetVehicleColumn(id: number | void, column: string, value: any) {\n  if (!id) return;\n\n  return (await db.update(`UPDATE vehicles SET \\`${column}\\` = ? WHERE id = ?`, [value, id])) === 1;\n}\n\nexport function SaveVehicleData(\n  values: any, // -.-\n  batch?: boolean,\n) {\n  const query = \"UPDATE vehicles SET `stored` = ?, data = ? WHERE id = ?\";\n\n  return batch ? db.batch(query, values) : db.update(query, values);\n}\n\nexport function CreateNewVehicle(\n  plate: string,\n  vin: string,\n  owner: number | null,\n  group: string | null,\n  model: string,\n  vehicleClass: number,\n  data: object,\n  stored: string | null,\n) {\n  return db.insert(\n    \"INSERT INTO vehicles (plate, vin, owner, `group`, model, class, data, `stored`) VALUES (?, ?, ?, ?, ?, ?, ?, ?)\",\n    [plate, vin, owner, group, model, vehicleClass, JSON.stringify(data), stored],\n  );\n}\n\nexport async function DeleteVehicle(id: number) {\n  return (await db.update(\"DELETE FROM vehicles WHERE id = ?\", [id])) === 1;\n}\n"
  },
  {
    "path": "server/vehicle/events.ts",
    "content": "import { OxVehicle } from './class';\n\non('onResourceStop', (resource: string) => OxVehicle.saveAll(resource));\n\non('entityRemoved', (entityId: number) => OxVehicle.getFromEntity(entityId)?.respawn());\n"
  },
  {
    "path": "server/vehicle/index.ts",
    "content": "import { OxVehicle, Vec3 } from \"./class\";\nimport { CreateNewVehicle, GetStoredVehicleFromId, IsPlateAvailable, type VehicleRow } from \"./db\";\nimport { GetVehicleData } from \"../../common/vehicles\";\nimport { DEBUG } from \"../../common/config\";\nimport \"./class\";\nimport \"./commands\";\nimport \"./events\";\nimport type { VehicleProperties } from \"@overextended/ox_lib/server\";\n\nif (DEBUG) import(\"./parser\");\n\nexport interface CreateVehicleData {\n  model: string;\n  owner?: number;\n  group?: string;\n  stored?: string;\n  properties?: Partial<VehicleProperties>;\n}\n\nexport async function CreateVehicle(\n  data: string | (CreateVehicleData & Partial<VehicleRow>),\n  coords?: Vec3,\n  heading?: number,\n  invokingScript = GetInvokingResource(),\n) {\n  if (typeof data === \"string\") data = { model: data };\n\n  const vehicleData = GetVehicleData(data.model as string);\n\n  if (!vehicleData)\n    throw new Error(\n      `Failed to create vehicle '${data.model}' (model is invalid).\\nEnsure vehicle exists in '@ox_core/common/data/vehicles.json'`,\n    );\n\n  if (data.id) {\n    const vehicle = OxVehicle.getFromVehicleId(data.id);\n\n    if (vehicle) {\n      if (vehicle.entity && DoesEntityExist(vehicle.entity)) {\n        return vehicle;\n      }\n\n      vehicle.despawn(true);\n    }\n  }\n\n  const isOwned = !!(data.owner || data.group);\n\n  if (!data.vin) data.vin = await OxVehicle.generateVin(vehicleData, isOwned);\n\n  data.plate =\n    data.vin && data.plate\n      ? data.plate\n      : data.plate && (await IsPlateAvailable(data.plate))\n        ? data.plate\n        : await OxVehicle.generatePlate();\n\n  const metadata = data.data || ({} as { properties?: Partial<VehicleProperties>; [key: string]: any });\n  metadata.properties = data.properties || data.data?.properties || ({} as Partial<VehicleProperties>);\n\n  if (!data.id && data.vin && isOwned) {\n    data.id = await CreateNewVehicle(\n      data.plate,\n      data.vin,\n      data.owner || null,\n      data.group || null,\n      data.model,\n      vehicleData.class,\n      metadata,\n      data.stored || null,\n    );\n  }\n\n  const properties = data.properties || metadata.properties || ({} as Partial<VehicleProperties>);\n  delete metadata.properties;\n\n  const vehicle = new OxVehicle(\n    data.vin,\n    invokingScript,\n    data.plate,\n    data.model,\n    vehicleData.make,\n    data.stored || null,\n    metadata,\n    properties,\n    data.id,\n    data.owner,\n    data.group,\n  );\n\n  if (coords) {\n    vehicle.respawn(coords, heading || 0);\n  }\n\n  if (vehicle.entity) vehicle.setStored(null, false);\n\n  return vehicle;\n}\n\nexport async function SpawnVehicle(id: number | string, coords?: Vec3, heading?: number) {\n  const invokingScript = GetInvokingResource();\n  const vehicle = await GetStoredVehicleFromId(id, typeof id === \"string\" ? \"vin\" : \"id\");\n\n  if (!vehicle) return;\n\n  return await CreateVehicle(vehicle, coords, heading, invokingScript);\n}\n\nexports(\"CreateVehicle\", CreateVehicle);\nexports(\"SpawnVehicle\", SpawnVehicle);\n"
  },
  {
    "path": "server/vehicle/parser.ts",
    "content": "import { addCommand, triggerClientCallback } from \"@overextended/ox_lib/server\";\nimport { GetTopVehicleStats, GetVehicleData } from \"../../common/vehicles\";\nimport type { VehicleData, TopVehicleStats } from \"types\";\n\nfunction SortObjectProperties(obj: object) {\n  return Object.fromEntries(Object.entries(obj).sort());\n}\n\naddCommand<{ parseAll: boolean }>(\n  \"parsevehicles\",\n  async (playerId, args) => {\n    const response: [Record<string, VehicleData>, TopVehicleStats, string[]] | void = await triggerClientCallback(\n      \"ox:generateVehicleData\",\n      playerId,\n      args.parseAll,\n    );\n\n    if (!response) return;\n\n    const updatedVehicles = args.parseAll\n      ? SortObjectProperties({ ...response[0] })\n      : SortObjectProperties({ ...GetVehicleData(), ...response[0] });\n    const updatedStats = args.parseAll\n      ? SortObjectProperties({ ...response[1] })\n      : SortObjectProperties({ ...GetTopVehicleStats(), ...response[1] });\n\n    if (response[2].length)\n      console.log(\n        `^3Failed to parse data for ${response[2].length} invalid vehicles.\\n${JSON.stringify(response[2], null, 2)}^0`,\n      );\n\n    SaveResourceFile(\"ox_core\", \"/common/data/vehicleStats.json\", JSON.stringify(updatedStats, null, 2), -1);\n    SaveResourceFile(\"ox_core\", \"/common/data/vehicles.json\", JSON.stringify(updatedVehicles, null, 2), -1);\n  },\n  {\n    help: \"Parses and generates vehicle data for all vehicle models available on a client.\",\n    params: [{ name: \"parseAll\", optional: true, help: \"Include vehicles with existing data in the data generation.\" }],\n    restricted: \"group.admin\",\n  },\n);\n"
  },
  {
    "path": "sql/install.sql",
    "content": "/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\n\n/*!40101 SET NAMES utf8 */;\n\n/*!50503 SET NAMES utf8mb4 */;\n\n/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\n\n/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;\n\n/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\n\nCREATE DATABASE IF NOT EXISTS `overextended` DEFAULT CHARACTER\nSET utf8mb4 COLLATE utf8mb4_unicode_ci;\n\nUSE `overextended`;\n\nCREATE TABLE IF NOT EXISTS `users` (\n  `userId` INT UNSIGNED NOT NULL AUTO_INCREMENT,\n  `username` VARCHAR(50) DEFAULT NULL,\n  `license2` VARCHAR(50) DEFAULT NULL,\n  `steam` VARCHAR(20) DEFAULT NULL,\n  `fivem` VARCHAR(10) DEFAULT NULL,\n  `discord` VARCHAR(20) DEFAULT NULL,\n  PRIMARY KEY (`userId`)\n);\n\nCREATE TABLE IF NOT EXISTS `characters`\n(\n  `charId`      INT UNSIGNED AUTO_INCREMENT\n      PRIMARY KEY,\n  `userId`      INT UNSIGNED                                             NOT NULL,\n  `stateId`     VARCHAR(7)                                               NOT NULL,\n  `firstName`   VARCHAR(50)                                              NOT NULL,\n  `lastName`    VARCHAR(50)                                              NOT NULL,\n  `fullName`    VARCHAR(101) AS (CONCAT(`firstName`, ' ', `lastName`)) STORED,\n  `gender`      VARCHAR(10)                                              NOT NULL,\n  `dateOfBirth` DATE                                                     NOT NULL,\n  `phoneNumber` VARCHAR(20)                                              NULL,\n  `lastPlayed`  DATETIME                     DEFAULT CURRENT_TIMESTAMP() NOT NULL,\n  `isDead`      TINYINT(1)                   DEFAULT 0                   NOT NULL,\n  `x`           FLOAT                                                    NULL,\n  `y`           FLOAT                                                    NULL,\n  `z`           FLOAT                                                    NULL,\n  `heading`     FLOAT                                                    NULL,\n  `health`      TINYINT UNSIGNED                                         NULL,\n  `armour`      TINYINT UNSIGNED                                         NULL,\n  `statuses`    LONGTEXT COLLATE utf8mb4_bin DEFAULT JSON_OBJECT()       NOT NULL\n      CHECK (JSON_VALID(`statuses`)),\n  `deleted`     DATE                                                     NULL,\n  CONSTRAINT `characters_stateId_unique`\n      UNIQUE (`stateId`),\n  CONSTRAINT `characters_userId_fk`\n      FOREIGN KEY (`userId`) REFERENCES `users` (`userId`)\n          ON UPDATE CASCADE ON DELETE CASCADE\n);\n\nCREATE FULLTEXT INDEX IF NOT EXISTS `characters_fullName_index`\n  ON `characters` (`fullName`);\n\nCREATE INDEX IF NOT EXISTS `characters_userId_key`\n  ON `characters` (`userId`);\n\nCREATE TABLE IF NOT EXISTS `character_inventory` (\n  `charId` INT UNSIGNED NOT NULL,\n  `inventory` JSON NULL DEFAULT NULL,\n  PRIMARY KEY (`charId`),\n  KEY `character_inventory_charId_key` (`charId`),\n  CONSTRAINT `character_inventory_charId_fk` FOREIGN KEY (`charId`) REFERENCES `characters` (`charId`) ON DELETE CASCADE ON UPDATE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS `ox_groups` (\n  `name` VARCHAR(20) NOT NULL,\n  `label` VARCHAR(50) NOT NULL,\n  `type` VARCHAR(50) NULL,\n  `colour` TINYINT UNSIGNED DEFAULT NULL,\n  `hasAccount` TINYINT(1) NOT NULL DEFAULT '0',\n  PRIMARY KEY (`name`)\n);\n\nCREATE TABLE IF NOT EXISTS `character_groups` (\n  `charId` INT UNSIGNED NOT NULL,\n  `name` VARCHAR(20) NOT NULL,\n  `grade` TINYINT UNSIGNED NOT NULL DEFAULT 1,\n  `isActive` TINYINT(1) NOT NULL DEFAULT 0,\n  UNIQUE KEY `name` (`name`, `charId`),\n  KEY `character_groups_charId_key` (`charId`),\n  CONSTRAINT `character_groups_charId_fk` FOREIGN KEY (`charId`) REFERENCES `characters` (`charId`) ON DELETE CASCADE ON UPDATE CASCADE,\n  CONSTRAINT `character_groups_name_fk` FOREIGN KEY (`name`) REFERENCES `ox_groups` (`name`) ON DELETE CASCADE ON UPDATE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS `ox_inventory` (\n  `owner` VARCHAR(60) DEFAULT NULL,\n  `name` VARCHAR(60) NOT NULL,\n  `data` JSON DEFAULT NULL,\n  `lastupdated` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n  UNIQUE KEY `owner` (`owner`, `name`)\n);\n\nCREATE TABLE IF NOT EXISTS `vehicles` (\n  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,\n  `plate` CHAR(8) NOT NULL DEFAULT '',\n  `vin` CHAR(17) NOT NULL,\n  `owner` INT UNSIGNED NULL DEFAULT NULL,\n  `group` VARCHAR(20) NULL DEFAULT NULL,\n  `model` VARCHAR(20) NOT NULL,\n  `class` TINYINT UNSIGNED NULL DEFAULT NULL,\n  `data` JSON NOT NULL,\n  `trunk` JSON NULL DEFAULT NULL,\n  `glovebox` JSON NULL DEFAULT NULL,\n  `stored` VARCHAR(50) NULL DEFAULT NULL,\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `plate` (`plate`),\n  UNIQUE KEY `vin` (`vin`),\n  KEY `vehicles_owner_key` (`owner`),\n  CONSTRAINT `vehicles_owner_fk` FOREIGN KEY (`owner`) REFERENCES `characters` (`charId`) ON DELETE CASCADE ON UPDATE CASCADE,\n  CONSTRAINT `vehicles_group_fk` FOREIGN KEY (`group`) REFERENCES `ox_groups` (`name`) ON DELETE CASCADE ON UPDATE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS `ox_statuses` (\n  `name` VARCHAR(20) NOT NULL,\n  `default` TINYINT (3) UNSIGNED NOT NULL DEFAULT 0,\n  `onTick` DECIMAL(8, 7) DEFAULT 0\n);\n\nINSERT INTO `ox_statuses` (`name`, `default`, `onTick`) VALUES\n  ('hunger', 0, 0.02),\n  ('thirst', 0, 0.05),\n  ('stress', 0, -0.10);\n\nCREATE TABLE IF NOT EXISTS `ox_licenses` (\n  `name` VARCHAR(20) NOT NULL,\n  `label` VARCHAR(50) NOT NULL,\n  UNIQUE KEY `name` (`name`)\n);\n\nINSERT INTO `ox_licenses` (`name`, `label`) VALUES\n  ('weapon', 'Weapon License'),\n  ('driver', \"Driver's License\");\n\nCREATE TABLE IF NOT EXISTS `character_licenses` (\n  `charId` INT UNSIGNED NOT NULL,\n  `name` VARCHAR(20) DEFAULT NULL,\n  `data` JSON NOT NULL DEFAULT (JSON_OBJECT()),\n  UNIQUE KEY `name` (`name`, `charId`),\n  KEY `character_licenses_charId_key` (`charId`),\n  CONSTRAINT `character_licenses_charId_fk` FOREIGN KEY (`charId`) REFERENCES `characters` (`charId`) ON DELETE CASCADE ON UPDATE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS `accounts`\n(\n  `id`        INT UNSIGNED                                                        NOT NULL\n      PRIMARY KEY,\n  `label`     VARCHAR(50)                                                         NOT NULL,\n  `owner`     INT UNSIGNED                                                        NULL,\n  `group`     VARCHAR(20)                                                         NULL,\n  `balance`   INT                                              DEFAULT 0          NOT NULL,\n  `isDefault` TINYINT(1)                                       DEFAULT 0          NOT NULL,\n  `type`      ENUM ('personal', 'shared', 'group', 'inactive') DEFAULT 'personal' NOT NULL,\n  CONSTRAINT `accounts_group_fk`\n      FOREIGN KEY (`group`) REFERENCES `ox_groups` (`name`)\n          ON UPDATE SET NULL ON DELETE SET NULL,\n  CONSTRAINT `accounts_owner_fk`\n      FOREIGN KEY (`owner`) REFERENCES `characters` (`charId`)\n          ON UPDATE SET NULL ON DELETE SET NULL\n);\n\nCREATE FULLTEXT INDEX IF NOT EXISTS `accounts_label_index`\n  ON `accounts` (`label`);\n\nCREATE TABLE `account_roles` (\n  `id` INT(11) NOT NULL AUTO_INCREMENT,\n  `name` VARCHAR(50) NOT NULL DEFAULT '',\n  `deposit` TINYINT(1) NOT NULL DEFAULT '0',\n  `withdraw` TINYINT(1) NOT NULL DEFAULT '0',\n  `addUser` TINYINT(1) NOT NULL DEFAULT '0',\n  `removeUser` TINYINT(1) NOT NULL DEFAULT '0',\n  `manageUser` TINYINT(1) NOT NULL DEFAULT '0',\n  `transferOwnership` TINYINT(1) NOT NULL DEFAULT '0',\n  `viewHistory` TINYINT(1) NOT NULL DEFAULT '0',\n  `manageAccount` TINYINT(1) NOT NULL DEFAULT '0',\n  `closeAccount` TINYINT(1) NOT NULL DEFAULT '0',\n  `sendInvoice` TINYINT(1) NOT NULL DEFAULT '0',\n  `payInvoice` TINYINT(1) NOT NULL DEFAULT '0',\n  PRIMARY KEY (`id`),\n  UNIQUE INDEX `name` (`name`)\n);\n\nINSERT INTO `account_roles` (`id`, `name`, `deposit`, `withdraw`, `addUser`, `removeUser`, `manageUser`, `transferOwnership`, `viewHistory`, `manageAccount`, `closeAccount`, `sendInvoice`, `payInvoice`) VALUES\n  (1, 'viewer', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\n  (2, 'contributor', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\n  (3, 'manager', 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1),\n  (4, 'owner', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);\n\nCREATE TABLE IF NOT EXISTS `ox_group_grades` (\n  `group` VARCHAR(20) NOT NULL,\n  `grade` TINYINT UNSIGNED NOT NULL DEFAULT 1,\n  `label` VARCHAR(50) NOT NULL,\n  `accountRole` VARCHAR(50) NULL DEFAULT NULL,\n  PRIMARY KEY (`group`, `grade`),\n  CONSTRAINT `ox_group_grades_group_fk` FOREIGN KEY (`group`) REFERENCES `ox_groups` (`name`) ON DELETE CASCADE ON UPDATE CASCADE,\n  CONSTRAINT `FK_ox_group_grades_account_roles` FOREIGN KEY (`accountRole`) REFERENCES `account_roles` (`name`) ON UPDATE CASCADE ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS `accounts_access` (\n  `accountId` INT UNSIGNED NOT NULL,\n  `charId` INT UNSIGNED NOT NULL,\n  `role` VARCHAR(50) NOT NULL DEFAULT 'viewer',\n  PRIMARY KEY (`accountId`, `charId`),\n  CONSTRAINT `accounts_access_accountId_fk` FOREIGN KEY (`accountId`) REFERENCES `accounts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,\n  CONSTRAINT `accounts_access_charId_fk` FOREIGN KEY (`charId`) REFERENCES `characters` (`charId`) ON DELETE CASCADE ON UPDATE CASCADE,\n  CONSTRAINT `FK_accounts_access_account_roles` FOREIGN KEY (`role`) REFERENCES `account_roles` (`name`) ON UPDATE CASCADE ON DELETE CASCADE\n);\n\n\nCREATE TABLE IF NOT EXISTS `accounts_transactions` (\n  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,\n  `actorId` INT UNSIGNED DEFAULT NULL,\n  `fromId` INT UNSIGNED DEFAULT NULL,\n  `toId` INT UNSIGNED DEFAULT NULL,\n  `amount` INT NOT NULL,\n  `message` VARCHAR(255) NOT NULL,\n  `note` VARCHAR(255) DEFAULT NULL,\n  `fromBalance` INT DEFAULT NULL,\n  `toBalance` INT DEFAULT NULL,\n  `date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  PRIMARY KEY (`id`),\n  CONSTRAINT `accounts_transactions_actorId_fk` FOREIGN KEY (`actorId`) REFERENCES `characters` (`charId`) ON DELETE CASCADE ON UPDATE CASCADE,\n  CONSTRAINT `accounts_transactions_fromId_fk` FOREIGN KEY (`fromId`) REFERENCES `accounts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,\n  CONSTRAINT `accounts_transactions_toId_fk` FOREIGN KEY (`toId`) REFERENCES `accounts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE\n);\n\nCREATE FULLTEXT INDEX IF NOT EXISTS `accounts_transactions_message_index`\n  ON `accounts_transactions` (`message`);\n\nCREATE TABLE IF NOT EXISTS `accounts_invoices`\n(\n    `id`          INT UNSIGNED AUTO_INCREMENT\n        PRIMARY KEY,\n    `actorId`     INT UNSIGNED                          NULL,\n    `payerId`     INT UNSIGNED                          NULL,\n    `fromAccount` INT UNSIGNED                          NOT NULL,\n    `toAccount`   INT UNSIGNED                          NOT NULL,\n    `amount`      INT UNSIGNED                          NOT NULL,\n    `message`     VARCHAR(255)                          NULL,\n    `sentAt`      TIMESTAMP DEFAULT CURRENT_TIMESTAMP() NOT NULL,\n    `dueDate`     TIMESTAMP                             NOT NULL,\n    `paidAt`      TIMESTAMP                             NULL,\n    CONSTRAINT `accounts_invoices_accounts_id_fk`\n        FOREIGN KEY (`fromAccount`) REFERENCES `accounts` (`id`),\n    CONSTRAINT `accounts_invoices_accounts_id_fk_2`\n        FOREIGN KEY (`toAccount`) REFERENCES `accounts` (`id`),\n    CONSTRAINT `accounts_invoices_characters_charId_fk`\n        FOREIGN KEY (`payerId`) REFERENCES `characters` (`charId`),\n    CONSTRAINT `accounts_invoices_characters_charId_fk_2`\n        FOREIGN KEY (`actorId`) REFERENCES `characters` (`charId`)\n);\n\nCREATE FULLTEXT INDEX IF NOT EXISTS `idx_message_fulltext`\n    ON `accounts_invoices` (`message`);\n\n/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;\n\n/*!40014 SET FOREIGN_KEY_CHECKS=IFNULL(@OLD_FOREIGN_KEY_CHECKS, 1) */;\n\n/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n\n/*!40111 SET SQL_NOTES=IFNULL(@OLD_SQL_NOTES, 1) */;\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"rootDir\": \".\",\n    \"noImplicitAny\": true,\n    \"strictNullChecks\": true,\n    \"module\": \"es2022\",\n    \"target\": \"es2023\",\n    \"lib\": [\"es2023\", \"esnext.disposable\"],\n    \"types\": [\"@citizenfx/client\", \"@citizenfx/server\"],\n    \"resolveJsonModule\": true,\n    \"esModuleInterop\": true,\n    \"allowUnreachableCode\": false,\n    \"strictFunctionTypes\": true,\n    \"moduleResolution\": \"bundler\",\n    \"noImplicitThis\": true,\n    \"noUnusedLocals\": true,\n    \"skipLibCheck\": true,\n    \"declaration\": true,\n    \"noEmit\": false,\n    \"emitDeclarationOnly\": true,\n    \"removeComments\": true,\n    \"outDir\": \"./package/\"\n  },\n  \"include\": [\"./\", \"./types/\"],\n  \"references\": [{ \"path\": \"./lib\" }]\n}\n"
  },
  {
    "path": "types/index.ts",
    "content": "export type Dict<T> = { [key: string]: T };\n\nexport interface Character {\n  charId: number;\n  stateId: string;\n  firstName: string;\n  lastName: string;\n  gender: string;\n  x?: number;\n  y?: number;\n  z?: number;\n  heading?: number;\n  lastPlayed?: string;\n  health?: number;\n  armour?: number;\n  isNew?: boolean;\n}\n\nexport interface NewCharacter {\n  firstName: string;\n  lastName: string;\n  gender: string;\n  date: number;\n}\n\nexport interface PlayerMetadata {\n  name: string;\n  firstName: string;\n  lastName: string;\n  gender: string;\n  dateOfBirth: string;\n  phoneNumber: string;\n  activeGroup?: string;\n}\n\nexport interface CharacterLicense {\n  issued: number;\n  suspended?: [number, number];\n  [key: string]: any;\n}\n\nexport type Vehicles = Dict<VehicleData>;\nexport type VehicleCategories = 'air' | 'land' | 'sea';\nexport type TopVehicleStats = Record<VehicleCategories, VehicleStats>;\n\nexport interface VehicleStats {\n  acceleration: number;\n  braking: number;\n  handling: number;\n  speed: number;\n  traction: number;\n}\n\nexport enum VehicleClasses {\n  COMPACT,\n  SEDAN,\n  SUV,\n  COUPE,\n  MUSCLE,\n  SPORTS_CLASSIC,\n  SPORTS,\n  SUPER,\n  MOTORCYCLE,\n  OFFROAD,\n  INDUSTRIAL,\n  UTILITY,\n  VANS,\n  CYCLES,\n  BOATS,\n  HELICOPTERS,\n  PLANES,\n  SERVICE,\n  EMERGENCY,\n  MILITARY,\n  COMMERCIAL,\n  TRAINS,\n  OPEN_WHEEL,\n}\n\nexport type VehicleTypes =\n  | 'amphibious_automobile'\n  | 'amphibious_quadbike'\n  | 'automobile'\n  | 'bicycle'\n  | 'bike'\n  | 'blimp'\n  | 'boat'\n  | 'heli'\n  | 'plane'\n  | 'quadbike'\n  | 'submarine'\n  | 'submarinecar'\n  | 'trailer'\n  | 'train';\n\nexport interface VehicleData extends VehicleStats {\n  class: VehicleClasses;\n  doors: number;\n  make: string;\n  name: string;\n  price: number;\n  seats: number;\n  type: VehicleTypes;\n  category: VehicleCategories;\n  weapons?: true;\n  [key: string]: unknown;\n}\n\nexport interface OxLicense {\n  name?: string;\n  label?: string;\n}\n\nexport interface OxStatus {\n  name: string;\n  default: number;\n  onTick: number;\n}\n\nexport interface OxAccountMetadata {\n  id: number;\n  balance: number;\n  isDefault: boolean;\n  label: string;\n  type: 'personal' | 'shared' | 'group';\n  owner?: number;\n  group?: string;\n}\n\nexport interface OxAccountUserMetadata extends OxAccountMetadata {\n  role: OxAccountRole;\n  ownerName: string;\n}\n\nexport interface DbGroup {\n  name: string;\n  label: string;\n  grades: string[];\n  accountRoles: Dict<OxAccountRole>;\n  type?: string;\n  colour?: number;\n  hasAccount: boolean;\n  activePlayers: Set<number>;\n}\n\nexport interface OxGroup extends DbGroup {\n  grades: string[];\n  principal: string;\n}\n\nexport interface CreateGroupProperties {\n  name: string;\n  label: string;\n  grades: {\n    label: string;\n    accountRole?: OxAccountRole;\n  }[];\n  type?: string;\n  colour?: number;\n  hasAccount?: boolean;\n}\n\nexport interface OxGroupPermissions {\n  [grade: string]: { [permission: string]: boolean };\n}\n\nexport type OxAccountRole = 'viewer' | 'contributor' | 'manager' | 'owner';\n\nexport interface OxAccountPermissions {\n  deposit: boolean;\n  withdraw: boolean;\n  addUser: boolean;\n  removeUser: boolean;\n  manageUser: boolean;\n  transferOwnership: boolean;\n  viewHistory: boolean;\n  manageAccount: boolean;\n  closeAccount: boolean;\n  sendInvoice: boolean;\n  payInvoice: boolean;\n}\n\nexport interface OxAccountInvoice {\n  id: number;\n  actorId?: number;\n  payerId?: number;\n  fromAccount: number;\n  toAccount: number;\n  amount: number;\n  message?: string;\n  sentAt: number;\n  dueDate: number;\n  paidAt?: number;\n}\n\nexport interface OxCreateInvoice {\n  /** The charId of the player creating the invoice. */\n  actorId?: number;\n  /** The accountId of the account issuing the invoice. */\n  fromAccount: number;\n  /** The accountId of the account receiving the invoice. */\n  toAccount: number;\n  amount: number;\n  message: string;\n  dueDate: string;\n}\n\nexport interface BanDetails {\n  userId: number;\n  token?: string;\n  reason?: string;\n  banned_at: number;\n  unban_at?: number;\n}\n"
  }
]