diff --git a/README.md b/README.md index 7c311a4..987c840 100644 --- a/README.md +++ b/README.md @@ -7,13 +7,13 @@ Allows you to connect an emulated ToyPad to your PC or video-game console. ## Features - Supports all available characters and vehicles -- Supports most if not all of the consoles the game is available for +- Save vehicle upgrades +- Supports most if not all of the consoles the game is available for (please test if you're able) - Confirmed working on Cemu, real Wii U and real PS4 - Can be configured easily by following the instructions below -- Mobile-friendly web interface ## Demo -![](https://i.imgur.com/Hg12EDL.jpg) +![](https://i.imgur.com/iyWVObT.png) Video for Cemu emulator: https://www.youtube.com/watch?v=7CBa9u2ip-Y @@ -72,17 +72,20 @@ Video for Cemu emulator: https://www.youtube.com/watch?v=7CBa9u2ip-Y ## Usage Type your single board computer's IP address in a browser to use the emulator. If you want to turn it off, just use the command from earlier (without -r) to shut the device down via SSH. +Note: Not currently usable on mobile devices. + ## Update To update this software, just pull the latest changes by running the following commands: ````bash cd LD-ToyPad-Emulator git pull +npm install ```` ## Acknowledgements * **ags131** for writing one of the main NodeJS libraries I'm using: [https://www.npmjs.com/package/node-ld](https://www.npmjs.com/package/node-ld). My project would've been impossible to create without this guy's research. -* **cort1237** for implementing writing of toy tags, therefore eliminating the need for a workaround when building vehicles. +* **cort1237** for implementing writing to toy tags as well as several UI updates and support for saving toy tags locally. ## License diff --git a/index.js b/index.js index 4f1a8ef..df1078e 100644 --- a/index.js +++ b/index.js @@ -1,20 +1,40 @@ /* - - Copyright © 2021 Berny23 + Copyright © 2021 Berny23 & Cort1237 This file is part of "ToyPad Emulator for Lego Dimensions" which is released under the "MIT" license. See file "LICENSE" or go to "https://choosealicense.com/licenses/mit" for full license details. - */ const ld = require ('node-ld') +const fs = require('fs'); const path = require('path'); +const { DH_CHECK_P_NOT_PRIME } = require('constants'); + +//Setup Webserver const express = require('express'); const app = express(); +const http = require('http'); +const server = http.createServer(app); +const { Server } = require("socket.io"); +const io = new Server(server); + +//File where tag info will be saved +const toytagFileName = './server/json/toytags.json'; var tp = new ld.ToyPadEmu() tp.registerDefaults() +initalizeToyTagsJSON(); //Run in case there were any leftovers from a previous run. + +//Create a token JSON object from provided vehicle data +/* Vehicle Data Explained: + * All data is transfered through a series of buffers. The data from these buffers needs to written to specific points (pages) in the token's + * buffer for it to be read properly. + * + * For vehicles: + * Page 24 is the ID of the vehicle + * Pages 23 & 25 are the upgrade data + */ function createVehicle(id, upgrades, uid){ upgrades = upgrades || [0,0]; var token = new Buffer(180); @@ -23,10 +43,11 @@ function createVehicle(id, upgrades, uid){ token.writeUInt32LE(upgrades[0],0x23*4); token.writeUInt16LE(id,0x24*4); token.writeUInt32LE(upgrades[1],0x25*4); - token.writeUInt16BE(1,0x26*4); + token.writeUInt16BE(1,0x26*4); //Page 26 is used for verification of somekind. return token; } +//Create a token JSON object from provided character data function createCharacter(id, uid){ var token = new Buffer(180) token.fill(0); // Game really only cares about 0x26 being 0 and D4 returning an ID @@ -35,61 +56,291 @@ function createCharacter(id, uid){ return token; } +//This finds a character or vehicles name from the ID provided. +function getNameFromID(id){ + if(id < 1000) + dbfilename = './server/json/charactermap.json'; + else + dbfilename = './server/json/tokenmap.json'; + var name = "test"; + const data = fs.readFileSync(dbfilename, 'utf8'); + const databases = JSON.parse(data); + databases.forEach(db => { + if(id == db.id){ + name = db.name + } + }); + + return name; +} + +//This finds and returns an JSON entry from toytags.json with the matching uid. +function getJSONFromUID(uid){ + const data = fs.readFileSync(toytagFileName, 'utf8'); + const databases = JSON.parse(data); + var entry; + databases.forEach(db => { + if(db.uid==uid) + entry = db; + }); + return entry; +} + +//This updates the pad index of a tag in toytags.json, so that info can be accessed locally. +function updatePadIndex(uid, index){ + //console.log('Planning to set UID: ' + uid + ' to index ' + index); + const data = fs.readFileSync(toytagFileName, 'utf8'); + const databases = JSON.parse(data); + databases.forEach(db => { + if(uid == db.uid){ + db.index = index; + } + }); + fs.writeFileSync(toytagFileName, JSON.stringify(databases, null, 4), function(){ + console.log('Set UID: ' + uid + ' to index ' + index); + }) +} + +//This searches toytags.json and returns to UID of the entry with the matching index. +function getUIDFromIndex(index){ + const data = fs.readFileSync(toytagFileName, 'utf8'); + const databases = JSON.parse(data); + var uid; + databases.forEach(db => { + if(index == db.index){ + uid = db.uid; + } + }); + return uid; +} + +//This updates the provided datatype, of the entry with the matching uid, with the provided data. +function writeJSONData(uid, datatype, data){ + //console.log('Planning to set '+ datatype + ' of ' + uid + ' to ' + data); + const tags = fs.readFileSync(toytagFileName, 'utf8'); + const databases = JSON.parse(tags); + databases.forEach(db => { + if(uid == db.uid){ + db[datatype] = data; + return; + } + }); + fs.writeFileSync(toytagFileName, JSON.stringify(databases, null, 4), function(){ + console.log('Set '+ datatype + ' of ' + uid + ' to ' + data); + }) +} + + +//This sets all saved index values to '-1' (meaning unplaced). +function initalizeToyTagsJSON(){ + const data = fs.readFileSync(toytagFileName, 'utf8'); + const databases = JSON.parse(data); + databases.forEach(db => { + db.index = "-1"; + }); + fs.writeFileSync(toytagFileName, JSON.stringify(databases, null, 4), function(){ + console.log("Initalized toytags.JSON"); + }) +} //When the game calls 'CMD_WRITE', writes the given data to the toytag in the top position. -tp._hook(tp.CMD_WRITE, (req, res) => { +/* Writing Tags Explained: + * A write occurs in three seperate function calls, and will repreat until either the write is canceled in game, + * or all three calls successfully write data. + * + * To appease the game all data is passed through and copied to the token in the top pad. But during this we can intercept what is being written + * and save the data locally as well. This lets us call that data back when we want to use that tag again. + * + * payload[1] tells what page is being written, and everything after is the data. + * page 24 - ID + * page 23 - Vehicle Upgrade Pt 1 + * page 26 - Vehicle Upgrades Pt 2 + * **When writing the pages requested for the write are sometimes ofset by 12, not sure why. + * + * This data is copied to the JSON for future use. + */ +tp.hook(tp.CMD_WRITE, (req, res) => { var ind = req.payload[0]; var page = req.payload[1]; - console.log('REQUEST (CMD_WRITE): index:', ind, 'page', page); + var data = req.payload.slice(2); + var uid = getUIDFromIndex('2'); + console.log('REQUEST (CMD_WRITE): index:', ind, 'page', page, 'data', data); + + //The ID is stored in page + if(page == 24 || page == 36){ + writeJSONData(uid,"id",data.readInt16LE(0)); + var name = getNameFromID(data.readInt16LE(0)); + writeJSONData(uid,"name",name); + writeJSONData(uid,"type","vehicle"); + } + else if(page == 23 || page == 35) + writeJSONData(uid, "vehicleUpgradesP23", data.readUInt32LE(0)); + else if (page == 25 || page == 37){ + writeJSONData(uid, "vehicleUpgradesP25", data.readUInt32LE(0)); + io.emit("refreshTokens"); //Refreshes the html's tag gui. + } + res.payload = new Buffer('00', 'hex'); var token = tp._tokens.find(t => t.index == ind); - if (token) + if (token){ req.payload.copy(token.token, 4 * page, 2, 6); + } + }); + + app.use(express.json()); +app.use(express.static(path.join(__dirname, 'server'))) + +//**Website requests** app.get('/', (request, response) => { - response.sendFile(path.join(__dirname, '/index.html')); + response.sendFile(path.join(__dirname, 'server/index.html')); }); +//Create a new Character and save that data to toytags.json app.post('/character', (request, response) => { - console.log('Placing character: ' + request.body.id); + console.log('Creating character: ' + request.body.id); var uid = tp.randomUID(); var character = createCharacter(request.body.id, uid); - tp.place(character, request.body.position, request.body.index, character.uid); - console.log('Character placed: ' + request.body.id); - response.send(uid); + var name = getNameFromID(request.body.id, "character"); + + //console.log("name: " + name, " uid: " + character.uid, " id: " + character.id) + + fs.readFile(toytagFileName, 'utf8', (err, data) => { + if(err){ + console.log(err) + } + else{ + const tags = JSON.parse(data.toString()); + + tags.push({ + name: name, + id: character.id, + uid: character.uid, + index: "-1", + type: 'character', + vehicleUpgradesP23: 0, + vehicleUpgradesP25: 0 + }); + + fs.writeFile(toytagFileName, JSON.stringify(tags, null, 4), 'utf8', (err) => { + if (err) { + console.log(`Error writing file: ${err}`); + } else { + console.log(`File is written successfully!`); + } + }); + } + }) + + console.log('Character created: ' + request.body.id); + response.send(); }); +//This is called when a token is placed or move onto a position on the toypad. +app.post('/characterPlace', (request, response) => { + console.log('Placing tag: ' + request.body.id); + var entry = getJSONFromUID(request.body.uid); + + //console.log(entry.type); + + if(entry.type == "character"){ + var character = createCharacter(request.body.id, request.body.uid); + tp.place(character, request.body.position, request.body.index, character.uid); + console.log('Placed character tag: ' + request.body.id); + updatePadIndex(character.uid, request.body.index); + response.send(); + } + else{ + var vehicle = createVehicle(request.body.id,[entry.vehicleUpgradesP23, entry.vehicleUpgradesP25],request.body.uid); + tp.place(vehicle, request.body.position, request.body.index, vehicle.uid); + console.log('Placed vehicle tag: ' + request.body.id); + updatePadIndex(vehicle.uid, request.body.index); + response.send(); + } +}) + +//Create a new vehicle and save that data to toytags.json app.post('/vehicle', (request, response) => { console.log('Placing vehicle: ' + request.body.id); var uid = tp.randomUID(); var vehicle = createVehicle(request.body.id, [0xEFFFFFFF, 0xEFFFFFFF], uid); - tp.place(vehicle, request.body.position, request.body.index, vehicle.uid); - console.log('Vehicle placed: ' + request.body.id); - response.send(uid); -}); + var name = getNameFromID(request.body.id, "vehicle"); -app.put('/character', (request, response) => { - console.log('Changing character: "' + request.body.uid + '" to position ' + request.body.position + ', index ' + request.body.index); - var character = createCharacter(request.body.id, request.body.uid); - tp.place(character, request.body.position, request.body.index, character.uid); - console.log('Character changed: "' + request.body.uid + '" to position ' + request.body.position + ', index ' + request.body.index); -}); + //console.log("name: " + name, " uid: " + vehicle.uid, " id: " + vehicle.id) + + fs.readFile(toytagFileName, 'utf8', (err, data) => { + if(err){ + console.log(err) + } + else{ + const tags = JSON.parse(data.toString()); + var entry = { + name: name, + id: request.body.id, + uid: vehicle.uid, + index: "-1", + type: 'vehicle', + vehicleUpgradesP23: 0xEFFFFFFF, + vehicleUpgradesP25: 0xEFFFFFFF + } -app.put('/vehicle', (request, response) => { - console.log('Changing vehicle: "' + request.body.uid + '" to position ' + request.body.position + ', index ' + request.body.index); - var vehicle = createVehicle(request.body.id, [0xEFFFFFFF, 0xEFFFFFFF], request.body.uid); - tp.place(vehicle, request.body.position, request.body.index, vehicle.uid); - console.log('Vehicle changed: "' + request.body.uid + '" to position ' + request.body.position + ', index ' + request.body.index); + //console.log(entry) + tags.push(entry); + + fs.writeFile(toytagFileName, JSON.stringify(tags, null, 4), 'utf8', (err) => { + if (err) { + console.log(`Error writing file: ${err}`); + } else { + console.log(`File is written successfully!`); + } + }); + } + }) + console.log('Vehicle placed: ' + request.body.id); + response.send(uid); }); +//This is called when a tag is removed from the board or needs to be moved. app.delete('/remove', (request, response) => { console.log('Removing item: ' + request.body.index); + console.log('DEBUG: pad-from-token: ', tp._tokens.filter(v => v.index == request.body.index)[0].pad); tp.remove(request.body.index); console.log('Item removed: ' + request.body.index); + updatePadIndex(request.body.uid, "-1"); response.send(true); }); -app.listen(80, () => console.log('Server running on port 80')); +//IO calls +io.on('connection', (socket) => { + //Removes a entry from toytags.json + socket.on('deleteToken', (uid) => { + console.log('IO Recieved: Deleting entry '+ uid + ' from JSON'); + const tags = fs.readFileSync(toytagFileName, 'utf8'); + const databases = JSON.parse(tags); + var index = -1; + var i = 0; + databases.forEach(db => { + if(uid == db.uid){ + index = i; + return; + } + i++; + }); + console.log('Entry to delete: ', index) + if (index > -1) { + databases.splice(index, 1); + } + fs.writeFileSync(toytagFileName, JSON.stringify(databases, null, 4), function(){ + if (index > -1) + console.log('Token not found'); + else + console.log('Deleted ', uid, ' from JSON'); + }) + io.emit("refreshTokens"); + }); +}); + +server.listen(80, () => console.log('Server running on port 80')); diff --git a/package.json b/package.json index 4f393f8..06e7354 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "license": "ISC", "dependencies": { "express": "^4.17.1", - "node-ld": "^1.1.6" + "node-ld": "^1.1.6", + "socket.io": "^4.2.0" } } diff --git a/server/index.html b/server/index.html new file mode 100644 index 0000000..2ee0c1a --- /dev/null +++ b/server/index.html @@ -0,0 +1,357 @@ + + + +
+ + + +
+ + +
+
+

LD ToyPad Emulator

+

+ → If you encounter a token that is not responsing, move to the toybox and then back to the toypad ←
+
+ Create characters and vehicles with boxes at the top then drag them to the toy pad.
+

+
+ +
+ +
+ +
+ +
+ +
+
+

Toy Box

+

Drag an entry to move it to the pad

+
+
    +
      +
    • +

      Drag here to delete

      +
    • +
    +
    +
    + +
    +

    The Toypad

    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + +
    + + + + + + + + + + diff --git a/server/json/charactermap.json b/server/json/charactermap.json new file mode 100644 index 0000000..bf1d3bc --- /dev/null +++ b/server/json/charactermap.json @@ -0,0 +1,88 @@ +[ + { "id": 1, "name": "Batman", "world": "DC Comics" }, + { "id": 2, "name": "Gandalf", "world": "Lord of the Rings" }, + { "id": 3, "name": "Wyldstyle", "world": "The LEGO Movie" }, + { "id": 4, "name": "Aquaman", "world": "DC Comics" }, + { "id": 5, "name": "Bad Cop", "world": "The LEGO Movie" }, + { "id": 6, "name": "Bane", "world": "DC Comics" }, + { "id": 7, "name": "Bart", "world": "The Simpsons" }, + { "id": 8, "name": "Benny", "world": "The LEGO Movie" }, + { "id": 9, "name": "Chell", "world": "Portal 2" }, + { "id": 10, "name": "Cole", "world": "Ninjago" }, + { "id": 11, "name": "Cragger", "world": "Legends of Chima" }, + { "id": 12, "name": "Cyborg", "world": "DC Comics" }, + { "id": 13, "name": "Cyberman", "world": "Doctor Who" }, + { "id": 14, "name": "Doc Brown", "world": "Back to the Future" }, + { "id": 15, "name": "The Doctor", "world": "Doctor Who" }, + { "id": 16, "name": "Emmet", "world": "The LEGO Movie" }, + { "id": 17, "name": "Eris", "world": "Legends of Chima" }, + { "id": 18, "name": "Gimli", "world": "Lord of the Rings" }, + { "id": 19, "name": "Smeagol", "world": "Lord of the Rings" }, + { "id": 20, "name": "Harley Quinn", "world": "DC Comics" }, + { "id": 21, "name": "Homer", "world": "The Simpsons" }, + { "id": 22, "name": "Jay", "world": "Ninjago" }, + { "id": 23, "name": "Joker", "world": "DC Comics" }, + { "id": 24, "name": "Kai", "world": "Ninjago" }, + { "id": 25, "name": "ACU", "world": "Jurrasic Park" }, + { "id": 26, "name": "Gamer Kid", "world": "Midway Arcade" }, + { "id": 27, "name": "Krusty", "world": "The Simpsons" }, + { "id": 28, "name": "Laval", "world": "Legends of Chima" }, + { "id": 29, "name": "Legolas", "world": "Lord of the Rings" }, + { "id": 30, "name": "Lloyd", "world": "Ninjago" }, + { "id": 31, "name": "Marty Mcfly", "world": "Back to the Future" }, + { "id": 32, "name": "Nya", "world": "Ninjago" }, + { "id": 33, "name": "Owen", "world": "Jurrasic Park" }, + { "id": 34, "name": "Peter Venkman", "world": "Ghostbusters" }, + { "id": 35, "name": "Slimer", "world": "Ghostbusters" }, + { "id": 36, "name": "Scooby Doo", "world": "Scooby-Doo" }, + { "id": 37, "name": "SenseiWu", "world": "Ninjago" }, + { "id": 38, "name": "Shaggy", "world": "Scooby-Doo" }, + { "id": 39, "name": "Stay Puft", "world": "Ghostbusters" }, + { "id": 40, "name": "Superman", "world": "DC Comics" }, + { "id": 41, "name": "Unikitty", "world": "The LEGO Movie" }, + { "id": 42, "name": "Wicked Witch", "world": "Wizard of OZ" }, + { "id": 43, "name": "Superwoman", "world": "DC Comics" }, + { "id": 44, "name": "Zane", "world": "Ninjago" }, + { "id": 45, "name": "Green Arrow", "world": "DC Comics" }, + { "id": 46, "name": "Supergirl", "world": "DC Comics" }, + { "id": 47, "name": "Abby Yates", "world": "Ghostbuster 2016" }, + { "id": 48, "name": "Finn", "world": "Adventure Time" }, + { "id": 49, "name": "Ethan Hunt", "world": "Mission Impossible" }, + { "id": 50, "name": "Lumpy Space Princess", "world": "Adventure Time" }, + { "id": 51, "name": "Jake", "world": "Adventure Time" }, + { "id": 52, "name": "Harry Potter", "world": "Harry Potter" }, + { "id": 53, "name": "Voldemort", "world": "Harry Potter" }, + { "id": 54, "name": "Michael Knight", "world":"Knight Rider"}, + { "id": 55, "name": "B.A. Baracus", "world": "A-Team" }, + { "id": 56, "name": "Newt", "world": "Fantastic Beasts" }, + { "id": 57, "name": "Sonic", "world": "Sonic" }, + { "id": 58, "name": "Future Update", "world": "N/A" }, + { "id": 59, "name": "Gizmo", "world": "Gremlins" }, + { "id": 60, "name": "Stripe", "world": "Gremlins" }, + { "id": 61, "name": "E.T.", "world": "E.T." }, + { "id": 62, "name": "Tina", "world": "Fantastic Beasts" }, + { "id": 63, "name": "Marceline", "world": "Adventure Time" }, + { "id": 64, "name": "Bat Girl", "world":"LEGO Batman Movie"}, + { "id": 65, "name": "Robin", "world":"LEGO Batman Movie"}, + { "id": 66, "name": "Sloth", "world":"Goonies" }, + { "id": 67, "name": "Hermione Granger", "world":"Harry Potter" }, + { "id": 68, "name": "Chase McCain", "world":"LEGO City" }, + { "id": 69, "name": "Excalibur Batman","world":"lego Batman Movie"}, + { "id": 70, "name": "Raven", "world":"Teen Titans Go"}, + { "id": 71, "name": "Beast Boy", "world":"Teen Titans Go"}, + { "id": 72, "name": "Beetle Juice", "world":"Beetle Juice"}, + { "id": 73, "name": "Lord Vortech", "world":"Lego Dimensions"}, + { "id": 74, "name": "Blossom", "world":"Power Puff Girls"}, + { "id": 75, "name": "Bubbles", "world":"Power Puff Girls"}, + { "id": 76, "name": "Buttercup", "world":"Power Puff Girls"}, + { "id": 77, "name": "Star Fire", "world":"Teen Titans Go"}, + { "id": 78, "name": "Test 15", "world":"15"}, + { "id": 79, "name": "Test 16", "world":"16"}, + { "id": 80, "name": "Test 17", "world":"17"}, + { "id": 81, "name": "Test 16", "world":"18"}, + { "id": 82, "name": "Test 17", "world":"19"}, + { "id": 83, "name": "Test 18", "world":"20"}, + { "id": 768, "name": "Unknown", "world":"Unknown"}, + { "id": 769, "name": "Supergirl Red Lantern", "world":"Dc Comics"}, + { "id": 770, "name": "Unknown", "world":"Unknown"} +] diff --git a/server/json/tokenmap.json b/server/json/tokenmap.json new file mode 100644 index 0000000..7ea717c --- /dev/null +++ b/server/json/tokenmap.json @@ -0,0 +1,247 @@ +[ + { "id": 1000, "upgrademap": 0, "rebuild": 0, "name": "Police Car" }, + { "id": 1001, "upgrademap": 0, "rebuild": 1, "name": "* Aerial Squad Car" }, + { "id": 1002, "upgrademap": 0, "rebuild": 2, "name": "* Missile Striker" }, + { "id": 1003, "upgrademap": 0, "rebuild": 0, "name": "Gravity Sprinter" }, + { "id": 1004, "upgrademap": 0, "rebuild": 1, "name": "* Street Shredder" }, + { "id": 1005, "upgrademap": 0, "rebuild": 2, "name": "* Sky Clobberer" }, + { "id": 1006, "upgrademap": 0, "rebuild": 0, "name": "Batmobile" }, + { "id": 1007, "upgrademap": 0, "rebuild": 1, "name": "* Batblaster" }, + { "id": 1008, "upgrademap": 0, "rebuild": 2, "name": "* Sonic Batray" }, + { "id": 1009, "upgrademap": 0, "rebuild": 0, "name": "Benny's Spaceship" }, + { "id": 1010, "upgrademap": 0, "rebuild": 1, "name": "* Lasercraft" }, + { "id": 1011, "upgrademap": 0, "rebuild": 2, "name": "* The Annihilator" }, + { "id": 1012, "upgrademap": 0, "rebuild": 0, "name": "Delorean" }, + { "id": 1013, "upgrademap": 0, "rebuild": 1, "name": "* Ultra Time Machine" }, + { "id": 1014, "upgrademap": 0, "rebuild": 2, "name": "* Electric Time Machine" }, + { "id": 1015, "upgrademap": 0, "rebuild": 0, "name": "Hoverboard" }, + { "id": 1016, "upgrademap": 0, "rebuild": 1, "name": "* Cyclone Board" }, + { "id": 1017, "upgrademap": 0, "rebuild": 2, "name": "* Ultimate Hoverjet" }, + { "id": 1018, "upgrademap": 0, "rebuild": 0, "name": "Eagle interceptor" }, + { "id": 1019, "upgrademap": 0, "rebuild": 1, "name": "* Eagle Skyblazer" }, + { "id": 1020, "upgrademap": 0, "rebuild": 2, "name": "* Eagle Swoop Diver" }, + { "id": 1021, "upgrademap": 0, "rebuild": 0, "name": "Cragger's Fireship" }, + { "id": 1022, "upgrademap": 0, "rebuild": 1, "name": "* Croc Command Sub" }, + { "id": 1023, "upgrademap": 0, "rebuild": 2, "name": "* Swamp Skimmer" }, + { "id": 1024, "upgrademap": 0, "rebuild": 0, "name": "Cyber Guard" }, + { "id": 1025, "upgrademap": 0, "rebuild": 1, "name": "* Cyber-Wrecker" }, + { "id": 1026, "upgrademap": 0, "rebuild": 2, "name": "* Laser Robot Walker" }, + { "id": 1027, "upgrademap": 0, "rebuild": 0, "name": "K9" }, + { "id": 1028, "upgrademap": 0, "rebuild": 1, "name": "* K9 Ruff Rover" }, + { "id": 1029, "upgrademap": 0, "rebuild": 2, "name": "* K9 Laser Cutter" }, + { "id": 1030, "upgrademap": 0, "rebuild": 0, "name": "TARDIS" }, + { "id": 1031, "upgrademap": 0, "rebuild": 1, "name": "* Laser-Pulse TARDIS" }, + { "id": 1032, "upgrademap": 0, "rebuild": 2, "name": "* Energy-Burst TARDIS" }, + { "id": 1033, "upgrademap": 0, "rebuild": 0, "name": "Emmet's Excavator" }, + { "id": 1034, "upgrademap": 0, "rebuild": 1, "name": "* The Destroydozer" }, + { "id": 1035, "upgrademap": 0, "rebuild": 2, "name": "* Destruct-o-Mech" }, + { "id": 1036, "upgrademap": 0, "rebuild": 0, "name": "Winged Monkey" }, + { "id": 1037, "upgrademap": 0, "rebuild": 1, "name": "* Battle Monkey" }, + { "id": 1038, "upgrademap": 0, "rebuild": 2, "name": "* Commander Monkey" }, + { "id": 1039, "upgrademap": 0, "rebuild": 0, "name": "Axe Chariot" }, + { "id": 1040, "upgrademap": 0, "rebuild": 1, "name": "* Axe Hurler" }, + { "id": 1041, "upgrademap": 0, "rebuild": 2, "name": "* Soaring Chariot" }, + { "id": 1042, "upgrademap": 0, "rebuild": 0, "name": "Shelob the Great" }, + { "id": 1043, "upgrademap": 0, "rebuild": 1, "name": "* 8-Legged Stalker" }, + { "id": 1044, "upgrademap": 0, "rebuild": 2, "name": "* Poison Slinger" }, + { "id": 1045, "upgrademap": 0, "rebuild": 0, "name": "Homer's Car" }, + { "id": 1046, "upgrademap": 0, "rebuild": 1, "name": "* Homercraft" }, + { "id": 1047, "upgrademap": 0, "rebuild": 2, "name": "* SubmaHomer" }, + { "id": 1048, "upgrademap": 0, "rebuild": 0, "name": "Taunt-o-Vision" }, + { "id": 1049, "upgrademap": 0, "rebuild": 1, "name": "* Blast Cam" }, + { "id": 1050, "upgrademap": 0, "rebuild": 2, "name": "* The MechaHomer" }, + { "id": 1051, "upgrademap": 0, "rebuild": 0, "name": "Velociraptor" }, + { "id": 1052, "upgrademap": 0, "rebuild": 1, "name": "* Spike Attack Raptor" }, + { "id": 1053, "upgrademap": 0, "rebuild": 2, "name": "* Venom Raptor" }, + { "id": 1054, "upgrademap": 0, "rebuild": 0, "name": "Gyro Sphere" }, + { "id": 1055, "upgrademap": 0, "rebuild": 1, "name": "* Sonic Beam Gyrosphere" }, + { "id": 1056, "upgrademap": 0, "rebuild": 2, "name": "* Speed Boost Gyrosphere" }, + { "id": 1057, "upgrademap": 0, "rebuild": 0, "name": "Clown Bike" }, + { "id": 1058, "upgrademap": 0, "rebuild": 1, "name": "* Cannon Bike" }, + { "id": 1059, "upgrademap": 0, "rebuild": 2, "name": "* Anti-Gravity Rocket Bike" }, + { "id": 1060, "upgrademap": 0, "rebuild": 0, "name": "Mighty Lion Rider" }, + { "id": 1061, "upgrademap": 0, "rebuild": 1, "name": "* Lion Blazer" }, + { "id": 1062, "upgrademap": 0, "rebuild": 2, "name": "* Fire Lion" }, + { "id": 1063, "upgrademap": 0, "rebuild": 0, "name": "Arrow Launcher" }, + { "id": 1064, "upgrademap": 0, "rebuild": 1, "name": "* Seeking Shooter" }, + { "id": 1065, "upgrademap": 0, "rebuild": 2, "name": "* Triple Ballista" }, + { "id": 1066, "upgrademap": 0, "rebuild": 0, "name": "Mystery Machine" }, + { "id": 1067, "upgrademap": 0, "rebuild": 1, "name": "* Mystery Tow" }, + { "id": 1068, "upgrademap": 0, "rebuild": 2, "name": "* Mystery Monster" }, + { "id": 1069, "upgrademap": 0, "rebuild": 0, "name": "Boulder Bomber" }, + { "id": 1070, "upgrademap": 0, "rebuild": 1, "name": "* Boulder Blaster" }, + { "id": 1071, "upgrademap": 0, "rebuild": 2, "name": "* Cyclone Jet" }, + { "id": 1072, "upgrademap": 0, "rebuild": 0, "name": "Storm Fighter" }, + { "id": 1073, "upgrademap": 0, "rebuild": 1, "name": "* Lightning Jet" }, + { "id": 1074, "upgrademap": 0, "rebuild": 2, "name": "* Electro-Shooter" }, + { "id": 1075, "upgrademap": 0, "rebuild": 0, "name": "Blade Bike" }, + { "id": 1076, "upgrademap": 0, "rebuild": 1, "name": "* Flying Fire Bike" }, + { "id": 1077, "upgrademap": 0, "rebuild": 2, "name": "* Blades of Fire" }, + { "id": 1078, "upgrademap": 0, "rebuild": 0, "name": "Samurai Mech" }, + { "id": 1079, "upgrademap": 0, "rebuild": 1, "name": "* Samurai Shooter" }, + { "id": 1080, "upgrademap": 0, "rebuild": 2, "name": "* Soaring Samurai Mech" }, + { "id": 1081, "upgrademap": 0, "rebuild": 0, "name": "Companion Cube" }, + { "id": 1082, "upgrademap": 0, "rebuild": 1, "name": "* Laser Deflector" }, + { "id": 1083, "upgrademap": 0, "rebuild": 2, "name": "* Gold Heart Emitter" }, + { "id": 1084, "upgrademap": 0, "rebuild": 0, "name": "Sentry Turret" }, + { "id": 1085, "upgrademap": 0, "rebuild": 1, "name": "* Turret Striker" }, + { "id": 1086, "upgrademap": 0, "rebuild": 2, "name": "* Flying Turret Carrier" }, + { "id": 1087, "upgrademap": 0, "rebuild": 0, "name": "Scooby Snack" }, + { "id": 1088, "upgrademap": 0, "rebuild": 1, "name": "* Scooby Fire Snack" }, + { "id": 1089, "upgrademap": 0, "rebuild": 2, "name": "* Scooby Ghost Snack" }, + { "id": 1090, "upgrademap": 0, "rebuild": 0, "name": "Cloud Cukko Car" }, + { "id": 1091, "upgrademap": 0, "rebuild": 1, "name": "* X-Stream Soaker" }, + { "id": 1092, "upgrademap": 0, "rebuild": 2, "name": "* Rainbow Cannon" }, + { "id": 1093, "upgrademap": 0, "rebuild": 0, "name": "Invisible Jet" }, + { "id": 1094, "upgrademap": 0, "rebuild": 1, "name": "* Stealth Laser Shooter" }, + { "id": 1095, "upgrademap": 0, "rebuild": 2, "name": "* Torpedo Bomber" }, + { "id": 1096, "upgrademap": 0, "rebuild": 0, "name": "Ninja Copter" }, + { "id": 1097, "upgrademap": 0, "rebuild": 1, "name": "* Glaciator" }, + { "id": 1098, "upgrademap": 0, "rebuild": 2, "name": "* Freeze Fighter" }, + { "id": 1099, "upgrademap": 0, "rebuild": 0, "name": "Traveling Time Train" }, + { "id": 1100, "upgrademap": 0, "rebuild": 1, "name": "* (Traveling Time Train - rebuilt 1)" }, + { "id": 1101, "upgrademap": 0, "rebuild": 2, "name": "* (Traveling Time Train - rebuilt 2)" }, + { "id": 1102, "upgrademap": 0, "rebuild": 0, "name": "Aqua Watercraft" }, + { "id": 1103, "upgrademap": 0, "rebuild": 1, "name": "* (Aqua Watercraft - rebuilt 1)" }, + { "id": 1104, "upgrademap": 0, "rebuild": 2, "name": "* (Aqua Watercraft - rebuilt 2)" }, + { "id": 1105, "upgrademap": 0, "rebuild": 0, "name": "Drill Driver" }, + { "id": 1106, "upgrademap": 0, "rebuild": 1, "name": "* (Drill Driver - rebuilt 1)" }, + { "id": 1107, "upgrademap": 0, "rebuild": 2, "name": "* (Drill Driver - rebuilt 2)" }, + { "id": 1108, "upgrademap": 0, "rebuild": 0, "name": "Quinn-mobile" }, + { "id": 1109, "upgrademap": 0, "rebuild": 1, "name": "* (Quinn-mobile - rebuilt 1)" }, + { "id": 1110, "upgrademap": 0, "rebuild": 2, "name": "* (Quinn-mobile - rebuilt 2)" }, + { "id": 1111, "upgrademap": 0, "rebuild": 0, "name": "The Jokers Chopper" }, + { "id": 1112, "upgrademap": 0, "rebuild": 1, "name": "* (The Jokers Chopper - rebuilt 1)" }, + { "id": 1113, "upgrademap": 0, "rebuild": 2, "name": "* (The Jokers Chopper - rebuilt 2)" }, + { "id": 1114, "upgrademap": 0, "rebuild": 0, "name": "Hover Pod" }, + { "id": 1115, "upgrademap": 0, "rebuild": 1, "name": "* (Hover Pod - rebuilt 1)" }, + { "id": 1116, "upgrademap": 0, "rebuild": 2, "name": "* (Hover Pod - rebuilt 2)" }, + { "id": 1117, "upgrademap": 0, "rebuild": 0, "name": "Dalek" }, + { "id": 1118, "upgrademap": 0, "rebuild": 1, "name": "* (Dalek - rebuilt 1)" }, + { "id": 1119, "upgrademap": 0, "rebuild": 2, "name": "* (Dalek - rebuilt 2)" }, + { "id": 1120, "upgrademap": 0, "rebuild": 0, "name": "Ecto-1" }, + { "id": 1121, "upgrademap": 0, "rebuild": 1, "name": "* (Ecto-1 - rebuilt 1)" }, + { "id": 1122, "upgrademap": 0, "rebuild": 2, "name": "* (Ecto-1 - rebuilt 2)" }, + { "id": 1123, "upgrademap": 0, "rebuild": 0, "name": "Ghost Trap" }, + { "id": 1124, "upgrademap": 0, "rebuild": 1, "name": "* (Ghost Trap - rebuilt 1)" }, + { "id": 1125, "upgrademap": 0, "rebuild": 2, "name": "* (Ghost Trap - rebuilt 2)" }, + { "id": 1126, "upgrademap": 0, "rebuild": 0, "name": "unknown" }, + { "id": 1127, "upgrademap": 0, "rebuild": 1, "name": "unknown" }, + { "id": 1128, "upgrademap": 0, "rebuild": 2, "name": "unknown" }, + { "id": 1129, "upgrademap": 0, "rebuild": 0, "name": "unknown" }, + { "id": 1130, "upgrademap": 0, "rebuild": 1, "name": "unknown" }, + { "id": 1131, "upgrademap": 0, "rebuild": 2, "name": "unknown" }, + { "id": 1132, "upgrademap": 0, "rebuild": 0, "name": "Llyod's Golden Dragon" }, + { "id": 1133, "upgrademap": 0, "rebuild": 1, "name": "* (Golden Dragon - rebuilt 1)" }, + { "id": 1134, "upgrademap": 0, "rebuild": 2, "name": "* (Golden Dragon - rebuilt 2)" }, + { "id": 1135, "upgrademap": 0, "rebuild": 0, "name": "unknown" }, + { "id": 1136, "upgrademap": 0, "rebuild": 0, "name": "unknown" }, + { "id": 1137, "upgrademap": 0, "rebuild": 0, "name": "unknown" }, + { "id": 1138, "upgrademap": 0, "rebuild": 0, "name": "unknown" }, + { "id": 1139, "upgrademap": 0, "rebuild": 0, "name": "unknown" }, + { "id": 1140, "upgrademap": 0, "rebuild": 0, "name": "unknown" }, + { "id": 1141, "upgrademap": 0, "rebuild": 0, "name": "unknown" }, + { "id": 1142, "upgrademap": 0, "rebuild": 0, "name": "unknown" }, + { "id": 1143, "upgrademap": 0, "rebuild": 0, "name": "unknown" }, + { "id": 1144, "upgrademap": 0, "rebuild": 0, "name": "Mega Flight Dragon" }, + { "id": 1145, "upgrademap": 0, "rebuild": 1, "name": "* (Mega Flight Dragon - rebuilt 1)" }, + { "id": 1146, "upgrademap": 0, "rebuild": 2, "name": "* (Mega Flight Dragon - rebuilt 2)" }, + { "id": 1147, "upgrademap": 0, "rebuild": 0, "name": "unknown" }, + { "id": 1148, "upgrademap": 0, "rebuild": 0, "name": "unknown" }, + { "id": 1149, "upgrademap": 0, "rebuild": 0, "name": "unknown" }, + { "id": 1150, "upgrademap": 0, "rebuild": 0, "name": "unknown" }, + { "id": 1151, "upgrademap": 0, "rebuild": 0, "name": "unknown" }, + { "id": 1152, "upgrademap": 0, "rebuild": 0, "name": "unknown" }, + { "id": 1153, "upgrademap": 0, "rebuild": 0, "name": "unknown" }, + { "id": 1154, "upgrademap": 0, "rebuild": 0, "name": "unknown" }, + { "id": 1155, "upgrademap": 0, "rebuild": 0, "name": "Flying White Dragon" }, + { "id": 1156, "upgrademap": 0, "rebuild": 1, "name": "* Golden Fire Dragon" }, + { "id": 1157, "upgrademap": 0, "rebuild": 2, "name": "* Ultra Destruction Dragon" }, + { "id": 1158, "upgrademap": 0, "rebuild": 0, "name": "Arcade Machine" }, + { "id": 1159, "upgrademap": 0, "rebuild": 1, "name": "* 8-bit Shooter" }, + { "id": 1160, "upgrademap": 0, "rebuild": 2, "name": "* The Pixelator" }, + { "id": 1161, "upgrademap": 0, "rebuild": 0, "name": "G-61555 Spy Hunter" }, + { "id": 1162, "upgrademap": 0, "rebuild": 1, "name": "* The Interdiver" }, + { "id": 1163, "upgrademap": 0, "rebuild": 2, "name": "* Aerial Spyhunter" }, + { "id": 1164, "upgrademap": 0, "rebuild": 0, "name": "Slime Shooter" }, + { "id": 1165, "upgrademap": 0, "rebuild": 1, "name": "* Slime Exploder" }, + { "id": 1166, "upgrademap": 0, "rebuild": 2, "name": "* Slime Streamer" }, + { "id": 1167, "upgrademap": 0, "rebuild": 0, "name": "Terror Dog" }, + { "id": 1168, "upgrademap": 0, "rebuild": 1, "name": "* Terror Dog Destroyer" }, + { "id": 1169, "upgrademap": 0, "rebuild": 2, "name": "* Soaring Terror Dog" }, + { "id": 1170, "upgrademap": 0, "rebuild": 0, "name": "Ancient War Elephant" }, + { "id": 1171, "upgrademap": 0, "rebuild": 1, "name": "* Cosmic Squid" }, + { "id": 1172, "upgrademap": 0, "rebuild": 2, "name": "* Psychic Submarine" }, + { "id": 1173, "upgrademap": 0, "rebuild": 0, "name": "BMO" }, + { "id": 1174, "upgrademap": 0, "rebuild": 1, "name": "* DOGMO" }, + { "id": 1175, "upgrademap": 0, "rebuild": 2, "name": "* SNAKEMO" }, + { "id": 1176, "upgrademap": 0, "rebuild": 0, "name": "Jakemoblie" }, + { "id": 1177, "upgrademap": 0, "rebuild": 1, "name": "* Snail Dude Jake" }, + { "id": 1178, "upgrademap": 0, "rebuild": 2, "name": "* Hover Jake" }, + { "id": 1179, "upgrademap": 0, "rebuild": 0, "name": "Lumpy Car" }, + { "id": 1180, "upgrademap": 0, "rebuild": 1, "name": "* Lumpy Truck" }, + { "id": 1181, "upgrademap": 0, "rebuild": 2, "name": "* Lumpy Land Whale" }, + { "id": 1182, "upgrademap": 0, "rebuild": 0, "name": "Lunatic Amp" }, + { "id": 1183, "upgrademap": 0, "rebuild": 1, "name": "* Lunatic Amp 2" }, + { "id": 1184, "upgrademap": 0, "rebuild": 2, "name": "* Lunatic Amp 3" }, + { "id": 1185, "upgrademap": 0, "rebuild": 0, "name": "B.A.s Van" }, + { "id": 1186, "upgrademap": 0, "rebuild": 1, "name": "* Fool Smasher" }, + { "id": 1187, "upgrademap": 0, "rebuild": 2, "name": "* The Pain Plane" }, + { "id": 1188, "upgrademap": 0, "rebuild": 0, "name": "Phone Home" }, + { "id": 1189, "upgrademap": 0, "rebuild": 1, "name": "* Phone Home 2" }, + { "id": 1190, "upgrademap": 0, "rebuild": 2, "name": "* Phone Home 3" }, + { "id": 1191, "upgrademap": 0, "rebuild": 0, "name": "Niffler" }, + { "id": 1192, "upgrademap": 0, "rebuild": 1, "name": "* Niffler 2" }, + { "id": 1193, "upgrademap": 0, "rebuild": 2, "name": "* Niffler 3" }, + { "id": 1194, "upgrademap": 0, "rebuild": 0, "name": "Swooping Evil" }, + { "id": 1195, "upgrademap": 0, "rebuild": 1, "name": "* Swooping Evil 2" }, + { "id": 1196, "upgrademap": 0, "rebuild": 2, "name": "* Swooping Evil 3" }, + { "id": 1197, "upgrademap": 0, "rebuild": 0, "name": "Ecto 1" }, + { "id": 1198, "upgrademap": 0, "rebuild": 1, "name": "* Ectozer" }, + { "id": 1199, "upgrademap": 0, "rebuild": 2, "name": "* Ecto1 Rebuild 2" }, + { "id": 1200, "upgrademap": 0, "rebuild": 2, "name": "Flash 'n' Finish" }, + { "id": 1201, "upgrademap": 0, "rebuild": 0, "name": "* Rampage Record Player" }, + { "id": 1202, "upgrademap": 0, "rebuild": 1, "name": "* Stripe's Throne" }, + { "id": 1203, "upgrademap": 0, "rebuild": 2, "name": "R.C. Racer" }, + { "id": 1204, "upgrademap": 0, "rebuild": 0, "name": "* Gadet-o-matic" }, + { "id": 1205, "upgrademap": 0, "rebuild": 1, "name": "* Scarlet Scorpion" }, + { "id": 1206, "upgrademap": 0, "rebuild": 0, "name": "Hogwarts Express" }, + { "id": 1207, "upgrademap": 0, "rebuild": 2, "name": "* Soaring Steam Plane" }, + { "id": 1208, "upgrademap": 0, "rebuild": 1, "name": "* Steam Warrior" }, + { "id": 1209, "upgrademap": 0, "rebuild": 2, "name": "Enchanted Car" }, + { "id": 1210, "upgrademap": 0, "rebuild": 0, "name": "* Shark Sub" }, + { "id": 1211, "upgrademap": 0, "rebuild": 1, "name": "* Monstrous Mouth" }, + { "id": 1212, "upgrademap": 0, "rebuild": 2, "name": "IMF Scrambler" }, + { "id": 1213, "upgrademap": 0, "rebuild": 0, "name": "* Shock Cycle" }, + { "id": 1214, "upgrademap": 0, "rebuild": 1, "name": "* IMF Covert Jet" }, + { "id": 1215, "upgrademap": 0, "rebuild": 2, "name": "IMF Sport Car" }, + { "id": 1216, "upgrademap": 0, "rebuild": 0, "name": "* IMF Tank" }, + { "id": 1217, "upgrademap": 0, "rebuild": 1, "name": "* IMF-Splorer" }, + { "id": 1218, "upgrademap": 0, "rebuild": 0, "name": "Sonic Speedster" }, + { "id": 1219, "upgrademap": 0, "rebuild": 1, "name": "* Sonic Speedster 2" }, + { "id": 1220, "upgrademap": 0, "rebuild": 2, "name": "* Sonic Speedster 3" }, + { "id": 1221, "upgrademap": 0, "rebuild": 0, "name": "The Tornado" }, + { "id": 1222, "upgrademap": 0, "rebuild": 1, "name": "* The Tornado 1" }, + { "id": 1223, "upgrademap": 0, "rebuild": 2, "name": "* The Tornado 2" }, + { "id": 1224, "upgrademap": 0, "rebuild": 0, "name": "K.I.T.T" }, + { "id": 1225, "upgrademap": 0, "rebuild": 1, "name": "* K.I.T.T. JET" }, + { "id": 1226, "upgrademap": 0, "rebuild": 2, "name": "* GOLIATH ARMORED SEMI" }, + { "id": 1227, "upgrademap": 0, "rebuild": 0, "name": "Police" }, + { "id": 1228, "upgrademap": 0, "rebuild": 1, "name": "* Hovercraft" }, + { "id": 1229, "upgrademap": 0, "rebuild": 2, "name": "* Plane" }, + { "id": 1230, "upgrademap": 0, "rebuild": 0, "name": "BIONIC STEED" }, + { "id": 1231, "upgrademap": 0, "rebuild": 1, "name": "* BAT RAPTOR" }, + { "id": 1232, "upgrademap": 0, "rebuild": 2, "name": "* ULTRA BAT" }, + { "id": 1233, "upgrademap": 0, "rebuild": 0, "name": "BAT WING" }, + { "id": 1234, "upgrademap": 0, "rebuild": 1, "name": "* BLACK THUNDER" }, + { "id": 1235, "upgrademap": 0, "rebuild": 2, "name": "* BAT TANK" }, + { "id": 1236, "upgrademap": 0, "rebuild": 0, "name": "Skeleton Organ" }, + { "id": 1237, "upgrademap": 0, "rebuild": 1, "name": "* Jukebox" }, + { "id": 1238, "upgrademap": 0, "rebuild": 2, "name": "* Skele-Turkey" }, + { "id": 1239, "upgrademap": 0, "rebuild": 0, "name": "Pirate Ship" }, + { "id": 1240, "upgrademap": 0, "rebuild": 1, "name": "* Fanged Fortune" }, + { "id": 1241, "upgrademap": 0, "rebuild": 2, "name": "* Inferno" }, + { "id": 1242, "upgrademap": 0, "rebuild": 0, "name": "Buckbeak" }, + { "id": 1243, "upgrademap": 0, "rebuild": 1, "name": "* Giant Owl" }, + { "id": 1244, "upgrademap": 0, "rebuild": 2, "name": "* Fierce Falcon" } +] diff --git a/server/json/toytags.json b/server/json/toytags.json new file mode 100644 index 0000000..fe51488 --- /dev/null +++ b/server/json/toytags.json @@ -0,0 +1 @@ +[] diff --git a/server/json/upgrademap.json b/server/json/upgrademap.json new file mode 100644 index 0000000..1edc43a --- /dev/null +++ b/server/json/upgrademap.json @@ -0,0 +1,224 @@ +{ + "speed":["Model Boost A"] +} + +"Speed":[{ + "name":"Model Boost Ability", + "desc":"Inital model speed has a boost for a short time.", + "cost":"cost":15000 +},{ + "name":"Boost Buff 1", + "desc":"Increased boost speed", + "cost":"15,000", +},{ + "name":"Movement Speed Buff 1", + "desc":"Increased model movement", + "cost":"15,000", +},{ + "name":"Jump Ability", + "desc":"Model can Jump ", + "cost":"20,000", +},{ + "name":"Boost Buff 2", + "desc":"Increased boost speed", + "cost":"20,000 Studs", +},{ + "name":"Movement Speed Buff 2", + "desc":"Increased model movement.", + "cost":"20,000 Studs", +}] + +"Power":[{ + "name":"Color Changing Bolts Ability", + "desc":"Gives the ability to fire tintable bolts", + "cost":"15,000", +},{ + "name":"Fire Speed Buff 1", + "desc":"Increased weapon fire rate", + "cost":"15,000 Studs", +},{ + "name":"Armor Buff", + "desc":"Model upgraded to have5 Armor Hearts ", + "cost":"15,000", +},{ + "name":"Instant Tow Bar", + "desc":"Tow Bars complete instantnly with vehicles that have them ", + "cost":"20,000", +},{ + "name":"Fire Speed Buff 2", + "desc":"Increased weapon fire rate", + "cost":"20,000 Studs", +},{ + "name":"Armor Buff", + "desc":"Model upgraded to have 6 armor hearts.", + "cost":"20,000 Studs", +}] +"Weapons":[{ + "name":"Mine Weapon", + "desc":"Mines are deployed", + "cost":"15,000 Studs", +},{ + "name":"Explode Ability", + "desc":"Model explodes after a count down (toggle off/on)", + "cost":"15,000 Studs", +}] +"Extras":[{ + "name":"Bolt Color Chooser", + "desc":"Allows you to tint bolt colors", + "cost":"15,000 Studs", +},{ + "name":"Enemy Hearts Ability", + "desc":"Enemy characters now drop hearts ", + "cost":"15,000", +},{ + "name":"Regenerate Armor Ability", + "desc":"Hearts on the model regenerate", + "cost":"15,000 Studs", +}] +"Colors":[{ + "name":"Skin 1", + "desc":"Changes the appearance of the model", + "cost":"15,000 Studs", +},{ + "name":"Tire Color Chooser", + "desc":"Allows you to pick tire colors", + "cost":"15,000 Studs", +},{ + "name":"Flame Color Choser", + "desc":"Choose exhaust flame color.", + "cost":"15,000 Studs", +}], +"Weapons", +{ + "name":"Spinning Weapon", + "desc":"Spinning objects are now fired to destroy distant threats ", + "cost":"20,000", +}, +"Weapons", +{ + "name":"Electric Shield", + "desc":"An electric field surrounds the model", + "cost":"20,000 Studs", +}, +"Extras 1", +{ + "name":"", + "desc":"", + "cost":"15,000 Studs", +}, +"Extras", +{ + "name":"Guardian Ability", + "desc":"Model will protect you by attacking enemies (needs an active weapon selected).", + "cost":"20,000 Studs", +}, +"Extras", +{ + "name":"Character Studs Ability", + "desc":"Enemies now give off lots of studs when they are defeated.", + "cost":"20,000 Studs", +}, +"Colors 1", +{ + "name":"", + "desc":" ", + "cost":"15,000 Studs", +} +"", +"Colors 2", +{ + "name":"", + "desc":"", + "cost":"50,000", +}, +"Colors 3", +{ + "name":"", + "desc":"", + "cost":"50,000", +}, +"Speed 1", +{ + "name":"Instant Accelerator Switch Ability", + "desc":"Accelerator Switches complete instantly when driven on.", + "cost":"50,000 Studs", +}, +"Speed 2", +{ + "name":"Boost Buff 3", + "desc":"Increased boost speed", + "cost":"50,000 Studs", +}, +"Speed 3", +{ + "name":"Movement Speed Buff 3", + "desc":"Increased model movement.", + "cost":"50,000 Studs", +}, +"Power 1", +{ + "name":"Instant Sonar Smash", + "desc":"Sonar smashes complete instantly rather than shaking.", + "cost":"50,000", +}, +"Power 2", +"", +{ + "name":"", + "desc":"", + "cost":"50,000", +}, +"Power 3", +{ + "name":"", + "desc":"", + "cost":"50,000", +}, +"Weapons 1", +{ + "name":"Swarm Weapon", + "desc":"Objects swarm around the model.", + "cost":"50,000 Studs", +}, +"Weapons 3", +{ + "name":"Speaker Attack Ability", + "desc":"Music makes nearby enemies dance for a set time.", + "cost":"50,000 Studs", +}, +"Extras 1", +{ + "name":"Engine Sound Chooser", + "desc":"Change the engine sounds.", + "cost":"50,000 Studs", +}, +"Extras 2", +{ + "name":"Armor Hearts Multiplier", + "desc":"Heart multiplier for player's health.", + "cost":"50,000 Studs", +}, +"Extras 3", +{ + "name":"Stud Magnet Ability", + "desc":"Studs are attracted to the vehicle", + "cost":"50,000 Studs", +}, +"Colors 1", +{ + "name":"Skin 3", + "desc":"Changes the appearance of the model.", + "cost":"50,000 Studs", +}, +"Colors 2", +{ + "name":"Model Color Chooser", + "desc":"Allows you to pick model color.", + "cost":"50,000 Studs", +}, +"Colors 3", +{ + "name":"", + "desc":"", + "cost":"50,000", +} \ No newline at end of file