1
0
mirror of https://github.com/shiroikitsu8/Bayshore_6r_legacy.git synced 2024-09-23 17:18:20 +02:00
This commit is contained in:
Shiroi Kitsu 2023-03-20 12:35:23 +07:00
parent 16232c0083
commit b0b8bec0d6
103 changed files with 57414 additions and 7869 deletions

View File

@ -1,5 +1,20 @@
# Bayshore
Wangan Midnight Maximum Tune 6 server reimplementation written in TypeScript
### THIS PROJECT IS CURRENTLY UNSUPPORTED. DO NOT MESSAGE ANYONE FOR HELP
# Bayshore 6R
Wangan Midnight Maximum Tune 6R server reimplementation written in TypeScript
this repo is based on the original repo (https://github.com/ProjectAsakura/Bayshore)
## What is working
- Same like 6
- VSORG [Expedition] (some of them maybe... expedition saving works)
- Highway [New Mode] (some of them maybe... highway saving works)
- Ghost Trophies Saving
## What is not working
- Transfer from 6
- Wanted Info for each area (game will crash... idk why)
## Credits
This software is part of [Project Asakura](https://github.com/ProjectAsakura).
@ -17,4 +32,4 @@ Donations are not required, however I'm only one person, and I'm still a student
This won't get you anything other than my gratitude, the entire project is and will always remain available to everyone for free.
## On TeknoParrot
The TeknoParrot team (TeknoGods) are not authorised to use **any part** of this project. **Do not integrate any portion of Bayshore into TeknoParrot.**
The TeknoParrot team (TeknoGods) are not authorised to use **any part** of this project. **Do not integrate any portion of Bayshore into TeknoParrot.**

View File

@ -10,9 +10,8 @@
"grantFullTuneTicketToNewUsers": 5,
"giftCarsFullyTuned": 0,
"scratchEnabled": 1,
"scratchType": 1,
"scratchType": 0,
"giveMeterReward": 0,
"newCardsBanned": 0,
"enableScreenshot": 0
"newCardsBanned": 0
}
}
}

View File

@ -20,18 +20,11 @@
"typescript": "^4.7.4"
},
"dependencies": {
"@opentelemetry/api": "^1.3.0",
"@opentelemetry/auto-instrumentations-node": "^0.35.0",
"@opentelemetry/exporter-metrics-otlp-grpc": "^0.34.0",
"@opentelemetry/exporter-trace-otlp-grpc": "^0.34.0",
"@opentelemetry/sdk-metrics": "^1.8.0",
"@opentelemetry/sdk-node": "^0.34.0",
"@opentelemetry/semantic-conventions": "^1.8.0",
"@prisma/client": "^4.0.0",
"@sentry/node": "^7.7.0",
"@sentry/tracing": "^7.7.0",
"@types/pem": "^1.9.6",
"body-parser": "^1.20.1",
"body-parser": "^1.20.0",
"dotenv": "^16.0.1",
"express": "^4.18.1",
"form-urlencoded": "^6.0.6",

View File

@ -1,150 +0,0 @@
-- CreateTable
CREATE TABLE "User" (
"id" SERIAL NOT NULL,
"chipId" TEXT NOT NULL,
"accessCode" TEXT NOT NULL,
"tutorials" BOOLEAN[],
"userBanned" BOOLEAN NOT NULL DEFAULT false,
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "UserItem" (
"dbId" SERIAL NOT NULL,
"category" INTEGER NOT NULL,
"itemId" INTEGER NOT NULL,
"userId" INTEGER NOT NULL,
CONSTRAINT "UserItem_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "Car" (
"userId" INTEGER NOT NULL,
"carId" SERIAL NOT NULL,
"name" TEXT NOT NULL,
"manufacturer" INTEGER NOT NULL,
"model" INTEGER NOT NULL,
"visualModel" INTEGER NOT NULL,
"customColor" INTEGER NOT NULL DEFAULT 0,
"defaultColor" INTEGER NOT NULL,
"wheel" INTEGER NOT NULL DEFAULT 0,
"wheelColor" INTEGER NOT NULL DEFAULT 0,
"aero" INTEGER NOT NULL DEFAULT 0,
"bonnet" INTEGER NOT NULL DEFAULT 0,
"wing" INTEGER NOT NULL DEFAULT 0,
"mirror" INTEGER NOT NULL DEFAULT 0,
"neon" INTEGER NOT NULL DEFAULT 0,
"trunk" INTEGER NOT NULL DEFAULT 0,
"plate" INTEGER NOT NULL DEFAULT 0,
"plateColor" INTEGER NOT NULL DEFAULT 0,
"plateNumber" INTEGER NOT NULL DEFAULT 0,
"tunePower" INTEGER NOT NULL DEFAULT 0,
"tuneHandling" INTEGER NOT NULL DEFAULT 0,
"title" TEXT NOT NULL DEFAULT 'New Car',
"level" INTEGER NOT NULL DEFAULT 0,
"windowSticker" BOOLEAN NOT NULL DEFAULT false,
"windowStickerString" TEXT NOT NULL DEFAULT '',
"windowStickerFont" INTEGER NOT NULL DEFAULT 0,
"rivalMarker" INTEGER NOT NULL DEFAULT 0,
"aura" INTEGER NOT NULL DEFAULT 0,
"auraMotif" INTEGER NOT NULL DEFAULT 0,
"ghostLevel" INTEGER NOT NULL DEFAULT 1,
"tuningPoints" INTEGER NOT NULL DEFAULT 0,
"odometer" INTEGER NOT NULL DEFAULT 0,
"playCount" INTEGER NOT NULL DEFAULT 0,
"earnedCustomColor" BOOLEAN NOT NULL DEFAULT false,
"carSettingsDbId" INTEGER NOT NULL,
"vsPlayCount" INTEGER NOT NULL DEFAULT 0,
"vsBurstCount" INTEGER NOT NULL DEFAULT 0,
"vsStarCount" INTEGER NOT NULL DEFAULT 0,
"vsCoolOrWild" INTEGER NOT NULL DEFAULT 0,
"vsSmoothOrRough" INTEGER NOT NULL DEFAULT 0,
"vsTripleStarMedals" INTEGER NOT NULL DEFAULT 0,
"vsDoubleStarMedals" INTEGER NOT NULL DEFAULT 0,
"vsSingleStarMedals" INTEGER NOT NULL DEFAULT 0,
"vsPlainMedals" INTEGER NOT NULL DEFAULT 0,
"rgPlayCount" INTEGER NOT NULL DEFAULT 0,
"rgWinCount" INTEGER NOT NULL DEFAULT 0,
"rgTrophy" INTEGER NOT NULL DEFAULT 0,
"rgScore" INTEGER NOT NULL DEFAULT 0,
"rgStamp" INTEGER NOT NULL DEFAULT 0,
"rgAcquireAllCrowns" BOOLEAN NOT NULL DEFAULT false,
"dressupLevel" INTEGER NOT NULL DEFAULT 0,
"dressupPoint" INTEGER NOT NULL DEFAULT 0,
"stPlayCount" INTEGER NOT NULL DEFAULT 0,
"stClearBits" INTEGER NOT NULL DEFAULT 0,
"stClearDivCount" INTEGER NOT NULL DEFAULT 0,
"stClearCount" INTEGER NOT NULL DEFAULT 0,
"stLoseBits" INTEGER NOT NULL DEFAULT 0,
"stConsecutiveWins" INTEGER NOT NULL DEFAULT 0,
"stConsecutiveWinsMax" INTEGER NOT NULL DEFAULT 0,
"stCompleted100Episodes" BOOLEAN NOT NULL DEFAULT false,
"carStateDbId" INTEGER NOT NULL,
CONSTRAINT "Car_pkey" PRIMARY KEY ("carId")
);
-- CreateTable
CREATE TABLE "CarItem" (
"carId" INTEGER NOT NULL,
"category" INTEGER NOT NULL,
"itemId" INTEGER NOT NULL,
"amount" INTEGER NOT NULL
);
-- CreateTable
CREATE TABLE "CarSettings" (
"dbId" SERIAL NOT NULL,
"view" BOOLEAN NOT NULL DEFAULT true,
"transmission" BOOLEAN NOT NULL DEFAULT false,
"retire" BOOLEAN NOT NULL DEFAULT false,
"meter" INTEGER NOT NULL DEFAULT 0,
"navigationMap" BOOLEAN NOT NULL DEFAULT true,
"volume" INTEGER NOT NULL DEFAULT 1,
"bgm" INTEGER NOT NULL DEFAULT 0,
"nameplate" INTEGER NOT NULL DEFAULT 0,
"nameplateColor" INTEGER NOT NULL DEFAULT 0,
"terminalBackground" INTEGER NOT NULL DEFAULT 0,
CONSTRAINT "CarSettings_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "CarState" (
"dbId" SERIAL NOT NULL,
"hasOpponentGhost" BOOLEAN NOT NULL DEFAULT false,
"eventJoined" BOOLEAN NOT NULL DEFAULT false,
"transferred" BOOLEAN NOT NULL DEFAULT false,
"toBeDeleted" BOOLEAN NOT NULL DEFAULT false,
CONSTRAINT "CarState_pkey" PRIMARY KEY ("dbId")
);
-- CreateIndex
CREATE UNIQUE INDEX "User_chipId_key" ON "User"("chipId");
-- CreateIndex
CREATE UNIQUE INDEX "Car_carSettingsDbId_key" ON "Car"("carSettingsDbId");
-- CreateIndex
CREATE UNIQUE INDEX "Car_carStateDbId_key" ON "Car"("carStateDbId");
-- CreateIndex
CREATE UNIQUE INDEX "CarItem_carId_key" ON "CarItem"("carId");
-- AddForeignKey
ALTER TABLE "UserItem" ADD CONSTRAINT "UserItem_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Car" ADD CONSTRAINT "Car_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Car" ADD CONSTRAINT "Car_carSettingsDbId_fkey" FOREIGN KEY ("carSettingsDbId") REFERENCES "CarSettings"("dbId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Car" ADD CONSTRAINT "Car_carStateDbId_fkey" FOREIGN KEY ("carStateDbId") REFERENCES "CarState"("dbId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "CarItem" ADD CONSTRAINT "CarItem_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -1,20 +0,0 @@
-- CreateTable
CREATE TABLE "TimeAttackRecord" (
"dbId" SERIAL NOT NULL,
"userId" INTEGER NOT NULL,
"model" INTEGER NOT NULL,
"time" INTEGER NOT NULL,
"course" INTEGER NOT NULL,
"section1Time" INTEGER NOT NULL,
"section2Time" INTEGER NOT NULL,
"section3Time" INTEGER NOT NULL,
"section4Time" INTEGER NOT NULL,
"section5Time" INTEGER,
"section6Time" INTEGER,
"section7Time" INTEGER,
CONSTRAINT "TimeAttackRecord_pkey" PRIMARY KEY ("dbId")
);
-- AddForeignKey
ALTER TABLE "TimeAttackRecord" ADD CONSTRAINT "TimeAttackRecord_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -1,8 +0,0 @@
/*
Warnings:
- Added the required column `isMorning` to the `TimeAttackRecord` table without a default value. This is not possible if the table is not empty.
*/
-- AlterTable
ALTER TABLE "TimeAttackRecord" ADD COLUMN "isMorning" BOOLEAN NOT NULL;

View File

@ -1,16 +0,0 @@
/*
Warnings:
- You are about to drop the column `userId` on the `TimeAttackRecord` table. All the data in the column will be lost.
- Added the required column `carId` to the `TimeAttackRecord` table without a default value. This is not possible if the table is not empty.
*/
-- DropForeignKey
ALTER TABLE "TimeAttackRecord" DROP CONSTRAINT "TimeAttackRecord_userId_fkey";
-- AlterTable
ALTER TABLE "TimeAttackRecord" DROP COLUMN "userId",
ADD COLUMN "carId" INTEGER NOT NULL;
-- AddForeignKey
ALTER TABLE "TimeAttackRecord" ADD CONSTRAINT "TimeAttackRecord_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -1,2 +0,0 @@
-- AlterTable
ALTER TABLE "Car" ADD COLUMN "regionId" INTEGER NOT NULL DEFAULT 0;

View File

@ -1,3 +0,0 @@
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0,
ALTER COLUMN "stLoseBits" SET DATA TYPE BIGINT;

View File

@ -1,9 +0,0 @@
-- DropIndex
DROP INDEX "CarItem_carId_key";
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "CarItem" ADD COLUMN "dbId" SERIAL NOT NULL,
ADD CONSTRAINT "CarItem_pkey" PRIMARY KEY ("dbId");

View File

@ -1,12 +0,0 @@
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "TimeAttackRecord" ADD COLUMN "tuneHandling" INTEGER NOT NULL DEFAULT 0,
ADD COLUMN "tunePower" INTEGER NOT NULL DEFAULT 0;
-- AlterTable
ALTER TABLE "User" ADD COLUMN "bookmarks" INTEGER[],
ADD COLUMN "carOrder" INTEGER[],
ADD COLUMN "currentSheet" INTEGER NOT NULL DEFAULT 0,
ADD COLUMN "lastSheet" INTEGER NOT NULL DEFAULT 0;

View File

@ -1,3 +0,0 @@
-- AlterTable
ALTER TABLE "Car" ADD COLUMN "rgRegionMapScore" INTEGER[],
ALTER COLUMN "stLoseBits" SET DEFAULT 0;

View File

@ -1,2 +0,0 @@
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;

View File

@ -1,50 +0,0 @@
/*
Warnings:
- You are about to drop the column `lastSheet` on the `User` table. All the data in the column will be lost.
- The primary key for the `UserItem` table will be changed. If it partially fails, the table could be left without primary key constraint.
- You are about to drop the column `dbId` on the `UserItem` table. All the data in the column will be lost.
*/
-- AlterTable
ALTER TABLE "Car" ADD COLUMN "lastPlayedAt" INTEGER NOT NULL DEFAULT 0,
ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "User" DROP COLUMN "lastSheet",
ADD COLUMN "lastScratched" INTEGER NOT NULL DEFAULT 0,
ALTER COLUMN "currentSheet" SET DEFAULT 1;
-- AlterTable
ALTER TABLE "UserItem" DROP CONSTRAINT "UserItem_pkey",
DROP COLUMN "dbId",
ADD COLUMN "earnedAt" INTEGER NOT NULL DEFAULT 0,
ADD COLUMN "type" INTEGER NOT NULL DEFAULT 0,
ADD COLUMN "userItemId" SERIAL NOT NULL,
ADD CONSTRAINT "UserItem_pkey" PRIMARY KEY ("userItemId");
-- CreateTable
CREATE TABLE "ScratchSheet" (
"id" SERIAL NOT NULL,
"userId" INTEGER NOT NULL,
"sheetNo" INTEGER NOT NULL,
CONSTRAINT "ScratchSheet_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "ScratchSquare" (
"id" SERIAL NOT NULL,
"sheetId" INTEGER NOT NULL,
"category" INTEGER NOT NULL,
"itemId" INTEGER NOT NULL,
"earned" BOOLEAN NOT NULL,
CONSTRAINT "ScratchSquare_pkey" PRIMARY KEY ("id")
);
-- AddForeignKey
ALTER TABLE "ScratchSheet" ADD CONSTRAINT "ScratchSheet_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ScratchSquare" ADD CONSTRAINT "ScratchSquare_sheetId_fkey" FOREIGN KEY ("sheetId") REFERENCES "ScratchSheet"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -1,22 +0,0 @@
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- CreateTable
CREATE TABLE "CarGTWing" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"pillar" INTEGER NOT NULL DEFAULT 0,
"pillarMaterial" INTEGER NOT NULL DEFAULT 0,
"mainWing" INTEGER NOT NULL DEFAULT 0,
"mainWingColor" INTEGER NOT NULL DEFAULT 0,
"wingTip" INTEGER NOT NULL DEFAULT 0,
"material" INTEGER NOT NULL DEFAULT 0,
CONSTRAINT "CarGTWing_pkey" PRIMARY KEY ("dbId")
);
-- CreateIndex
CREATE UNIQUE INDEX "CarGTWing_carId_key" ON "CarGTWing"("carId");
-- AddForeignKey
ALTER TABLE "CarGTWing" ADD CONSTRAINT "CarGTWing_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -1,3 +0,0 @@
-- AlterTable
ALTER TABLE "Car" ADD COLUMN "windowDecoration" INTEGER NOT NULL DEFAULT 0,
ALTER COLUMN "stLoseBits" SET DEFAULT 0;

View File

@ -1,26 +0,0 @@
/*
Warnings:
- You are about to drop the column `carId` on the `CarGTWing` table. All the data in the column will be lost.
- A unique constraint covering the columns `[carGTWingDbId]` on the table `Car` will be added. If there are existing duplicate values, this will fail.
- Added the required column `carGTWingDbId` to the `Car` table without a default value. This is not possible if the table is not empty.
*/
-- DropForeignKey
ALTER TABLE "CarGTWing" DROP CONSTRAINT "CarGTWing_carId_fkey";
-- DropIndex
DROP INDEX "CarGTWing_carId_key";
-- AlterTable
ALTER TABLE "Car" ADD COLUMN "carGTWingDbId" INTEGER NOT NULL,
ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "CarGTWing" DROP COLUMN "carId";
-- CreateIndex
CREATE UNIQUE INDEX "Car_carGTWingDbId_key" ON "Car"("carGTWingDbId");
-- AddForeignKey
ALTER TABLE "Car" ADD CONSTRAINT "Car_carGTWingDbId_fkey" FOREIGN KEY ("carGTWingDbId") REFERENCES "CarGTWing"("dbId") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -1,17 +0,0 @@
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- CreateTable
CREATE TABLE "CarCrown" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"area" INTEGER NOT NULL,
"ramp" INTEGER NOT NULL,
"path" INTEGER NOT NULL,
"trail" BIGINT NOT NULL DEFAULT 0,
CONSTRAINT "CarCrown_pkey" PRIMARY KEY ("dbId")
);
-- AddForeignKey
ALTER TABLE "CarCrown" ADD CONSTRAINT "CarCrown_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -1,14 +0,0 @@
/*
Warnings:
- A unique constraint covering the columns `[area]` on the table `CarCrown` will be added. If there are existing duplicate values, this will fail.
*/
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "CarCrown" ALTER COLUMN "trail" SET DEFAULT 0;
-- CreateIndex
CREATE UNIQUE INDEX "CarCrown_area_key" ON "CarCrown"("area");

View File

@ -1,6 +0,0 @@
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "CarCrown" ADD COLUMN "playedAt" INTEGER NOT NULL DEFAULT 0,
ALTER COLUMN "trail" SET DEFAULT 0;

View File

@ -1,14 +0,0 @@
/*
Warnings:
- Added the required column `tuneHandling` to the `CarCrown` table without a default value. This is not possible if the table is not empty.
- Added the required column `tunePower` to the `CarCrown` table without a default value. This is not possible if the table is not empty.
*/
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "CarCrown" ADD COLUMN "tuneHandling" INTEGER NOT NULL,
ADD COLUMN "tunePower" INTEGER NOT NULL,
ALTER COLUMN "trail" SET DEFAULT 0;

View File

@ -1,26 +0,0 @@
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "CarCrown" ALTER COLUMN "trail" DROP DEFAULT;
-- CreateTable
CREATE TABLE "GhostTrail" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"area" INTEGER NOT NULL,
"ramp" INTEGER NOT NULL,
"path" INTEGER NOT NULL,
"trail" BYTEA NOT NULL,
"time" INTEGER,
"driveData" BYTEA,
"trendBinaryByArea" BYTEA,
"tunePower" INTEGER NOT NULL,
"tuneHandling" INTEGER NOT NULL,
"playedAt" INTEGER NOT NULL,
CONSTRAINT "GhostTrail_pkey" PRIMARY KEY ("dbId")
);
-- AddForeignKey
ALTER TABLE "GhostTrail" ADD CONSTRAINT "GhostTrail_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -1,11 +0,0 @@
/*
Warnings:
- Added the required column `crownBattle` to the `GhostTrail` table without a default value. This is not possible if the table is not empty.
*/
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "GhostTrail" ADD COLUMN "crownBattle" BOOLEAN NOT NULL;

View File

@ -1,13 +0,0 @@
/*
Warnings:
- You are about to drop the column `tuneHandling` on the `GhostTrail` table. All the data in the column will be lost.
- You are about to drop the column `tunePower` on the `GhostTrail` table. All the data in the column will be lost.
*/
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "GhostTrail" DROP COLUMN "tuneHandling",
DROP COLUMN "tunePower";

View File

@ -1,11 +0,0 @@
/*
Warnings:
- You are about to drop the column `trail` on the `CarCrown` table. All the data in the column will be lost.
*/
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "CarCrown" DROP COLUMN "trail";

View File

@ -1,9 +0,0 @@
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "GhostTrail" ADD COLUMN "byAreaMergeSerial" INTEGER,
ADD COLUMN "byCarMergeSerial" INTEGER,
ADD COLUMN "byUserMergeSerial" INTEGER,
ADD COLUMN "trendBinaryByCar" BYTEA,
ADD COLUMN "trendBinaryByUser" BYTEA;

View File

@ -1,5 +0,0 @@
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "GhostTrail" ADD COLUMN "driveDMergeSerial" INTEGER;

View File

@ -1,8 +0,0 @@
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "GhostTrail" ADD COLUMN "tuneHandling" INTEGER NOT NULL DEFAULT 0,
ADD COLUMN "tunePower" INTEGER NOT NULL DEFAULT 0,
ALTER COLUMN "playedAt" SET DEFAULT 0,
ALTER COLUMN "crownBattle" SET DEFAULT false;

View File

@ -1,30 +0,0 @@
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- CreateTable
CREATE TABLE "GhostBattleRecord" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"tunePower" INTEGER NOT NULL DEFAULT 0,
"tuneHandling" INTEGER NOT NULL DEFAULT 0,
"opponent1CarId" INTEGER NOT NULL,
"opponent1Result" INTEGER NOT NULL,
"opponent1TunePower" INTEGER NOT NULL,
"opponent1TuneHandling" INTEGER NOT NULL,
"opponent2CarId" INTEGER,
"opponent2Result" INTEGER,
"opponent2TunePower" INTEGER,
"opponent2TuneHandling" INTEGER,
"opponent3CarId" INTEGER,
"opponent3Result" INTEGER,
"opponent3TunePower" INTEGER,
"opponent3TuneHandling" INTEGER,
"area" INTEGER NOT NULL DEFAULT 0,
"playedAt" INTEGER NOT NULL DEFAULT 0,
"playedShopName" TEXT NOT NULL DEFAULT 'Bayshore',
CONSTRAINT "GhostBattleRecord_pkey" PRIMARY KEY ("dbId")
);
-- AddForeignKey
ALTER TABLE "GhostBattleRecord" ADD CONSTRAINT "GhostBattleRecord_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -1,18 +0,0 @@
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- CreateTable
CREATE TABLE "CarPathandTuning" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"area" INTEGER NOT NULL DEFAULT 0,
"ramp" INTEGER NOT NULL DEFAULT 0,
"path" INTEGER NOT NULL DEFAULT 0,
"tunePower" INTEGER NOT NULL DEFAULT 17,
"tuneHandling" INTEGER NOT NULL DEFAULT 17,
CONSTRAINT "CarPathandTuning_pkey" PRIMARY KEY ("dbId")
);
-- AddForeignKey
ALTER TABLE "CarPathandTuning" ADD CONSTRAINT "CarPathandTuning_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -1,119 +0,0 @@
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "CarState" ADD COLUMN "competitionState" INTEGER NOT NULL DEFAULT 0;
-- AlterTable
ALTER TABLE "GhostBattleRecord" ADD COLUMN "ocmBattle" BOOLEAN NOT NULL DEFAULT false,
ADD COLUMN "ocmMainDay" BOOLEAN NOT NULL DEFAULT false;
-- AlterTable
ALTER TABLE "GhostTrail" ADD COLUMN "ocmBattle" BOOLEAN NOT NULL DEFAULT false,
ADD COLUMN "ocmMainDay" BOOLEAN NOT NULL DEFAULT false;
-- CreateTable
CREATE TABLE "OCMEvent" (
"dbId" SERIAL NOT NULL,
"competitionId" INTEGER NOT NULL,
"qualifyingPeriodStartAt" INTEGER NOT NULL,
"qualifyingPeriodCloseAt" INTEGER NOT NULL,
"competitionStartAt" INTEGER NOT NULL,
"competitionCloseAt" INTEGER NOT NULL,
"competitionEndAt" INTEGER NOT NULL,
"lengthOfPeriod" INTEGER NOT NULL,
"lengthOfInterval" INTEGER NOT NULL,
"area" INTEGER NOT NULL DEFAULT 0,
"minigamePatternId" INTEGER NOT NULL DEFAULT 0,
CONSTRAINT "OCMEvent_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "OCMPlayRecord" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"competitionId" INTEGER NOT NULL,
"periodId" INTEGER NOT NULL,
"brakingPoint" INTEGER,
"playedAt" INTEGER NOT NULL DEFAULT 0,
CONSTRAINT "OCMPlayRecord_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "OCMTop1Ghost" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"competitionId" INTEGER NOT NULL,
"periodId" INTEGER NOT NULL,
"result" INTEGER NOT NULL,
"tunePower" INTEGER NOT NULL DEFAULT 0,
"tuneHandling" INTEGER NOT NULL DEFAULT 0,
CONSTRAINT "OCMTop1Ghost_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "OCMTally" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"competitionId" INTEGER NOT NULL,
"periodId" INTEGER NOT NULL,
"result" INTEGER NOT NULL,
"tunePower" INTEGER NOT NULL DEFAULT 0,
"tuneHandling" INTEGER NOT NULL DEFAULT 0,
CONSTRAINT "OCMTally_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "OCMGhostBattleRecord" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"tunePower" INTEGER NOT NULL DEFAULT 0,
"tuneHandling" INTEGER NOT NULL DEFAULT 0,
"competitionId" INTEGER NOT NULL,
"periodId" INTEGER NOT NULL,
"result" INTEGER NOT NULL,
"area" INTEGER NOT NULL DEFAULT 0,
"playedAt" INTEGER NOT NULL DEFAULT 0,
"playedShopName" TEXT NOT NULL DEFAULT 'Bayshore',
"ocmMainDraw" BOOLEAN NOT NULL DEFAULT false,
CONSTRAINT "OCMGhostBattleRecord_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "OCMGhostTrail" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"area" INTEGER NOT NULL,
"ramp" INTEGER NOT NULL,
"path" INTEGER NOT NULL,
"trail" BYTEA NOT NULL,
"competitionId" INTEGER NOT NULL,
"periodId" INTEGER NOT NULL,
"playedAt" INTEGER NOT NULL DEFAULT 0,
"tunePower" INTEGER NOT NULL DEFAULT 0,
"tuneHandling" INTEGER NOT NULL DEFAULT 0,
"ocmBattle" BOOLEAN NOT NULL DEFAULT false,
"ocmMainDraw" BOOLEAN NOT NULL DEFAULT false,
CONSTRAINT "OCMGhostTrail_pkey" PRIMARY KEY ("dbId")
);
-- AddForeignKey
ALTER TABLE "OCMPlayRecord" ADD CONSTRAINT "OCMPlayRecord_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "OCMTop1Ghost" ADD CONSTRAINT "OCMTop1Ghost_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "OCMTally" ADD CONSTRAINT "OCMTally_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "OCMGhostBattleRecord" ADD CONSTRAINT "OCMGhostBattleRecord_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "OCMGhostTrail" ADD CONSTRAINT "OCMGhostTrail_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -1,17 +0,0 @@
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- CreateTable
CREATE TABLE "OCMPeriod" (
"dbId" SERIAL NOT NULL,
"competitionDbId" INTEGER NOT NULL,
"competitionId" INTEGER NOT NULL,
"periodId" INTEGER NOT NULL,
"startAt" INTEGER NOT NULL,
"closeAt" INTEGER NOT NULL,
CONSTRAINT "OCMPeriod_pkey" PRIMARY KEY ("dbId")
);
-- AddForeignKey
ALTER TABLE "OCMPeriod" ADD CONSTRAINT "OCMPeriod_competitionDbId_fkey" FOREIGN KEY ("competitionDbId") REFERENCES "OCMEvent"("dbId") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -1,17 +0,0 @@
/*
Warnings:
- You are about to drop the column `ocmBattle` on the `GhostTrail` table. All the data in the column will be lost.
- You are about to drop the column `ocmMainDay` on the `GhostTrail` table. All the data in the column will be lost.
- You are about to drop the column `ocmBattle` on the `OCMGhostTrail` table. All the data in the column will be lost.
*/
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "GhostTrail" DROP COLUMN "ocmBattle",
DROP COLUMN "ocmMainDay";
-- AlterTable
ALTER TABLE "OCMGhostTrail" DROP COLUMN "ocmBattle";

View File

@ -1,13 +0,0 @@
/*
Warnings:
- You are about to drop the column `ocmBattle` on the `GhostBattleRecord` table. All the data in the column will be lost.
- You are about to drop the column `ocmMainDay` on the `GhostBattleRecord` table. All the data in the column will be lost.
*/
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "GhostBattleRecord" DROP COLUMN "ocmBattle",
DROP COLUMN "ocmMainDay";

View File

@ -1,3 +0,0 @@
-- AlterTable
ALTER TABLE "Car" ADD COLUMN "country" TEXT NOT NULL DEFAULT 'JPN',
ALTER COLUMN "stLoseBits" SET DEFAULT 0;

View File

@ -1,15 +0,0 @@
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- CreateTable
CREATE TABLE "GhostRegisteredFromTerminal" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"competitionId" INTEGER,
"opponentCarId" INTEGER NOT NULL,
CONSTRAINT "GhostRegisteredFromTerminal_pkey" PRIMARY KEY ("dbId")
);
-- AddForeignKey
ALTER TABLE "GhostRegisteredFromTerminal" ADD CONSTRAINT "GhostRegisteredFromTerminal_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -1,35 +0,0 @@
-- AlterTable
ALTER TABLE "Car" ADD COLUMN "stampSheet" INTEGER[],
ADD COLUMN "stampSheetCount" INTEGER NOT NULL DEFAULT 0,
ADD COLUMN "vsStarCountMax" INTEGER NOT NULL DEFAULT 0,
ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- CreateTable
CREATE TABLE "CarChallenger" (
"id" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"challengerCarId" INTEGER NOT NULL,
"stamp" INTEGER NOT NULL,
"result" INTEGER NOT NULL,
"area" INTEGER NOT NULL,
CONSTRAINT "CarChallenger_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "CarStampTarget" (
"id" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"stampTargetCarId" INTEGER NOT NULL,
"returnCount" INTEGER NOT NULL,
"locked" BOOLEAN NOT NULL,
"recommended" BOOLEAN NOT NULL,
CONSTRAINT "CarStampTarget_pkey" PRIMARY KEY ("id")
);
-- AddForeignKey
ALTER TABLE "CarChallenger" ADD CONSTRAINT "CarChallenger_challengerCarId_fkey" FOREIGN KEY ("challengerCarId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "CarStampTarget" ADD CONSTRAINT "CarStampTarget_stampTargetCarId_fkey" FOREIGN KEY ("stampTargetCarId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -1,5 +0,0 @@
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "CarSettings" ALTER COLUMN "volume" SET DEFAULT 2;

View File

@ -1,17 +0,0 @@
-- AlterTable
ALTER TABLE "Car" ADD COLUMN "lastPlayedPlaceId" INTEGER,
ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- CreateTable
CREATE TABLE "PlaceList" (
"id" SERIAL NOT NULL,
"placeId" TEXT NOT NULL,
"regionId" INTEGER NOT NULL,
"locked" BOOLEAN NOT NULL,
"recommended" BOOLEAN NOT NULL,
CONSTRAINT "PlaceList_pkey" PRIMARY KEY ("id")
);
-- AddForeignKey
ALTER TABLE "Car" ADD CONSTRAINT "Car_lastPlayedPlaceId_fkey" FOREIGN KEY ("lastPlayedPlaceId") REFERENCES "PlaceList"("id") ON DELETE SET NULL ON UPDATE CASCADE;

View File

@ -1,17 +0,0 @@
/*
Warnings:
- You are about to drop the column `locked` on the `PlaceList` table. All the data in the column will be lost.
- You are about to drop the column `recommended` on the `PlaceList` table. All the data in the column will be lost.
- Added the required column `country` to the `PlaceList` table without a default value. This is not possible if the table is not empty.
- Added the required column `shopName` to the `PlaceList` table without a default value. This is not possible if the table is not empty.
*/
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "PlaceList" DROP COLUMN "locked",
DROP COLUMN "recommended",
ADD COLUMN "country" TEXT NOT NULL,
ADD COLUMN "shopName" TEXT NOT NULL;

View File

@ -0,0 +1,545 @@
-- CreateTable
CREATE TABLE "User" (
"id" SERIAL NOT NULL,
"chipId" TEXT NOT NULL,
"accessCode" TEXT NOT NULL,
"carOrder" INTEGER[],
"tutorials" BOOLEAN[],
"userBanned" BOOLEAN NOT NULL DEFAULT false,
"bookmarks" INTEGER[],
"currentSheet" INTEGER NOT NULL DEFAULT 1,
"lastScratched" INTEGER NOT NULL DEFAULT 0,
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "ScratchSheet" (
"id" SERIAL NOT NULL,
"userId" INTEGER NOT NULL,
"sheetNo" INTEGER NOT NULL,
CONSTRAINT "ScratchSheet_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "ScratchSquare" (
"id" SERIAL NOT NULL,
"sheetId" INTEGER NOT NULL,
"category" INTEGER NOT NULL,
"itemId" INTEGER NOT NULL,
"earned" BOOLEAN NOT NULL,
CONSTRAINT "ScratchSquare_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "UserItem" (
"userItemId" SERIAL NOT NULL,
"category" INTEGER NOT NULL,
"itemId" INTEGER NOT NULL,
"userId" INTEGER NOT NULL,
"type" INTEGER NOT NULL DEFAULT 0,
"earnedAt" INTEGER NOT NULL DEFAULT 0,
CONSTRAINT "UserItem_pkey" PRIMARY KEY ("userItemId")
);
-- CreateTable
CREATE TABLE "Car" (
"userId" INTEGER NOT NULL,
"carId" SERIAL NOT NULL,
"name" TEXT NOT NULL,
"manufacturer" INTEGER NOT NULL,
"model" INTEGER NOT NULL,
"visualModel" INTEGER NOT NULL,
"customColor" INTEGER NOT NULL DEFAULT 0,
"defaultColor" INTEGER NOT NULL,
"wheel" INTEGER NOT NULL DEFAULT 0,
"wheelColor" INTEGER NOT NULL DEFAULT 0,
"aero" INTEGER NOT NULL DEFAULT 0,
"bonnet" INTEGER NOT NULL DEFAULT 0,
"wing" INTEGER NOT NULL DEFAULT 0,
"mirror" INTEGER NOT NULL DEFAULT 0,
"neon" INTEGER NOT NULL DEFAULT 0,
"trunk" INTEGER NOT NULL DEFAULT 0,
"plate" INTEGER NOT NULL DEFAULT 0,
"plateColor" INTEGER NOT NULL DEFAULT 0,
"plateNumber" INTEGER NOT NULL DEFAULT 0,
"tunePower" INTEGER NOT NULL DEFAULT 0,
"tuneHandling" INTEGER NOT NULL DEFAULT 0,
"title" TEXT NOT NULL DEFAULT 'New Car',
"level" INTEGER NOT NULL DEFAULT 0,
"windowSticker" BOOLEAN NOT NULL DEFAULT false,
"windowStickerString" TEXT NOT NULL DEFAULT '',
"windowStickerFont" INTEGER NOT NULL DEFAULT 0,
"windowDecoration" INTEGER NOT NULL DEFAULT 0,
"rivalMarker" INTEGER NOT NULL DEFAULT 0,
"lastPlayedAt" INTEGER NOT NULL DEFAULT 0,
"aura" INTEGER NOT NULL DEFAULT 0,
"regionId" INTEGER NOT NULL DEFAULT 0,
"country" TEXT NOT NULL DEFAULT 'JPN',
"tuningPoints" INTEGER NOT NULL DEFAULT 0,
"odometer" INTEGER NOT NULL DEFAULT 0,
"playCount" INTEGER NOT NULL DEFAULT 0,
"earnedCustomColor" BOOLEAN NOT NULL DEFAULT false,
"carSettingsDbId" INTEGER NOT NULL,
"auraMotif" INTEGER NOT NULL DEFAULT 0,
"vsPlayCount" INTEGER NOT NULL DEFAULT 0,
"vsBurstCount" INTEGER NOT NULL DEFAULT 0,
"vsStarCount" INTEGER NOT NULL DEFAULT 0,
"vsStarCountMax" INTEGER NOT NULL DEFAULT 0,
"vsCoolOrWild" INTEGER NOT NULL DEFAULT 0,
"vsSmoothOrRough" INTEGER NOT NULL DEFAULT 0,
"vsTripleStarMedals" INTEGER NOT NULL DEFAULT 0,
"vsDoubleStarMedals" INTEGER NOT NULL DEFAULT 0,
"vsSingleStarMedals" INTEGER NOT NULL DEFAULT 0,
"vsPlainMedals" INTEGER NOT NULL DEFAULT 0,
"ghostLevel" INTEGER NOT NULL DEFAULT 1,
"rgPlayCount" INTEGER NOT NULL DEFAULT 0,
"rgWinCount" INTEGER NOT NULL DEFAULT 0,
"rgTrophy" INTEGER NOT NULL DEFAULT 0,
"rgScore" INTEGER NOT NULL DEFAULT 0,
"rgStamp" INTEGER NOT NULL DEFAULT 0,
"rgAcquireAllCrowns" BOOLEAN NOT NULL DEFAULT false,
"rgRegionMapScore" INTEGER[],
"stampSheetCount" INTEGER NOT NULL DEFAULT 0,
"stampSheet" INTEGER[],
"dressupLevel" INTEGER NOT NULL DEFAULT 0,
"dressupPoint" INTEGER NOT NULL DEFAULT 0,
"stPlayCount" INTEGER NOT NULL DEFAULT 0,
"stClearBits" INTEGER NOT NULL DEFAULT 0,
"stClearDivCount" INTEGER NOT NULL DEFAULT 0,
"stClearCount" INTEGER NOT NULL DEFAULT 0,
"stLoseBits" BIGINT NOT NULL DEFAULT 0,
"stConsecutiveWins" INTEGER NOT NULL DEFAULT 0,
"stConsecutiveWinsMax" INTEGER NOT NULL DEFAULT 0,
"stCompleted100Episodes" BOOLEAN NOT NULL DEFAULT false,
"rgScoreVs_2" INTEGER NOT NULL DEFAULT 0,
"rgHighwayClearCount" INTEGER NOT NULL DEFAULT 0,
"rgHighwayPoint" INTEGER NOT NULL DEFAULT 0,
"rgHighwayStationClearBits" INTEGER NOT NULL DEFAULT 0,
"rgHighwayPreviousDice" INTEGER NOT NULL DEFAULT 0,
"lastPlayedPlaceId" INTEGER,
"carGTWingDbId" INTEGER NOT NULL,
"carStateDbId" INTEGER NOT NULL,
CONSTRAINT "Car_pkey" PRIMARY KEY ("carId")
);
-- CreateTable
CREATE TABLE "CarGTWing" (
"dbId" SERIAL NOT NULL,
"pillar" INTEGER NOT NULL DEFAULT 0,
"pillarMaterial" INTEGER NOT NULL DEFAULT 0,
"mainWing" INTEGER NOT NULL DEFAULT 0,
"mainWingColor" INTEGER NOT NULL DEFAULT 0,
"wingTip" INTEGER NOT NULL DEFAULT 0,
"material" INTEGER NOT NULL DEFAULT 0,
CONSTRAINT "CarGTWing_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "CarItem" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"category" INTEGER NOT NULL,
"itemId" INTEGER NOT NULL,
"amount" INTEGER NOT NULL,
CONSTRAINT "CarItem_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "CarSettings" (
"dbId" SERIAL NOT NULL,
"view" BOOLEAN NOT NULL DEFAULT true,
"transmission" BOOLEAN NOT NULL DEFAULT false,
"retire" BOOLEAN NOT NULL DEFAULT false,
"meter" INTEGER NOT NULL DEFAULT 0,
"navigationMap" BOOLEAN NOT NULL DEFAULT true,
"volume" INTEGER NOT NULL DEFAULT 2,
"bgm" INTEGER NOT NULL DEFAULT 0,
"nameplate" INTEGER NOT NULL DEFAULT 0,
"nameplateColor" INTEGER NOT NULL DEFAULT 0,
"terminalBackground" INTEGER NOT NULL DEFAULT 0,
CONSTRAINT "CarSettings_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "CarState" (
"dbId" SERIAL NOT NULL,
"hasOpponentGhost" BOOLEAN NOT NULL DEFAULT false,
"eventJoined" BOOLEAN NOT NULL DEFAULT false,
"transferred" BOOLEAN NOT NULL DEFAULT false,
"toBeDeleted" BOOLEAN NOT NULL DEFAULT false,
"competitionState" INTEGER NOT NULL DEFAULT 0,
CONSTRAINT "CarState_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "CarPathandTuning" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"area" INTEGER NOT NULL DEFAULT 0,
"ramp" INTEGER NOT NULL DEFAULT 0,
"path" INTEGER NOT NULL DEFAULT 0,
"tunePower" INTEGER NOT NULL DEFAULT 17,
"tuneHandling" INTEGER NOT NULL DEFAULT 17,
"lastPlayedAt" INTEGER NOT NULL DEFAULT 0,
CONSTRAINT "CarPathandTuning_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "CarCrown" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"area" INTEGER NOT NULL,
"ramp" INTEGER NOT NULL,
"path" INTEGER NOT NULL,
"playedAt" INTEGER NOT NULL DEFAULT 0,
"tunePower" INTEGER NOT NULL,
"tuneHandling" INTEGER NOT NULL,
CONSTRAINT "CarCrown_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "TimeAttackRecord" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"model" INTEGER NOT NULL,
"time" INTEGER NOT NULL,
"course" INTEGER NOT NULL,
"isMorning" BOOLEAN NOT NULL,
"section1Time" INTEGER NOT NULL,
"section2Time" INTEGER NOT NULL,
"section3Time" INTEGER NOT NULL,
"section4Time" INTEGER NOT NULL,
"section5Time" INTEGER,
"section6Time" INTEGER,
"section7Time" INTEGER,
"tunePower" INTEGER NOT NULL DEFAULT 0,
"tuneHandling" INTEGER NOT NULL DEFAULT 0,
CONSTRAINT "TimeAttackRecord_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "GhostTrail" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"area" INTEGER NOT NULL,
"ramp" INTEGER NOT NULL,
"path" INTEGER NOT NULL,
"trail" BYTEA NOT NULL,
"time" INTEGER,
"driveData" BYTEA,
"driveDMergeSerial" INTEGER,
"trendBinaryByUser" BYTEA,
"byUserMergeSerial" INTEGER,
"trendBinaryByArea" BYTEA,
"byAreaMergeSerial" INTEGER,
"trendBinaryByCar" BYTEA,
"byCarMergeSerial" INTEGER,
"playedAt" INTEGER NOT NULL DEFAULT 0,
"tunePower" INTEGER NOT NULL DEFAULT 0,
"tuneHandling" INTEGER NOT NULL DEFAULT 0,
"crownBattle" BOOLEAN NOT NULL DEFAULT false,
CONSTRAINT "GhostTrail_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "GhostBattleRecord" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"tunePower" INTEGER NOT NULL DEFAULT 0,
"tuneHandling" INTEGER NOT NULL DEFAULT 0,
"opponent1CarId" INTEGER NOT NULL,
"opponent1Result" INTEGER NOT NULL,
"opponent1TunePower" INTEGER NOT NULL,
"opponent1TuneHandling" INTEGER NOT NULL,
"opponent2CarId" INTEGER,
"opponent2Result" INTEGER,
"opponent2TunePower" INTEGER,
"opponent2TuneHandling" INTEGER,
"opponent3CarId" INTEGER,
"opponent3Result" INTEGER,
"opponent3TunePower" INTEGER,
"opponent3TuneHandling" INTEGER,
"area" INTEGER NOT NULL DEFAULT 0,
"playedAt" INTEGER NOT NULL DEFAULT 0,
"playedShopName" TEXT NOT NULL DEFAULT 'Bayshore',
CONSTRAINT "GhostBattleRecord_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "OCMEvent" (
"dbId" SERIAL NOT NULL,
"competitionId" INTEGER NOT NULL,
"qualifyingPeriodStartAt" INTEGER NOT NULL,
"qualifyingPeriodCloseAt" INTEGER NOT NULL,
"competitionStartAt" INTEGER NOT NULL,
"competitionCloseAt" INTEGER NOT NULL,
"competitionEndAt" INTEGER NOT NULL,
"lengthOfPeriod" INTEGER NOT NULL,
"lengthOfInterval" INTEGER NOT NULL,
"area" INTEGER NOT NULL DEFAULT 0,
"minigamePatternId" INTEGER NOT NULL DEFAULT 0,
CONSTRAINT "OCMEvent_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "OCMPlayRecord" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"competitionId" INTEGER NOT NULL,
"periodId" INTEGER NOT NULL,
"brakingPoint" INTEGER,
"playedAt" INTEGER NOT NULL DEFAULT 0,
CONSTRAINT "OCMPlayRecord_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "OCMTop1Ghost" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"competitionId" INTEGER NOT NULL,
"periodId" INTEGER NOT NULL,
"result" INTEGER NOT NULL,
"tunePower" INTEGER NOT NULL DEFAULT 0,
"tuneHandling" INTEGER NOT NULL DEFAULT 0,
CONSTRAINT "OCMTop1Ghost_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "OCMTop1GhostTrail" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"area" INTEGER NOT NULL,
"ramp" INTEGER NOT NULL,
"path" INTEGER NOT NULL,
"trail" BYTEA NOT NULL,
"competitionId" INTEGER NOT NULL,
"periodId" INTEGER NOT NULL,
"playedAt" INTEGER NOT NULL DEFAULT 0,
"tunePower" INTEGER NOT NULL DEFAULT 0,
"tuneHandling" INTEGER NOT NULL DEFAULT 0,
"ocmMainDraw" BOOLEAN NOT NULL DEFAULT false,
CONSTRAINT "OCMTop1GhostTrail_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "OCMTally" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"competitionId" INTEGER NOT NULL,
"periodId" INTEGER NOT NULL,
"result" INTEGER NOT NULL,
"tunePower" INTEGER NOT NULL DEFAULT 0,
"tuneHandling" INTEGER NOT NULL DEFAULT 0,
CONSTRAINT "OCMTally_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "OCMGhostBattleRecord" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"tunePower" INTEGER NOT NULL DEFAULT 0,
"tuneHandling" INTEGER NOT NULL DEFAULT 0,
"competitionId" INTEGER NOT NULL,
"periodId" INTEGER NOT NULL,
"result" INTEGER NOT NULL,
"area" INTEGER NOT NULL DEFAULT 0,
"playedAt" INTEGER NOT NULL DEFAULT 0,
"playedShopName" TEXT NOT NULL DEFAULT 'Bayshore',
"ocmMainDraw" BOOLEAN NOT NULL DEFAULT false,
CONSTRAINT "OCMGhostBattleRecord_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "OCMGhostTrail" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"area" INTEGER NOT NULL,
"ramp" INTEGER NOT NULL,
"path" INTEGER NOT NULL,
"trail" BYTEA NOT NULL,
"competitionId" INTEGER NOT NULL,
"periodId" INTEGER NOT NULL,
"playedAt" INTEGER NOT NULL DEFAULT 0,
"tunePower" INTEGER NOT NULL DEFAULT 0,
"tuneHandling" INTEGER NOT NULL DEFAULT 0,
"ocmMainDraw" BOOLEAN NOT NULL DEFAULT false,
CONSTRAINT "OCMGhostTrail_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "OCMPeriod" (
"dbId" SERIAL NOT NULL,
"competitionDbId" INTEGER NOT NULL,
"competitionId" INTEGER NOT NULL,
"periodId" INTEGER NOT NULL,
"startAt" INTEGER NOT NULL,
"closeAt" INTEGER NOT NULL,
CONSTRAINT "OCMPeriod_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "GhostRegisteredFromTerminal" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"competitionId" INTEGER,
"opponentCarId" INTEGER NOT NULL,
CONSTRAINT "GhostRegisteredFromTerminal_pkey" PRIMARY KEY ("dbId")
);
-- CreateTable
CREATE TABLE "CarChallenger" (
"id" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"challengerCarId" INTEGER NOT NULL,
"stamp" INTEGER NOT NULL,
"result" INTEGER NOT NULL,
"area" INTEGER NOT NULL,
"lastPlayedAt" INTEGER NOT NULL DEFAULT 0,
CONSTRAINT "CarChallenger_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "CarStampTarget" (
"id" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"stampTargetCarId" INTEGER NOT NULL,
"returnCount" INTEGER NOT NULL,
"locked" BOOLEAN NOT NULL,
"recommended" BOOLEAN NOT NULL,
CONSTRAINT "CarStampTarget_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "PlaceList" (
"id" SERIAL NOT NULL,
"placeId" TEXT NOT NULL,
"regionId" INTEGER NOT NULL,
"shopName" TEXT NOT NULL,
"country" TEXT NOT NULL,
CONSTRAINT "PlaceList_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "GhostExpedition" (
"dbId" SERIAL NOT NULL,
"carId" INTEGER NOT NULL,
"ghostExpeditionId" INTEGER NOT NULL,
"sugorokuPoint" INTEGER NOT NULL DEFAULT 0,
"earnedScore" INTEGER NOT NULL DEFAULT 0,
"score" INTEGER NOT NULL DEFAULT 0,
CONSTRAINT "GhostExpedition_pkey" PRIMARY KEY ("dbId")
);
-- CreateIndex
CREATE UNIQUE INDEX "User_chipId_key" ON "User"("chipId");
-- CreateIndex
CREATE UNIQUE INDEX "Car_carSettingsDbId_key" ON "Car"("carSettingsDbId");
-- CreateIndex
CREATE UNIQUE INDEX "Car_carGTWingDbId_key" ON "Car"("carGTWingDbId");
-- CreateIndex
CREATE UNIQUE INDEX "Car_carStateDbId_key" ON "Car"("carStateDbId");
-- CreateIndex
CREATE UNIQUE INDEX "CarCrown_area_key" ON "CarCrown"("area");
-- AddForeignKey
ALTER TABLE "ScratchSheet" ADD CONSTRAINT "ScratchSheet_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "ScratchSquare" ADD CONSTRAINT "ScratchSquare_sheetId_fkey" FOREIGN KEY ("sheetId") REFERENCES "ScratchSheet"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "UserItem" ADD CONSTRAINT "UserItem_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Car" ADD CONSTRAINT "Car_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Car" ADD CONSTRAINT "Car_carGTWingDbId_fkey" FOREIGN KEY ("carGTWingDbId") REFERENCES "CarGTWing"("dbId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Car" ADD CONSTRAINT "Car_carSettingsDbId_fkey" FOREIGN KEY ("carSettingsDbId") REFERENCES "CarSettings"("dbId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Car" ADD CONSTRAINT "Car_carStateDbId_fkey" FOREIGN KEY ("carStateDbId") REFERENCES "CarState"("dbId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Car" ADD CONSTRAINT "Car_lastPlayedPlaceId_fkey" FOREIGN KEY ("lastPlayedPlaceId") REFERENCES "PlaceList"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "CarItem" ADD CONSTRAINT "CarItem_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "CarPathandTuning" ADD CONSTRAINT "CarPathandTuning_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "CarCrown" ADD CONSTRAINT "CarCrown_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "TimeAttackRecord" ADD CONSTRAINT "TimeAttackRecord_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "GhostTrail" ADD CONSTRAINT "GhostTrail_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "GhostBattleRecord" ADD CONSTRAINT "GhostBattleRecord_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "OCMPlayRecord" ADD CONSTRAINT "OCMPlayRecord_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "OCMTop1Ghost" ADD CONSTRAINT "OCMTop1Ghost_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "OCMTally" ADD CONSTRAINT "OCMTally_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "OCMGhostBattleRecord" ADD CONSTRAINT "OCMGhostBattleRecord_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "OCMGhostTrail" ADD CONSTRAINT "OCMGhostTrail_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "OCMPeriod" ADD CONSTRAINT "OCMPeriod_competitionDbId_fkey" FOREIGN KEY ("competitionDbId") REFERENCES "OCMEvent"("dbId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "GhostRegisteredFromTerminal" ADD CONSTRAINT "GhostRegisteredFromTerminal_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "CarChallenger" ADD CONSTRAINT "CarChallenger_challengerCarId_fkey" FOREIGN KEY ("challengerCarId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "CarStampTarget" ADD CONSTRAINT "CarStampTarget_stampTargetCarId_fkey" FOREIGN KEY ("stampTargetCarId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "GhostExpedition" ADD CONSTRAINT "GhostExpedition_carId_fkey" FOREIGN KEY ("carId") REFERENCES "Car"("carId") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -0,0 +1,5 @@
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "GhostExpeditionWantedCar" ADD COLUMN "ghostExpeditionId" INTEGER NOT NULL DEFAULT 1;

View File

@ -2,4 +2,4 @@
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "CarPathandTuning" ADD COLUMN "lastPlayedAt" INTEGER NOT NULL DEFAULT 0;
ALTER TABLE "GhostExpeditionWantedCar" ADD COLUMN "area" INTEGER NOT NULL DEFAULT 0;

View File

@ -0,0 +1,8 @@
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "GhostExpeditionWantedCar" ADD COLUMN "challengerCarId" INTEGER,
ADD COLUMN "locked" BOOLEAN NOT NULL DEFAULT false,
ALTER COLUMN "numOfHostages" SET DEFAULT 1,
ALTER COLUMN "defeatedMeCount" SET DEFAULT 1;

View File

@ -0,0 +1,14 @@
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- CreateTable
CREATE TABLE "GhostExpeditionEvent" (
"dbId" SERIAL NOT NULL,
"ghostExpeditionId" INTEGER NOT NULL,
"startAt" INTEGER NOT NULL,
"endAt" INTEGER NOT NULL,
"aftereventEndAt" INTEGER NOT NULL,
"opponentCountry" INTEGER NOT NULL,
CONSTRAINT "GhostExpeditionEvent_pkey" PRIMARY KEY ("dbId")
);

View File

@ -2,4 +2,4 @@
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "CarChallenger" ADD COLUMN "lastPlayedAt" INTEGER NOT NULL DEFAULT 0;
ALTER TABLE "GhostExpeditionEvent" ALTER COLUMN "opponentCountry" SET DATA TYPE TEXT;

View File

@ -1,3 +0,0 @@
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0,
ALTER COLUMN "regionId" SET DEFAULT 1;

View File

@ -0,0 +1,5 @@
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "GhostExpeditionWantedCar" ADD COLUMN "lockTime" INTEGER NOT NULL DEFAULT 0;

View File

@ -1,5 +0,0 @@
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- AlterTable
ALTER TABLE "FileList" ADD COLUMN "filePath" TEXT NOT NULL DEFAULT '';

View File

@ -1,6 +1,5 @@
-- AlterTable
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0,
ALTER COLUMN "regionId" SET DEFAULT 18;
ALTER TABLE "Car" ALTER COLUMN "stLoseBits" SET DEFAULT 0;
-- CreateTable
CREATE TABLE "FileList" (
@ -11,6 +10,7 @@ CREATE TABLE "FileList" (
"sha1sum" TEXT NOT NULL,
"notBefore" INTEGER NOT NULL,
"notAfter" INTEGER NOT NULL,
"filePath" TEXT NOT NULL,
CONSTRAINT "FileList_pkey" PRIMARY KEY ("fileId")
);

View File

@ -2,426 +2,440 @@
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("POSTGRES_URL")
provider = "postgresql"
url = env("POSTGRES_URL")
}
model User {
id Int @id @default(autoincrement())
chipId String @unique
accessCode String
cars Car[]
carOrder Int[]
items UserItem[]
tutorials Boolean[]
userBanned Boolean @default(false)
bookmarks Int[]
ScratchSheet ScratchSheet[]
currentSheet Int @default(1)
lastScratched Int @default(0) // Timestamp
id Int @id @default(autoincrement())
chipId String @unique
accessCode String
cars Car[]
carOrder Int[]
items UserItem[]
tutorials Boolean[]
userBanned Boolean @default(false)
bookmarks Int[]
ScratchSheet ScratchSheet[]
currentSheet Int @default(1)
lastScratched Int @default(0) // Timestamp
}
model ScratchSheet {
id Int @id @default(autoincrement())
User User @relation(fields: [userId], references: [id])
userId Int
sheetNo Int // Player's sheet number (i.e. first sheet)
squares ScratchSquare[]
id Int @id @default(autoincrement())
User User @relation(fields: [userId], references: [id])
userId Int
sheetNo Int // Player's sheet number (i.e. first sheet)
squares ScratchSquare[]
}
model ScratchSquare {
id Int @id @default(autoincrement())
Sheet ScratchSheet @relation(fields: [sheetId], references: [id])
sheetId Int
category Int
itemId Int
earned Boolean
id Int @id @default(autoincrement())
Sheet ScratchSheet @relation(fields: [sheetId], references: [id])
sheetId Int
category Int
itemId Int
earned Boolean
}
model UserItem {
userItemId Int @id @default(autoincrement())
category Int
itemId Int
User User @relation(fields: [userId], references: [id])
userId Int
type Int @default(0)
earnedAt Int @default(0)
userItemId Int @id @default(autoincrement())
category Int
itemId Int
User User @relation(fields: [userId], references: [id])
userId Int
type Int @default(0)
earnedAt Int @default(0)
}
model Car {
user User @relation(fields: [userId], references: [id])
userId Int
user User @relation(fields: [userId], references: [id])
userId Int
// This is the Car object itself
carId Int @id @default(autoincrement())
name String
manufacturer Int
model Int
visualModel Int
customColor Int @default(0)
defaultColor Int
wheel Int @default(0)
wheelColor Int @default(0)
aero Int @default(0)
bonnet Int @default(0)
wing Int @default(0)
mirror Int @default(0)
neon Int @default(0)
trunk Int @default(0)
plate Int @default(0)
plateColor Int @default(0)
plateNumber Int @default(0)
tunePower Int @default(0)
tuneHandling Int @default(0)
title String @default("New Car")
level Int @default(0)
windowSticker Boolean @default(false)
windowStickerString String @default("")
windowStickerFont Int @default(0)
windowDecoration Int @default(0)
rivalMarker Int @default(0)
lastPlayedAt Int @default(0)
aura Int @default(0)
regionId Int @default(18)
country String @default("JPN")
// This is the Car object itself
carId Int @id @default(autoincrement())
name String
manufacturer Int
model Int
visualModel Int
customColor Int @default(0)
defaultColor Int
wheel Int @default(0)
wheelColor Int @default(0)
aero Int @default(0)
bonnet Int @default(0)
wing Int @default(0)
mirror Int @default(0)
neon Int @default(0)
trunk Int @default(0)
plate Int @default(0)
plateColor Int @default(0)
plateNumber Int @default(0)
tunePower Int @default(0)
tuneHandling Int @default(0)
title String @default("New Car")
level Int @default(0)
windowSticker Boolean @default(false)
windowStickerString String @default("")
windowStickerFont Int @default(0)
windowDecoration Int @default(0)
rivalMarker Int @default(0)
lastPlayedAt Int @default(0)
aura Int @default(0)
regionId Int @default(0)
country String @default("JPN")
// This is more data about the car
tuningPoints Int @default(0)
odometer Int @default(0)
playCount Int @default(0)
earnedCustomColor Boolean @default(false)
carSettingsDbId Int @unique
settings CarSettings @relation(fields: [carSettingsDbId], references: [dbId])
// This is more data about the car
tuningPoints Int @default(0)
odometer Int @default(0)
playCount Int @default(0)
earnedCustomColor Boolean @default(false)
carSettingsDbId Int @unique
settings CarSettings @relation(fields: [carSettingsDbId], references: [dbId])
auraMotif Int @default(0)
vsPlayCount Int @default(0)
vsBurstCount Int @default(0)
vsStarCount Int @default(0)
vsStarCountMax Int @default(0)
vsCoolOrWild Int @default(0)
vsSmoothOrRough Int @default(0)
vsTripleStarMedals Int @default(0)
vsDoubleStarMedals Int @default(0)
vsSingleStarMedals Int @default(0)
vsPlainMedals Int @default(0)
// VS
auraMotif Int @default(0)
vsPlayCount Int @default(0)
vsBurstCount Int @default(0)
vsStarCount Int @default(0)
vsStarCountMax Int @default(0)
vsCoolOrWild Int @default(0)
vsSmoothOrRough Int @default(0)
vsTripleStarMedals Int @default(0)
vsDoubleStarMedals Int @default(0)
vsSingleStarMedals Int @default(0)
vsPlainMedals Int @default(0)
ghostLevel Int @default(1)
rgPlayCount Int @default(0)
rgWinCount Int @default(0)
rgTrophy Int @default(0)
rgScore Int @default(0)
rgStamp Int @default(1)
rgAcquireAllCrowns Boolean @default(false)
rgRegionMapScore Int[]
stampSheetCount Int @default(0)
stampSheet Int[]
// Ghost
ghostLevel Int @default(1)
rgPlayCount Int @default(0)
rgWinCount Int @default(0)
rgTrophy Int @default(0)
rgScore Int @default(0)
rgStamp Int @default(1)
rgAcquireAllCrowns Boolean @default(false)
rgRegionMapScore Int[]
stampSheetCount Int @default(0)
stampSheet Int[]
dressupLevel Int @default(0)
dressupPoint Int @default(0)
// Dress Up
dressupLevel Int @default(0)
dressupPoint Int @default(0)
stPlayCount Int @default(0)
stClearBits Int @default(0)
stClearDivCount Int @default(0)
stClearCount Int @default(0)
stLoseBits BigInt @default(0)
stConsecutiveWins Int @default(0)
stConsecutiveWinsMax Int @default(0)
stCompleted100Episodes Boolean @default(false)
// Story
stPlayCount Int @default(0)
stClearBits Int @default(0)
stClearDivCount Int @default(0)
stClearCount Int @default(0)
stLoseBits BigInt @default(0)
stConsecutiveWins Int @default(0)
stConsecutiveWinsMax Int @default(0)
stCompleted100Episodes Boolean @default(false)
lastPlayedPlaceId Int?
lastPlayedPlace PlaceList? @relation(fields: [lastPlayedPlaceId], references: [id])
// Highway Ghost
rgScoreVs_2 Int @default(0)
rgHighwayClearCount Int @default(0)
rgHighwayPoint Int @default(0)
rgHighwayStationClearBits Int @default(0)
rgHighwayPreviousDice Int @default(0)
items CarItem[]
carGTWingDbId Int @unique
gtWing CarGTWing @relation(fields: [carGTWingDbId], references: [dbId])
carStateDbId Int @unique
state CarState @relation(fields: [carStateDbId], references: [dbId])
TimeAttackRecord TimeAttackRecord[]
CarCrown CarCrown[]
GhostTrail GhostTrail[]
GhostBattleRecord GhostBattleRecord[]
CarPathandTuning CarPathandTuning[]
OCMGhostBattleRecord OCMGhostBattleRecord[]
OCMTally OCMTally[]
OCMTop1Ghost OCMTop1Ghost[]
OCMGhostTrail OCMGhostTrail[]
OCMPlayRecord OCMPlayRecord[]
GhostRegisteredFromTerminal GhostRegisteredFromTerminal[]
CarStampTarget CarStampTarget[]
CarChallenger CarChallenger[]
// Last Played
lastPlayedPlaceId Int?
lastPlayedPlace PlaceList? @relation(fields: [lastPlayedPlaceId], references: [id])
items CarItem[]
carGTWingDbId Int @unique
gtWing CarGTWing @relation(fields: [carGTWingDbId], references: [dbId])
carStateDbId Int @unique
state CarState @relation(fields: [carStateDbId], references: [dbId])
TimeAttackRecord TimeAttackRecord[]
CarCrown CarCrown[]
GhostTrail GhostTrail[]
GhostBattleRecord GhostBattleRecord[]
CarPathandTuning CarPathandTuning[]
OCMGhostBattleRecord OCMGhostBattleRecord[]
OCMTally OCMTally[]
OCMTop1Ghost OCMTop1Ghost[]
OCMGhostTrail OCMGhostTrail[]
OCMPlayRecord OCMPlayRecord[]
GhostRegisteredFromTerminal GhostRegisteredFromTerminal[]
CarStampTarget CarStampTarget[]
CarChallenger CarChallenger[]
GhostExpedition GhostExpedition[]
GhostExpeditionWantedCar GhostExpeditionWantedCar[]
}
model CarGTWing {
dbId Int @id @default(autoincrement())
car Car?
dbId Int @id @default(autoincrement())
car Car?
pillar Int @default(0)
pillarMaterial Int @default(0)
mainWing Int @default(0)
mainWingColor Int @default(0)
wingTip Int @default(0)
material Int @default(0)
pillar Int @default(0)
pillarMaterial Int @default(0)
mainWing Int @default(0)
mainWingColor Int @default(0)
wingTip Int @default(0)
material Int @default(0)
}
model CarItem {
dbId Int @id @default(autoincrement())
Car Car @relation(fields: [carId], references: [carId])
carId Int
category Int
itemId Int
amount Int
dbId Int @id @default(autoincrement())
Car Car @relation(fields: [carId], references: [carId])
carId Int
category Int
itemId Int
amount Int
}
model CarSettings {
dbId Int @id @default(autoincrement())
car Car?
dbId Int @id @default(autoincrement())
car Car?
view Boolean @default(true)
transmission Boolean @default(false)
retire Boolean @default(false)
meter Int @default(0)
navigationMap Boolean @default(true)
volume Int @default(2)
bgm Int @default(0)
nameplate Int @default(0)
nameplateColor Int @default(0)
terminalBackground Int @default(0)
view Boolean @default(true)
transmission Boolean @default(false)
retire Boolean @default(false)
meter Int @default(0)
navigationMap Boolean @default(true)
volume Int @default(2)
bgm Int @default(0)
nameplate Int @default(0)
nameplateColor Int @default(0)
terminalBackground Int @default(0)
}
model CarState {
dbId Int @id @default(autoincrement())
car Car?
dbId Int @id @default(autoincrement())
car Car?
hasOpponentGhost Boolean @default(false)
eventJoined Boolean @default(false)
transferred Boolean @default(false)
toBeDeleted Boolean @default(false)
competitionState Int @default(0)
hasOpponentGhost Boolean @default(false)
eventJoined Boolean @default(false)
transferred Boolean @default(false)
toBeDeleted Boolean @default(false)
competitionState Int @default(0)
}
model CarPathandTuning {
dbId Int @id @default(autoincrement())
car Car @relation(fields: [carId], references: [carId])
carId Int
area Int @default(0)
ramp Int @default(0)
path Int @default(0)
tunePower Int @default(17)
tuneHandling Int @default(17)
lastPlayedAt Int @default(0)
dbId Int @id @default(autoincrement())
car Car @relation(fields: [carId], references: [carId])
carId Int
area Int @default(0)
ramp Int @default(0)
path Int @default(0)
tunePower Int @default(17)
tuneHandling Int @default(17)
lastPlayedAt Int @default(0)
}
model CarCrown {
dbId Int @id @default(autoincrement())
car Car @relation(fields: [carId], references: [carId])
carId Int
area Int @unique
ramp Int
path Int
playedAt Int @default(0)
tunePower Int
tuneHandling Int
dbId Int @id @default(autoincrement())
car Car @relation(fields: [carId], references: [carId])
carId Int
area Int @unique
ramp Int
path Int
playedAt Int @default(0)
tunePower Int
tuneHandling Int
}
model TimeAttackRecord {
dbId Int @id @default(autoincrement())
dbId Int @id @default(autoincrement())
car Car @relation(fields: [carId], references: [carId])
carId Int
car Car @relation(fields: [carId], references: [carId])
carId Int
model Int // Car model, literally just the `model` field from Car
time Int
course Int
isMorning Boolean
section1Time Int @map("section1Time")
section2Time Int @map("section2Time")
section3Time Int @map("section3Time")
section4Time Int @map("section4Time")
section5Time Int? @map("section5Time")
section6Time Int? @map("section6Time")
section7Time Int? @map("section7Time")
tunePower Int @default(0) // Car Power
tuneHandling Int @default(0) // Car Handling
model Int // Car model, literally just the `model` field from Car
time Int
course Int
isMorning Boolean
section1Time Int @map("section1Time")
section2Time Int @map("section2Time")
section3Time Int @map("section3Time")
section4Time Int @map("section4Time")
section5Time Int? @map("section5Time")
section6Time Int? @map("section6Time")
section7Time Int? @map("section7Time")
tunePower Int @default(0) // Car Power
tuneHandling Int @default(0) // Car Handling
}
model GhostTrail {
dbId Int @id @default(autoincrement())
car Car @relation(fields: [carId], references: [carId])
carId Int
area Int
ramp Int
path Int
trail Bytes
time Int?
driveData Bytes? @db.ByteA
driveDMergeSerial Int?
trendBinaryByUser Bytes? @db.ByteA
byUserMergeSerial Int?
trendBinaryByArea Bytes? @db.ByteA
byAreaMergeSerial Int?
trendBinaryByCar Bytes? @db.ByteA
byCarMergeSerial Int?
playedAt Int @default(0)
tunePower Int @default(0)
tuneHandling Int @default(0)
crownBattle Boolean @default(false)
dbId Int @id @default(autoincrement())
car Car @relation(fields: [carId], references: [carId])
carId Int
area Int
ramp Int
path Int
trail Bytes
time Int?
driveData Bytes? @db.ByteA
driveDMergeSerial Int?
trendBinaryByUser Bytes? @db.ByteA
byUserMergeSerial Int?
trendBinaryByArea Bytes? @db.ByteA
byAreaMergeSerial Int?
trendBinaryByCar Bytes? @db.ByteA
byCarMergeSerial Int?
playedAt Int @default(0)
tunePower Int @default(0)
tuneHandling Int @default(0)
crownBattle Boolean @default(false)
}
model GhostBattleRecord {
dbId Int @id @default(autoincrement())
car Car @relation(fields: [carId], references: [carId])
carId Int
tunePower Int @default(0)
tuneHandling Int @default(0)
opponent1CarId Int
opponent1Result Int
opponent1TunePower Int
opponent1TuneHandling Int
opponent2CarId Int?
opponent2Result Int?
opponent2TunePower Int?
opponent2TuneHandling Int?
opponent3CarId Int?
opponent3Result Int?
opponent3TunePower Int?
opponent3TuneHandling Int?
area Int @default(0)
playedAt Int @default(0)
playedShopName String @default("Bayshore")
dbId Int @id @default(autoincrement())
car Car @relation(fields: [carId], references: [carId])
carId Int
tunePower Int @default(0)
tuneHandling Int @default(0)
opponent1CarId Int
opponent1Result Int
opponent1TunePower Int
opponent1TuneHandling Int
opponent2CarId Int?
opponent2Result Int?
opponent2TunePower Int?
opponent2TuneHandling Int?
opponent3CarId Int?
opponent3Result Int?
opponent3TunePower Int?
opponent3TuneHandling Int?
area Int @default(0)
playedAt Int @default(0)
playedShopName String @default("Bayshore")
}
model OCMEvent {
dbId Int @id @default(autoincrement())
competitionId Int
qualifyingPeriodStartAt Int
qualifyingPeriodCloseAt Int
competitionStartAt Int
competitionCloseAt Int
competitionEndAt Int
lengthOfPeriod Int
lengthOfInterval Int
area Int @default(0)
minigamePatternId Int @default(0)
dbId Int @id @default(autoincrement())
competitionId Int
qualifyingPeriodStartAt Int
qualifyingPeriodCloseAt Int
competitionStartAt Int
competitionCloseAt Int
competitionEndAt Int
lengthOfPeriod Int
lengthOfInterval Int
area Int @default(0)
minigamePatternId Int @default(0)
OCMPeriod OCMPeriod[]
OCMPeriod OCMPeriod[]
}
model OCMPlayRecord {
dbId Int @id @default(autoincrement())
car Car @relation(fields: [carId], references: [carId])
carId Int
competitionId Int
periodId Int
brakingPoint Int?
playedAt Int @default(0)
dbId Int @id @default(autoincrement())
car Car @relation(fields: [carId], references: [carId])
carId Int
competitionId Int
periodId Int
brakingPoint Int?
playedAt Int @default(0)
}
model OCMTop1Ghost {
dbId Int @id @default(autoincrement())
car Car @relation(fields: [carId], references: [carId])
carId Int
competitionId Int
periodId Int
result Int
tunePower Int @default(0)
tuneHandling Int @default(0)
dbId Int @id @default(autoincrement())
car Car @relation(fields: [carId], references: [carId])
carId Int
competitionId Int
periodId Int
result Int
tunePower Int @default(0)
tuneHandling Int @default(0)
}
model OCMTop1GhostTrail {
dbId Int @id @default(autoincrement())
carId Int
area Int
ramp Int
path Int
trail Bytes
competitionId Int
periodId Int
playedAt Int @default(0)
tunePower Int @default(0)
tuneHandling Int @default(0)
ocmMainDraw Boolean @default(false)
dbId Int @id @default(autoincrement())
carId Int
area Int
ramp Int
path Int
trail Bytes
competitionId Int
periodId Int
playedAt Int @default(0)
tunePower Int @default(0)
tuneHandling Int @default(0)
ocmMainDraw Boolean @default(false)
}
model OCMTally {
dbId Int @id @default(autoincrement())
car Car @relation(fields: [carId], references: [carId])
carId Int
competitionId Int
periodId Int
result Int
tunePower Int @default(0)
tuneHandling Int @default(0)
dbId Int @id @default(autoincrement())
car Car @relation(fields: [carId], references: [carId])
carId Int
competitionId Int
periodId Int
result Int
tunePower Int @default(0)
tuneHandling Int @default(0)
}
model OCMGhostBattleRecord {
dbId Int @id @default(autoincrement())
car Car @relation(fields: [carId], references: [carId])
carId Int
tunePower Int @default(0)
tuneHandling Int @default(0)
competitionId Int
periodId Int
result Int
area Int @default(0)
playedAt Int @default(0)
playedShopName String @default("Bayshore")
ocmMainDraw Boolean @default(false)
dbId Int @id @default(autoincrement())
car Car @relation(fields: [carId], references: [carId])
carId Int
tunePower Int @default(0)
tuneHandling Int @default(0)
competitionId Int
periodId Int
result Int
area Int @default(0)
playedAt Int @default(0)
playedShopName String @default("Bayshore")
ocmMainDraw Boolean @default(false)
}
model OCMGhostTrail {
dbId Int @id @default(autoincrement())
car Car @relation(fields: [carId], references: [carId])
carId Int
area Int
ramp Int
path Int
trail Bytes
competitionId Int
periodId Int
playedAt Int @default(0)
tunePower Int @default(0)
tuneHandling Int @default(0)
ocmMainDraw Boolean @default(false)
dbId Int @id @default(autoincrement())
car Car @relation(fields: [carId], references: [carId])
carId Int
area Int
ramp Int
path Int
trail Bytes
competitionId Int
periodId Int
playedAt Int @default(0)
tunePower Int @default(0)
tuneHandling Int @default(0)
ocmMainDraw Boolean @default(false)
}
model OCMPeriod {
dbId Int @id @default(autoincrement())
OCMEvent OCMEvent @relation(fields: [competitionDbId], references: [dbId])
competitionDbId Int
competitionId Int
periodId Int
startAt Int
closeAt Int
dbId Int @id @default(autoincrement())
OCMEvent OCMEvent @relation(fields: [competitionDbId], references: [dbId])
competitionDbId Int
competitionId Int
periodId Int
startAt Int
closeAt Int
}
model GhostRegisteredFromTerminal {
dbId Int @id @default(autoincrement())
car Car @relation(fields: [carId], references: [carId])
carId Int
competitionId Int?
opponentCarId Int
dbId Int @id @default(autoincrement())
car Car @relation(fields: [carId], references: [carId])
carId Int
competitionId Int?
opponentCarId Int
}
model CarChallenger {
id Int @id @default(autoincrement())
challengerCar Car @relation(fields: [challengerCarId], references: [carId])
id Int @id @default(autoincrement())
challengerCar Car @relation(fields: [challengerCarId], references: [carId])
carId Int
challengerCarId Int
stamp Int
result Int
area Int
lastPlayedAt Int @default(0)
lastPlayedAt Int @default(0)
}
model CarStampTarget {
id Int @id @default(autoincrement())
stampTargetCar Car @relation(fields: [stampTargetCarId], references: [carId])
carId Int
carId Int
stampTargetCarId Int
returnCount Int
locked Boolean
@ -429,13 +443,47 @@ model CarStampTarget {
}
model PlaceList {
id Int @id @default(autoincrement())
car Car[]
id Int @id @default(autoincrement())
car Car[]
placeId String
regionId Int
shopName String
country String
placeId String
regionId Int
shopName String
country String
}
model GhostExpedition {
dbId Int @id @default(autoincrement())
car Car @relation(fields: [carId], references: [carId])
carId Int
ghostExpeditionId Int
sugorokuPoint Int @default(0)
earnedScore Int @default(0)
score Int @default(0)
}
model GhostExpeditionWantedCar {
dbId Int @id @default(autoincrement())
car Car @relation(fields: [carId], references: [carId])
carId Int
bonus Int @default(0)
numOfHostages Int @default(1)
defeatedMeCount Int @default(1)
hostage Int?
ghostExpeditionId Int @default(1)
area Int @default(0)
locked Boolean @default(false)
lockTime Int @default(0)
challengerCarId Int?
}
model GhostExpeditionEvent {
dbId Int @id @default(autoincrement())
ghostExpeditionId Int
startAt Int
endAt Int
aftereventEndAt Int
opponentCountry String
}
model FileList {
@ -446,5 +494,5 @@ model FileList {
sha1sum String
notBefore Int
notAfter Int
filePath String @default("")
filePath String
}

View File

@ -4,7 +4,6 @@ import { unzipSync } from "zlib";
import { Module } from "./module";
import iconv from "iconv-lite";
import { Config } from "./config";
import * as common from "./modules/util/common";
// TODO: Move this into the config
const STARTUP_URI = `https://${Config.getConfig().serverIp || "localhost"}:9002`;
@ -72,11 +71,11 @@ export default class AllnetModule extends Module {
const adjusted = now;
let shopName = Config.getConfig().shopName;
let shopNick = Config.getConfig().shopName;
let shopNick = Config.getConfig().shopNickname;
let regionName = Config.getConfig().regionName;
let placeId = Config.getConfig().placeId;
let country = Config.getConfig().country;
let regionId = common.sanitizeInputNotZero(Number(Config.getConfig().regionId)) || 1;
let regionId = Config.getConfig().regionId;
// TODO: Implement board authentication here.

View File

@ -47,16 +47,12 @@ export interface GameOptions {
grantFullTuneTicketToNewUsers: number;
// Give meter reward every n*100 play
giveMeterReward: number; // 1 is on, 0 is off
giveMeterReward: number; //1 is on, 0 is off
// if the new card is not in the User databese
// set this option to 1 will not create a new card
// and prevent new card registration
newCardsBanned: number; // 1 is on, 0 is off
// revision check
// set this option to 1 to enable screenshot feature
enableScreenshot: number; // 1 is on, 0 is off
newCardsBanned: number;//1 is on, 0 is off
}
export class Config {

View File

@ -1,18 +1,6 @@
// Bayshore - a Wangan Midnight Maximum Tune 6 private server.
// Made with love by Luna, and part of Project Asakura.
import process from 'process';
import * as dotenv from "dotenv";
dotenv.config({path: __dirname + '/.env'});
let tracing: any = {};
if (process.env.OPENTELEMETRY_ENABLED === "true") {
console.log('Enabling OpenTelemetry-compatible tracing...');
tracing = require('./tracing');
tracing.startTracing();
}
import express, { Router } from 'express';
import {PrismaClient} from '@prisma/client';
import https, {globalAgent} from 'https';
@ -22,9 +10,13 @@ import bodyParser from 'body-parser';
import AllnetModule from './allnet';
import MuchaModule from './mucha';
import { Config } from './config';
import process from 'process';
import * as Sentry from '@sentry/node';
import * as Tracing from '@sentry/tracing';
import * as common from './modules/util/common';
import * as common from './util/common';
import * as dotenv from "dotenv";
dotenv.config({path: __dirname + '/.env'});
globalAgent.options.keepAlive = true;
@ -35,10 +27,9 @@ export const prisma = new PrismaClient();
const appRouter = Router();
const PORT_ALLNET = process.env.ALLNET_PORT !== undefined ? parseInt(process.env.ALLNET_PORT) : 80;
const PORT_MUCHA = process.env.MUCHA_PORT !== undefined ? parseInt(process.env.MUCHA_PORT) : 10082;
const PORT_BNGI = process.env.SERVICE_PORT !== undefined ? parseInt(process.env.SERVICE_PORT) : 9002;
const PORT_API = process.env.API_PORT !== undefined ? parseInt(process.env.API_PORT) : 9003;
const PORT_ALLNET = 80;
const PORT_MUCHA = 10082;
const PORT_BNGI = 9002;
const app = express();
const muchaApp = express();
@ -64,29 +55,6 @@ if (useSentry) {
});
}
if (process.env.OPENTELEMETRY_ENABLED === "true") {
tracing.startHttpMetrics([
{
app,
options: {
appName: 'service'
}
},
{
app: muchaApp,
options: {
appName: 'mucha'
}
},
{
app: allnetApp,
options: {
appName: 'allnet'
}
}
]);
}
// Get the current timestamp
let timestamp: string = common.getTimeStamp();
@ -173,4 +141,4 @@ https.createServer({key, cert}, muchaApp).listen(PORT_MUCHA, '0.0.0.0', 511, ()
// Create the game server
https.createServer({key, cert}, app).listen(PORT_BNGI, '0.0.0.0', 511, () => {
console.log(`Game server listening on port ${PORT_BNGI}!`);
})
})

View File

@ -2,13 +2,16 @@ import { Application } from "express";
import { Config } from "../config";
import { Module } from "module";
import { prisma } from "..";
import { User } from "@prisma/client";
import Long from "long";
// Import Proto
import * as wm from "../wmmt/wm.proto";
// Import Util
import * as common from "./util/common";
import * as carFunctions from "./cars/functions";
import * as common from "../util/common";
import * as scratch from "../util/scratch";
import * as terminal from "../util/terminal/check_car";
export default class CarModule extends Module {
@ -21,60 +24,223 @@ export default class CarModule extends Module {
let body = wm.wm.protobuf.LoadCarRequest.decode(req.body);
// Get the car (required data only) with the given id
let car = await carFunctions.getCar(body.carId);
let car = await prisma.car.findFirst({
where: {
carId: body.carId
},
include: {
settings: true,
items: true,
gtWing: true,
lastPlayedPlace: true,
}
});
// Get Registered HoF Data
let registeredTarget = await carFunctions.getRegisteredTarget(body.carId);
// Get Challenger Data
let opponentsTarget = await carFunctions.getOpponentsTarget(body.carId, registeredTarget.registeredargetAvailable);
// Set Screenshot Count
let screenshotCount = 0;
// Check if screenshot feature enabled or not
let enableScreenshot = Config.getConfig().gameOptions.enableScreenshot || 0;
// Screenshot feature enabled
if(enableScreenshot === 1)
// Error handling if ghostLevel accidentally set to 0 or more than 10
if(car!.ghostLevel < 1)
{
// Set the screnshot chance count
screenshotCount = 99;
car!.ghostLevel = 1;
}
if(car!.ghostLevel > 11)
{
car!.ghostLevel = 10;
}
// Convert the database lose bits to a Long
let longLoseBits = Long.fromString(car!.stLoseBits.toString());
// Get Registered Target
let getTarget = await prisma.ghostRegisteredFromTerminal.findFirst({
where:{
carId: body.carId
}
});
let opponentGhost;
let opponentTrailId;
let opponentCompetitionId;
let registeredTarget: boolean = false;
if(getTarget)
{
console.log('Registered Opponents Available');
let getTargetTrail = await prisma.oCMTop1GhostTrail.findFirst({
where:{
carId: getTarget.opponentCarId,
competitionId: Number(getTarget.competitionId)
},
orderBy:{
periodId: 'desc'
}
});
if(getTargetTrail)
{
let getTargetCar = await prisma.car.findFirst({
where:{
carId: getTarget.opponentCarId
},
include:{
gtWing: true,
lastPlayedPlace: true
}
});
opponentGhost = wm.wm.protobuf.GhostCar.create({
car: {
...getTargetCar!,
tunePower: getTargetTrail!.tunePower,
tuneHandling: getTargetTrail!.tuneHandling,
},
area: getTargetTrail!.area,
ramp: getTargetTrail!.ramp,
path: getTargetTrail!.path,
nonhuman: false,
type: wm.wm.protobuf.GhostType.GHOST_NORMAL,
trailId: getTargetTrail!.dbId
});
opponentTrailId = Number(getTargetTrail!.dbId);
opponentCompetitionId = Number(getTarget.competitionId);
}
registeredTarget = true;
}
// Check opponents stamp target
// Will skip this if user's have Hall of Fame ghost registered
let carsChallengers;
let returnCount = 1;
let opponentTargetCount = 0;
if(registeredTarget === false)
{
opponentTargetCount = await prisma.carStampTarget.count({
where:{
stampTargetCarId: body.carId,
recommended: true,
},
orderBy:{
locked: 'desc'
}
});
if(opponentTargetCount > 0)
{
console.log('Challengers Available');
// Randomize pick
let random: number = 1;
// Randomize it 5 times
for(let i=0; i<5; i++)
{
random = Math.floor(Math.random() * opponentTargetCount);
}
// Try randomize it again if it's 1
if(random === 1)
{
random = Math.floor(Math.random() * opponentTargetCount);
}
// Check opponents target
let opponentTarget = await prisma.carStampTarget.findMany({
where:{
stampTargetCarId: body.carId,
recommended: true,
},
orderBy:{
locked: 'desc'
},
skip: random,
take: 1,
});
// Get all of the friend cars for the carId provided
let challengers = await prisma.carChallenger.findFirst({
where: {
challengerCarId: opponentTarget[0].carId,
carId: body.carId
},
orderBy:{
id: 'desc'
}
});
if(challengers)
{
returnCount = opponentTarget[0].returnCount;
let carTarget = await prisma.car.findFirst({
where:{
carId: challengers.challengerCarId
},
include:{
gtWing: true,
lastPlayedPlace: true
}
})
let result = 0;
if(challengers.result > 0)
{
result = -Math.abs(challengers.result);
}
else{
result = Math.abs(challengers.result);
}
carsChallengers = wm.wm.protobuf.ChallengerCar.create({
car: carTarget!,
stamp: challengers.stamp,
result: result,
area: challengers.area
});
}
}
}
// VS ORG
let getVSORGData = await prisma.ghostExpedition.findFirst({
where:{
carId: body.carId
},
orderBy:{
dbId: 'desc'
}
})
// Response data
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
// wm.protobuf.Car;
car: car,
// Other Car Data (tuningPoint, odometer, playCount, etc)
...car,
stLoseBits: car.longLoseBits,
car: {
...car!,
},
tuningPoint: car!.tuningPoints,
setting: car!.settings,
rgPreviousVersionPlayCount: 0,
stCompleted_100Episodes: car!.stCompleted100Episodes,
auraMotifAutoChange: false,
screenshotCount: screenshotCount,
screenshotCount: 0,
transferred: false,
...car!,
stLoseBits: longLoseBits,
ownedItems: car!.items,
lastPlayedAt: car!.lastPlayedAt,
announceEventModePrize: true,
// Stamp or Challenger
challenger: opponentsTarget.challenger,
challengerReturnCount: opponentsTarget.challengerReturnCount,
numOfChallengers: opponentsTarget.numOfChallengers,
challenger: carsChallengers || null,
challengerReturnCount: returnCount || null,
numOfStampTargetCars: opponentTargetCount + 1 || null,
// OCM Challenge Top 1
opponentGhost: registeredTarget.opponentGhost,
opponentTrailId: registeredTarget.opponentTrailId,
opponentCompetitionId: registeredTarget.opponentCompetitionId,
opponentGhost: opponentGhost || null,
opponentTrailId: opponentTrailId || null,
opponentCompetitionId: opponentCompetitionId || null,
// Owned Item
ownedItems: car.items,
// Announce Event Mode Prize
announceEventModePrize: true
// VS ORG
rgExpeditionScore: getVSORGData?.score || 0,
ghostExpeditionState: wm.wm.protobuf.GhostExpeditionParticipantState.EXPEDITION_NOT_PARTICIPATED,
};
// Generate the load car response message
@ -91,18 +257,283 @@ export default class CarModule extends Module {
// Get the request body for the create car request
let body = wm.wm.protobuf.CreateCarRequest.decode(req.body);
// Create the Car
let createCar = await carFunctions.createCar(body);
let tune = createCar.tune;
let carInsert = createCar.carInsert;
// Trim Mojibake
body.cardChipId = body.cardChipId.replace('<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0000', '');
// Check if user's other car have unique window sticker
let windowSticker = await carFunctions.getWindowSticker(body.userId);
let additionalWindowStickerInsert = windowSticker.additionalWindowStickerInsert
// Get the current date/time (unix epoch)
let date = Math.floor(new Date().getTime() / 1000)
// Retrieve user from card chip / user id
let user: User | null;
// User ID provided, use that
if (body.userId) {
user = await prisma.user.findFirst({
where: {
id: body.userId
},
});
} else { // No user id, use card chip
user = await prisma.user.findFirst({
where: {
chipId: body.cardChipId,
accessCode: body.accessCode
},
})
}
// User not found, terminate
if (!user) throw new Error();
// Generate blank car settings object
let settings = await prisma.carSettings.create({
data: {}
});
// Generate blank car state object
let state = await prisma.carState.create({
data: {}
})
let gtWing = await prisma.carGTWing.create({
data: {}
})
// Sets if full tune is used or not
// let fullyTuned = false;
// 0: Stock Tune
// 1: Basic Tune (600 HP)
// 2: Fully Tuned (840 HP)
let tune = 0;
// If a user item has been used
if (body.userItemId)
{
console.log(`Item used - ID ${body.userItemId}`);
// Remove the user item from the database
let item = await prisma.userItem.delete({
where: {
userItemId: body.userItemId
}
});
console.log('Item deleted!');
switch(item.category)
{
case 203: // Car Tune Ticket
// Switch on item id
switch(item.itemId)
{
// Discarded Vehicle Card
case 1: tune = 1; break;
case 2: tune = 1; break;
case 3: tune = 1; break;
// Fully Tuned Ticket
case 5: tune = 2; break;
default: // Unknown item type, throw unsupported error
throw Error("Unsupported itemId: " + item.itemId);
}
break;
case 201: // Special Car Ticket
// Fully tuned special cars
if (scratch.fullyTunedCars.includes(item.itemId))
{
// Car is fully tuned
tune = 2;
}
// Basic tuned special cars
if (scratch.basicTunedCars.includes(item.itemId))
{
// If gift cars fully tuned is set
if (Config.getConfig().gameOptions.giftCarsFullyTuned)
{
// Car is fully tuned
tune = 2;
}
else // Gift cars fully tuned not set
{
// Car is basic tuned
tune = 1;
}
}
// Stock tuned special cars
if (scratch.stockTunedCars.includes(item.itemId))
{
// If gift cars fully tuned is set
if (Config.getConfig().gameOptions.giftCarsFullyTuned)
{
// Car is fully tuned
tune = 2;
}
else // Gift cars fully tuned not set
{
// Car is stock
tune = 0;
}
}
break;
}
console.log(`Item category was ${item.category} and item game ID was ${item.itemId}`);
}
// Other cases, may occur if item is not detected as 'used'
// User item not used, but car has 740 HP by default
else if (body.car &&
(body.car.tunePower == 17) && (body.car.tuneHandling == 17))
{
// Car is fully tuned
tune = 2;
// Check if created car is from terminal scratch car
await terminal.checkScratchCar(body.userId, body.car.visualModel!)
}
// User item not used, but car has 600 HP by default
else if (body.car &&
(body.car.tunePower == 10) && (body.car.tuneHandling == 10))
{
// Car is basic tuned
tune = 1;
}
// User item not used, but gift cars fully tuned switch is set
else if (Config.getConfig().gameOptions.giftCarsFullyTuned)
{
// List of event / exclusive car IDs
let event_cars = [
0x7A, // Mini
0x82, // S660
0x83, // S2000
0x89, // NDERC
0x8B, // GS130 (Starts at 20 Stories by default)
];
// If the car visual model is not null and is in the list of event cars
if (body.car.visualModel && event_cars.includes(body.car.visualModel))
{
// Set full tune used to be true
tune = 2;
}
}
// Randomize regionId
let regionId: number = 18;
// Randomize it 5 times
for(let i=0; i<5; i++)
{
regionId = Math.floor(Math.random() * 47) + 1;
}
// Try randomize it again if it's 1
if(regionId === 1)
{
regionId = Math.floor(Math.random() * 47) + 1;
}
// Error handling if regionId is below 1 or above 47
if(regionId < 1 || regionId > 47)
{
regionId = Math.floor(Math.random() * 10) + 10;
}
/// Switch on tune status
let getCarTune = await carFunctions.getCarTune(tune, carInsert);
let additionalInsert = getCarTune.additionalInsert;
// Default car values
let carInsert = {
userId: user.id,
manufacturer: body.car.manufacturer!,
defaultColor: body.car.defaultColor!,
model: body.car.model!,
visualModel: body.car.visualModel!,
name: body.car.name!,
title: body.car.title!,
level: body.car.level!,
tunePower: body.car.tunePower!,
tuneHandling: body.car.tuneHandling!,
carSettingsDbId: settings.dbId,
carStateDbId: state.dbId,
carGTWingDbId: gtWing.dbId,
regionId: regionId,
lastPlayedAt: date,
lastPlayedPlaceId: 1, // Server Default
};
// Check if user have more than one cars
let checkWindowSticker = await prisma.car.findFirst({
where: {
userId: body.userId
},
select: {
windowStickerString: true,
windowStickerFont: true
}
});
let additionalWindowStickerInsert = {
}
// If more than one cars, get the window sticker string
if(checkWindowSticker)
{
additionalWindowStickerInsert = {
windowStickerString: checkWindowSticker.windowStickerString,
windowStickerFont: checkWindowSticker.windowStickerFont,
}
}
// Additional car values (for basic / full tune)
let additionalInsert = {
}
// Switch on tune status
switch(tune)
{
// 0: Stock, nothing extra
case 1: // Basic Tune
// Updated default values
carInsert.level = 2; // C8
carInsert.tunePower = 10; // 600 HP
carInsert.tuneHandling = 10; // 600 HP
// Additional basic tune values
additionalInsert = {
ghostLevel: 4,
stClearBits: 0,
stLoseBits: 0,
stClearCount: 20,
stClearDivCount: 1,
stConsecutiveWins: 20,
stConsecutiveWinsMax: 20
};
break;
case 2: // Fully Tuned
// Updated default values
carInsert.level = 8; // C3
carInsert.tunePower = 17; // 740 HP
carInsert.tuneHandling = 17; // 740 HP
// Additional full tune values
additionalInsert = {
ghostLevel: 10,
stClearBits: 0,
stLoseBits: 0,
stClearCount: 80,
stClearDivCount: 4,
stConsecutiveWins: 80,
stConsecutiveWinsMax: 80
};
}
// Insert the car into the database
let car = await prisma.car.create({
@ -114,26 +545,30 @@ export default class CarModule extends Module {
});
// Get the user's current car order
let carOrder = createCar.user.carOrder;
await carFunctions.carOrder(carOrder, car, createCar.user.id);
let carOrder = user.carOrder;
// Add the new car to the front of the id
carOrder.unshift(car.carId);
// Add the car to the front of the order
await prisma.user.update({
where: {
id: user.id
},
data: {
carOrder: carOrder
}
});
console.log(`Created new car ${car.name} with ID ${car.carId}`);
// Response data
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
// User ID
accessCode: body.accessCode,
banapassportAmId: body.banapassportAmId,
//mbid: number|null,
// Car Data
carId: car.carId,
car,
...carInsert,
...additionalInsert,
// Expiring Full Tuned Ticket
//fullTunedCarCouponUnreceivableAt: number|null
...additionalInsert
}
// Generate the load car response message
@ -150,52 +585,165 @@ export default class CarModule extends Module {
// Get the request body for the update car request
let body = wm.wm.protobuf.UpdateCarRequest.decode(req.body);
// Not deleting car
if(body.toBeDeleted === false || body.toBeDeleted === undefined || body.toBeDeleted === null)
// Get the ghost result for the car
let cars = body?.car;
// Declare data
let data : any;
// Car is set
if (cars)
{
// Update the car
await carFunctions.updateCar(body);
// Get current date
let date = Math.floor(new Date().getTime() / 1000);
// Update the car setting
await carFunctions.updateCarSetting(body);
// Car update data
data = {
customColor: common.sanitizeInput(cars.customColor),
wheel: common.sanitizeInput(cars.wheel),
wheelColor: common.sanitizeInput(cars.wheelColor),
aero: common.sanitizeInput(cars.aero),
bonnet: common.sanitizeInput(cars.bonnet),
wing: common.sanitizeInput(cars.wing),
mirror: common.sanitizeInput(cars.mirror),
neon: common.sanitizeInput(cars.neon),
trunk: common.sanitizeInput(cars.trunk),
plate: common.sanitizeInput(cars.plate),
plateColor: common.sanitizeInput(cars.plateColor),
plateNumber: common.sanitizeInput(cars.plateNumber),
windowSticker: common.sanitizeInput(cars.windowSticker),
windowDecoration: common.sanitizeInput(cars.windowDecoration),
rivalMarker: common.sanitizeInput(cars.rivalMarker),
aura: common.sanitizeInput(cars.aura),
auraMotif: common.sanitizeInput(cars.auraMotif),
rgStamp: common.sanitizeInputNotZero(body.rgStamp),
lastPlayedAt: date
}
// Update the car window Sticker
await carFunctions.updateCarWindowSticker(body);
// Update the car info
await prisma.car.update({
where: {
carId: body.carId
},
data: data
})
}
// Update the car Custom Wing
await carFunctions.updateCarCustomWing(body);
// Get the car with the given id
let car = await prisma.car.findFirst({
where: {
carId: body.carId
},
include: {
settings: true,
gtWing: true,
lastPlayedPlace: true
}
});
// Update the car settings
await prisma.carSettings.update({
where: {
dbId: car?.carSettingsDbId,
},
data: {
...body.setting
}
});
// Get car item (custom color or discarded card)
if(body.earnedItems.length !== 0)
{
console.log('Car Item reward available, continuing ...');
for(let i=0; i<body.earnedItems.length; i++){
await prisma.carItem.create({
data: {
carId: body.carId,
category: body.earnedItems[i].category,
itemId: body.earnedItems[i].itemId,
amount: 1
}
});
}
// Update the user data
let userData = await prisma.car.findFirst({
where:{
carId: body.carId
},
select:{
userId: true,
windowStickerString: true
}
})
// Newer window sticker string is different from the older one
// Check if window sticker string is not null
// (windowStickerString value when changing custom color in driver unit is undefined)
if(body.car?.windowStickerString)
{
if(userData!.windowStickerString !== body.car.windowStickerString){
console.log('Updating Window Sticker');
await prisma.car.updateMany({
where: {
userId: userData!.userId
},
data: {
windowStickerString: body.car.windowStickerString,
windowStickerFont: body.car.windowStickerFont!
}
})
}
}
// Deleting car
else
{
console.log('Deleting Car ID : ' + body.carId);
// Mark Deleted Car
await prisma.carState.update({
where:{
// Get car item (custom color or discarded card)
if(body.earnedItems.length !== 0){
console.log('Car Item reward available, continuing ...');
for(let i=0; i<body.earnedItems.length; i++){
await prisma.carItem.create({
data: {
carId: body.carId,
category: body.earnedItems[i].category,
itemId: body.earnedItems[i].itemId,
amount: 1
}
});
}
}
// Update the GT Wing (custom wing) info
// Get the GT Wing data for the car
let gtWing = body.car?.gtWing;
let dataGTWing: any;
// GT Wing is set
if (gtWing)
{
dataGTWing = {
pillar: common.sanitizeInput(gtWing.pillar),
pillarMaterial: common.sanitizeInput(gtWing.pillarMaterial),
mainWing: common.sanitizeInput(gtWing.mainWing),
mainWingColor: common.sanitizeInput(gtWing.mainWingColor),
wingTip: common.sanitizeInput(gtWing.wingTip),
material: common.sanitizeInput(gtWing.material),
}
await prisma.carGTWing.update({
where: {
dbId: body.carId
},
data:{
toBeDeleted: body.toBeDeleted
}
},
data: dataGTWing
})
}
// Check if this is in getting new custom color screen or not
else if(body.car?.carId !== null && body.car?.carId !== undefined)
{
// GT Wing not set
if(gtWing === undefined || gtWing === null)
{
dataGTWing = {
pillar: 0,
pillarMaterial: 0,
mainWing: 0,
mainWingColor: 0,
wingTip: 0,
material: 0,
}
await prisma.carGTWing.update({
where: {
dbId: body.carId
},
data: dataGTWing
})
}
}
// Response data
let msg = {

View File

@ -1,86 +0,0 @@
import { Config } from "../../config";
import { prisma } from "../..";
// Import Util
import * as scratch from "../terminal/scratch";
// Create Car With Item
export async function createCarWithItem(userItemId: number)
{
console.log(`Item used - ID ${userItemId}`);
// Remove the user item from the database
let item = await prisma.userItem.delete({
where: {
userItemId: userItemId
}
});
let tune = 0;
console.log('Item deleted!');
switch(item.category)
{
case 203: // Car Tune Ticket
// Switch on item id
switch(item.itemId)
{
// Discarded Vehicle Card
case 1: tune = 1; break;
case 2: tune = 1; break;
case 3: tune = 1; break;
// Fully Tuned Ticket
case 5: tune = 2; break;
default: // Unknown item type, throw unsupported error
throw Error("Unsupported itemId: " + item.itemId);
}
break;
case 201: // Special Car Ticket
// Fully tuned special cars
if (scratch.fullyTunedCars.includes(item.itemId))
{
// Car is fully tuned
tune = 2;
}
// Basic tuned special cars
if (scratch.basicTunedCars.includes(item.itemId))
{
// If gift cars fully tuned is set
if (Config.getConfig().gameOptions.giftCarsFullyTuned)
{
// Car is fully tuned
tune = 2;
}
else // Gift cars fully tuned not set
{
// Car is basic tuned
tune = 1;
}
}
// Stock tuned special cars
if (scratch.stockTunedCars.includes(item.itemId))
{
// If gift cars fully tuned is set
if (Config.getConfig().gameOptions.giftCarsFullyTuned)
{
// Car is fully tuned
tune = 2;
}
else // Gift cars fully tuned not set
{
// Car is stock
tune = 0;
}
}
break;
}
console.log(`Item category was ${item.category} and item game ID was ${item.itemId}`);
return { tune }
}

View File

@ -1,669 +0,0 @@
import { prisma } from "../..";
import { User } from "@prisma/client";
import { Config } from "../../config";
import Long from "long";
// Import Proto
import { wm } from "../../wmmt/wm.proto";
import * as wmproto from "../../wmmt/wm.proto";
// Import Util
import * as common from "../util/common";
import * as car_tune from "./car_tune";
import * as terminal from "../terminal/check_car";
// Get Car Data
export async function getCar(carId: number)
{
// Get the car (required data only) with the given id
let car = await prisma.car.findFirst({
where: {
carId: carId
},
include: {
settings: true,
items: true,
gtWing: true,
lastPlayedPlace: true,
}
});
// Error handling if ghostLevel accidentally set to 0 or more than 10
if(car!.ghostLevel < 1)
{
car!.ghostLevel = 1;
}
if(car!.ghostLevel > 11)
{
car!.ghostLevel = 10;
}
// Convert the database lose bits to a Long
let longLoseBits = Long.fromString(car!.stLoseBits.toString());
return { ...car!, longLoseBits }
}
// Get Opponents Target
export async function getRegisteredTarget(carId: number)
{
// Get Registered Target
let getTarget = await prisma.ghostRegisteredFromTerminal.findFirst({
where:{
carId: carId
}
});
let opponentGhost;
let opponentTrailId;
let opponentCompetitionId;
let registeredargetAvailable: boolean = false;
if(getTarget)
{
console.log('Registered Opponents Available');
let getTargetTrail = await prisma.oCMTop1GhostTrail.findFirst({
where:{
carId: getTarget.opponentCarId,
competitionId: Number(getTarget.competitionId)
},
orderBy:{
periodId: 'desc'
}
});
if(getTargetTrail)
{
let getTargetCar = await prisma.car.findFirst({
where:{
carId: getTarget.opponentCarId
},
include:{
gtWing: true,
lastPlayedPlace: true
}
});
opponentGhost = wmproto.wm.protobuf.GhostCar.create({
car: {
...getTargetCar!,
tunePower: getTargetTrail!.tunePower,
tuneHandling: getTargetTrail!.tuneHandling,
},
area: getTargetTrail!.area,
ramp: getTargetTrail!.ramp,
path: getTargetTrail!.path,
nonhuman: false,
type: wmproto.wm.protobuf.GhostType.GHOST_NORMAL,
trailId: getTargetTrail!.dbId
});
opponentTrailId = Number(getTargetTrail!.dbId);
opponentCompetitionId = Number(getTarget.competitionId);
}
registeredargetAvailable = true;
}
return { opponentGhost, opponentTrailId, opponentCompetitionId, registeredargetAvailable }
}
// Get Opponents Target
export async function getOpponentsTarget(carId: number, registeredargetAvailable: boolean)
{
// Check opponents stamp target
// Will skip this if user's have Hall of Fame ghost registered
let challenger;
let challengerReturnCount = 1;
let opponentTargetCount = 0;
let numOfChallengers: number = 0;
if(registeredargetAvailable === false)
{
// Check opponents target
opponentTargetCount = await prisma.carStampTarget.count({
where:{
stampTargetCarId: carId,
recommended: true,
},
orderBy:{
locked: 'desc'
}
});
if(opponentTargetCount > 0)
{
console.log('Challengers Available');
// Randomize pick
let random: number = 1;
let randomArray: number[] = [];
let maxNumber = 5;
if(opponentTargetCount < 5)
{
maxNumber = opponentTargetCount;
}
// Randomize it 5 times
while(randomArray.length < maxNumber)
{
// Pick random car Id
random = Math.floor(Math.random() * opponentTargetCount);
// Try randomize it again if it's 0, and fix if more than car length
if(random < 1 || random >= opponentTargetCount)
{
random = Math.floor(Math.random() * opponentTargetCount);
}
// Random Number not yet selected
if(randomArray.indexOf(random) === -1)
{
// Push current number to array
randomArray.push(random);
}
}
// Pick the array number
let pickRandom = Math.floor(Math.random() * randomArray.length);
random = randomArray[pickRandom];
// Check opponents target
let opponentTarget = await prisma.carStampTarget.findMany({
where:{
stampTargetCarId: carId,
recommended: true,
},
orderBy: [
{
id: 'asc'
},
{
recommended: 'desc'
}
],
skip: random,
take: 1,
});
// Get Opponents Challengers
let carChallengers = await prisma.carChallenger.findFirst({
where: {
challengerCarId: opponentTarget[0].carId,
carId: carId
},
orderBy:{
id: 'desc'
}
});
// Challengers Available
if(carChallengers)
{
// Get Shuttle
challengerReturnCount = opponentTarget[0].returnCount;
// Get Car Target
let carTarget = await prisma.car.findFirst({
where:{
carId: carChallengers.challengerCarId
},
include:{
gtWing: true,
lastPlayedPlace: true
}
});
// Car Target Available
if(carTarget)
{
// Get Advantage
let result = 0;
if(carChallengers.result > 0)
{
result = -Math.abs(carChallengers.result);
}
else{
result = Math.abs(carChallengers.result);
}
// Error handling if regionId is below 1 or above 47
if(carTarget!.regionId < 1 || carTarget!.regionId > 47)
{
carTarget!.regionId = Math.floor(Math.random() * 10) + 10;
}
// Push the data
challenger = wmproto.wm.protobuf.ChallengerCar.create({
car: carTarget,
stamp: carChallengers.stamp,
result: result,
area: carChallengers.area
});
}
}
// Get Number of Challengers
numOfChallengers = opponentTargetCount + 1;
}
}
return { challenger, challengerReturnCount, numOfChallengers }
}
// Create Car
export async function createCar(body: wm.protobuf.CreateCarRequest)
{
// Get the current date/time (unix epoch)
let date = Math.floor(new Date().getTime() / 1000);
// Retrieve user from card chip / user id
let user: User | null;
// User ID provided, use that
if (body.userId)
{
user = await prisma.user.findFirst({
where: {
id: body.userId
},
});
}
// No user id, use card chip
else
{
user = await prisma.user.findFirst({
where: {
chipId: body.cardChipId,
accessCode: body.accessCode
},
});
}
// User not found, terminate
if (!user) throw new Error();
// Generate blank car settings object
let settings = await prisma.carSettings.create({
data: {}
});
// Generate blank car state object
let state = await prisma.carState.create({
data: {}
});
let gtWing = await prisma.carGTWing.create({
data: {}
});
// Sets if full tune is used or not
// let fullyTuned = false;
// 0: Stock Tune
// 1: Basic Tune (600 HP)
// 2: Fully Tuned (840 HP)
let tune = 0;
// If a user item has been used
if (body.userItemId)
{
let carUtilFunctions = await car_tune.createCarWithItem(body.userItemId);
tune = carUtilFunctions.tune;
}
// Other cases, may occur if item is not detected as 'used'
// User item not used, but car has 740 HP by default
else if (body.car && body.car.tunePower == 17 && body.car.tuneHandling == 17)
{
// Car is fully tuned
tune = 2;
// Check if created car is from terminal scratch car
await terminal.checkScratchCar(body.userId, body.car.visualModel!)
}
// User item not used, but car has 600 HP by default
else if (body.car && body.car.tunePower == 10 && body.car.tuneHandling == 10)
{
// Car is basic tuned
tune = 1;
}
// User item not used, but gift cars fully tuned switch is set
else if (Config.getConfig().gameOptions.giftCarsFullyTuned)
{
// List of event / exclusive car IDs
let event_cars = [
0x7A, // Mini
0x82, // S660
0x83, // S2000
0x89, // NDERC
0x8B, // GS130 (Starts at 20 Stories by default)
];
// If the car visual model is not null and is in the list of event cars
if (body.car.visualModel && event_cars.includes(body.car.visualModel))
{
// Set full tune used to be true
tune = 2;
}
}
// Randomize pick
let random: number = 1;
let randomArray: number[] = [];
// Randomize it 5 times
while(randomArray.length < 5)
{
// Pick random car Id
random = Math.floor(Math.random() * 47) + 1;
// Try randomize it again if it's 0, and fix if more than car length
if(random < 1 || random > 47)
{
random = Math.floor(Math.random() * 47) + 1;
}
// Random Number not yet selected
if(randomArray.indexOf(random) === -1)
{
// Push current number to array
randomArray.push(random);
}
}
// Pick the array number
let pickRandom = Math.floor(Math.random() * randomArray.length);
random = randomArray[pickRandom];
// Default car values
let carInsert = {
userId: user.id,
manufacturer: body.car.manufacturer!,
defaultColor: body.car.defaultColor!,
model: body.car.model!,
visualModel: body.car.visualModel!,
name: body.car.name!,
title: body.car.title!,
level: body.car.level!,
tunePower: body.car.tunePower!,
tuneHandling: body.car.tuneHandling!,
carSettingsDbId: settings.dbId,
carStateDbId: state.dbId,
carGTWingDbId: gtWing.dbId,
regionId: random,
lastPlayedAt: date,
lastPlayedPlaceId: 1, // Server Default
};
return { carInsert, tune, user }
}
// Get Window Sticker
export async function getWindowSticker(userId: number)
{
// Check if user have more than one cars
let checkWindowSticker = await prisma.car.findFirst({
where: {
userId: userId
},
select: {
windowStickerString: true,
windowStickerFont: true
}
});
let additionalWindowStickerInsert = {};
// If more than one cars, get the window sticker string
if(checkWindowSticker)
{
additionalWindowStickerInsert = {
windowStickerString: checkWindowSticker.windowStickerString,
windowStickerFont: checkWindowSticker.windowStickerFont,
}
}
return { additionalWindowStickerInsert }
}
// Get Car Tune
export async function getCarTune(tune: number, carInsert: any)
{
// Additional car values (for basic / full tune)
let additionalInsert = {};
switch(tune)
{
// 0: Stock, nothing extra
case 1: // Basic Tune
// Updated default values
carInsert.level = 2; // C8
carInsert.tunePower = 10; // 600 HP
carInsert.tuneHandling = 10; // 600 HP
// Additional basic tune values
additionalInsert = {
ghostLevel: 4,
stClearBits: 0,
stLoseBits: 0,
stClearCount: 20,
stClearDivCount: 1,
stConsecutiveWins: 20,
stConsecutiveWinsMax: 20
};
break;
case 2: // Fully Tuned
// Updated default values
carInsert.level = 8; // C3
carInsert.tunePower = 17; // 740 HP
carInsert.tuneHandling = 17; // 740 HP
// Additional full tune values
additionalInsert = {
ghostLevel: 10,
stClearBits: 0,
stLoseBits: 0,
stClearCount: 80,
stClearDivCount: 4,
stConsecutiveWins: 80,
stConsecutiveWinsMax: 80
};
}
return { additionalInsert }
}
// Car Order
export async function carOrder(carOrder: any, car: any, userId: number)
{
// Add the new car to the front of the id
carOrder.unshift(car.carId);
// Add the car to the front of the order
await prisma.user.update({
where: {
id: userId
},
data: {
carOrder: carOrder
}
});
console.log(`Created new car ${car.name} with ID ${car.carId}`);
}
// Update Car
export async function updateCar(body: wm.protobuf.UpdateCarRequest)
{
// Get the ghost result for the car
let cars = body?.car;
// Declare data
let data: any;
// Get the current date/time (unix epoch)
let date = Math.floor(new Date().getTime() / 1000);
// Car is set
if (cars)
{
// Car update data
data = {
customColor: common.sanitizeInput(cars.customColor),
wheel: common.sanitizeInput(cars.wheel),
wheelColor: common.sanitizeInput(cars.wheelColor),
aero: common.sanitizeInput(cars.aero),
bonnet: common.sanitizeInput(cars.bonnet),
wing: common.sanitizeInput(cars.wing),
mirror: common.sanitizeInput(cars.mirror),
neon: common.sanitizeInput(cars.neon),
trunk: common.sanitizeInput(cars.trunk),
plate: common.sanitizeInput(cars.plate),
plateColor: common.sanitizeInput(cars.plateColor),
plateNumber: common.sanitizeInput(cars.plateNumber),
windowSticker: common.sanitizeInput(cars.windowSticker),
windowDecoration: common.sanitizeInput(cars.windowDecoration),
rivalMarker: common.sanitizeInput(cars.rivalMarker),
aura: common.sanitizeInput(cars.aura),
auraMotif: common.sanitizeInput(cars.auraMotif),
rgStamp: common.sanitizeInputNotZero(body.rgStamp),
lastPlayedAt: date
};
// Update the car info
await prisma.car.update({
where: {
carId: body.carId
},
data: data
});
}
}
// Update Car Setting
export async function updateCarSetting(body: wm.protobuf.UpdateCarRequest)
{
// Get the car with the given id
let car = await prisma.car.findFirst({
where: {
carId: body.carId
},
include: {
settings: true,
gtWing: true,
lastPlayedPlace: true
}
});
// Update the car settings
await prisma.carSettings.update({
where: {
dbId: car?.carSettingsDbId,
},
data: {
...body.setting
}
});
}
// Update car Window Sticker
export async function updateCarWindowSticker(body: wm.protobuf.UpdateCarRequest)
{
// Update the user data
let userData = await prisma.car.findFirst({
where:{
carId: body.carId
},
select:{
userId: true,
windowStickerString: true
}
});
// Newer window sticker string is different from the older one
// Check if window sticker string is not null
// (windowStickerString value when changing custom color in driver unit is undefined)
if(body.car?.windowStickerString)
{
if(userData!.windowStickerString !== body.car.windowStickerString){
console.log('Updating Window Sticker');
await prisma.car.updateMany({
where: {
userId: userData!.userId
},
data: {
windowStickerString: body.car.windowStickerString,
windowStickerFont: body.car.windowStickerFont!
}
});
}
}
}
// Update Car Custom Wing
export async function updateCarCustomWing(body: wm.protobuf.UpdateCarRequest)
{
// Update the GT Wing (custom wing) info
// Get the GT Wing data for the car
let gtWing = body.car?.gtWing;
let dataGTWing: any;
// GT Wing is set
if (gtWing)
{
dataGTWing = {
pillar: common.sanitizeInput(gtWing.pillar),
pillarMaterial: common.sanitizeInput(gtWing.pillarMaterial),
mainWing: common.sanitizeInput(gtWing.mainWing),
mainWingColor: common.sanitizeInput(gtWing.mainWingColor),
wingTip: common.sanitizeInput(gtWing.wingTip),
material: common.sanitizeInput(gtWing.material),
};
await prisma.carGTWing.update({
where: {
dbId: body.carId
},
data: dataGTWing
});
}
// Check if this is in getting new custom color screen or not
else if(body.car?.carId !== null && body.car?.carId !== undefined)
{
// GT Wing not set
if(gtWing === undefined || gtWing === null)
{
dataGTWing = {
pillar: 0,
pillarMaterial: 0,
mainWing: 0,
mainWingColor: 0,
wingTip: 0,
material: 0,
};
await prisma.carGTWing.update({
where: {
dbId: body.carId
},
data: dataGTWing
});
}
}
}

View File

@ -7,13 +7,12 @@ import { Config } from "../config";
import * as wm from "../wmmt/wm.proto";
// Import Util
import * as common from "./util/common";
import * as gameFunction from "./game/functions";
import * as meter_reward from "./util/meter_reward";
import * as story from "./game/story";
import * as time_attack from "./game/time_attack";
import * as ghost from "./game/ghost";
import * as versus from "./game/versus";
import * as common from "../util/common";
import * as meter_reward from "../util/games/meter_reward";
import * as story from "../util/games/story";
import * as time_attack from "../util/games/time_attack";
import * as ghost from "../util/games/ghost";
import * as versus from "../util/games/versus";
export default class GameModule extends Module {
@ -36,10 +35,15 @@ export default class GameModule extends Module {
}
});
// Declare some variable for message response
let ghostModePlay:boolean = false;
let updateNewTrail:boolean = true;
let OCMModePlay:boolean = false;
// Declare some variable
// Default value is 'false', inside 'BASE_PATH/src/util/games/ghost.ts' file
let ghostModePlay;
// Default value is 'true', inside 'BASE_PATH/src/util/games/ghost.ts' file
let updateNewTrail;
// Default value is 'false', inside 'BASE_PATH/src/util/games/ghost.ts' file
let OCMModePlay;
// Switch on the gamemode
switch (body.gameMode)
@ -96,15 +100,96 @@ export default class GameModule extends Module {
}
}
// Get car item
// Car item reward from the game is available
if(body.earnedItems.length !== 0)
{
console.log('Car Item reward available, continuing ...');
for(let i=0; i<body.earnedItems.length; i++){
await prisma.carItem.create({
data: {
carId: body.carId,
category: body.earnedItems[i].category,
itemId: body.earnedItems[i].itemId,
amount: 1
}
});
}
}
// Check if earned some items
await gameFunction.getItem(body);
// Get user item
// User item reward from the game is available
if(body.earnedUserItems.length !== 0)
{
console.log('User Item reward available, continuing ...');
for(let i=0; i<body.earnedUserItems.length; i++){
await prisma.userItem.create({
data: {
category: body.earnedUserItems[i].category,
itemId: body.earnedUserItems[i].itemId,
userId: body.car!.userId!,
earnedAt: 0,
type: 0
}
});
}
}
// Update Car Data
await gameFunction.updateCar(body, car);
// Check playet at timestamp
let timestamps = 0;
if(body.car?.lastPlayedAt !== undefined && body.car?.lastPlayedAt !== null)
{
if(body.car.lastPlayedAt !== 0)
{
timestamps = body.car.lastPlayedAt;
}
else
{
timestamps = Math.floor(new Date().getTime() / 1000);
}
}
// Update Car Order and Save Tutorial
await gameFunction.updateOrderTutorial(body);
// Check P & H must not more than 34 (fully tuned value)
let tunePower = 0;
let tuneHandling = 0;
let totalTune = body.car!.tunePower + body.car!.tuneHandling;
if(totalTune <= 34)
{
tunePower = body.car!.tunePower;
tuneHandling = body.car!.tuneHandling;
}
// Update car
await prisma.car.update({
where: {
carId: body.carId,
},
data: {
aura: body.car!.aura!,
auraMotif: body.car!.auraMotif!,
odometer: body.odometer,
playCount: body.playCount,
level: body.car!.level!,
title: body.car!.title!,
tunePower: tunePower,
tuneHandling: tuneHandling,
windowSticker: body.car!.windowSticker!,
lastPlayedAt: timestamps,
regionId: body.car!.regionId!,
rgStamp: common.sanitizeInputNotZero(body.rgResult?.rgStamp),
stampSheetCount: common.sanitizeInputNotZero(body.rgResult?.stampSheetCount)
}
})
// Update car settings
await prisma.carSettings.update({
where: {
dbId: car!.carSettingsDbId
},
data: {
...body.setting
}
});
// Every n*100 play give reward
// Check this feature config
@ -117,15 +202,61 @@ export default class GameModule extends Module {
await meter_reward.giveMeterRewards(body);
}
// Update user
let user = await prisma.user.findFirst({
where: {
id: body.car!.userId!
}
});
// -----------------------------------------------------------------------------------------------
// Additional Message for Response Data
let additionalSesionIdMsg = {};
// User object exists
if (user)
{
// Get user tutorials
let storedTutorials = user!.tutorials;
// Update any seen tutorials
body.confirmedTutorials.forEach(
(idx) => storedTutorials[idx] = true
);
// Get the order of the user's cars
let carOrder = user?.carOrder;
// Get the index of the selected car
let index = carOrder.indexOf(body.carId);
// Only splice array when item is found
if (index > -1)
{
carOrder.splice(index, 1); // 2nd parameter means remove one item only
}
// Add it back to the front
carOrder.unshift(body.carId);
// Otherwise, just ignore it
// Update the values
await prisma.user.update({
where: {
id: body.car!.userId!
},
data: {
tutorials: storedTutorials,
carOrder: carOrder
}
});
}
// Response data
let msg;
// Ghost Battle mode or Crown Ghost Battle game mode is completed
if(ghostModePlay === true && OCMModePlay === false && updateNewTrail === true)
{
additionalSesionIdMsg = {
msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
// Set session for saving ghost trail Ghost Battle Mode or Crown Ghost Battle Mode
ghostSessionId: Math.floor(Math.random() * 100) + 1
@ -134,24 +265,21 @@ export default class GameModule extends Module {
// OCM Battle game mode is completed
else if(ghostModePlay === true && OCMModePlay === true && updateNewTrail === true)
{
additionalSesionIdMsg = {
msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
// Set session for saving ghost trail Competition (OCM) Ghost Battle Mode
// Set session for saving ghost trail OCM Ghost Battle Mode
ghostSessionId: Math.floor(Math.random() * 100) + 101
}
}
// -----------------------------------------------------------------------------------------------
// Story mode or TA mode is completed
else
{
msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS
// Response data
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
// Ghost Session ID
...additionalSesionIdMsg,
// Available Tickets (maybe for VS)
//availableTickets: wm.protobuf.UserItem[]
// No session for saving ghost trail (not playing Ghost Battle Mode / Retiring)
}
}
// Encode the response
@ -168,6 +296,9 @@ export default class GameModule extends Module {
// Get the request content
let body = wm.wm.protobuf.LoadGameHistoryRequest.decode(req.body);
// Empty list of time attack records for the player's car
let ta_records : wm.wm.protobuf.LoadGameHistoryResponse.TimeAttackRecord[] = [];
// Get the car info
let car = await prisma.car.findFirst({
where: {
@ -179,26 +310,242 @@ export default class GameModule extends Module {
}
});
// Get Time Attack Record
let taRecords = await gameFunction.getTimeAttackRecord(body);
// Get the car's time attack records
let records = await prisma.timeAttackRecord.findMany({
where: {
carId: body.carId
}
});
// Get Ghost Battle Record
let ghostBattleRecord = await gameFunction.getGhostBattleRecord(body);
// Loop over all of the records
for(let record of records)
{
// This code could probably be done with less DB calls in the future
// Calculate the total rank, total participants for the record
let wholeData = await prisma.timeAttackRecord.findMany({
where: {
course: record.course
},
orderBy: {
time: 'asc'
}
});
// Get the overall number of participants
let wholeParticipants = wholeData.length;
// Whole rank (default: 1)
let wholeRank = 1;
// Loop over all of the participants
for(let row of wholeData)
{
// If the car ID does not match
if (row.carId !== body.carId)
{
// Increment whole rank
wholeRank++;
}
else // Model ID matches
{
// Break the loop
break;
}
}
// Calculate the model rank, model participants for the record
let modelData = await prisma.timeAttackRecord.findMany({
where: {
course: record.course,
model: record.model
},
orderBy: {
time: 'asc'
}
});
// Get the overall number of participants (with the same car model)
let modelParticipants = modelData.length;
// Model rank (default: 1)
let modelRank = 1;
// Loop over all of the participants
for(let row of modelData)
{
// If the car ID does not match
if (row.carId !== body.carId)
{
// Increment whole rank
modelRank++;
}
else // Model ID matches
{
// Break the loop
break;
}
}
// Generate the time attack record object and add it to the list
ta_records.push(wm.wm.protobuf.LoadGameHistoryResponse.TimeAttackRecord.create({
course: record.course,
time: record.time,
tunePower: record.tunePower,
tuneHandling: record.tuneHandling,
wholeParticipants: wholeParticipants,
wholeRank: wholeRank,
modelParticipants: modelParticipants,
modelRank: modelRank
}));
}
// Get user ghost battle mode history data
let ghostHistoryData = await prisma.ghostBattleRecord.findMany({
where: {
carId: body.carId,
},
orderBy: {
playedAt: 'desc'
},
take: 3
});
// Empty list of ghost battle history records for the player's car
let list_ghostHistoryData: wm.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord[] = [];
for(let i=0; i<ghostHistoryData.length; i++){
// User car setting
let carSetings = wm.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord.GhostCarSetting.create({
tunePower: ghostHistoryData![i].tunePower,
tuneHandling: ghostHistoryData![i].tuneHandling,
});
// ----Ghost Opponent 1----
let ghostOpponentCar = await prisma.car.findFirst({
where: {
carId: ghostHistoryData![i].opponent1CarId!
}
});
// If opponent is default ghost or random ghost
if(!(ghostOpponentCar)){
ghostOpponentCar = await prisma.car.findFirst({});
ghostOpponentCar!.name = '';
ghostOpponentCar!.manufacturer = 12;
ghostOpponentCar!.model = 105;
ghostOpponentCar!.visualModel = 130;
ghostOpponentCar!.regionId = 18;
ghostOpponentCar!.country = 'GLB';
}
// Get Opponent 1 tune
ghostOpponentCar!.tunePower = ghostHistoryData![i].opponent1TunePower!;
ghostOpponentCar!.tuneHandling = ghostHistoryData![i].opponent1TuneHandling!;
// Get the Data
let ghostOpponent = wm.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord.GhostBattleRecordCar.create({
car: {
...ghostOpponentCar!
},
result: ghostHistoryData![i].opponent1Result!
});
// ------------------------
// ----Ghost Opponent 2 & 3----
// Empty list of ghost battle records for the player's car
let ghostMob: wm.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord.GhostBattleRecordCar[] = [];
// ----Ghost Opponent 2----
if(ghostHistoryData[i]?.opponent2CarId !== null && ghostHistoryData[i]?.opponent2CarId !== undefined)
{
let ghostOpponentCar2 = await prisma.car.findFirst({
where: {
carId: ghostHistoryData![i].opponent2CarId!
}
});
// If opponent is default ghost or random ghost
if(!(ghostOpponentCar2)){
ghostOpponentCar2 = await prisma.car.findFirst({});
ghostOpponentCar2!.name = '';
ghostOpponentCar2!.manufacturer = 12;
ghostOpponentCar2!.model = 105;
ghostOpponentCar2!.visualModel = 130;
ghostOpponentCar2!.regionId = 18;
ghostOpponentCar2!.country = 'GLB';
}
// Get Opponent 2 tune
ghostOpponentCar2!.tunePower = ghostHistoryData![i].opponent2TunePower!;
ghostOpponentCar2!.tuneHandling = ghostHistoryData![i].opponent2TuneHandling!;
// Get the Data
ghostMob.push(wm.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord.GhostBattleRecordCar.create({
car: {
...ghostOpponentCar2!
},
result: ghostHistoryData![i].opponent2Result!
}));
}
// ------------------------
// ----Ghost Opponent 3----
if(ghostHistoryData[i]?.opponent3CarId !== null && ghostHistoryData[i]?.opponent3CarId !== undefined)
{
let ghostOpponentCar3 = await prisma.car.findFirst({
where: {
carId: ghostHistoryData![i].opponent3CarId!
}
});
// If opponent is default ghost or random ghost
if(!(ghostOpponentCar3)){
ghostOpponentCar3 = await prisma.car.findFirst({});
ghostOpponentCar3!.name = '';
ghostOpponentCar3!.manufacturer = 12;
ghostOpponentCar3!.model = 105;
ghostOpponentCar3!.visualModel = 130;
ghostOpponentCar3!.regionId = 18;
ghostOpponentCar3!.country = 'GLB';
}
// Get Opponent 3 tune
ghostOpponentCar3!.tunePower = ghostHistoryData![i].opponent3TunePower!;
ghostOpponentCar3!.tuneHandling = ghostHistoryData![i].opponent3TuneHandling!;
// Get the Data
ghostMob.push(wm.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord.GhostBattleRecordCar.create({
car: {
...ghostOpponentCar3!
},
result: ghostHistoryData![i].opponent3Result!
}));
}
// ----------------------------
// Push the ghost battle history data
list_ghostHistoryData.push(wm.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord.create({
carSetting: carSetings,
opponent: ghostOpponent,
mobs: ghostMob || null,
area: ghostHistoryData![i].area,
playedAt: ghostHistoryData![i].playedAt,
playedShopName: ghostHistoryData![i].playedShopName
}));
}
// Get current date
let date = Math.floor(new Date().getTime() / 1000);
// Response data
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
// Time Attack Record
taRecords: taRecords.ta_records,
taRankingUpdatedAt: taRecords.date,
// Ghost Battle Record
ghostHistory: ghostBattleRecord.ghostBattle_records,
taRecords: ta_records,
taRankingUpdatedAt: date,
ghostHistory: list_ghostHistoryData,
ghostBattleCount: car!.rgPlayCount,
ghostBattleWinCount: car!.rgWinCount,
// Stamp Sheet
stampSheetCount: car!.stampSheetCount,
stampSheet: car!.stampSheet
}
@ -225,27 +572,5 @@ export default class GameModule extends Module {
// Send the response to the client
common.sendResponse(message, res);
})
// Save Screenshot
app.post('/method/save_screenshot', async (req, res) => {
// Get the request body
let body = wm.wm.protobuf.SaveScreenshotRequest.decode(req.body);
// Perform the save screenshot request for the car
await gameFunction.saveScreenshot(body);
// Response data
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
};
// Encode the response
let message = wm.wm.protobuf.SaveScreenshotResponse.encode(msg);
// Send the response to the client
common.sendResponse(message, res);
})
}
}

View File

@ -1,450 +0,0 @@
import { prisma } from "../..";
import { Config } from "../../config";
import path from "path";
import fs from "fs";
// Import Proto
import { wm } from "../../wmmt/wm.proto";
import * as wmproto from "../../wmmt/wm.proto";
// Import Util
import * as common from "../util/common";
// Get some item
export async function getItem(body: wm.protobuf.SaveGameResultRequest)
{
// Get car item
// Car item reward from the game is available
if(body.earnedItems.length !== 0)
{
console.log('Car Item reward available, continuing ...');
for(let i=0; i<body.earnedItems.length; i++){
await prisma.carItem.create({
data: {
carId: body.carId,
category: body.earnedItems[i].category,
itemId: body.earnedItems[i].itemId,
amount: 1
}
});
}
}
// Get user item
// User item reward from the game is available
if(body.earnedUserItems.length !== 0)
{
console.log('User Item reward available, continuing ...');
for(let i=0; i<body.earnedUserItems.length; i++){
await prisma.userItem.create({
data: {
category: body.earnedUserItems[i].category,
itemId: body.earnedUserItems[i].itemId,
userId: body.car!.userId!,
earnedAt: 0,
type: 0
}
});
}
}
}
// Update the Car
export async function updateCar(body: wm.protobuf.SaveGameResultRequest, car: any)
{
// Check playet at timestamp
let timestamps = 0;
if(body.car?.lastPlayedAt !== undefined && body.car?.lastPlayedAt !== null)
{
if(body.car.lastPlayedAt !== 0)
{
timestamps = body.car.lastPlayedAt;
}
else
{
timestamps = Math.floor(new Date().getTime() / 1000);
}
}
// Check P & H must not more than 34 (fully tuned value)
let tunePower = 0;
let tuneHandling = 0;
let totalTune = body.car!.tunePower + body.car!.tuneHandling;
if(totalTune <= 34)
{
tunePower = body.car!.tunePower;
tuneHandling = body.car!.tuneHandling;
}
// Update car
await prisma.car.update({
where: {
carId: body.carId,
},
data: {
aura: body.car!.aura!,
auraMotif: body.car!.auraMotif!,
odometer: body.odometer,
playCount: body.playCount,
level: body.car!.level!,
title: body.car!.title!,
tunePower: tunePower,
tuneHandling: tuneHandling,
windowSticker: body.car!.windowSticker!,
lastPlayedAt: timestamps,
rgStamp: common.sanitizeInputNotZero(body.rgResult?.rgStamp),
stampSheetCount: common.sanitizeInputNotZero(body.rgResult?.stampSheetCount)
}
})
// Update car settings
await prisma.carSettings.update({
where: {
dbId: car!.carSettingsDbId
},
data: {
...body.setting
}
});
}
// Update Car Order and Saving Tutorial
export async function updateOrderTutorial(body: wm.protobuf.SaveGameResultRequest)
{
// Get User
let user = await prisma.user.findFirst({
where: {
id: body.car!.userId!
}
});
// User Available
if (user)
{
// Get user tutorials
let storedTutorials = user!.tutorials;
// Update any seen tutorials
body.confirmedTutorials.forEach(
(idx) => storedTutorials[idx] = true
);
// Get the order of the user's cars
let carOrder = user?.carOrder;
// Get the index of the selected car
let index = carOrder.indexOf(body.carId);
// Only splice array when item is found
if (index > -1)
{
carOrder.splice(index, 1); // 2nd parameter means remove one item only
}
// Add it back to the front
carOrder.unshift(body.carId);
// Otherwise, just ignore it
// Update the values
await prisma.user.update({
where: {
id: body.car!.userId!
},
data: {
tutorials: storedTutorials,
carOrder: carOrder
}
});
}
}
// Get User's Time Attack Record
export async function getTimeAttackRecord(body: wm.protobuf.LoadGameHistoryRequest)
{
// Empty list of time attack records for the player's car
let ta_records : wmproto.wm.protobuf.LoadGameHistoryResponse.TimeAttackRecord[] = [];
// Get the car's time attack records
let records = await prisma.timeAttackRecord.findMany({
where: {
carId: body.carId
}
});
// Loop over all of the records
for(let record of records)
{
// This code could probably be done with less DB calls in the future
// Calculate the total rank, total participants for the record
let wholeData = await prisma.timeAttackRecord.findMany({
where: {
course: record.course
},
orderBy: {
time: 'asc'
}
});
// Get the overall number of participants
let wholeParticipants = wholeData.length;
// Whole rank (default: 1)
let wholeRank = 1;
// Loop over all of the participants
for(let row of wholeData)
{
// If the car ID does not match
if (row.carId !== body.carId)
{
// Increment whole rank
wholeRank++;
}
else // Model ID matches
{
// Break the loop
break;
}
}
// Calculate the model rank, model participants for the record
let modelData = await prisma.timeAttackRecord.findMany({
where: {
course: record.course,
model: record.model
},
orderBy: {
time: 'asc'
}
});
// Get the overall number of participants (with the same car model)
let modelParticipants = modelData.length;
// Model rank (default: 1)
let modelRank = 1;
// Loop over all of the participants
for(let row of modelData)
{
// If the car ID does not match
if (row.carId !== body.carId)
{
// Increment whole rank
modelRank++;
}
else // Model ID matches
{
// Break the loop
break;
}
}
// Generate the time attack record object and add it to the list
ta_records.push(wmproto.wm.protobuf.LoadGameHistoryResponse.TimeAttackRecord.create({
course: record.course,
time: record.time,
tunePower: record.tunePower,
tuneHandling: record.tuneHandling,
wholeParticipants: wholeParticipants,
wholeRank: wholeRank,
modelParticipants: modelParticipants,
modelRank: modelRank
}));
}
// Get the current date/time (unix epoch)
let date = Math.floor(new Date().getTime() / 1000);
return { ta_records, date }
}
// Get User's Ghost Battle Record
export async function getGhostBattleRecord(body: wm.protobuf.LoadGameHistoryRequest)
{
// Get user ghost battle mode history data
let ghostHistoryData = await prisma.ghostBattleRecord.findMany({
where: {
carId: body.carId,
},
orderBy: {
playedAt: 'desc'
},
take: 3
});
// Empty list of ghost battle history records for the player's car
let ghostBattle_records: wmproto.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord[] = [];
for(let i=0; i<ghostHistoryData.length; i++)
{
// User car setting
let carSetings = wmproto.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord.GhostCarSetting.create({
tunePower: ghostHistoryData![i].tunePower,
tuneHandling: ghostHistoryData![i].tuneHandling,
});
// ----Ghost Opponent 1----
let ghostOpponentCar = await prisma.car.findFirst({
where: {
carId: ghostHistoryData![i].opponent1CarId!
}
});
// If opponent is default ghost or random ghost
if(!(ghostOpponentCar))
{
ghostOpponentCar = await prisma.car.findFirst({});
ghostOpponentCar!.name = '';
ghostOpponentCar!.manufacturer = 12;
ghostOpponentCar!.model = 105;
ghostOpponentCar!.visualModel = 130;
ghostOpponentCar!.regionId = 18;
ghostOpponentCar!.country = 'IDN';
}
// Get Opponent 1 tune
ghostOpponentCar!.tunePower = ghostHistoryData![i].opponent1TunePower!;
ghostOpponentCar!.tuneHandling = ghostHistoryData![i].opponent1TuneHandling!;
// Get the Data
let ghostOpponent = wmproto.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord.GhostBattleRecordCar.create({
car: {
...ghostOpponentCar!
},
result: ghostHistoryData![i].opponent1Result!
});
// ------------------------
// ----Ghost Opponent 2 & 3----
// Empty list of ghost battle records for the player's car
let ghostMob: wmproto.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord.GhostBattleRecordCar[] = [];
// ----Ghost Opponent 2----
if(ghostHistoryData[i]?.opponent2CarId !== null && ghostHistoryData[i]?.opponent2CarId !== undefined)
{
let ghostOpponentCar2 = await prisma.car.findFirst({
where: {
carId: ghostHistoryData![i].opponent2CarId!
}
});
// If opponent is default ghost or random ghost
if(!(ghostOpponentCar2))
{
ghostOpponentCar2 = await prisma.car.findFirst({});
ghostOpponentCar2!.name = '';
ghostOpponentCar2!.manufacturer = 12;
ghostOpponentCar2!.model = 105;
ghostOpponentCar2!.visualModel = 130;
ghostOpponentCar2!.regionId = 18;
ghostOpponentCar2!.country = 'IDN';
}
// Get Opponent 2 tune
ghostOpponentCar2!.tunePower = ghostHistoryData![i].opponent2TunePower!;
ghostOpponentCar2!.tuneHandling = ghostHistoryData![i].opponent2TuneHandling!;
// Get the Data
ghostMob.push(wmproto.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord.GhostBattleRecordCar.create({
car: {
...ghostOpponentCar2!
},
result: ghostHistoryData![i].opponent2Result!
}));
}
// ------------------------
// ----Ghost Opponent 3----
if(ghostHistoryData[i]?.opponent3CarId !== null && ghostHistoryData[i]?.opponent3CarId !== undefined)
{
let ghostOpponentCar3 = await prisma.car.findFirst({
where: {
carId: ghostHistoryData![i].opponent3CarId!
}
});
// If opponent is default ghost or random ghost
if(!(ghostOpponentCar3))
{
ghostOpponentCar3 = await prisma.car.findFirst({});
ghostOpponentCar3!.name = '';
ghostOpponentCar3!.manufacturer = 12;
ghostOpponentCar3!.model = 105;
ghostOpponentCar3!.visualModel = 130;
ghostOpponentCar3!.regionId = 18;
ghostOpponentCar3!.country = 'IDN';
}
// Get Opponent 3 tune
ghostOpponentCar3!.tunePower = ghostHistoryData![i].opponent3TunePower!;
ghostOpponentCar3!.tuneHandling = ghostHistoryData![i].opponent3TuneHandling!;
// Get the Data
ghostMob.push(wmproto.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord.GhostBattleRecordCar.create({
car: {
...ghostOpponentCar3!
},
result: ghostHistoryData![i].opponent3Result!
}));
}
// ----------------------------
// Push the ghost battle history data
ghostBattle_records.push(wmproto.wm.protobuf.LoadGameHistoryResponse.GhostBattleRecord.create({
carSetting: carSetings,
opponent: ghostOpponent,
mobs: ghostMob || null,
area: ghostHistoryData![i].area,
playedAt: ghostHistoryData![i].playedAt,
playedShopName: ghostHistoryData![i].playedShopName
}));
}
return { ghostBattle_records }
}
// Save Screenshot
export async function saveScreenshot(body: wm.protobuf.SaveScreenshotRequest)
{
// Check if screenshot feature enabled or not
let enableScreenshot = Config.getConfig().gameOptions.enableScreenshot || 0;
// Screenshot feature enabled
if(enableScreenshot === 1)
{
let filename: string | undefined = undefined;
filename = `${body.timestamp}_${body.carId}_${body.imageType}.png`;
let dir = path.join('screenshot');
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
// Combine the filename with the save location
let fullname = path.join('screenshot', filename);
// Attempt to write to the file
fs.writeFile(fullname, body.image, (err) => {
if (err)
{
console.log(err);
}
else
{
console.log(`Screenshot saved successfully as '${filename}'`)
}
});
}
}

View File

@ -3,17 +3,18 @@ import { Module } from "module";
import { prisma } from "..";
import { CarPathandTuning } from "@prisma/client";
import Long from "long";
import { Config } from "../config";
// Import Proto
import * as wm from "../wmmt/wm.proto";
import * as wmsrv from "../wmmt/service.proto";
// Import Util
import * as common from "./util/common";
import * as ghostFunctions from "./ghost/functions";
import * as ghost_save_trail from "./ghost/ghost_save_trail";
import * as ghost_trail from "./ghost/ghost_util/ghost_trail";
import * as ghost_area from "./ghost/ghost_util/ghost_area";
import * as common from "../util/common";
import * as ghost_save_trail from "../util/ghost/ghost_save_trail";
import * as ghost_trail from "../util/ghost/ghost_trail";
import * as ghost_area from "../util/ghost/ghost_area";
import * as ghost_default_car from "../util/ghost/ghost_default_car";
export default class GhostModule extends Module {
@ -33,35 +34,152 @@ export default class GhostModule extends Module {
gtWing: true,
lastPlayedPlace: true
}
});
})
// Get Challenged Opponent History
let getStampTargets = await ghostFunctions.getOpponentHistory(body.carId);
let opponentHistory = getStampTargets.opponentHistory;
// Car History
let findChallenger = await prisma.carChallenger.findMany({
where: {
challengerCarId: body.carId
},
orderBy:{
lastPlayedAt: 'desc'
},
take: 10
})
// Get Stamp Target
let getStampTarget = await ghostFunctions.getStampTarget(body.carId);
let stampTarget = getStampTarget.stampTarget;
// Get Challengers
let getChallengers = await ghostFunctions.getChallengers(body.carId);
let challengers = getChallengers.challengers;
let carsHistory: wm.wm.protobuf.Car[] = [];
if(findChallenger.length > 0)
{
for(let i=0; i<findChallenger.length; i++)
{
let car = await prisma.car.findFirst({
where: {
carId: findChallenger[i].carId
},
include:{
gtWing: true,
lastPlayedPlace: true
},
orderBy: {
carId: 'asc'
},
take: 10
});
carsHistory.push(wm.wm.protobuf.Car.create({
...car!
}))
}
}
let carsStamp: wm.wm.protobuf.StampTargetCar[] = [];
let carsChallenger: wm.wm.protobuf.ChallengerCar[] = [];
// Get all of the friend cars for the carId provided
let stampTargets = await prisma.carStampTarget.findMany({
where: {
stampTargetCarId: body.carId,
recommended: true
},
orderBy:{
locked: 'desc'
}
});
if(stampTargets)
{
for(let i=0; i<stampTargets.length; i++)
{
let carTarget = await prisma.car.findFirst({
where:{
carId: stampTargets[i].carId
},
include:{
gtWing: true,
lastPlayedPlace: true
}
})
carsStamp.push(
wm.wm.protobuf.StampTargetCar.create({
car: carTarget!,
returnCount: stampTargets[i].returnCount,
locked: stampTargets[i].locked,
})
);
}
}
// Get all of the challenger car for the carId provided except beated car
let checkBeatedCar = await prisma.carStampTarget.findMany({
where: {
stampTargetCarId: body.carId,
recommended: false
},
orderBy:{
carId: 'asc'
}
});
let arrChallengerCarId = [];
for(let i=0; i<checkBeatedCar.length; i++)
{
arrChallengerCarId.push(checkBeatedCar[i].carId);
}
let challengers = await prisma.carChallenger.findMany({
where: {
carId: body.carId,
NOT: {
challengerCarId: { in: arrChallengerCarId }, // Except beated challenger id
},
}
});
if(challengers)
{
for(let i=0; i<challengers.length; i++)
{
let carTarget = await prisma.car.findFirst({
where:{
carId: challengers[i].challengerCarId
},
include:{
gtWing: true,
lastPlayedPlace: true
}
})
let result = 0;
if(challengers[i].result > 0)
{
result = -Math.abs(challengers[i].result);
}
else{
result = Math.abs(challengers[i].result);
}
carsChallenger.push(
wm.wm.protobuf.ChallengerCar.create({
car: carTarget!,
stamp: challengers[i].stamp,
result: result,
area: challengers[i].area
})
);
}
}
// Response data
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
// Challengers
challengers: challengers || null,
stampTargetCars: stampTarget || null,
// History
history: opponentHistory || null,
// Stamp
stampSheetCount: car?.stampSheetCount || 0,
stampTargetCars: carsStamp || null,
challengers: carsChallenger || null,
stampSheetCount: car!.stampSheetCount,
stampSheet: car?.stampSheet || null,
stampReturnStats: car?.stampSheet || null,
history: carsHistory || null,
promotedToBuddy: false
};
// Encode the response
@ -76,21 +194,92 @@ export default class GhostModule extends Module {
app.post('/method/load_stamp_target', async (req, res) => {
// Get the request body for the load stamp target request
let body = wm.wm.protobuf.LoadStampTargetRequest.decode(req.body);
let body = wm.wm.protobuf.LoadStampTargetRequest.decode(req.body);
// Get Stamp Target
let getStampTarget = await ghostFunctions.getStampTarget(body.carId);
let stampTarget = getStampTarget.stampTarget;
let carsStamp: wm.wm.protobuf.StampTargetCar[] = [];
let carsChallenger: wm.wm.protobuf.ChallengerCar[] = [];
// Get Challengers
let getChallengers = await ghostFunctions.getChallengers(body.carId);
let challengers = getChallengers.challengers;
// Get all of the friend cars for the carId provided
let stampTargets = await prisma.carStampTarget.findMany({
where: {
stampTargetCarId: body.carId,
recommended: true
},
orderBy:{
locked: 'asc'
}
});
if(stampTargets)
{
for(let i=0; i<stampTargets.length; i++)
{
let carTarget = await prisma.car.findFirst({
where:{
carId: stampTargets[i].carId
},
include:{
gtWing: true,
lastPlayedPlace: true
}
})
carsStamp.push(
wm.wm.protobuf.StampTargetCar.create({
car: carTarget!,
returnCount: stampTargets[i].returnCount,
locked: stampTargets[i].locked,
})
);
}
}
// Get all of the friend cars for the carId provided
let challengers = await prisma.carChallenger.findMany({
where: {
carId: body.carId
}
});
if(stampTargets)
{
for(let i=0; i<challengers.length; i++)
{
let carTarget = await prisma.car.findFirst({
where:{
carId: challengers[i].challengerCarId
},
include:{
gtWing: true,
lastPlayedPlace: true
}
})
let result = 0;
if(challengers[i].result > 0)
{
result = -Math.abs(challengers[i].result);
}
else{
result = Math.abs(challengers[i].result);
}
carsChallenger.push(
wm.wm.protobuf.ChallengerCar.create({
car: carTarget!,
stamp: challengers[i].stamp,
result: result,
area: challengers[i].area
})
);
}
}
// Response data
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
cars: stampTarget,
challengers: challengers
cars: carsStamp,
challengers: carsChallenger
};
// Encode the response
@ -101,7 +290,7 @@ export default class GhostModule extends Module {
})
// Search Cars by Level
// Ghost Mode
app.post('/method/search_cars_by_level', async (req, res) => {
// Get the request body for the search cars by level request
@ -137,36 +326,189 @@ export default class GhostModule extends Module {
});
}
// Randomizing the starting ramp and path based on selected area
let rampVal = 0;
let pathVal = 0;
// Get the ramp and path id
let ghost_areas = await ghost_area.GhostArea(body.area);
// Set the value
let rampVal = ghost_areas.rampVal;
let pathVal = ghost_areas.pathVal;
rampVal = ghost_areas.rampVal;
pathVal = ghost_areas.pathVal;
// Get Ghost Car
let getGhostCar = await ghostFunctions.getGhostCar(car, body.area, rampVal, pathVal);
let lists_ghostcar = getGhostCar.lists_ghostcar;
// Empty list of ghost car records
let lists_ghostcar: wm.wm.protobuf.GhostCar[] = [];
let arr = [];
let maxNumber = 0;
// If all user car data available is more than 10 for certain level
if(car.length > 10)
{
maxNumber = 10 // Limit to 10 (game default)
}
// If no more than 10
else
{
maxNumber = car.length;
}
// Choose the user's car data randomly to appear
while(arr.length < maxNumber)
{
// Pick random car Id
let randomNumber: number = Math.floor(Math.random() * car.length);
if(arr.indexOf(randomNumber) === -1){
// Push current number to array
arr.push(randomNumber);
// Check if ghost trail for certain car is available
let ghost_trails = await prisma.ghostTrail.findFirst({
where: {
carId: car[randomNumber].carId,
area: body.area,
crownBattle: false
},
orderBy: {
playedAt: 'desc'
}
});
// If regionId is 0 or not set, game will crash after defeating the ghost
if(car[randomNumber]!.regionId === 0)
{
let randomRegionId = Math.floor(Math.random() * 47) + 1;
car[randomNumber].regionId = randomRegionId;
}
// Push user's car data without ghost trail
if(!(ghost_trails))
{
lists_ghostcar.push(wm.wm.protobuf.GhostCar.create({
car: car[randomNumber]
}));
}
// Push user's car data with ghost trail
else
{
// Set the tunePower used when playing certain area
car[randomNumber].tunePower = ghost_trails!.tunePower;
// Set the tuneHandling used when playing certain area
car[randomNumber].tuneHandling = ghost_trails!.tuneHandling;
// Push data to Ghost car proto
lists_ghostcar.push(wm.wm.protobuf.GhostCar.create({
car: car[randomNumber],
nonhuman: false,
type: wm.wm.protobuf.GhostType.GHOST_NORMAL,
trailId: ghost_trails!.dbId!
}));
}
}
}
// Check again if car list for that selected region is available of not
if(body.regionId !== null && body.regionId !== undefined && body.regionId !== 0 && car.length < 1)
if(body.regionId !== null && body.regionId !== undefined && body.regionId !== 0)
{
let checkGhostSearchByRegion = await ghostFunctions.checkGhostSearchByRegion(body.ghostLevel, body.regionId);
lists_ghostcar = checkGhostSearchByRegion.lists_ghostcar;
if(car.length < 1)
{
// Get current date
let date = Math.floor(new Date().getTime() / 1000);
let playedPlace = wm.wm.protobuf.Place.create({
placeId: Config.getConfig().placeId,
regionId: Config.getConfig().regionId,
shopName: Config.getConfig().shopName,
country: Config.getConfig().country
});
let tunePowerDefault = 0
let tuneHandlingDefault = 0;
if(body.ghostLevel === 1)
{
tunePowerDefault = 1;
tuneHandlingDefault = 4;
}
else if(body.ghostLevel === 2)
{
tunePowerDefault = 5;
tuneHandlingDefault = 5;
}
else if(body.ghostLevel === 3)
{
tunePowerDefault = 8;
tuneHandlingDefault = 7;
}
else if(body.ghostLevel === 4)
{
tunePowerDefault = 10;
tuneHandlingDefault = 10;
}
else if(body.ghostLevel === 5)
{
tunePowerDefault = 15;
tuneHandlingDefault = 10;
}
else if(body.ghostLevel === 6)
{
tunePowerDefault = 18;
tuneHandlingDefault = 10;
}
else if(body.ghostLevel === 7)
{
tunePowerDefault = 20;
tuneHandlingDefault = 10;
}
else if(body.ghostLevel === 8)
{
tunePowerDefault = 21;
tuneHandlingDefault = 10;
}
else if(body.ghostLevel === 9)
{
tunePowerDefault = 22;
tuneHandlingDefault = 10;
}
else if(body.ghostLevel === 10)
{
tunePowerDefault = 24;
tuneHandlingDefault = 10;
}
else if(body.ghostLevel === 11)
{
tunePowerDefault = 24;
tuneHandlingDefault = 24;
}
// Generate default S660 car data
let ghost_default_cars = await ghost_default_car.DefaultGhostCarHonda();
// Push data to Ghost car proto
lists_ghostcar.push(wm.wm.protobuf.GhostCar.create({
car: {
...ghost_default_cars.cars,
regionId: body.regionId,
tunePower: tunePowerDefault,
tuneHandling: tuneHandlingDefault,
lastPlayedAt: date,
lastPlayedPlace: playedPlace
},
nonhuman: true,
type: wm.wm.protobuf.GhostType.GHOST_DEFAULT,
}))
}
// else{} have car list
}
// Response data
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
// Area Value
ramp: rampVal,
path: pathVal,
// Ghost Car List
ghosts: lists_ghostcar,
// Ghost Selection Method
selectionMethod: Number(wm.wm.protobuf.GhostSelectionMethod.GHOST_SELECT_BY_LEVEL)
};
@ -178,6 +520,298 @@ export default class GhostModule extends Module {
})
app.post('/method/search_cars', async (req, res) => {
// Get the request body for the load ghost drive data request
let body = wm.wm.protobuf.SearchCarsRequest.decode(req.body);
// Find ghost car
let car;
switch(body.selectionMethod)
{
// GHOST_SELECT_BY_MANUFACTURER = 16
case wm.wm.protobuf.GhostSelectionMethod.GHOST_SELECT_BY_MANUFACTURER:
{
let selectManufacturer = body.selectManufacturer;
car = await prisma.car.findMany({
where:{
manufacturer: selectManufacturer
},
include:{
gtWing: true,
lastPlayedPlace: true
}
});
break;
}
// GHOST_SELECT_BY_OTHER_MANUFACTURER = 17
case wm.wm.protobuf.GhostSelectionMethod.GHOST_SELECT_BY_OTHER_MANUFACTURER:
{
let selectManufacturer = body.selectManufacturer;
car = await prisma.car.findMany({
where:{
manufacturer: selectManufacturer
},
include:{
gtWing: true,
lastPlayedPlace: true
}
});
break;
}
// GHOST_SELECT_BY_REGION_MANUFACTURER = 20
case wm.wm.protobuf.GhostSelectionMethod.GHOST_SELECT_BY_REGION_MANUFACTURER:
{
let selectManufacturer = body.selectManufacturer;
car = await prisma.car.findMany({
where:{
manufacturer: selectManufacturer
},
include:{
gtWing: true,
lastPlayedPlace: true
}
});
break;
}
default:
{
car = await prisma.car.findMany({
include:{
gtWing: true,
lastPlayedPlace: true
}
});
break;
}
}
// Randomizing the starting ramp and path based on selected area
let rampVal = 0;
let pathVal = 0;
// Get the ramp and path id
let ghost_areas = await ghost_area.GhostArea(body.area);
// Set the value
rampVal = ghost_areas.rampVal;
pathVal = ghost_areas.pathVal;
// Empty list of ghost car records
let lists_ghostcar: wm.wm.protobuf.GhostCar[] = [];
let arr = [];
let maxNumber = 0;
if(car.length === 0)
{
if(body.selectionMethod === wm.wm.protobuf.GhostSelectionMethod.GHOST_SELECT_BY_MANUFACTURER ||
body.selectionMethod === wm.wm.protobuf.GhostSelectionMethod.GHOST_SELECT_BY_OTHER_MANUFACTURER ||
body.selectionMethod === wm.wm.protobuf.GhostSelectionMethod.GHOST_SELECT_BY_REGION_MANUFACTURER)
{
// Default car here
let ghost_default_cars: any;
if(body.selectManufacturer === 0) // BMW (Blood, Memory, Wonichan Moe)
{
ghost_default_cars = await ghost_default_car.DefaultGhostCarBMW();
}
else if(body.selectManufacturer === 1) // CHEVROLET
{
ghost_default_cars = await ghost_default_car.DefaultGhostCarChevrolet();
}
else if(body.selectManufacturer === 2) // MAZDA
{
ghost_default_cars = await ghost_default_car.DefaultGhostCarMazda();
}
else if(body.selectManufacturer === 3) // MERCEDES BENZ
{
// TODO: default car here
ghost_default_cars = await ghost_default_car.DefaultGhostCarMercedes();
}
else if(body.selectManufacturer === 4) // MITSUBISHI
{
// TODO: default car here
ghost_default_cars = await ghost_default_car.DefaultGhostCarMitsubishi();
}
else if(body.selectManufacturer === 5) // NISSAN
{
ghost_default_cars = await ghost_default_car.DefaultGhostCarNissan();
}
/*else if(body.selectManufacturer === 6) // ???
{
// TODO: default car here
ghost_default_cars = await ghost_default_car.DefaultGhostCar???();
}*/
else if(body.selectManufacturer === 7) // SUBARU
{
// TODO: default car here
ghost_default_cars = await ghost_default_car.DefaultGhostCarSubaru();
}
else if(body.selectManufacturer === 8) // TOYOTA
{
ghost_default_cars = await ghost_default_car.DefaultGhostCarToyota();
}
else if(body.selectManufacturer === 9) // AUDI
{
// TODO: default car here
ghost_default_cars = await ghost_default_car.DefaultGhostCarAudi();
}
else if(body.selectManufacturer === 10) // DODGE
{
// TODO: default car here
ghost_default_cars = await ghost_default_car.DefaultGhostCarDodge();
}
else if(body.selectManufacturer === 11) // LAMBORGHINI
{
ghost_default_cars = await ghost_default_car.DefaultGhostCarLamborghini();
}
else if(body.selectManufacturer === 12) // HONDA
{
ghost_default_cars = await ghost_default_car.DefaultGhostCarHonda();
}
else if(body.selectManufacturer === 13) // ACURA
{
ghost_default_cars = await ghost_default_car.DefaultGhostCarAcura();
}
else if(body.selectManufacturer === 14) // PORSCHE
{
ghost_default_cars = await ghost_default_car.DefaultGhostCarPorsche();
}
else // OTHER MAYBE?
{
ghost_default_cars = await ghost_default_car.DefaultGhostCarHonda();
}
// Get current date
let date = Math.floor(new Date().getTime() / 1000);
let playedPlace = wm.wm.protobuf.Place.create({
placeId: Config.getConfig().placeId,
regionId: Config.getConfig().regionId,
shopName: Config.getConfig().shopName,
country: Config.getConfig().country
});
for(let i=0; i<3; i++)
{
lists_ghostcar.push(wm.wm.protobuf.GhostCar.create({
car: {
...ghost_default_cars.cars,
carId: 999999999-i, // prevent dupilcate id
lastPlayedAt: date,
lastPlayedPlace: playedPlace
},
area: body.area,
ramp: rampVal,
path: pathVal,
nonhuman: true,
}))
}
}
}
else
{
// If all user car data available is more than 10 for certain level
if(car.length > 10)
{
maxNumber = 10 // Limit to 10 (game default)
}
// If no more than 10
else
{
maxNumber = car.length;
}
// Choose the user's car data randomly to appear
while(arr.length < maxNumber)
{
// Pick random car Id
let randomNumber: number = Math.floor(Math.random() * car.length);
if(arr.indexOf(randomNumber) === -1)
{
// Push current number to array
arr.push(randomNumber);
// Check if ghost trail for certain car is available
let ghost_trails = await prisma.ghostTrail.findFirst({
where: {
carId: car[randomNumber].carId,
area: body.area,
crownBattle: false
},
orderBy: {
playedAt: 'desc'
}
});
// If regionId is 0 or not set, game will crash after defeating the ghost
if(car[randomNumber]!.regionId === 0)
{
let randomRegionId = Math.floor(Math.random() * 47) + 1;
car[randomNumber].regionId = randomRegionId;
}
// Push user's car data without ghost trail
if(!(ghost_trails))
{
lists_ghostcar.push(wm.wm.protobuf.GhostCar.create({
car: car[randomNumber],
area: body.area,
ramp: rampVal,
path: pathVal,
nonhuman: true,
type: wm.wm.protobuf.GhostType.GHOST_DEFAULT,
}));
}
// Push user's car data with ghost trail
else
{
// Set the tunePower used when playing certain area
car[randomNumber].tunePower = ghost_trails!.tunePower;
// Set the tuneHandling used when playing certain area
car[randomNumber].tuneHandling = ghost_trails!.tuneHandling;
// Push data to Ghost car proto
lists_ghostcar.push(wm.wm.protobuf.GhostCar.create({
car: car[randomNumber],
area: body.area,
ramp: rampVal,
path: pathVal,
nonhuman: false,
type: wm.wm.protobuf.GhostType.GHOST_NORMAL,
trailId: ghost_trails!.dbId!
}));
}
}
}
}
// Response data
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
ramp: rampVal,
path: pathVal,
ghosts: lists_ghostcar,
selectionMethod: wm.wm.protobuf.PathSelectionMethod.PATH_NORMAL
};
// Encode the response
let message = wm.wm.protobuf.SearchCarsResponse.encode(msg);
// Send the response to the client
common.sendResponse(message, res);
})
// Load Normal Ghost Trail data
app.post('/method/load_ghost_drive_data', async (req, res) => {
@ -197,7 +831,7 @@ export default class GhostModule extends Module {
let ghost_trails = await prisma.ghostTrail.findFirst({
where: {
carId: body.carTunings[i].carId!,
path: body.path,
path: path,
},
orderBy: {
playedAt: 'desc'
@ -207,8 +841,7 @@ export default class GhostModule extends Module {
// ---Get the user and opponent ghost trail data---
let ghostType: number = wm.wm.protobuf.GhostType.GHOST_NORMAL;
let lists_binarydriveData;
if(ghost_trails?.driveData !== null && ghost_trails?.driveData !== undefined)
{
if(ghost_trails?.driveData !== null && ghost_trails?.driveData !== undefined){
lists_binarydriveData = wm.wm.protobuf.BinaryData.create({
data: ghost_trails!.driveData!,
mergeSerial: ghost_trails!.driveDMergeSerial!
@ -216,8 +849,7 @@ export default class GhostModule extends Module {
}
let lists_binaryByArea
if(ghost_trails?.trendBinaryByArea !== null && ghost_trails?.trendBinaryByArea !== undefined)
{
if(ghost_trails?.trendBinaryByArea !== null && ghost_trails?.trendBinaryByArea !== undefined){
lists_binaryByArea = wm.wm.protobuf.BinaryData.create({
data: ghost_trails!.trendBinaryByArea!,
mergeSerial: ghost_trails!.byAreaMergeSerial!
@ -225,8 +857,7 @@ export default class GhostModule extends Module {
}
let lists_binaryByCar
if(ghost_trails?.trendBinaryByCar !== null && ghost_trails?.trendBinaryByCar !== undefined)
{
if(ghost_trails?.trendBinaryByCar !== null && ghost_trails?.trendBinaryByCar !== undefined){
lists_binaryByCar = wm.wm.protobuf.BinaryData.create({
data: ghost_trails!.trendBinaryByCar!,
mergeSerial: ghost_trails!.byCarMergeSerial!
@ -234,8 +865,7 @@ export default class GhostModule extends Module {
}
let lists_binaryByUser
if(ghost_trails?.trendBinaryByUser !== null && ghost_trails?.trendBinaryByUser !== undefined)
{
if(ghost_trails?.trendBinaryByUser !== null && ghost_trails?.trendBinaryByUser !== undefined){
lists_binaryByUser = wm.wm.protobuf.BinaryData.create({
data: ghost_trails!.trendBinaryByUser!,
mergeSerial: ghost_trails!.byUserMergeSerial!
@ -258,7 +888,6 @@ export default class GhostModule extends Module {
// Response data
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
path: path,
data: lists_ghostcar
};
@ -286,7 +915,6 @@ export default class GhostModule extends Module {
actualSessionId = common.getBigIntFromLong(body.ghostSessionId);
}
// -----------------------------------------------------------------------------------------
// OCM game mode session id
if(actualSessionId > 100 && actualSessionId < 201)
{
@ -317,7 +945,6 @@ export default class GhostModule extends Module {
await ghost_save_trail.savePathAndTuning(body);
}
}
// -----------------------------------------------------------------------------------------
// Response data
let msg = {
@ -351,8 +978,6 @@ export default class GhostModule extends Module {
// Query parameter from OCM Battle available
if(pTrailId)
{
console.log('Requesting OCM Ghost Trail');
// Get the trail data
let ghost_trails = await ghost_trail.getOCMGhostTrail(pCarId, pTrailId);
@ -365,8 +990,6 @@ export default class GhostModule extends Module {
// Query parameter from Crown Ghost Battle available
else
{
console.log('Requesting Crown Ghost Trail');
// Get the crown trail data
let ghost_trails = await ghost_trail.getCrownGhostTrail(pCarId, pArea);

View File

@ -1,398 +0,0 @@
import { Config } from "../../config";
import { prisma } from "../..";
// Import Proto
import * as wmproto from "../../wmmt/wm.proto";
// Get Challenged Opponent History
export async function getOpponentHistory(carId: number)
{
// Car History
let findChallenger = await prisma.carChallenger.findMany({
where: {
challengerCarId: carId
},
orderBy:{
lastPlayedAt: 'desc'
},
take: 20
});
let opponentHistory: wmproto.wm.protobuf.Car[] = [];
let inserted = 0;
if(findChallenger.length > 0)
{
for(let i=0; i<findChallenger.length; i++)
{
let car = await prisma.car.findFirst({
where: {
carId: findChallenger[i].carId
},
include:{
gtWing: true,
lastPlayedPlace: true
}
});
if(car)
{
// Error handling if regionId is below 1 or above 47
if(car!.regionId < 1 || car!.regionId > 47)
{
car!.regionId = Math.floor(Math.random() * 10) + 10;
}
opponentHistory.push(wmproto.wm.protobuf.Car.create({
...car!
}));
inserted++;
}
if(inserted > 10)
{
break;
}
}
}
return { opponentHistory }
}
// Get Stamp Target
export async function getStampTarget(carId: number)
{
// Get all of the friend cars for the carId provided
let getStampTargets = await prisma.carStampTarget.findMany({
where: {
stampTargetCarId: carId,
recommended: true
},
orderBy:{
locked: 'desc'
},
take: 10
});
let stampTarget: wmproto.wm.protobuf.StampTargetCar[] = [];
if(getStampTargets)
{
for(let i=0; i<getStampTargets.length; i++)
{
let carTarget = await prisma.car.findFirst({
where:{
carId: getStampTargets[i].carId
},
include:{
gtWing: true,
lastPlayedPlace: true
}
});
// Error handling if regionId is below 1 or above 47
if(carTarget!.regionId < 1 || carTarget!.regionId > 47)
{
carTarget!.regionId = Math.floor(Math.random() * 10) + 10;
}
stampTarget.push(
wmproto.wm.protobuf.StampTargetCar.create({
car: carTarget!,
returnCount: getStampTargets[i].returnCount,
locked: getStampTargets[i].locked,
recommended: getStampTargets[i].recommended
})
);
}
}
return { stampTarget }
}
// Get Challengers
export async function getChallengers(carId: number)
{
// Get all of the challenger car for the carId provided except beated car
let checkBeatedCar = await prisma.carStampTarget.findMany({
where: {
stampTargetCarId: carId,
recommended: false
},
orderBy:{
carId: 'asc'
}
});
let challengers: wmproto.wm.protobuf.ChallengerCar[] = [];
let arrChallengerCarId = [];
// Push beated carId to array
for(let i=0; i<checkBeatedCar.length; i++)
{
arrChallengerCarId.push(checkBeatedCar[i].carId);
}
// Find Opponent Challengers except beated car
let getChallengers = await prisma.carChallenger.findMany({
where: {
carId: carId,
NOT: {
challengerCarId: { in: arrChallengerCarId }, // Except beated challenger id
}
},
take: 10
});
if(getChallengers)
{
for(let i=0; i<getChallengers.length; i++)
{
let carTarget = await prisma.car.findFirst({
where:{
carId: getChallengers[i].challengerCarId
},
include:{
gtWing: true,
lastPlayedPlace: true
}
})
let result = 0;
if(getChallengers[i].result > 0)
{
result = -Math.abs(getChallengers[i].result);
}
else{
result = Math.abs(getChallengers[i].result);
}
// Error handling if regionId is below 1 or above 47
if(carTarget!.regionId < 1 || carTarget!.regionId > 47)
{
carTarget!.regionId = Math.floor(Math.random() * 10) + 10;
}
challengers.push(
wmproto.wm.protobuf.ChallengerCar.create({
car: carTarget!,
stamp: getChallengers[i].stamp,
result: result,
area: getChallengers[i].area
})
);
}
}
return { challengers }
}
// Get Ghost Car
export async function getGhostCar(car: any, area: number, ramp: number, path: number)
{
// Empty list of ghost car records
let lists_ghostcar: wmproto.wm.protobuf.GhostCar[] = [];
let arr = [];
let maxNumber = 0;
// If all user car data available is more than 10 for certain level
if(car.length > 10)
{
maxNumber = 10 // Limit to 10 (game default)
}
// If no more than 10
else
{
maxNumber = car.length;
}
// Choose the user's car data randomly to appear
while(arr.length < maxNumber)
{
// Randomize pick
let random: number = 1;
// Randomize it 5 times
for(let i=0; i<5; i++)
{
random = Math.floor(Math.random() * car.length);
}
// Try randomize it again if it's 1
if(random === 1)
{
random = Math.floor(Math.random() * car.length);
}
if(arr.indexOf(random) === -1)
{
// Push current number to array
arr.push(random);
// Check if ghost trail for certain car is available
let ghost_trails = await prisma.ghostTrail.findFirst({
where: {
carId: car[random].carId,
area: area,
crownBattle: false
},
orderBy: {
playedAt: 'desc'
}
});
// Error handling if regionId is below 1 or above 47
if(car!.regionId < 1 || car!.regionId > 47)
{
car!.regionId = Math.floor(Math.random() * 10) + 10;
}
// Push user's car data without ghost trail
if(!(ghost_trails))
{
lists_ghostcar.push(wmproto.wm.protobuf.GhostCar.create({
car: car[random]
}));
}
// Push user's car data with ghost trail
else
{
// Set the tunePower used when playing certain area
car[random].tunePower = ghost_trails!.tunePower;
// Set the tuneHandling used when playing certain area
car[random].tuneHandling = ghost_trails!.tuneHandling;
// Push data to Ghost car proto
lists_ghostcar.push(wmproto.wm.protobuf.GhostCar.create({
car: car[random],
nonhuman: false,
type: wmproto.wm.protobuf.GhostType.GHOST_NORMAL,
trailId: ghost_trails!.dbId!
}));
}
}
}
return { lists_ghostcar }
}
// Check Ghost Car when using Search by Region
export async function checkGhostSearchByRegion(ghostLevel: number, regionId: number)
{
// Get current date
let date = Math.floor(new Date().getTime() / 1000);
let playedPlace = wmproto.wm.protobuf.Place.create({
placeId: Config.getConfig().placeId,
regionId: Config.getConfig().regionId,
shopName: Config.getConfig().shopName,
country: Config.getConfig().country
});
let tunePowerDefault = 0
let tuneHandlingDefault = 0;
if(ghostLevel === 1)
{
tunePowerDefault = 1;
tuneHandlingDefault = 4;
}
else if(ghostLevel === 2)
{
tunePowerDefault = 5;
tuneHandlingDefault = 5;
}
else if(ghostLevel === 3)
{
tunePowerDefault = 8;
tuneHandlingDefault = 7;
}
else if(ghostLevel === 4)
{
tunePowerDefault = 10;
tuneHandlingDefault = 10;
}
else if(ghostLevel === 5)
{
tunePowerDefault = 15;
tuneHandlingDefault = 10;
}
else if(ghostLevel === 6)
{
tunePowerDefault = 18;
tuneHandlingDefault = 10;
}
else if(ghostLevel === 7)
{
tunePowerDefault = 20;
tuneHandlingDefault = 10;
}
else if(ghostLevel === 8)
{
tunePowerDefault = 21;
tuneHandlingDefault = 10;
}
else if(ghostLevel === 9)
{
tunePowerDefault = 22;
tuneHandlingDefault = 10;
}
else if(ghostLevel === 10)
{
tunePowerDefault = 24;
tuneHandlingDefault = 10;
}
else if(ghostLevel === 11)
{
tunePowerDefault = 24;
tuneHandlingDefault = 24;
}
// Generate default S660 car data
let car = wmproto.wm.protobuf.Car.create({
carId: 999999999, // Don't change this
name: '',
regionId: regionId, // IDN (福井)
manufacturer: 12, // HONDA
model: 105, // S660 [JW5]
visualModel: 130, // S660 [JW5]
defaultColor: 0,
customColor: 0,
wheel: 20,
wheelColor: 0,
aero: 0,
bonnet: 0,
wing: 0,
mirror: 0,
neon: 0,
trunk: 0,
plate: 0,
plateColor: 0,
plateNumber: 0,
tunePower: tunePowerDefault,
tuneHandling: tuneHandlingDefault,
rivalMarker: 32,
aura: 551,
windowSticker: true,
windowStickerString: '',
windowStickerFont: 0,
title: 'No Ghost for this Region',
level: 65, // SSSSS
lastPlayedAt: date,
country: 'JPN',
lastPlayedPlace: playedPlace
});
// Push data to Ghost car proto
let lists_ghostcar: wmproto.wm.protobuf.GhostCar[] = [];
lists_ghostcar.push(wmproto.wm.protobuf.GhostCar.create({
car: car,
nonhuman: true,
type: wmproto.wm.protobuf.GhostType.GHOST_DEFAULT,
}));
return { lists_ghostcar }
}

View File

@ -1,391 +0,0 @@
// Import Proto
import { prisma } from "../..";
import { Config } from "../../config";
import { wm } from "../../wmmt/wm.proto";
// Import Util
import * as common from "../util/common";
import * as ghost_stamp from "./ghost_stamp";
import * as ghost_get_area_from_path from "./ghost_util/ghost_get_area_from_path";
// Save ghost history battle
export async function saveGhostHistory(body: wm.protobuf.SaveGameResultRequest)
{
console.log('Saving Ghost Battle History');
let updateNewTrail: boolean = true;
let saveExGhostHistory: any = {};
// Get the car result for the car
let car = body?.car;
if(car)
{
saveExGhostHistory = {
carId: common.sanitizeInput(car.carId),
tunePower: common.sanitizeInput(car.tunePower),
tuneHandling: common.sanitizeInput(car.tuneHandling),
playedAt: common.sanitizeInputNotZero(body.playedAt),
playedShopName: Config.getConfig().shopName
}
}
// Get the rg result for the car
let rgResult = body?.rgResult;
if(rgResult)
{
if(rgResult.opponents)
{
// Get how many opponents available
for(let i=0; i<rgResult.opponents.length; i++)
{
// First opponent data
if(i == 0)
{
// Get first opponent carId
saveExGhostHistory.opponent1CarId = rgResult.opponents[0].carId;
// Get first opponent tunePower
saveExGhostHistory.opponent1TunePower = rgResult.opponents[0].tunePower;
// Get first opponent tunePower
saveExGhostHistory.opponent1TuneHandling = rgResult.opponents[0].tuneHandling;
// Get the advantage distance between first opponent and user
saveExGhostHistory.opponent1Result = rgResult.opponents[0].result;
}
// Second opponent data
else if(i == 1)
{
// Get second opponent carId
saveExGhostHistory.opponent2CarId = rgResult.opponents[1].carId;
// Get second opponent tunePower
saveExGhostHistory.opponent2TunePower = rgResult.opponents[1].tunePower;
// Get second opponent tuneHandling
saveExGhostHistory.opponent2TuneHandling = rgResult.opponents[1].tuneHandling;
// Get the advantage distance between second opponent and user
saveExGhostHistory.opponent2Result = rgResult.opponents[1].result;
}
// Third opponent data
else if(i == 2)
{
// Get third opponent carId
saveExGhostHistory.opponent3CarId = rgResult.opponents[2].carId;
// Get third opponent tunePower
saveExGhostHistory.opponent3TunePower = rgResult.opponents[2].tunePower;
// Get third opponent tuneHandling
saveExGhostHistory.opponent3TuneHandling = rgResult.opponents[2].tuneHandling;
// Get the advantage distance between third opponent and user
saveExGhostHistory.opponent3Result = rgResult.opponents[2].result;
}
}
}
// Get played Area
if(common.sanitizeInput(rgResult.path))
{
let getArea = await ghost_get_area_from_path.getArea(rgResult.path);
saveExGhostHistory.area = getArea.area
}
}
await prisma.ghostBattleRecord.create({
data: saveExGhostHistory
});
// Sending stamp to opponents
await ghost_stamp.sendStamp(body);
// Return the value to 'BASE_PATH/src/util/games/ghost.ts'
return { updateNewTrail }
}
export async function saveOCMGhostHistory(body: wm.protobuf.SaveGameResultRequest)
{
let updateNewTrail: boolean = true;
let saveExGhostHistory: any = {};
// Get the car result for the car
let car = body?.car;
if(car)
{
saveExGhostHistory = {
carId: common.sanitizeInput(car.carId),
tunePower: common.sanitizeInput(car.tunePower),
tuneHandling: common.sanitizeInput(car.tuneHandling),
playedAt: common.sanitizeInputNotZero(body.playedAt),
playedShopName: Config.getConfig().shopName
}
}
// Get the rg result for the car
let rgResult = body?.rgResult;
if(rgResult)
{
if(rgResult.opponents)
{
// Get the advantage distance between first opponent and user
saveExGhostHistory.result = rgResult.opponents[0].result;
}
// Get area
if(common.sanitizeInput(rgResult.path))
{
let getArea = await ghost_get_area_from_path.getArea(rgResult.path);
saveExGhostHistory.area = getArea.area
}
}
// Get current date
let date = Math.floor(new Date().getTime() / 1000);
// Get currently active OCM event
let ocmEventDate = await prisma.oCMEvent.findFirst({
where: {
// qualifyingPeriodStartAt is less than current date
qualifyingPeriodStartAt: { lte: date },
// competitionEndAt is greater than current date
competitionEndAt: { gte: date },
},
orderBy:{
competitionId: 'desc'
}
});
// ----------Get available OCM Record (Qualifying or Main Draw)----------
// Current date is OCM main draw
let countGBR;
if(ocmEventDate!.competitionStartAt < date && ocmEventDate!.competitionCloseAt > date)
{
// Set OCM Main draw value to true
saveExGhostHistory.ocmMainDraw = true
// Get the user's available OCM Battle Record data
countGBR = await prisma.oCMTally.findFirst({
where:{
carId: saveExGhostHistory.carId,
competitionId: ocmEventDate!.competitionId,
}
});
}
// Current date is OCM qualifying day
else
{
// Set OCM Main draw value to false
saveExGhostHistory.ocmMainDraw = false
// Get the user's available OCM Battle Record data
countGBR = await prisma.oCMGhostBattleRecord.findFirst({
where:{
carId: saveExGhostHistory.carId,
ocmMainDraw: saveExGhostHistory.ocmMainDraw,
competitionId: ocmEventDate!.competitionId,
periodId: 0
}
});
}
// ----------------------------------------------------------------
// User have OCM Battle Record data available
if(countGBR)
{
// Check if the newest advantage distance is bigger than the older advantage distance
if(countGBR.result < saveExGhostHistory.result)
{
console.log('OCM Ghost Tally found');
// Current date is OCM Main Draw
if(ocmEventDate!.competitionStartAt < date && ocmEventDate!.competitionCloseAt > date)
{
// Get OCM Period ID
let OCM_periodId = await prisma.oCMPeriod.findFirst({
where:{
competitionId: ocmEventDate!.competitionId,
startAt:
{
lte: date, // competitionStartAt is less than current date
},
closeAt:
{
gte: date, // competitionCloseAt is greater than current date
}
},
select:{
periodId: true
}
});
let checkGhost = await prisma.oCMGhostBattleRecord.findFirst({
where:{
carId: saveExGhostHistory.carId,
competitionId: ocmEventDate!.competitionId,
}
});
if(checkGhost)
{
console.log('Updating OCM Ghost Battle Record entry');
// Get the user's available OCM Battle Record data
let getGBR = await prisma.oCMGhostBattleRecord.findFirst({
where:{
carId: saveExGhostHistory.carId,
competitionId: ocmEventDate!.competitionId,
}
});
// Update ghost battle record
await prisma.oCMGhostBattleRecord.update({
where:{
dbId: getGBR!.dbId
},
data: {
...saveExGhostHistory,
competitionId: ocmEventDate!.competitionId,
periodId: OCM_periodId!.periodId
}
});
}
else
{
console.log('Creating new OCM Ghost Battle Record entry');
// Create new ghost battle record
await prisma.oCMGhostBattleRecord.create({
data: {
...saveExGhostHistory,
competitionId: ocmEventDate!.competitionId,
periodId: OCM_periodId!.periodId
}
});
}
console.log('Updating OCM Tally Record');
// Update the OCM Tally Record
await prisma.oCMTally.update({
where:{
dbId: countGBR.dbId
},
data: {
periodId: OCM_periodId!.periodId,
result: body.rgResult!.opponents![0].result,
tunePower: body.car?.tunePower!,
tuneHandling: body.car?.tuneHandling!
}
});
}
// Current date is OCM Qualifying
else
{
// Update ghost battle record
await prisma.oCMGhostBattleRecord.update({
where:{
dbId: countGBR.dbId
},
data: {
...saveExGhostHistory,
competitionId: ocmEventDate!.competitionId,
periodId: 0
}
});
}
}
// Newest advantage distance is smaller than the older advantage distance
else
{
console.log('Result record is lower than previous record');
// Don't update the User's OCM ghost trail
updateNewTrail = false;
}
}
// User don't have OCM Battle Record data available
else
{
console.log('OCM Ghost Battle Record not found');
console.log('Creating new OCM Ghost Battle Record entry');
// Current date is OCM Main Draw
if(ocmEventDate!.competitionStartAt < date && ocmEventDate!.competitionCloseAt > date)
{
// Get OCM Period ID
let OCM_periodId = await prisma.oCMPeriod.findFirst({
where:{
competitionId: ocmEventDate!.competitionId,
},
orderBy:{
periodId: 'desc'
},
select:{
periodId: true
}
});
// Update ghost battle record
await prisma.oCMGhostBattleRecord.create({
data: {
...saveExGhostHistory,
competitionId: ocmEventDate!.competitionId,
periodId: OCM_periodId!.periodId
}
});
let ocmTallyfind = await prisma.oCMTally.findFirst({
where:{
carId: saveExGhostHistory.carId,
competitionId: ocmEventDate!.competitionId,
},
});
if(ocmTallyfind)
{
console.log('Updating OCM Tally Record');
// Update the OCM Tally Record
await prisma.oCMTally.update({
where:{
dbId: ocmTallyfind.dbId
},
data: {
periodId: OCM_periodId!.periodId,
result: body.rgResult!.opponents![0].result,
tunePower: body.car?.tunePower!,
tuneHandling: body.car?.tuneHandling!
}
});
}
}
// Current date is OCM Qualifying
else
{
// Update ghost battle record
await prisma.oCMGhostBattleRecord.create({
data: {
...saveExGhostHistory,
competitionId: ocmEventDate!.competitionId,
periodId: 0
}
});
}
}
// Return the value to 'BASE_PATH/src/util/games/ghost.ts'
return { updateNewTrail }
}

View File

@ -7,9 +7,9 @@ import { Config } from "../config";
import * as wm from "../wmmt/wm.proto";
// Import Util
import * as common from "./util/common";
import * as ghost_ocm from "./ghost/ghost_ocm";
import * as ghost_ocm_area from "./ghost/ghost_util/ghost_ocm_area";
import * as common from "../util/common";
import * as ghost_ocm from "../util/ghost/ghost_ocm";
import * as ghost_ocm_area from "../util/ghost/ghost_ocm_area";
export default class GhostModule extends Module {
@ -181,6 +181,7 @@ export default class GhostModule extends Module {
// Get Current OCM Period
let OCMCurrentPeriod = await prisma.oCMPeriod.findFirst({
where: {
competitionDbId: ocmEventDate!.dbId,
competitionId: ocmEventDate!.competitionId
},
orderBy: {
@ -419,9 +420,11 @@ export default class GhostModule extends Module {
if(!(ocmEventDate))
{
ocmEventDate = await prisma.oCMEvent.findFirst({
orderBy:{
competitionId: 'desc'
},
orderBy: [
{
dbId: 'desc'
},
],
});
}
@ -462,6 +465,9 @@ export default class GhostModule extends Module {
carId: ocmTallyRecord!.carId,
competitionId: ocmEventDate!.competitionId,
periodId: period_id,
area: areaVal,
ramp: rampVal,
path: pathVal,
},
orderBy:{
playedAt: 'desc'
@ -491,9 +497,6 @@ export default class GhostModule extends Module {
// Set Ghost stuff Value
cars!.lastPlayedAt = checkGhostTrail.playedAt
ghostTrailId = checkGhostTrail.dbId!;
areaVal = Number(checkGhostTrail.area);
rampVal = Number(checkGhostTrail.ramp);
pathVal = Number(checkGhostTrail.path);
ghostTypes = wm.wm.protobuf.GhostType.GHOST_NORMAL;
}
}
@ -508,6 +511,9 @@ export default class GhostModule extends Module {
carId: 999999999,
competitionId: ocmEventDate!.competitionId,
periodId: 0,
area: areaVal,
ramp: rampVal,
path: pathVal
},
orderBy:{
playedAt: 'desc'
@ -550,10 +556,7 @@ export default class GhostModule extends Module {
});
// Set Ghost stuff Value
ghostTrailId = checkGhostTrail!.dbId;
areaVal = Number(checkGhostTrail!.area);
rampVal = Number(checkGhostTrail!.ramp);
pathVal = Number(checkGhostTrail!.path);
ghostTrailId = checkGhostTrail!.dbId!;
ghostTypes = wm.wm.protobuf.GhostType.GHOST_NORMAL;
}
else if(ocmEventDate!.competitionCloseAt < date && ocmEventDate!.competitionEndAt > date)

620
src/modules/ghost_vsorg.ts Normal file
View File

@ -0,0 +1,620 @@
import { Application } from "express";
import { Module } from "module";
import { prisma } from "..";
// Import Proto
import * as wm from "../wmmt/wm.proto";
import * as wmsrv from "../wmmt/service.proto";
// Import Util
import * as common from "../util/common";
export default class GhostModule extends Module {
register(app: Application): void {
app.post('/method/load_ghost_expedition_info', async (req, res) => {
// Get the request body for the load stamp target request
let body = wm.wm.protobuf.LoadGhostExpeditionInfoRequest.decode(req.body);
// Get User data
let userScores = await prisma.ghostExpedition.findFirst({
where:{
carId: body.carId,
ghostExpeditionId: body.ghostExpeditionId
}
})
// Get local store score
let localScores = await prisma.ghostExpedition.findMany({
where:{
ghostExpeditionId: body.ghostExpeditionId
},
orderBy:{
score: 'desc'
}
})
// Totaling local store score
let sumLocalScore = 0;
for(let i=0; i<localScores.length; i++)
{
sumLocalScore += localScores[i].score;
}
// Response data
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
sugorokuPoint: userScores?.sugorokuPoint || 0,
score: userScores?.score || 0,
localScore: sumLocalScore,
};
// Encode the response
let message = wm.wm.protobuf.LoadGhostExpeditionInfoResponse.encode(msg);
// Send the response to the client
common.sendResponse(message, res);
})
app.post('/method/load_ghost_expedition_target_by_path', async (req, res) => {
// Get the request body for the load stamp target request
let body = wm.wm.protobuf.LoadGhostExpeditionTargetByPathRequest.decode(req.body);
let areaExpedition: wm.wm.protobuf.LoadGhostExpeditionTargetByPathResponse.AreaStats[] = [];
for(let j=0; j<19; j++)
{
// 14 - 16 are dummy area, 17 is C1 Closed
if(j >= 14){
j = 18; // GID_RUNAREA_HIROSHIMA
}
let areaVal = 0;
let pathVal = 0;
if(j === 0){ // GID_RUNAREA_C1
areaVal = 0;
pathVal = 0;
}
else if(j === 1){ // GID_RUNAREA_RING
areaVal = 1;
pathVal = 10;
}
else if(j === 2){ // GID_RUNAREA_SUBTOKYO_3_4
areaVal = 2;
pathVal = 16;
}
else if(j === 3){ // GID_RUNAREA_SUBTOKYO_5
areaVal = 3;
pathVal = 18;
}
else if(j === 4){ // GID_RUNAREA_WANGAN
areaVal = 4;
pathVal = 20;
}
else if(j === 5){ // GID_RUNAREA_K1
areaVal = 5;
pathVal = 27;
}
else if(j === 6){ // GID_RUNAREA_YAESU
areaVal = 6;
pathVal = 34;
}
else if(j === 7){ // GID_RUNAREA_YOKOHAMA
areaVal = 7;
pathVal = 38;
}
else if(j === 8){ // GID_RUNAREA_NAGOYA
areaVal = 8;
pathVal = 49;
}
else if(j === 9){ // GID_RUNAREA_OSAKA
areaVal = 9;
pathVal = 50;
}
else if(j === 10){ // GID_RUNAREA_KOBE
areaVal = 10;
pathVal = 54;
}
else if(j === 11){ // GID_RUNAREA_FUKUOKA
areaVal = 11;
pathVal = 58;
}
else if(j === 12){ // GID_RUNAREA_HAKONE
areaVal = 12;
pathVal = 62;
}
else if(j === 13){ // GID_RUNAREA_TURNPIKE
areaVal = 13;
pathVal = 64;
}
//14 - 16 are dummy area, 17 is GID_RUNAREA_C1_CLOSED
else if(j === 18){ // GID_RUNAREA_HIROSHIMA
areaVal = 18;
pathVal = 56;
}
// Get Wanted List
let wantedInfo: wm.wm.protobuf.LoadGhostExpeditionTargetByPathResponse.AreaStats.WantedInfo[] = [];
let checkWantedList = await prisma.ghostExpeditionWantedCar.findMany({
where:{
ghostExpeditionId: body.ghostExpeditionId,
area: j
},
orderBy:{
bonus: 'desc'
},
take: 10
})
// TODO: FIX THIS STUFF
/* GAME SOMETIMES BUT MOSTLY WILL CRASH IF I ADDED WANTED INFO... HUH?!?!?!??!?!?! WTF GAME?!?!?
if(checkWantedList.length > 0)
{
wantedInfo.push(wm.wm.protobuf.LoadGhostExpeditionTargetByPathResponse.AreaStats.WantedInfo.create({
wantedLevel: checkWantedList[0].bonus,
numOfWantedCars: checkWantedList.length
}))
areaExpedition.push(wm.wm.protobuf.LoadGhostExpeditionTargetByPathResponse.AreaStats.create({
area: areaVal,
path: pathVal,
wantedInfo: wantedInfo
}));
}
else
{
areaExpedition.push(wm.wm.protobuf.LoadGhostExpeditionTargetByPathResponse.AreaStats.create({
area: areaVal,
path: pathVal,
wantedInfo: null
}));
}*/
// Push the path per area (if not set.. all will become kandabashi ramp)
areaExpedition.push(wm.wm.protobuf.LoadGhostExpeditionTargetByPathResponse.AreaStats.create({
area: areaVal,
path: pathVal,
wantedInfo: null
}));
}
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
areas: areaExpedition,
selectionMethod: wm.wm.protobuf.PathSelectionMethod.PATH_NORMAL // idk what this is
};
// Encode the response
let message = wm.wm.protobuf.LoadGhostExpeditionTargetByPathResponse.encode(msg);
// Send the response to the client
common.sendResponse(message, res);
})
app.post('/method/load_ghost_expedition_targets', async (req, res) => {
// Get the request body for the load stamp target request
let body = wm.wm.protobuf.LoadGhostExpeditionTargetsRequest.decode(req.body);
// Get the area id and ramp id
let area = 0;
let ramp = 0; // this is important to set, if not.. the path shown when selecting car tune and loading screen will get randomized
let path = 0;
if(body.path)
{
if(body.path >= 0 && body.path <= 9){ // GID_PATH_C1
area = Number(0);
ramp = 0;
}
else if(body.path >= 10 && body.path <= 15){ // GID_PATH_N9
area = Number(1);
ramp = 4;
}
else if(body.path >= 16 && body.path <= 17){ // GID_PATH_WTEAST
area = Number(2);
ramp = 6;
}
else if(body.path >= 18 && body.path <= 19){ // GID_PATH_WT_UP_DOWN
area = Number(3);
ramp = 8;
}
else if(body.path >= 20 && body.path <= 26){ // GID_PATH_WG
area = Number(4);
ramp = 10;
}
else if(body.path >= 27 && body.path <= 33){ // GID_PATH_KG
area = Number(5);
ramp = 14;
}
else if(body.path >= 34 && body.path <= 37){ // GID_PATH_YS
area = Number(6);
ramp = 18;
}
else if(body.path >= 38 && body.path <= 48){ // GID_PATH_KG_SHINYAMASHITA_MINATOMIRAI
area = Number(7);
ramp = 21;
}
else if(body.path === 49){ // GID_PATH_NGR
area = Number(8);
ramp = 25;
}
else if(body.path >= 50 && body.path <= 53){ // GID_PATH_OS
area = Number(9);
ramp = 26;
}
else if(body.path >= 54 && body.path <= 55){ // GID_PATH_KB
area = Number(10);
ramp = 27;
}
else if(body.path >= 58 && body.path <= 61){ // GID_PATH_FK
area = Number(11);
ramp = 29;
}
else if(body.path >= 62 && body.path <= 63){ // GID_PATH_HK
area = Number(12);
ramp = 33;
}
else if(body.path >= 64 && body.path <= 65){ // GID_PATH_TP
area = Number(13);
ramp = 35;
}
else if(body.path >= 56 && body.path <= 57){ // GID_PATH_HS
area = Number(18);
ramp = 37;
}
path = Number(body.path);
}
let lists_candidates: wm.wm.protobuf.GhostCar[] = [];
let lists_wanted: wm.wm.protobuf.WantedCar[] = [];
// Check wanted car
let wantedCarList = await prisma.ghostExpeditionWantedCar.findMany({
where:{
ghostExpeditionId: body.ghostExpeditionId,
area: area
},
take: 10
})
// Make array for excluding wanted car from non wanted car
let arrayWantedCarId = [];
for(let i=0; i<wantedCarList.length; i++)
{
arrayWantedCarId.push(wantedCarList[i].carId);
}
// Get Expedition (VSORG) VS Ghost Region
let ghostExpeditionRegion = await prisma.ghostExpeditionEvent.findFirst({
where: {
ghostExpeditionId: body.ghostExpeditionId
},
});
let country = 'JPN';
let regionId: number = 20;
if(ghostExpeditionRegion!.opponentCountry === 'IDN')
{
country = 'IDN';
regionId = 18;
}
else if(ghostExpeditionRegion!.opponentCountry === 'AUS')
{
country = 'AUS';
regionId = 2;
}
else if(ghostExpeditionRegion!.opponentCountry === 'CHN')
{
country = 'CHN';
regionId = 10;
}
else if(ghostExpeditionRegion!.opponentCountry === 'HKG')
{
country = 'HKG';
regionId = 15;
}
else if(ghostExpeditionRegion!.opponentCountry === 'PHL')
{
country = 'PHL';
regionId = 30;
}
// Get Canditate list
let car = await prisma.car.findMany({
where:{
NOT: {
carId: { in: arrayWantedCarId }, // except wanted car
}
},
include:{
gtWing: true,
lastPlayedPlace: true
}
});
let arr = [];
let maxNumber = 0;
// If all user car data available is more than 10 for certain level
if(car.length > 10)
{
maxNumber = 10 // Limit to 10 (game default)
}
// If no more than 10
else
{
maxNumber = car.length;
}
while(arr.length < maxNumber)
{
// Pick random car Id
let randomNumber: number = Math.floor(Math.random() * car.length);
if(arr.indexOf(randomNumber) === -1)
{
// Push current number to array
arr.push(randomNumber);
// Push data to Ghost car proto
lists_candidates.push(wm.wm.protobuf.GhostCar.create({
car: {
...car[randomNumber],
country: country,
regionId: regionId
},
area: area,
ramp: ramp,
path: path,
nonhuman: false,
type: wm.wm.protobuf.GhostType.GHOST_REGION,
}));
}
}
// Get store result performance
let localScores = await prisma.ghostExpedition.findMany({
where:{
ghostExpeditionId: body.ghostExpeditionId
}
})
let sumLocalScore = 0;
let recentWinners: wm.wm.protobuf.CarEntry[] = []
for(let i=0; i<localScores.length; i++)
{
// total the local store score
sumLocalScore += localScores[i].score;
if(localScores[i].carId !== body.carId)
{
let car = await prisma.car.findFirst({
where:{
carId: localScores[i].carId
}
});
// Push to recent store winner
recentWinners.push(wm.wm.protobuf.CarEntry.create({
name: car!.name,
level: car!.level,
title: car!.title,
model: car!.model,
visualModel: car!.visualModel,
defaultColor: car!.defaultColor,
score: localScores[i].score,
}))
}
}
// Get Wanted List
for(let i=0; i<wantedCarList.length; i++)
{
let wantedCar = await prisma.car.findFirst({
where:{
carId: wantedCarList[i].carId
},
include:{
gtWing: true,
lastPlayedPlace: true
}
});
if(wantedCar)
{
let ghostcar = wm.wm.protobuf.GhostCar.create({
car: {
...wantedCar,
country: country,
regionId: regionId
},
area: area,
ramp: ramp,
path: path,
nonhuman: false,
type: wm.wm.protobuf.GhostType.GHOST_REGION,
});
let car = await prisma.car.findFirst({
where:{
carId: body.carId
}
})
// idk what hostages for
let hostages = wm.wm.protobuf.CarEntry.create({
name: car!.name,
level: car!.level,
title: car!.title,
model: car!.model,
visualModel: car!.visualModel,
defaultColor: car!.defaultColor,
score: wantedCarList[i].bonus, // idk what this is
})
lists_wanted.push(wm.wm.protobuf.WantedCar.create({
ghost: ghostcar,
wantedId: wantedCar.carId, // id?
bonus: wantedCarList[i].bonus, // for bonus store win
numOfHostages: 1, // idk what this is for
defeatedMeCount: wantedCarList[i].defeatedMeCount, // for bonus movements
hostage: hostages // idk what this is for
}))
}
}
// Response data
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
candidates: lists_candidates,
localScore: sumLocalScore,
wantedCars: lists_wanted,
recentWinners: recentWinners // store result performance
};
// Encode the response
let message = wm.wm.protobuf.LoadGhostExpeditionTargetsResponse.encode(msg);
// Send the response to the client
common.sendResponse(message, res);
})
// Lock Wanted
app.post('/method/lock_wanted', async (req, res) => {
// Get the request body for the load stamp target request
let body = wmsrv.wm.protobuf.LockWantedRequest.decode(req.body);
// Get the current date/time (unix epoch)
let date = Math.floor(new Date().getTime() / 1000);
// Wanted Lock Variable
let locked: boolean = false;
let lockTime: number = 0;
// Handling to auto unlock the Wanted Ghost
await prisma.ghostExpeditionWantedCar.updateMany({
where:{
lockTime: {
lt: date
}
},
data:{
locked: locked,
lockTime: lockTime
}
});
// Lock the Wanted Ghost
if(body.lockTime > 0)
{
locked = true;
lockTime = date + 600;
}
// Change the Wanted Ghost Lock Status
await prisma.ghostExpeditionWantedCar.updateMany({
where:{
carId: body.wantedId
},
data:{
locked: locked,
lockTime: lockTime
}
});
// Response data
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
};
// Encode the response
let message = wmsrv.wm.protobuf.LockWantedResponse.encode(msg);
// Send the response to the client
common.sendResponse(message, res);
})
// Load Ghost Expedition Result
app.post('/method/load_ghost_expedition_result', async (req, res) => {
// Get the request body for the load stamp target request
let body = wmsrv.wm.protobuf.LoadGhostExpeditionResultRequest.decode(req.body);
// Get User data
let userScores = await prisma.ghostExpedition.findFirst({
where:{
carId: body.carId,
ghostExpeditionId: body.ghostExpeditionId
}
})
// Get local store score
let localScores = await prisma.ghostExpedition.findMany({
where:{
ghostExpeditionId: body.ghostExpeditionId
},
orderBy:{
score: 'desc'
}
})
// Totaling local store score
let sumLocalScore = 0;
let ghostExpeditionRankings: wm.wm.protobuf.GhostExpeditionRankingEntry[] = []
for(let i=0; i<localScores.length; i++)
{
sumLocalScore += localScores[i].score;
}
// Get car score
for(let i=0; i<localScores.length; i++)
{
let car = await prisma.car.findFirst({
where:{
carId: localScores[i].carId
},
orderBy:{
carId: 'asc'
},
include:{
gtWing: true,
lastPlayedPlace: true
}
});
if(car)
{
ghostExpeditionRankings.push(wm.wm.protobuf.GhostExpeditionRankingEntry.create({
rank: i+1,
score: localScores[i].score,
car: car!
}));
}
}
// Response data
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
score: userScores?.score || 0,
localScore: sumLocalScore,
localRanking: ghostExpeditionRankings
}
// Encode the response
let message = wmsrv.wm.protobuf.LoadGhostExpeditionResultResponse.encode(msg);
// Send the response to the client
common.sendResponse(message, res);
})
}
}

View File

@ -1,4 +1,4 @@
import { Application } from "express";
import e, { Application } from "express";
import { Module } from "module";
import { Config } from "../config";
import { prisma } from "..";
@ -9,9 +9,7 @@ import * as wm from "../wmmt/wm.proto";
import * as wmsrv from "../wmmt/service.proto";
// Import Util
import * as common from "./util/common";
import * as crown_list from "./resource/crown_list";
import * as ranking from "./resource/ranking";
import * as common from "../util/common";
export default class ResourceModule extends Module {
@ -25,13 +23,10 @@ export default class ResourceModule extends Module {
// Empty list of place records
let places: wm.wm.protobuf.Place[] = [];
// Region ID must not 0
let regionId = common.sanitizeInputNotZero(Number(Config.getConfig().regionId)) || 1;
// Response data
places.push(new wm.wm.protobuf.Place({
placeId: Config.getConfig().placeId || 'JPN0123',
regionId: regionId,
regionId: Number(Config.getConfig().regionId) || 1,
shopName: Config.getConfig().shopName || 'Bayshore',
country: Config.getConfig().country || 'JPN'
}));
@ -49,28 +44,12 @@ export default class ResourceModule extends Module {
await prisma.placeList.create({
data:{
placeId: Config.getConfig().placeId || 'JPN0123',
regionId: regionId,
regionId: Number(Config.getConfig().regionId) || 1,
shopName: Config.getConfig().shopName || 'Bayshore',
country: Config.getConfig().country || 'JPN'
}
})
}
else
{
if(checkPlaceList.shopName !== Config.getConfig().shopName)
{
await prisma.placeList.update({
where:{
id: checkPlaceList.id
},
data:{
regionId: regionId,
shopName: Config.getConfig().shopName,
country: Config.getConfig().country
}
})
}
}
// Encode the response
let message = wm.wm.protobuf.PlaceList.encode({places});
@ -79,6 +58,7 @@ export default class ResourceModule extends Module {
common.sendResponse(message, res);
})
// Get Ranking data for attract screen (TA, Ghost, VS)
app.get('/resource/ranking', async (req, res) => {
@ -88,16 +68,252 @@ export default class ResourceModule extends Module {
let lists: wmsrv.wm.protobuf.Ranking.List[] = [];
// Get TA Ranking
let rankingTA = await ranking.getTimeAttackRanking();
lists.push( ...rankingTA.lists );
for(let i=0; i<25; i++){ // GID_TACOURSE ID
// Get VS Outrun Ranking
let rankingVSOutrun = await ranking.getVSOutrunRanking();
lists.push( ...rankingVSOutrun.lists );
// Get the TA time per course
let ta_time = await prisma.timeAttackRecord.findMany({
where: {
course: i
},
orderBy: {
time: 'asc'
},
take: 10, // Take top 10
});
// Get Ghost Trophies Ranking
let rankingGhostTrophies = await ranking.getTGhostTrophiesRanking();
lists.push( ...rankingGhostTrophies.lists );
// TA time record by user is available for certain course
if(ta_time.length > 0){
// Empty list of ranking records for user time attack
let list_ta: wmsrv.wm.protobuf.Ranking.Entry[] = [];
// Get the TA time data
for(let j=0; j<ta_time.length; j++){
// Get the car data
let car_ta = await prisma.car.findFirst({
where: {
carId: ta_time[j].carId
}
});
// Push the data to the ranking data
list_ta.push(wmsrv.wm.protobuf.Ranking.Entry.create({
carId: ta_time[j].carId,
rank: car_ta!.level,
result: ta_time[j].time,
name: car_ta!.name,
regionId: car_ta!.regionId,
model: car_ta!.model,
visualModel: car_ta!.visualModel,
defaultColor: car_ta!.defaultColor,
tunePower: ta_time[j].tunePower, // Set the tunePower used when playing TA
tuneHandling: ta_time[j].tuneHandling, // Set the tuneHandling used when playing TA
title: car_ta!.title,
level: car_ta!.level
}));
}
// If the TA time record by user is less than 10 user
if(ta_time.length < 11){
// Take the remaining unfilled
for(let j=ta_time.length; j<11; j++){
let resultTime = 599999; // 9:59:999 time
// GID_TACOURSE_TOKYOALL & GID_TACOURSE_KANAGAWAALL area
if(i === 22 || i === 23){
resultTime = 1199999; // 19:59:999 time
}
// Push the data to the ranking data
list_ta.push(wmsrv.wm.protobuf.Ranking.Entry.create({
carId: 0,
rank: 0,
result: resultTime,
name: '',
regionId: 1, // Hokkaido
model: Math.floor(Math.random() * 50), // Randomizing Car data
visualModel: Math.floor(Math.random() * 100), // Randomizing Car data
defaultColor: 0,
tunePower: 0,
tuneHandling: 0,
title: 'Wangan Beginner', // 湾岸の新人
level: 0 // N
}));
}
}
lists.push(new wmsrv.wm.protobuf.Ranking.List({
rankingType: i, // RANKING_TA_*AREA*
topRecords: list_ta
}));
}
// There is no user's TA record for certain area
else{
// Empty list of ranking records for time attack
let list_ta: wmsrv.wm.protobuf.Ranking.Entry[] = [];
// Generate the top 10 TA time data
for(let j=0; j<11; j++){
let resulttime = 599999; // 9:59:999 time
// GID_TACOURSE_TOKYOALL & GID_TACOURSE_KANAGAWAALL area
if(i === 22 || i === 23){
resulttime = 1199999 // 19:59:999 time
}
// Push the data to the ranking data
list_ta.push(wmsrv.wm.protobuf.Ranking.Entry.create({
carId: 0,
rank: 0,
result: resulttime,
name: '',
regionId: 1, // Hokkaido
model: Math.floor(Math.random() * 50), // Randomizing Car data
visualModel: Math.floor(Math.random() * 100), // Randomizing Car data
defaultColor: 0,
tunePower: 0,
tuneHandling: 0,
title: 'Wangan Beginner', // 湾岸の新人
level: 0 // N
}));
}
// Push the certain area ranking data to the list
lists.push(new wmsrv.wm.protobuf.Ranking.List({
rankingType: i, // RANKING_TA_*AREA*
topRecords: list_ta // Top 10 TA time record data
}));
}
}
// Get VS Star Ranking
// Get the user's VS Stars data
let car_vs = await prisma.car.findMany({
orderBy: {
vsStarCount: 'desc'
},
take: 20, // Take top 20
});
// Empty list of ranking records for VS Stars
let list_vs: wmsrv.wm.protobuf.Ranking.Entry[] = [];
// Get the VS stars data
for(let i=0; i<car_vs.length; i++){
// Push the car data to the ranking data
list_vs.push(wmsrv.wm.protobuf.Ranking.Entry.create({
carId: car_vs[i].carId,
rank: car_vs[i].level,
result: car_vs[i].vsStarCount,
name: car_vs[i].name,
regionId: car_vs[i].regionId,
model: car_vs[i].model,
visualModel: car_vs[i].visualModel,
defaultColor: car_vs[i].defaultColor,
tunePower: car_vs[i].tunePower,
tuneHandling: car_vs[i].tuneHandling,
title: car_vs[i].title,
level: car_vs[i].level
}));
}
// If the VS stars record by user is less than 20 user
if(car_vs.length < 20){
// Take the remaining unfilled
for(let j=car_vs.length; j<21; j++){
// Push the data to the ranking data
list_vs.push(wmsrv.wm.protobuf.Ranking.Entry.create({
carId: 0,
rank: 0,
result: 0,
name: '',
regionId: 1, // Hokkaido
model: Math.floor(Math.random() * 50), // Randomizing Car data
visualModel: Math.floor(Math.random() * 100), // Randomizing Car data
defaultColor: 0,
tunePower: 0,
tuneHandling: 0,
title: 'Wangan Beginner', // 湾岸の新人
level: 0 // N
}));
}
}
// Push the data
lists.push(new wmsrv.wm.protobuf.Ranking.List({
rankingType: 100, // RANKING_VS_STAR
topRecords: list_vs // Top 20 VS stars record data
}));
// Get Ghost Defeated Ranking
// Get the user's Ghost Win data
let car_ghost = await prisma.car.findMany({
orderBy: {
rgWinCount: 'desc'
},
take: 20, // Take top 20
});
// Empty list of ranking records for Ghost Battle Win
let list_ghost: wmsrv.wm.protobuf.Ranking.Entry[] = [];
// Get the Ghost Battle Win data
for(let i=0; i<car_ghost.length; i++){
// Push the car data to the ranking data
list_ghost.push(wmsrv.wm.protobuf.Ranking.Entry.create({
carId: car_ghost[i].carId,
rank: car_ghost[i].level,
result: car_ghost[i].rgWinCount,
name: car_ghost[i].name,
regionId: car_ghost[i].regionId,
model: car_ghost[i].model,
visualModel: car_ghost[i].visualModel,
defaultColor: car_ghost[i].defaultColor,
tunePower: car_ghost[i].tunePower,
tuneHandling: car_ghost[i].tuneHandling,
title: car_ghost[i].title,
level: car_ghost[i].level
}));
}
// If the Ghost Win record by user is less than 20 user
if(car_ghost.length < 20){
// Take the remaining unfilled
for(let j=car_ghost.length; j<21; j++){
// Push the data to the ranking data
list_ghost.push(wmsrv.wm.protobuf.Ranking.Entry.create({
carId: 0,
rank: 0,
result: 0,
name: '',
regionId: 1, // Hokkaido
model: Math.floor(Math.random() * 50), // Randomizing Car data
visualModel: Math.floor(Math.random() * 100), // Randomizing Car data
defaultColor: 0,
tunePower: 0,
tuneHandling: 0,
title: 'Wangan Beginner', // 湾岸の新人
level: 0 // N
}));
}
}
// Push the data
lists.push(new wmsrv.wm.protobuf.Ranking.List({
rankingType: 101, // RANKING_GHOST_DEFEATED_COUNT
topRecords: list_ghost // Top 20 Ghost Win record data
}));
// Encode the response
let message = wmsrv.wm.protobuf.Ranking.encode({lists});
@ -113,14 +329,168 @@ export default class ResourceModule extends Module {
console.log('crown_list');
// Empty list of crown records
let crowns: wmsrv.wm.protobuf.Crown[] = [];
let list_crown: wmsrv.wm.protobuf.Crown[] = [];
// Get Crown List
let crown_lists = await crown_list.getCrownList();
crowns.push( ...crown_lists.list_crown );
// Get the crown holder data
let car_crown = await prisma.carCrown.findMany({
orderBy: {
area: 'asc'
},
distinct: ['area']
});
// Crown holder data available
if(car_crown.length !== 0)
{
let counter = 0;
// Loop GID_RUNAREA
for(let i=0; i<19; i++)
{
// After Kobe is Hiroshima then Fukuoka and the rest
if(i > 14)
{
i = 18; // GID_RUNAREA_HIROSHIMA
}
// Crown holder for certain area available
if(car_crown[counter].area === i)
{
// Get user's data
let car = await prisma.car.findFirst({
where: {
carId: car_crown[counter].carId
},
include: {
gtWing: true,
lastPlayedPlace: true
}
});
// Set the tunePower and tuneHandling used when capturing ghost crown
car!.tunePower = car_crown[counter].tunePower;
car!.tuneHandling = car_crown[counter].tuneHandling;
// Error handling if played At timestamp value is current date and timestamp is bigger than 9 July 2022 (using GMT+7 timestamp)
if(car_crown[counter].playedAt !== 0 && car_crown[counter].playedAt >= 1657299600)
{
// Acquired crown timestamp - 1 day
car!.lastPlayedAt = car_crown[counter].playedAt - 172800;
// Acquired crown timestamp - 1 day
car_crown[counter].playedAt = car_crown[counter].playedAt - 172800;
}
// Error handling if played At timestamp value is 0 or timestamp is less than 9 July 2022 (using GMT+7 timestamp)
else if(car_crown[counter].playedAt === 0 || car_crown[counter].playedAt < 1657299600)
{
// Acquired crown timestamp become 9 July 2022 (using GMT+7 timestamp)
car!.lastPlayedAt = 1657299600;
// Acquired crown timestamp become 9 July 2022 (using GMT+7 timestamp)
car_crown[counter].playedAt = 1657299600;
}
// Push the car data to the crown holder data
// GID_RUNAREA_HIROSHIMA
if(car_crown[counter].area === 18)
{
let listCrown = wmsrv.wm.protobuf.Crown.create({
carId: car_crown[counter].carId,
area: car_crown[counter].area,
unlockAt: car_crown[counter].playedAt,
car: car!
});
list_crown.splice(11, 0, listCrown);
}
// GID_RUNAREA_C1 - GID_RUNAREA_TURNPIKE
else
{
list_crown.push(wmsrv.wm.protobuf.Crown.create({
carId: car_crown[counter].carId,
area: car_crown[counter].area,
unlockAt: car_crown[counter].playedAt,
car: car!
}));
}
if(counter < car_crown.length-1)
{
counter++;
}
}
// Crown holder for certain area not available
else
{
// Push the default data by the game to the crown holder data
// GID_RUNAREA_HIROSHIMA
if(i === 18)
{
let listCrown = wmsrv.wm.protobuf.Crown.create({
carId: 999999999-i,
area: i,
unlockAt: 0,
});
list_crown.splice(11, 0, listCrown);
}
// GID_RUNAREA_C1 - GID_RUNAREA_TURNPIKE
else
{
list_crown.push(wmsrv.wm.protobuf.Crown.create({
carId: 999999999-i,
area: i,
unlockAt: 0,
}));
}
}
}
}
// There is no user's crown holder data available
else
{
// Loop GID_RUNAREA
for(let i=0; i<19; i++)
{
// After Kobe is Hiroshima then Fukuoka and the rest
if(i > 14)
{
i = 18; // GID_RUNAREA_HIROSHIMA
}
// Push the default data by the game to the crown holder data
// GID_RUNAREA_HIROSHIMA
if(i === 18)
{
let listCrown = wmsrv.wm.protobuf.Crown.create({
carId: 999999999-i,
area: i,
unlockAt: 0,
});
// Push it after Kobe
list_crown.splice(11, 0, listCrown);
}
// GID_RUNAREA_C1 - GID_RUNAREA_TURNPIKE
else
{
list_crown.push(wmsrv.wm.protobuf.Crown.create({
carId: 999999999-i,
area: i,
unlockAt: 0,
}));
}
}
}
// Response data
let msg = {
crowns: list_crown
};
// Encode the response
let message = wmsrv.wm.protobuf.CrownList.encode( {crowns} );
let message = wmsrv.wm.protobuf.CrownList.encode(msg);
// Send the response to the client
common.sendResponse(message, res);
@ -140,6 +510,7 @@ export default class ResourceModule extends Module {
}
});
res.sendFile(path.resolve(paths!.filePath, req.params.filename), { cacheControl: false });
});
@ -208,5 +579,186 @@ export default class ResourceModule extends Module {
// Send the response to the client
common.sendResponse(message, res);
})
// Ghost Expedition (VSORG) Ranking
app.get('/resource/ghost_expedition_ranking', async (req, res) => {
console.log('ghost_expedition_ranking');
let ghostExpeditionRankings: wm.wm.protobuf.GhostExpeditionRankingEntry[] = [];
// Get VSORG / Expedition Participant Ranking
let localScores = await prisma.ghostExpedition.findMany({
where:{
ghostExpeditionId: Number(req.query.ghost_expedition_id)
},
orderBy:{
score: 'desc'
}
})
// Get car score
let car;
let todaysMvps;
for(let i=0; i<localScores.length; i++)
{
car = await prisma.car.findFirst({
where:{
carId: localScores[i].carId
},
orderBy:{
carId: 'asc'
},
include:{
gtWing: true,
lastPlayedPlace: true
}
});
if(car)
{
ghostExpeditionRankings.push(wm.wm.protobuf.GhostExpeditionRankingEntry.create({
rank: i+1,
score: localScores[i].score,
car: car!
}));
if(i === 0)
{
todaysMvps = wm.wm.protobuf.GhostExpeditionRankingEntry.create({
rank: i+1,
score: localScores[i].score,
car: car!
});
}
}
}
// Totaling score for store score
let sum = 0;
for(let i=0; i<localScores.length; i++)
{
sum += localScores[i].score;
}
// Response data
let msg = {
localScore: sum,
todaysMvp: todaysMvps || null,
localRanking: ghostExpeditionRankings || null
};
// Encode the response
let message = wm.wm.protobuf.GhostExpeditionRanking.encode(msg);
// Send the response to the client
common.sendResponse(message, res);
})
// Lock Wanted List
app.get('/resource/lock_wanted_list', async (req, res) => {
console.log('lock_wanted_list');
let wanteds: wmsrv.wm.protobuf.WantedCar[] = [];
// TODO: Actual stuff here
// This is literally just bare-bones so the shit boots
// Get the current date/time (unix epoch)
let date = Math.floor(new Date().getTime() / 1000);
// Get VSORG Event Date
let ghostExpeditionDate = await prisma.ghostExpeditionEvent.findFirst({
where: {
// qualifyingPeriodStartAt is less than equal current date
startAt: { lte: date },
// competitionEndAt is greater than equal current date
aftereventEndAt: { gte: date },
},
});
// Check Wanted Car
let wantedCarList = await prisma.ghostExpeditionWantedCar.findMany({
where:{
ghostExpeditionId: ghostExpeditionDate?.ghostExpeditionId,
locked: true
}
});
// Wanted Car Exists
if(wantedCarList.length > 0)
{
for(let i=0; i<wantedCarList.length; i++)
{
let wantedCar = await prisma.car.findFirst({
where:{
carId: wantedCarList[i].carId
}
});
let ghostcar = wm.wm.protobuf.GhostCar.create({
car: wantedCar!,
area: wantedCarList[i].area,
});
wanteds.push(wm.wm.protobuf.WantedCar.create({
ghost: ghostcar,
wantedId: wantedCarList[i].carId,
bonus: wantedCarList[i].bonus,
numOfHostages: wantedCarList[i].numOfHostages
}))
}
}
// Encode the response
let message = wmsrv.wm.protobuf.LockWantedList.encode({wanteds});
// Send the response to the client
common.sendResponse(message, res);
})
// Ghost Expedition Participants
app.get('/resource/ghost_expedition_participants', async (req, res) => {
console.log('ghost_expedition_participants');
// Get url query
let ghost_expedition_id = Number(req.query.ghost_expedition_id);
let place_id = String(req.query.place_id);
// Get local store participant
let localParticipant = await prisma.ghostExpedition.findMany({
where:{
ghostExpeditionId: ghost_expedition_id
},
orderBy:{
score: 'desc'
}
})
let arrayParticipant = [];
for(let i=0; i<localParticipant.length; i++)
{
arrayParticipant.push(localParticipant[i].carId);
}
// Response data
let msg = {
placeId: place_id,
participantCars: arrayParticipant
};
// Encode the response
let message = wm.wm.protobuf.GhostExpeditionParticipants.encode(msg);
// Send the response to the client
common.sendResponse(message, res);
})
}
}

View File

@ -1,175 +0,0 @@
import { prisma } from "../..";
//Import Proto
import wmsrv from "../../wmmt/service.proto";
// Get Crown List
export async function getCrownList()
{
// Empty list of crown records
let list_crown: wmsrv.wm.protobuf.Crown[] = [];
// Get the current date/time (unix epoch)
let date = Math.floor(new Date().getTime() / 1000);
// Get the crown holder data
let car_crown = await prisma.carCrown.findMany({
orderBy: {
area: 'asc'
},
distinct: ['area']
});
// Crown holder data available
if(car_crown.length !== 0)
{
let counter = 0;
// Loop GID_RUNAREA
for(let i=0; i<19; i++)
{
// After Kobe is Hiroshima then Fukuoka and the rest
if(i > 14)
{
i = 18; // GID_RUNAREA_HIROSHIMA
}
// Crown holder for certain area available
if(car_crown[counter].area === i)
{
// Get user's data
let car = await prisma.car.findFirst({
where: {
carId: car_crown[counter].carId
},
include: {
gtWing: true,
lastPlayedPlace: true
}
});
// Set the tunePower and tuneHandling used when capturing ghost crown
car!.tunePower = car_crown[counter].tunePower;
car!.tuneHandling = car_crown[counter].tuneHandling;
// Acquired crown timestamp - 1 day (prevent locking)
car!.lastPlayedAt = car_crown[counter].playedAt - 172800;
// Acquired crown timestamp - 1 day (prevent locking)
car_crown[counter].playedAt = car_crown[counter].playedAt - 172800;
// PlayedAt still bigger than current date (prevent locking)
if(car_crown[counter].playedAt > date)
{
car_crown[counter].playedAt = date;
}
// PlayedAt still smaller than 1674579600
else if(car_crown[counter].playedAt < 1674579600)
{
car_crown[counter].playedAt = 1674579600;
}
// Error handling if regionId is below 1 or above 47
if(car!.regionId < 1 || car!.regionId > 47)
{
car!.regionId = Math.floor(Math.random() * 10) + 10;
}
// Push the car data to the crown holder data
// GID_RUNAREA_HIROSHIMA
if(car_crown[counter].area === 18)
{
let listCrown = wmsrv.wm.protobuf.Crown.create({
carId: car_crown[counter].carId,
area: car_crown[counter].area,
unlockAt: car_crown[counter].playedAt,
car: car!
});
// Push it after Kobe
list_crown.splice(11, 0, listCrown);
}
// GID_RUNAREA_C1 - GID_RUNAREA_TURNPIKE
else
{
list_crown.push(wmsrv.wm.protobuf.Crown.create({
carId: car_crown[counter].carId,
area: car_crown[counter].area,
unlockAt: car_crown[counter].playedAt,
car: car!
}));
}
if(counter < car_crown.length-1)
{
counter++;
}
}
// Crown holder for certain area not available
else
{
// Push the default data by the game to the crown holder data
// GID_RUNAREA_HIROSHIMA
if(i === 18)
{
let listCrown = wmsrv.wm.protobuf.Crown.create({
carId: 999999999-i,
area: i,
unlockAt: date - 1000,
});
// Push it after Kobe
list_crown.splice(11, 0, listCrown);
}
// GID_RUNAREA_C1 - GID_RUNAREA_TURNPIKE
else
{
list_crown.push(wmsrv.wm.protobuf.Crown.create({
carId: 999999999-i,
area: i,
unlockAt: date - 1000,
}));
}
}
}
}
// There is no user's crown holder data available
else
{
// Loop GID_RUNAREA
for(let i=0; i<19; i++)
{
// After Kobe is Hiroshima then Fukuoka and the rest
if(i > 14)
{
i = 18; // GID_RUNAREA_HIROSHIMA
}
// Push the default data by the game to the crown holder data
// GID_RUNAREA_HIROSHIMA
if(i === 18)
{
let listCrown = wmsrv.wm.protobuf.Crown.create({
carId: 999999999-i,
area: i,
unlockAt: date - 1000,
});
// Push it after Kobe
list_crown.splice(11, 0, listCrown);
}
// GID_RUNAREA_C1 - GID_RUNAREA_TURNPIKE
else
{
list_crown.push(wmsrv.wm.protobuf.Crown.create({
carId: 999999999-i,
area: i,
unlockAt: date - 1000,
}));
}
}
}
return { list_crown }
}

View File

@ -1,279 +0,0 @@
import { prisma } from "../..";
//Import Proto
import * as wmsrv from "../../wmmt/service.proto";
// Get TA Ranking
export async function getTimeAttackRanking()
{
// Empty list ranking records
let lists: wmsrv.wm.protobuf.Ranking.List[] = [];
// Get TA Ranking
for(let i=0; i<25; i++) // GID_TACOURSE ID
{
// Get the TA time per course
let ta_time = await prisma.timeAttackRecord.findMany({
where: {
course: i
},
orderBy: {
time: 'asc'
},
take: 10, // Take top 10
});
// TA time record by user is available for certain course
if(ta_time.length > 0)
{
// Empty list of ranking records for user time attack
let list_ta: wmsrv.wm.protobuf.Ranking.Entry[] = [];
// Get the TA time data
for(let j=0; j<ta_time.length; j++){
// Get the car data
let car_ta = await prisma.car.findFirst({
where: {
carId: ta_time[j].carId
}
});
// Push the data to the ranking data
list_ta.push(wmsrv.wm.protobuf.Ranking.Entry.create({
carId: ta_time[j].carId,
rank: car_ta!.level,
result: ta_time[j].time,
name: car_ta!.name,
regionId: car_ta!.regionId,
model: car_ta!.model,
visualModel: car_ta!.visualModel,
defaultColor: car_ta!.defaultColor,
tunePower: ta_time[j].tunePower, // Set the tunePower used when playing TA
tuneHandling: ta_time[j].tuneHandling, // Set the tuneHandling used when playing TA
title: car_ta!.title,
level: car_ta!.level
}));
}
// If the TA time record by user is less than 10 user
if(ta_time.length < 11)
{
// Take the remaining unfilled
for(let j=ta_time.length; j<11; j++){
let resultTime = 599999; // 9:59:999 time
// GID_TACOURSE_TOKYOALL & GID_TACOURSE_KANAGAWAALL area
if(i === 22 || i === 23){
resultTime = 1199999; // 19:59:999 time
}
// Push the data to the ranking data
list_ta.push(wmsrv.wm.protobuf.Ranking.Entry.create({
carId: 0,
rank: 0,
result: resultTime,
name: '',
regionId: 1, // Hokkaido
model: Math.floor(Math.random() * 50), // Randomizing Car data
visualModel: Math.floor(Math.random() * 100), // Randomizing Car data
defaultColor: 0,
tunePower: 0,
tuneHandling: 0,
title: 'Wangan Beginner', // 湾岸の新人
level: 0 // N
}));
}
}
lists.push(new wmsrv.wm.protobuf.Ranking.List({
rankingType: i, // RANKING_TA_*AREA*
topRecords: list_ta
}));
}
// There is no user's TA record for certain area
else
{
// Empty list of ranking records for time attack
let list_ta: wmsrv.wm.protobuf.Ranking.Entry[] = [];
// Generate the top 10 TA time data
for(let j=0; j<11; j++){
let resulttime = 599999; // 9:59:999 time
// GID_TACOURSE_TOKYOALL & GID_TACOURSE_KANAGAWAALL area
if(i === 22 || i === 23){
resulttime = 1199999 // 19:59:999 time
}
// Push the data to the ranking data
list_ta.push(wmsrv.wm.protobuf.Ranking.Entry.create({
carId: 0,
rank: 0,
result: resulttime,
name: '',
regionId: 1, // Hokkaido
model: Math.floor(Math.random() * 50), // Randomizing Car data
visualModel: Math.floor(Math.random() * 100), // Randomizing Car data
defaultColor: 0,
tunePower: 0,
tuneHandling: 0,
title: 'Wangan Beginner', // 湾岸の新人
level: 0 // N
}));
}
// Push the certain area ranking data to the list
lists.push(new wmsrv.wm.protobuf.Ranking.List({
rankingType: i, // RANKING_TA_*AREA*
topRecords: list_ta // Top 10 TA time record data
}));
}
}
return { lists }
}
// Get VS Outrun Ranking
export async function getVSOutrunRanking()
{
// Empty list ranking records
let lists: wmsrv.wm.protobuf.Ranking.List[] = [];
// Get VS Star Ranking
// Get the user's VS Stars data
let car_vs = await prisma.car.findMany({
orderBy: {
vsStarCount: 'desc'
},
take: 20, // Take top 20
});
// Empty list of ranking records for VS Stars
let list_vs: wmsrv.wm.protobuf.Ranking.Entry[] = [];
// Get the VS stars data
for(let i=0; i<car_vs.length; i++)
{
// Push the car data to the ranking data
list_vs.push(wmsrv.wm.protobuf.Ranking.Entry.create({
carId: car_vs[i].carId,
rank: car_vs[i].level,
result: car_vs[i].vsStarCount,
name: car_vs[i].name,
regionId: car_vs[i].regionId,
model: car_vs[i].model,
visualModel: car_vs[i].visualModel,
defaultColor: car_vs[i].defaultColor,
tunePower: car_vs[i].tunePower,
tuneHandling: car_vs[i].tuneHandling,
title: car_vs[i].title,
level: car_vs[i].level
}));
}
// If the VS stars record by user is less than 20 user
if(car_vs.length < 20)
{
// Take the remaining unfilled
for(let j=car_vs.length; j<21; j++)
{
// Push the data to the ranking data
list_vs.push(wmsrv.wm.protobuf.Ranking.Entry.create({
carId: 0,
rank: 0,
result: 0,
name: '',
regionId: 1, // Hokkaido
model: Math.floor(Math.random() * 50), // Randomizing Car data
visualModel: Math.floor(Math.random() * 100), // Randomizing Car data
defaultColor: 0,
tunePower: 0,
tuneHandling: 0,
title: 'Wangan Beginner', // 湾岸の新人
level: 0 // N
}));
}
}
// Push the data
lists.push(new wmsrv.wm.protobuf.Ranking.List({
rankingType: 100, // RANKING_VS_STAR
topRecords: list_vs // Top 20 VS stars record data
}));
return { lists }
}
// Get Ghost Trophies Ranking
export async function getTGhostTrophiesRanking()
{
// Empty list ranking records
let lists: wmsrv.wm.protobuf.Ranking.List[] = [];
// Get Ghost Defeated Ranking
// Get the user's Ghost Win data
let car_ghost = await prisma.car.findMany({
orderBy: {
rgWinCount: 'desc'
},
take: 20, // Take top 20
});
// Empty list of ranking records for Ghost Battle Win
let list_ghost: wmsrv.wm.protobuf.Ranking.Entry[] = [];
// Get the Ghost Battle Win data
for(let i=0; i<car_ghost.length; i++){
// Push the car data to the ranking data
list_ghost.push(wmsrv.wm.protobuf.Ranking.Entry.create({
carId: car_ghost[i].carId,
rank: car_ghost[i].level,
result: car_ghost[i].rgWinCount,
name: car_ghost[i].name,
regionId: car_ghost[i].regionId,
model: car_ghost[i].model,
visualModel: car_ghost[i].visualModel,
defaultColor: car_ghost[i].defaultColor,
tunePower: car_ghost[i].tunePower,
tuneHandling: car_ghost[i].tuneHandling,
title: car_ghost[i].title,
level: car_ghost[i].level
}));
}
// If the Ghost Win record by user is less than 20 user
if(car_ghost.length < 20){
// Take the remaining unfilled
for(let j=car_ghost.length; j<21; j++){
// Push the data to the ranking data
list_ghost.push(wmsrv.wm.protobuf.Ranking.Entry.create({
carId: 0,
rank: 0,
result: 0,
name: '',
regionId: 1, // Hokkaido
model: Math.floor(Math.random() * 50), // Randomizing Car data
visualModel: Math.floor(Math.random() * 100), // Randomizing Car data
defaultColor: 0,
tunePower: 0,
tuneHandling: 0,
title: 'Wangan Beginner', // 湾岸の新人
level: 0 // N
}));
}
}
// Push the data
lists.push(new wmsrv.wm.protobuf.Ranking.List({
rankingType: 101, // RANKING_GHOST_DEFEATED_COUNT
topRecords: list_ghost // Top 20 Ghost Win record data
}));
return { lists }
}

View File

@ -1,12 +1,12 @@
import { Application } from "express";
import { Module } from "module";
import { prisma } from "..";
// Import Proto
import * as wm from "../wmmt/wm.proto";
// Import Util
import * as common from "./util/common";
import * as startupFunctions from "./startup/functions";
import * as common from "../util/common";
export default class StartupModule extends Module {
@ -21,9 +21,108 @@ export default class StartupModule extends Module {
// Get current date
let date = Math.floor(new Date().getTime() / 1000);
// Get Competition (OCM) Event Date
let getCompetitionSchedule = await startupFunctions.competitionSchedule(date, null);
let additionalCompetitionMsg = getCompetitionSchedule.additionalCompetitionMsg;
// Get current / previous active OCM Event
let ocmEventDate = await prisma.oCMEvent.findFirst({
where: {
// qualifyingPeriodStartAt is less than current date
qualifyingPeriodStartAt: { lte: date },
// competitionEndAt is greater than current date
competitionEndAt: { gte: date },
},
orderBy: {
competitionEndAt: 'desc',
}
});
let pastEvent = 0;
if(!(ocmEventDate))
{
ocmEventDate = await prisma.oCMEvent.findFirst({
orderBy:{
competitionId: 'desc'
}
});
pastEvent = 1;
}
// Declare GhostCompetitionSchedule
let competitionSchedule;
let lastCompetitionId: number = 0;
if(ocmEventDate)
{
let pastDay = date - ocmEventDate.competitionEndAt
if(pastDay < 604800)
{
console.log("OCM Event Available");
// Creating GhostCompetitionSchedule
competitionSchedule = wm.wm.protobuf.GhostCompetitionSchedule.create({
// OCM Competition ID (1 = C1 (Round 16), 4 = Nagoya (Round 19), 8 = Hiroshima (Round 21))
competitionId: ocmEventDate.competitionId,
// OCM Qualifying Start Timestamp
qualifyingPeriodStartAt: ocmEventDate.qualifyingPeriodStartAt,
// OCM Qualifying Close Timestamp
qualifyingPeriodCloseAt: ocmEventDate.qualifyingPeriodCloseAt,
// OCM Competition (Main Draw) Start Timestamp
competitionStartAt: ocmEventDate.competitionStartAt,
// OCM Competition (Main Draw) Close Timestamp
competitionCloseAt: ocmEventDate.competitionCloseAt,
// OCM Competition (Main Draw) End Timestamp
competitionEndAt: ocmEventDate.competitionEndAt,
// idk what this is
lengthOfPeriod: ocmEventDate.lengthOfPeriod,
// idk what this is
lengthOfInterval: ocmEventDate.lengthOfInterval,
// Area for the event (GID_RUNAREA_*, 8 is GID_RUNAREA_NAGOYA)
area: ocmEventDate.area,
// idk what this is
minigamePatternId: ocmEventDate.minigamePatternId
});
}
if(pastEvent === 1)
{
console.log("Previous OCM Event Available");
lastCompetitionId = ocmEventDate.competitionId
}
}
// Get VSORG Event Date
let ghostExpeditionDate = await prisma.ghostExpeditionEvent.findFirst({
where: {
// qualifyingPeriodStartAt is less than equal current date
startAt: { lte: date },
// competitionEndAt is greater than equal current date
aftereventEndAt: { gte: date },
},
})
let vsOrgEventDate;
if(ghostExpeditionDate)
{
vsOrgEventDate = wm.wm.protobuf.GhostExpeditionSchedule.create({
ghostExpeditionId: ghostExpeditionDate.ghostExpeditionId,
startAt: ghostExpeditionDate.startAt,
endAt: ghostExpeditionDate.endAt,
aftereventEndAt: ghostExpeditionDate.aftereventEndAt,
opponentCountry: ghostExpeditionDate.opponentCountry // not sure if this connected to ghostExpeditionId or not
});
}
// Response data
let msg = {
@ -40,9 +139,14 @@ export default class StartupModule extends Module {
pluses: 0,
releaseAt: 0 // idk what this is
},
// OCM
latestCompetitionId: lastCompetitionId || null,
competitionSchedule: competitionSchedule || null, // OCM Event Available or not
// Competition (OCM)
...additionalCompetitionMsg
// VSORG
expeditionSchedule: vsOrgEventDate || null,
expeditionEventWasHeld: true
}
// Encode the response
@ -73,7 +177,6 @@ export default class StartupModule extends Module {
common.sendResponse(message, res);
});
// Ping
app.post('/method/ping', (req, res) => {
@ -93,7 +196,6 @@ export default class StartupModule extends Module {
})
// Register System Stats
app.post('/method/register_system_stats', async (req, res) => {
let body = wm.wm.protobuf.RegisterSystemStatsRequest.decode(req.body);
@ -114,7 +216,6 @@ export default class StartupModule extends Module {
})
// Update Event Mode Serial
app.post('/method/update_event_mode_serial', async (req, res) => {
let body = wm.wm.protobuf.UpdateEventModeSerialRequest.decode(req.body);
@ -125,10 +226,7 @@ export default class StartupModule extends Module {
// Response data
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
serialError: wm.wm.protobuf.EventModeSerialErrorCode.SERIAL_SUCCESS,
eventModeSerial: body.eventModeSerial || '285013990002',
startAt: 0,
endAt: 2147483647
serialError: wm.wm.protobuf.EventModeSerialErrorCode.SERIAL_NO_INPUT
}
// Encode the response
@ -139,7 +237,6 @@ export default class StartupModule extends Module {
})
// Submit Client Log
app.post('/method/submit_client_log', async (req, res) => {
let body = wm.wm.protobuf.SubmitClientLogRequest.decode(req.body);

View File

@ -1,128 +0,0 @@
import { prisma } from "../..";
// Import Proto
import * as wm from "../../wmmt/wm.proto";
// Get Competition (OCM) Schedule
export async function competitionSchedule(date: any, competitionId: any)
{
// Get the Competition (OCM) schedule
let ghostCompetitionSchedule;
// Request by compedtitionId
if(competitionId)
{
ghostCompetitionSchedule = await prisma.oCMEvent.findFirst({
where: {
competitionId: competitionId
},
orderBy: {
competitionId: 'desc'
}
});
}
// Request by date
else
{
ghostCompetitionSchedule = await prisma.oCMEvent.findFirst({
where: {
// qualifyingPeriodStartAt is less than current date
qualifyingPeriodStartAt: { lte: Number(date) },
// competitionEndAt is greater than current date
competitionEndAt: { gte: Number(date) },
}
});
}
// Other variable
let competitionSchedule;
let lastCompetitionId: number = 0;
let additionalCompetitionMsg = {};
// Currently no Active Competition (OCM) Event.. Getting Previous Competition (OCM) Event
let pastEvent = 0;
if(!(ghostCompetitionSchedule))
{
ghostCompetitionSchedule = await prisma.oCMEvent.findFirst({
orderBy:{
competitionId: 'desc'
}
});
pastEvent = 1;
}
// Previous / Current Competition (OCM) available
if(ghostCompetitionSchedule)
{
console.log('Ghost Competition (OCM) Available');
let pastDay = date - ghostCompetitionSchedule.competitionEndAt;
if(pastDay < 604800)
{
// Creating GhostCompetitionSchedule
competitionSchedule = wm.wm.protobuf.GhostCompetitionSchedule.create({
// Competition ID
competitionId: ghostCompetitionSchedule.competitionId,
// Competition Qualifying Start Timestamp
qualifyingPeriodStartAt: ghostCompetitionSchedule.qualifyingPeriodStartAt,
// Competition Qualifying Close Timestamp
qualifyingPeriodCloseAt: ghostCompetitionSchedule.qualifyingPeriodCloseAt,
// Competition (Main Draw) Start Timestamp
competitionStartAt: ghostCompetitionSchedule.competitionStartAt,
// Competition (Main Draw) Close Timestamp
competitionCloseAt: ghostCompetitionSchedule.competitionCloseAt,
// Competition (Main Draw) End Timestamp
competitionEndAt: ghostCompetitionSchedule.competitionEndAt,
// Competition (Main Draw) length per periods
lengthOfPeriod: ghostCompetitionSchedule.lengthOfPeriod,
// Competition (Main Draw) interval (for tallying) per periods
lengthOfInterval: ghostCompetitionSchedule.lengthOfInterval,
// Area for the Competition Event (GID_RUNAREA_*)
area: ghostCompetitionSchedule.area,
// idk what this is
minigamePatternId: ghostCompetitionSchedule.minigamePatternId
});
}
// It's previous Competition (OCM) event
if(pastEvent === 1)
{
// Get current date
let dates = Math.floor(new Date().getTime() / 1000);
let lastScheduleCompetitionId = await prisma.oCMEvent.findFirst({
where: {
competitionCloseAt: { lte: dates }
},
orderBy:{
competitionId: 'desc'
}
});
lastCompetitionId = lastScheduleCompetitionId?.competitionId || 0;
}
// Competition (OCM) Response Message
additionalCompetitionMsg = {
latestCompetitionId: lastCompetitionId,
competitionSchedule: competitionSchedule,
}
}
return { additionalCompetitionMsg, competitionSchedule }
}

View File

@ -8,8 +8,8 @@ import { Car } from "@prisma/client";
import * as wm from "../wmmt/wm.proto";
// Import Util
import * as scratch from "./terminal/scratch";
import * as common from "./util/common";
import * as scratch from "../util/scratch";
import * as common from "../util/common";
export default class TerminalModule extends Module {
@ -186,9 +186,7 @@ export default class TerminalModule extends Module {
// Get the query from the request
let query = req.query;
let cars: wm.wm.protobuf.Car[] = [];
let car;
let arr = [];
let cars;
// Check the query limit
let queryLimit = 10
@ -212,23 +210,22 @@ export default class TerminalModule extends Module {
queryLastPlayedPlaceId = getLastPlayedPlaceId.id;
}
car = await prisma.car.findMany({
cars = await prisma.car.findMany({
take: queryLimit,
where: {
lastPlayedPlaceId: queryLastPlayedPlaceId
},
include:{
gtWing: true,
lastPlayedPlace: true
},
orderBy: {
carId: "asc"
}
});
}
else
{
// Get all of the cars matching the query
car = await prisma.car.findMany({
cars = await prisma.car.findMany({
take: queryLimit,
where: {
OR:[
{
@ -247,49 +244,9 @@ export default class TerminalModule extends Module {
include:{
gtWing: true,
lastPlayedPlace: true
},
orderBy: {
carId: "asc"
}
});
}
if(car.length > 0)
{
if(car.length < queryLimit)
{
queryLimit = car.length;
}
// Choose the user's car data randomly to appear
while(arr.length < queryLimit)
{
// Randomize pick
let random: number = 1;
// Randomize it 5 times
for(let i=0; i<5; i++)
{
random = Math.floor(Math.random() * car.length);
}
// Try randomize it again if it's 1
if(random === 1)
{
random = Math.floor(Math.random() * car.length);
}
if(arr.indexOf(random) === -1)
{
// Push current number to array
arr.push(random);
cars.push(wm.wm.protobuf.Car.create({
...car[random]
}));
}
}
}
let msg = {
hitCount: cars.length,
@ -678,31 +635,32 @@ export default class TerminalModule extends Module {
periodId: 'desc'
}
],
include:{
car: true
},
distinct: ["carId"],
take: 50
})
numOfParticipants = ocmParticipant.length;
periodId = 0;
let ranking = 0;
if(numOfParticipants > 0)
{
if(ocmParticipant)
{
periodId = ocmParticipant[0].periodId;
for(let i=0; i<ocmParticipant.length; i++)
{
let cars = await prisma.car.findFirst({
where:{
carId: ocmParticipant[i].carId
},
include:{
gtWing: true,
lastPlayedPlace: true
}
});
let ocmGhostrecord = await prisma.oCMGhostBattleRecord.findFirst({
where:{
carId: ocmParticipant[0].carId,
competitionId: ocmEventDate!.competitionId,
},
select:{
playedShopName: true,
playedAt: true
}
});
@ -718,14 +676,14 @@ export default class TerminalModule extends Module {
rank: i + 1,
result: ocmParticipant[i].result,
carId: ocmParticipant[i].carId,
name: ocmParticipant[i].car.name,
regionId: ocmParticipant[i].car.regionId,
model: ocmParticipant[i].car.model,
visualModel: ocmParticipant[i].car.visualModel,
defaultColor: ocmParticipant[i].car.defaultColor,
title: ocmParticipant[i].car.title,
level: ocmParticipant[i].car.level,
windowStickerString: ocmParticipant[i].car.windowStickerString,
name: cars!.name,
regionId: cars!.regionId,
model: cars!.model,
visualModel: cars!.visualModel,
defaultColor: cars!.defaultColor,
title: cars!.title,
level: cars!.level,
windowStickerString: cars!.windowStickerString,
playedShopName: playedShopName,
playedAt: ocmGhostrecord!.playedAt
});
@ -738,66 +696,18 @@ export default class TerminalModule extends Module {
rank: i + 1,
result: ocmParticipant[i].result,
carId: ocmParticipant[i].carId,
name: ocmParticipant[i].car.name,
regionId: ocmParticipant[i].car.regionId,
model: ocmParticipant[i].car.model,
visualModel: ocmParticipant[i].car.visualModel,
defaultColor: ocmParticipant[i].car.defaultColor,
title: ocmParticipant[i].car.title,
level: ocmParticipant[i].car.level,
windowStickerString: ocmParticipant[i].car.windowStickerString,
name: cars!.name,
regionId: cars!.regionId,
model: cars!.model,
visualModel: cars!.visualModel,
defaultColor: cars!.defaultColor,
title: cars!.title,
level: cars!.level,
windowStickerString: cars!.windowStickerString,
playedShopName: playedShopName,
playedAt: ocmGhostrecord!.playedAt
}));
}
if(!(ownRecords))
{
let ocmPersonalRank = [{ result: 0, position: 0 }];
ocmPersonalRank = await prisma.$queryRaw`
select "result", "position" from
(select *, row_number() over(order by "result" DESC) as "position" from "OCMTally"
where "competitionId" = ${body.competitionId}) "OCMTally" where "carId" = ${body.carId}`;
if(ocmPersonalRank.length > 0)
{
let userCar = await prisma.car.findFirst({
where:{
carId: body.carId
}
});
let userPlayedAt = await prisma.oCMGhostBattleRecord.findFirst({
where:{
carId: body.carId,
competitionId: body.competitionId
},
select:{
playedAt: true
}
});
let myRank = Number(ocmPersonalRank[0].position);
let myResult = Number(ocmPersonalRank[0].result);
ownRecords = wm.wm.protobuf.LoadGhostCompetitionRankingResponse.Entry.create({
rank: myRank,
result: myResult,
carId: userCar!.carId,
name: userCar!.name,
regionId: userCar!.regionId,
model: userCar!.model,
visualModel: userCar!.visualModel,
defaultColor: userCar!.defaultColor,
title: userCar!.title,
level: userCar!.level,
windowStickerString: userCar!.windowStickerString,
playedShopName: playedShopName,
playedAt: userPlayedAt?.playedAt || 0
});
}
}
}
}
// Current date is OCM qualifying day
@ -811,21 +721,27 @@ export default class TerminalModule extends Module {
},
orderBy: {
result: 'desc'
},
include:{
car: true
},
distinct: ["carId"],
}
})
numOfParticipants = ocmParticipant.length;
periodId = 0;
let ranking = 0;
if(numOfParticipants > 0)
if(ocmParticipant)
{
for(let i=0; i<numOfParticipants; i++)
for(let i=0; i<ocmParticipant.length; i++)
{
let cars = await prisma.car.findFirst({
where:{
carId: ocmParticipant[i].carId
},
include:{
gtWing: true,
lastPlayedPlace: true
}
})
if(ocmParticipant[i].carId === body.carId && ranking === 0)
{
// User car setting
@ -833,21 +749,37 @@ export default class TerminalModule extends Module {
rank: i + 1,
result: ocmParticipant[i].result,
carId: ocmParticipant[i].carId,
name: ocmParticipant[i].car.name,
regionId: ocmParticipant[i].car.regionId,
model: ocmParticipant[i].car.model,
visualModel: ocmParticipant[i].car.visualModel,
defaultColor: ocmParticipant[i].car.defaultColor,
title: ocmParticipant[i].car.title,
level: ocmParticipant[i].car.level,
windowStickerString: ocmParticipant[i].car.windowStickerString,
playedShopName: playedShopName,
name: cars!.name,
regionId: cars!.regionId,
model: cars!.model,
visualModel: cars!.visualModel,
defaultColor: cars!.defaultColor,
title: cars!.title,
level: cars!.level,
windowStickerString: cars!.windowStickerString,
playedShopName: ocmParticipant[i].playedShopName,
playedAt: ocmParticipant[i].playedAt
});
ranking++;
break;
}
// Generate OCM Top Records
topRecords.push(wm.wm.protobuf.LoadGhostCompetitionRankingResponse.Entry.create({
rank: i + 1,
result: ocmParticipant[i].result,
carId: ocmParticipant[i].carId,
name: cars!.name,
regionId: cars!.regionId,
model: cars!.model,
visualModel: cars!.visualModel,
defaultColor: cars!.defaultColor,
title: cars!.title,
level: cars!.level,
windowStickerString: cars!.windowStickerString,
playedShopName: ocmParticipant[i].playedShopName,
playedAt: ocmParticipant[i].playedAt
}));
}
}
}
@ -856,52 +788,41 @@ export default class TerminalModule extends Module {
{
console.log('Current / Previous OCM Day : OCM has Ended');
// Get Current OCM Period and All User's Record
let ocmParticipant = await prisma.oCMTally.findMany({
where:{
competitionId: ocmEventDate!.competitionId,
periodId: 999999999
},
orderBy: [
{
result: 'desc'
},
{
periodId: 'desc'
}
],
include:{
car: true
},
distinct: ["carId"],
take: 10
orderBy: {
result: 'desc'
}
})
numOfParticipants = ocmParticipant.length;
periodId = 0;
let ranking = 0;
if(numOfParticipants > 0)
{
periodId = ocmParticipant[0].periodId;
if(ocmParticipant)
{
for(let i=0; i<ocmParticipant.length; i++)
{
let cars = await prisma.car.findFirst({
where:{
carId: ocmParticipant[i].carId
},
include:{
gtWing: true,
lastPlayedPlace: true
}
});
let ocmGhostrecord = await prisma.oCMGhostBattleRecord.findFirst({
where:{
carId: ocmParticipant[0].carId,
competitionId: ocmEventDate!.competitionId,
},
select:{
playedShopName: true,
playedAt: true
}
});
if(ocmGhostrecord?.playedShopName !== null && ocmGhostrecord?.playedShopName !== undefined)
{
playedShopName = ocmGhostrecord.playedShopName;
}
if(ocmParticipant[i].carId === body.carId && ranking === 0)
{
// User car setting
@ -909,15 +830,15 @@ export default class TerminalModule extends Module {
rank: i + 1,
result: ocmParticipant[i].result,
carId: ocmParticipant[i].carId,
name: ocmParticipant[i].car.name,
regionId: ocmParticipant[i].car.regionId,
model: ocmParticipant[i].car.model,
visualModel: ocmParticipant[i].car.visualModel,
defaultColor: ocmParticipant[i].car.defaultColor,
title: ocmParticipant[i].car.title,
level: ocmParticipant[i].car.level,
windowStickerString: ocmParticipant[i].car.windowStickerString,
playedShopName: playedShopName,
name: cars!.name,
regionId: cars!.regionId,
model: cars!.model,
visualModel: cars!.visualModel,
defaultColor: cars!.defaultColor,
title: cars!.title,
level: cars!.level,
windowStickerString: cars!.windowStickerString,
playedShopName: ocmGhostrecord!.playedShopName,
playedAt: ocmGhostrecord!.playedAt
});
@ -929,66 +850,18 @@ export default class TerminalModule extends Module {
rank: i + 1,
result: ocmParticipant[i].result,
carId: ocmParticipant[i].carId,
name: ocmParticipant[i].car.name,
regionId: ocmParticipant[i].car.regionId,
model: ocmParticipant[i].car.model,
visualModel: ocmParticipant[i].car.visualModel,
defaultColor: ocmParticipant[i].car.defaultColor,
title: ocmParticipant[i].car.title,
level: ocmParticipant[i].car.level,
windowStickerString: ocmParticipant[i].car.windowStickerString,
playedShopName: playedShopName,
name: cars!.name,
regionId: cars!.regionId,
model: cars!.model,
visualModel: cars!.visualModel,
defaultColor: cars!.defaultColor,
title: cars!.title,
level: cars!.level,
windowStickerString: cars!.windowStickerString,
playedShopName: ocmGhostrecord!.playedShopName,
playedAt: ocmGhostrecord!.playedAt
}));
}
if(!(ownRecords))
{
let ocmPersonalRank = [{ result: 0, position: 0 }];
ocmPersonalRank = await prisma.$queryRaw`
select "result", "position" from
(select *, row_number() over(order by "result" DESC) as "position" from "OCMTally"
where "competitionId" = ${body.competitionId}) "OCMTally" where "carId" = ${body.carId}`;
if(ocmPersonalRank.length > 0)
{
let userCar = await prisma.car.findFirst({
where:{
carId: body.carId
}
});
let userPlayedAt = await prisma.oCMGhostBattleRecord.findFirst({
where:{
carId: body.carId,
competitionId: body.competitionId
},
select:{
playedAt: true
}
});
let myRank = Number(ocmPersonalRank[0].position);
let myResult = Number(ocmPersonalRank[0].result);
ownRecords = wm.wm.protobuf.LoadGhostCompetitionRankingResponse.Entry.create({
rank: myRank,
result: myResult,
carId: userCar!.carId,
name: userCar!.name,
regionId: userCar!.regionId,
model: userCar!.model,
visualModel: userCar!.visualModel,
defaultColor: userCar!.defaultColor,
title: userCar!.title,
level: userCar!.level,
windowStickerString: userCar!.windowStickerString,
playedShopName: playedShopName,
playedAt: userPlayedAt?.playedAt || 0
});
}
}
}
}
@ -1130,6 +1003,24 @@ export default class TerminalModule extends Module {
});
app.post('/method/save_screenshot', async (req, res) => {
// Get the information from the request
let body = wm.wm.protobuf.SaveScreenshotRequest.decode(req.body);
// Response data
let msg = {
error: wm.wm.protobuf.ErrorCode.ERR_SUCCESS,
};
// Encode the response
let message = wm.wm.protobuf.SaveScreenshotResponse.encode(msg);
// Send the response to the client
common.sendResponse(message, res);
});
/*
app.post('/method/load_unreceived_user_items', async (req, res) => {

View File

@ -6,7 +6,7 @@ import { prisma } from "..";
import * as wm from "../wmmt/wm.proto";
// Import Util
import * as common from "./util/common";
import * as common from "../util/common";
export default class TimeAttackModule extends Module {

View File

@ -7,8 +7,8 @@ import { prisma } from "..";
import * as wm from "../wmmt/wm.proto";
// Import Util
import * as scratch from "./terminal/scratch";
import * as common from "./util/common";
import * as scratch from "../util/scratch";
import * as common from "../util/common";
export default class UserModule extends Module {
@ -19,6 +19,9 @@ export default class UserModule extends Module {
// Get the request body for the load user request
let body = wm.wm.protobuf.LoadUserRequest.decode(req.body);
// Trim Mojibake (happens if user using release version of bngrw)
body.cardChipId = body.cardChipId.replace('<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0000', '');
// Block blank card.ini data and vanilla TP blank card data
if(body.cardChipId.match(/7F5C9744F11111114326.*/) || body.cardChipId.match(/0000000000.*/))
@ -26,7 +29,7 @@ export default class UserModule extends Module {
body.cardChipId = '';
body.accessCode = '';
}
// Get the user from the database
let user = await prisma.user.findFirst({
where: {
@ -39,9 +42,6 @@ export default class UserModule extends Module {
state: true,
gtWing: true,
lastPlayedPlace: true
},
where:{
state: { toBeDeleted: false } // except deleted car
}
}
}
@ -58,6 +58,10 @@ export default class UserModule extends Module {
cars: [],
spappState: wm.wm.protobuf.SmartphoneAppState.SPAPP_UNREGISTERED,
transferState: wm.wm.protobuf.TransferState.NOT_REGISTERED,
fullTunedCarTicket: false, // TODO: Maybe... idk
ghostVs_2Locked: false, // TODO: Maybe... idk
ghostVs_3Locked: false, // TODO: Maybe... idk
ghostHighwayLocked: false, // TODO: Maybe... idk
};
if (!body.cardChipId || !body.accessCode)
@ -74,30 +78,11 @@ export default class UserModule extends Module {
}
// Check if new card registration is allowed or not
let newCardsBanned = Config.getConfig().gameOptions.newCardsBanned || 0;
let newCardsBanned = Config.getConfig().gameOptions.newCardsBanned;
// New card registration is allowed
if (newCardsBanned === 0)
{
let checkUser = await prisma.user.findFirst({
where:{
chipId: body.cardChipId
}
});
if(checkUser)
{
msg.error = wm.wm.protobuf.ErrorCode.ERR_USER_LOCKED;
// Encode the response
let message = wm.wm.protobuf.LoadUserResponse.encode(msg);
// Send the response to the client
common.sendResponse(message, res);
return;
}
let user = await prisma.user.create({
data: {
chipId: body.cardChipId,
@ -236,8 +221,8 @@ export default class UserModule extends Module {
if (user.carOrder.length > 0)
{
// Sort the player's car list using the car order property
user.cars = user.cars.sort(function(a, b)
{
user.cars = user.cars.sort(function(a, b){
// User, and both car IDs exist
if (user)
{
@ -348,6 +333,22 @@ export default class UserModule extends Module {
}
})
}
// Check ghost trophy count if more than 50 or not
let ghostExpeditionLocked: boolean = true;
let checkRgTrophy = await prisma.car.findFirst({
where:{
userId: user.id,
rgTrophy:{
gte: 50 // greater than equal 50
}
}
})
if(checkRgTrophy)
{
ghostExpeditionLocked = false;
}
// Response data
@ -388,7 +389,13 @@ export default class UserModule extends Module {
wasCreatedToday: false,
// Invite Friend Campaign Event
participatedInInviteFriendCampaign: false
participatedInInviteFriendCampaign: false,
// TODO: Make saving about this
ghostExpeditionLocked: ghostExpeditionLocked, // must more than 50 rgTrophy
ghostVs_2Locked: false,
ghostVs_3Locked: false,
ghostHighwayLocked: false,
}
@ -606,6 +613,9 @@ export default class UserModule extends Module {
// Get the request body for the create user request
let body = wm.wm.protobuf.CreateUserRequest.decode(req.body);
// Trim Mojibake (happens if user using release version of bngrw)
body.cardChipId = body.cardChipId.replace('<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0000', '');
// Get the user info via the card chip id
let user = await prisma.user.findFirst({
where: {

View File

@ -1,85 +0,0 @@
// OpenTelemetry tracing module
import * as opentelemetry from '@opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { diag, DiagConsoleLogger, DiagLogLevel } from '@opentelemetry/api';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc';
import { Resource } from '@opentelemetry/resources';
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
import process from 'process';
import {Request, Response, Application} from 'express';
import { AggregationTemporality, MeterProvider, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';
export function startTracing() {
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.INFO);
const sdk = new opentelemetry.NodeSDK({
traceExporter: new OTLPTraceExporter({
url: process.env.OPENTELEMETRY_OTLP_URI,
headers: {}
}),
resource: new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: 'bayshore',
[SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]:
process.env.NODE_ENV !== undefined ? process.env.NODE_ENV : 'development',
}),
instrumentations: [getNodeAutoInstrumentations()]
});
sdk.start();
}
interface MiddlewareOpts {
appName: string,
}
interface HttpMetricsParameter {
app: Application,
options: MiddlewareOpts
}
// TODO: Implement stuff in such a way to make it be possible to view data like
// time attack clears per hour, story stuff etc etc. Not now tho, later
export function startHttpMetrics(apps: HttpMetricsParameter[]) {
const provider = new MeterProvider({
resource: new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: 'bayshore',
[SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]:
process.env.NODE_ENV !== undefined ? process.env.NODE_ENV : 'development',
}),
});
function configureMiddleware(opts: MiddlewareOpts) {
let meter = provider.getMeter(opts.appName);
var counter = meter.createCounter('requests_made', {
description: 'Number of requests registered to application'
});
return function(req: Request, res: Response, next: CallableFunction) {
counter.add(1, {
url: req.url
});
next();
}
}
console.log('Registering middleware metrics');
for (let appObj of apps) {
console.log(`Registered metrics application for ${appObj.options.appName}`);
appObj.app.use(configureMiddleware(appObj.options));
}
const exporter = new OTLPMetricExporter({
url: process.env.OPENTELEMETRY_OTLP_HTTP_URI,
});
provider.addMetricReader(new PeriodicExportingMetricReader({
exporter,
exportIntervalMillis: 15000,
exportTimeoutMillis: 1000,
}));
console.log('Metrics started');
}

View File

@ -44,21 +44,18 @@ export function getBigIntFromLong(n: Long)
}
// Undefined Input Sanitization
export function sanitizeInput(value: any)
{
return (value == null || value == undefined) ? undefined : value;
}
// Undefined and Zero Input Sanitization
export function sanitizeInputNotZero(value: any)
{
return (value !== null && value !== undefined && value !== 0) ? value : undefined;
}
// Get Time Stamp
export function getTimeStamp(date: Date = new Date())
{
// Return a timestamp string for the current / provided time

View File

@ -5,9 +5,10 @@ import { wm } from "../../wmmt/wm.proto";
import wmproto from "../../wmmt/wm.proto";
// Import Util
import * as common from "../util/common";
import * as common from "../../util/common";
import * as ghost_history from "../ghost/ghost_history";
import * as ghost_stamp from "../ghost/ghost_stamp";
import * as ghost_crown from "../ghost/ghost_crown";
// Save ghost battle result
export async function saveGhostBattleResult(body: wm.protobuf.SaveGameResultRequest, car: any)
@ -29,6 +30,7 @@ export async function saveGhostBattleResult(body: wm.protobuf.SaveGameResultRequ
let dataGhost : any;
let dataCar : any;
let dataCarGTWing: any;
let dataHighway : any;
// Get the ghost result for the car
let cars = body?.car;
@ -106,6 +108,7 @@ export async function saveGhostBattleResult(body: wm.protobuf.SaveGameResultRequ
dressupPoint: common.sanitizeInput(ghostResult.dressupPoint),
stampSheet: stampSheet,
stampSheetCount: common.sanitizeInputNotZero(ghostResult.stampSheetCount),
rgTrophy: common.sanitizeInputNotZero(ghostResult.rgTrophy),
}
// Count total win based on region map score
@ -122,7 +125,21 @@ export async function saveGhostBattleResult(body: wm.protobuf.SaveGameResultRequ
// Set the data
dataGhost.rgWinCount = winCounter;
dataGhost.rgScore = winCounter;
dataGhost.rgTrophy = winCounter;
}
}
// Get the ghost result for the car
let highwayResult = body.rgResult?.highwayResult;
// ghostResult is set
if (highwayResult)
{
// Highway Ghost update data
dataHighway = {
rgHighwayClearCount: common.sanitizeInput(highwayResult.rgHighwayClearCount),
rgHighwayPoint: common.sanitizeInput(highwayResult.rgHighwayPoint),
rgHighwayStationClearBits: common.sanitizeInput(highwayResult.rgHighwayStationClearBits),
rgHighwayPreviousDice: common.sanitizeInput(highwayResult.rgHighwayPreviousDice),
}
}
@ -134,6 +151,7 @@ export async function saveGhostBattleResult(body: wm.protobuf.SaveGameResultRequ
data: {
...dataGhost,
...dataCar,
...dataHighway
}
});
@ -195,136 +213,7 @@ export async function saveGhostBattleResult(body: wm.protobuf.SaveGameResultRequ
{
console.log('Win the Crown Ghost Battle');
// Get the ghost crown result
let ghostResultCrown = body?.rgResult;
// Declare data
let dataCrown : any;
// ghostResultCrown is set
if (ghostResultCrown)
{
let carId: number = 0;
if(body.carId)
{
carId = Number(body.carId);
}
// Ghost Crown update data
dataCrown = {
carId: carId,
playedAt: common.sanitizeInput(body.playedAt),
tunePower: common.sanitizeInput(body.car?.tunePower),
tuneHandling: common.sanitizeInput(body.car?.tuneHandling),
}
// Get the area id and ramp id
let area = 0;
let ramp = 0;
let path = 0;
if(body.rgResult?.path)
{
if(body.rgResult?.path >= 0 && body.rgResult?.path <= 9){ // GID_PATH_C1
area = Number(0);
ramp = Number(Math.floor(Math.random() * 4));
}
else if(body.rgResult?.path >= 10 && body.rgResult?.path <= 15){ // GID_PATH_N9
area = Number(1);
ramp = Number(Math.floor(Math.random() * 2) + 4);
}
else if(body.rgResult?.path >= 16 && body.rgResult?.path <= 17){ // GID_PATH_WTEAST
area = Number(2);
ramp = Number(Math.floor(Math.random() * 2) + 6);
}
else if(body.rgResult?.path >= 18 && body.rgResult?.path <= 19){ // GID_PATH_WT_UP_DOWN
area = Number(3);
ramp = Number(Math.floor(Math.random() * 2) + 8);
}
else if(body.rgResult?.path >= 20 && body.rgResult?.path <= 26){ // GID_PATH_WG
area = Number(4);
ramp = Number(Math.floor(Math.random() * 4) + 10);
}
else if(body.rgResult?.path >= 27 && body.rgResult?.path <= 33){ // GID_PATH_KG
area = Number(5);
ramp = Number(Math.floor(Math.random() * 4) + 14);
}
else if(body.rgResult?.path >= 34 && body.rgResult?.path <= 37){ // GID_PATH_YS
area = Number(6);
ramp = Number(Math.floor(Math.random() * 3) + 18);
}
else if(body.rgResult?.path >= 38 && body.rgResult?.path <= 48){ // GID_PATH_KG_SHINYAMASHITA_MINATOMIRAI
area = Number(7);
ramp = Number(Math.floor(Math.random() * 4) + 21);
}
else if(body.rgResult?.path === 49){ // GID_PATH_NGR
area = Number(8);
ramp = Number(25);
}
else if(body.rgResult?.path >= 50 && body.rgResult?.path <= 53){ // GID_PATH_OS
area = Number(9);
ramp = Number(26);
}
else if(body.rgResult?.path >= 54 && body.rgResult?.path <= 55){ // GID_PATH_KB
area = Number(10);
ramp = Number(Math.floor(Math.random() * 2) + 27);
}
else if(body.rgResult?.path >= 58 && body.rgResult?.path <= 61){ // GID_PATH_FK
area = Number(11);
ramp = Number(Math.floor(Math.random() * 4) + 29);
}
else if(body.rgResult?.path >= 62 && body.rgResult?.path <= 63){ // GID_PATH_HK
area = Number(12);
ramp = Number(Math.floor(Math.random() * 2) + 33);
}
else if(body.rgResult?.path >= 64 && body.rgResult?.path <= 65){ // GID_PATH_TP
area = Number(13);
ramp = Number(Math.floor(Math.random() * 2) + 35);
}
else if(body.rgResult?.path >= 56 && body.rgResult?.path <= 57){ // GID_PATH_HS
area = Number(18);
ramp = Number(Math.floor(Math.random() * 2) + 27);
}
path = Number(body.rgResult.path);
}
// Get the available crown holder data
let carCrowns = await prisma.carCrown.count({
where: {
area: area
}
});
// Crown holder data available
if(carCrowns !== 0)
{
// Update it to the new one
let areaVal = Number(area);
await prisma.carCrown.update({
where: {
area: areaVal
},
data: {
...dataCrown,
area: area,
ramp: ramp,
path: path
}
});
}
// Crown holder data not available or still default crown holder data
else
{
await prisma.carCrown.create({
data: {
...dataCrown,
area: area,
ramp: ramp,
path: path
}
});
}
}
await ghost_crown.saveCrownData(body);
updateNewTrail = true;
}
@ -516,10 +405,10 @@ export async function saveGhostBattleResult(body: wm.protobuf.SaveGameResultRequ
break;
}
// Ghost Battle Select from Bookmarks (12)
// Ghost Battle Select from Bookmars (12)
case wmproto.wm.protobuf.GhostSelectionMethod.GHOST_SELECT_FROM_BOOKMARKS:
{
console.log('Normal Ghost Mode Found - Select from Bookmarks');
console.log('Normal Ghost Mode Found - Select from Bookmars');
ghost_historys = await ghost_history.saveGhostHistory(body);
@ -531,6 +420,192 @@ export async function saveGhostBattleResult(body: wm.protobuf.SaveGameResultRequ
break;
}
// Ghost Battle Expedition (13)
case wmproto.wm.protobuf.GhostSelectionMethod.GHOST_EXPEDITION:
{
console.log('Normal Ghost Mode Found - VS Other Region (Expedition)');
ghost_historys = await ghost_history.saveVSORGGhostHistory(body);
// Return Stamp (Shuttle Match)
await ghost_stamp.shuttleReturnStamp(body);
// Update the updateNewTrail value
updateNewTrail = ghost_historys.updateNewTrail;
break;
}
// Ghost Battle Select by Place (14)
case wmproto.wm.protobuf.GhostSelectionMethod.GHOST_SELECT_BY_PLACE:
{
console.log('Normal Ghost Mode Found - Select by Place');
// TODO: Make saving
ghost_historys = await ghost_history.saveGhostHistory(body);
// Return Stamp (Shuttle Match)
await ghost_stamp.shuttleReturnStamp(body);
// Update the updateNewTrail value
updateNewTrail = ghost_historys.updateNewTrail;
break;
}
// Ghost Battle Select by Other Place (15)
case wmproto.wm.protobuf.GhostSelectionMethod.GHOST_SELECT_BY_OTHER_PLACE:
{
console.log('Normal Ghost Mode Found - Select by Other Place');
// TODO: Make saving
ghost_historys = await ghost_history.saveGhostHistory(body);
// Return Stamp (Shuttle Match)
await ghost_stamp.shuttleReturnStamp(body);
// Update the updateNewTrail value
updateNewTrail = ghost_historys.updateNewTrail;
break;
}
// Ghost Battle Select by Manufacturer (16)
case wmproto.wm.protobuf.GhostSelectionMethod.GHOST_SELECT_BY_MANUFACTURER:
{
console.log('Normal Ghost Mode Found - Select by Manufacturer');
// TODO: Make saving
ghost_historys = await ghost_history.saveGhostHistory(body);
// Return Stamp (Shuttle Match)
await ghost_stamp.shuttleReturnStamp(body);
// Update the updateNewTrail value
updateNewTrail = ghost_historys.updateNewTrail;
break;
}
// Ghost Battle Select by Other Manufacturer (17)
case wmproto.wm.protobuf.GhostSelectionMethod.GHOST_SELECT_BY_OTHER_MANUFACTURER:
{
console.log('Normal Ghost Mode Found - Select by Other Manufacturer');
// TODO: Make saving
ghost_historys = await ghost_history.saveGhostHistory(body);
// Return Stamp (Shuttle Match)
await ghost_stamp.shuttleReturnStamp(body);
// Update the updateNewTrail value
updateNewTrail = ghost_historys.updateNewTrail;
break;
}
// Ghost Battle Select by Played (18)
case wmproto.wm.protobuf.GhostSelectionMethod.GHOST_SELECT_BY_PLAYED:
{
console.log('Normal Ghost Mode Found - Select by Played');
// TODO: Make saving
ghost_historys = await ghost_history.saveGhostHistory(body);
// Return Stamp (Shuttle Match)
await ghost_stamp.shuttleReturnStamp(body);
// Update the updateNewTrail value
updateNewTrail = ghost_historys.updateNewTrail;
break;
}
// Ghost Battle Select by Region Manufacturer (20)
case wmproto.wm.protobuf.GhostSelectionMethod.GHOST_SELECT_BY_REGION_MANUFACTURER:
{
console.log('Normal Ghost Mode Found - Select by Region Manufacturer');
// TODO: Make saving
ghost_historys = await ghost_history.saveGhostHistory(body);
// Return Stamp (Shuttle Match)
await ghost_stamp.shuttleReturnStamp(body);
// Update the updateNewTrail value
updateNewTrail = ghost_historys.updateNewTrail;
break;
}
// Ghost Battle Select by Region Played (22)
case wmproto.wm.protobuf.GhostSelectionMethod.GHOST_SELECT_BY_REGION_PLAYED:
{
console.log('Normal Ghost Mode Found - Select by Region Played');
// TODO: Make saving
ghost_historys = await ghost_history.saveGhostHistory(body);
// Return Stamp (Shuttle Match)
await ghost_stamp.shuttleReturnStamp(body);
// Update the updateNewTrail value
updateNewTrail = ghost_historys.updateNewTrail;
break;
}
// Ghost Battle Select by Region Station (23)
case wmproto.wm.protobuf.GhostSelectionMethod.GHOST_SELECT_BY_REGION_STATION:
{
console.log('Normal Ghost Mode Found - Select by Region Station');
// TODO: Make saving
ghost_historys = await ghost_history.saveGhostHistory(body);
// Return Stamp (Shuttle Match)
await ghost_stamp.shuttleReturnStamp(body);
// Update the updateNewTrail value
updateNewTrail = ghost_historys.updateNewTrail;
break;
}
// Ghost Battle Select by Region Boss (24)
case wmproto.wm.protobuf.GhostSelectionMethod.GHOST_SELECT_BY_REGION_BOSS:
{
console.log('Normal Ghost Mode Found - Select by Region Boss');
// TODO: Make saving
ghost_historys = await ghost_history.saveGhostHistory(body);
// Return Stamp (Shuttle Match)
await ghost_stamp.shuttleReturnStamp(body);
// Update the updateNewTrail value
updateNewTrail = ghost_historys.updateNewTrail;
break;
}
// Ghost Battle Select by Region Place (25)
case wmproto.wm.protobuf.GhostSelectionMethod.GHOST_SELECT_BY_REGION_PLACE:
{
console.log('Normal Ghost Mode Found - Select by Region Place');
// TODO: Make saving
ghost_historys = await ghost_history.saveGhostHistory(body);
// Return Stamp (Shuttle Match)
await ghost_stamp.shuttleReturnStamp(body);
// Update the updateNewTrail value
updateNewTrail = ghost_historys.updateNewTrail;
break;
}
}
}
// Retiring Ghost Battle
@ -549,14 +624,11 @@ export async function saveGhostBattleResult(body: wm.protobuf.SaveGameResultRequ
// Get the ghost result for the car
let ghostResult = body?.rgResult;
// Declare data
let dataGhost : any;
// ghostResult is set
if (ghostResult)
{
// Ghost update data
dataGhost = {
let dataGhost = {
rgPlayCount: common.sanitizeInput(ghostResult.rgPlayCount),
}
@ -571,6 +643,7 @@ export async function saveGhostBattleResult(body: wm.protobuf.SaveGameResultRequ
});
}
}
// Retiring OCM for mini games
else if(body.rgResult!.selectionMethod === wmproto.wm.protobuf.GhostSelectionMethod.GHOST_COMPETITION)
{
@ -659,6 +732,15 @@ export async function saveGhostBattleResult(body: wm.protobuf.SaveGameResultRequ
}
});
}
// Retiring VS ORG
else if(body.rgResult!.selectionMethod === wmproto.wm.protobuf.GhostSelectionMethod.GHOST_EXPEDITION)
{
console.log('VSORG (Expedition) Ghost Mode Found but Retiring');
await ghost_history.saveVSORGGhostRetireHistory(body);
}
// TODO: Highway Ghost Mode Retiring Saving
// Return the value to 'BASE_PATH/src/modules/game.ts'
return { ghostModePlay, updateNewTrail, OCMModePlay }

View File

@ -5,8 +5,8 @@ import { prisma } from "../..";
import { wm } from "../../wmmt/wm.proto";
// Import Util
import * as common from "../util/common";
import * as check_step from "./games_util/check_step";
import * as common from "../common";
import * as check_step from "../games/games_util/check_step";
// Save story result
@ -35,7 +35,7 @@ export async function saveStoryResult(body: wm.protobuf.SaveGameResultRequest, c
}
// If the current consecutive wins is greater than the previous max
if (storyResult.stConsecutiveWins! > car!.stConsecutiveWinsMax)
if (storyResult.stConsecutiveWins! > car.stConsecutiveWinsMax)
{
// Update the maximum consecutive wins;
data.stConsecutiveWinsMax = storyResult.stConsecutiveWins;
@ -46,8 +46,11 @@ export async function saveStoryResult(body: wm.protobuf.SaveGameResultRequest, c
{
// Convert them to BigInt and add to the data
data.stLoseBits = common.getBigIntFromLong(storyResult.stLoseBits);
stLoseBits = data.stLoseBits
if(data.stLoseBits > 0)
{
stLoseBits = data.stLoseBits
}
// If a loss has been recorded
if (stLoseBits > 0)
{
@ -55,6 +58,10 @@ export async function saveStoryResult(body: wm.protobuf.SaveGameResultRequest, c
data.stConsecutiveWins = 0;
}
}
else
{
stLoseBits = 0;
}
// Calling check step function (BASE_PATH/src/util/games/games_util/check_step.ts)
let check_steps = await check_step.checkCurrentStep(body);

View File

@ -52,20 +52,14 @@ export async function saveTimeAttackResult(body: wm.protobuf.SaveGameResultReque
cheatedTime = true;
}
// Check the time again
if (body.taResult!.time <= 0 || body.taResult!.time >= 1200000 || body.taResult!.time.toString() == "-2147483648")
{
cheatedTime = true;
}
// Not Cheated Time
if(cheatedTime === false)
{
// Record already exists
if (currentRecord)
{
// Current time record is faster than previous time record and time record is below 20 minutes
if (body.taResult!.time < currentRecord.time && body.taResult!.time < 1200000)
// If the existing record is faster, do not continue
if (body.taResult!.time < currentRecord.time)
{
console.log('Updating time attack record...');
@ -90,32 +84,28 @@ export async function saveTimeAttackResult(body: wm.protobuf.SaveGameResultReque
});
}
}
// Creating a new record
else
else // Creating a new record
{
if (body.taResult!.time < 1200000)
{
console.log('Creating new time attack record');
console.log('Creating new time attack record');
await prisma.timeAttackRecord.create({
data: {
carId: body.carId,
model: body.car!.model!,
time: body.taResult!.time,
isMorning: body.taResult!.isMorning,
course: body.taResult!.course,
section1Time: body!.taResult!.section_1Time,
section2Time: body!.taResult!.section_2Time,
section3Time: body!.taResult!.section_3Time,
section4Time: body!.taResult!.section_4Time,
section5Time: body!.taResult!.section_5Time,
section6Time: body!.taResult!.section_6Time,
section7Time: body!.taResult!.section_7Time,
tunePower: body!.car!.tunePower,
tuneHandling: body!.car!.tuneHandling
}
});
}
await prisma.timeAttackRecord.create({
data: {
carId: body.carId,
model: body.car!.model!,
time: body.taResult!.time,
isMorning: body.taResult!.isMorning,
course: body.taResult!.course,
section1Time: body!.taResult!.section_1Time,
section2Time: body!.taResult!.section_2Time,
section3Time: body!.taResult!.section_3Time,
section4Time: body!.taResult!.section_4Time,
section5Time: body!.taResult!.section_5Time,
section6Time: body!.taResult!.section_6Time,
section7Time: body!.taResult!.section_7Time,
tunePower: body!.car!.tunePower,
tuneHandling: body!.car!.tuneHandling
}
});
}
}
// else {} cheated time, ignore it

View File

@ -4,7 +4,7 @@ import { prisma } from "../..";
import { wm } from "../../wmmt/wm.proto";
// Import Util
import * as common from "../util/common";
import * as common from "../common";
// Save versus battle result

View File

@ -0,0 +1,143 @@
import { prisma } from "../..";
// Import Proto
import { wm } from "../../wmmt/wm.proto";
// Import Util
import * as common from "../../util/common";
// Saving Crown Data
export async function saveCrownData(body: wm.protobuf.SaveGameResultRequest)
{
// Get the ghost crown result
let ghostResultCrown = body?.rgResult;
// Declare data
let dataCrown : any;
// ghostResultCrown is set
if (ghostResultCrown)
{
let carId: number = 0;
if(body.carId)
{
carId = Number(body.carId);
}
// Ghost Crown update data
dataCrown = {
carId: carId,
playedAt: common.sanitizeInput(body.playedAt),
tunePower: common.sanitizeInput(body.car?.tunePower),
tuneHandling: common.sanitizeInput(body.car?.tuneHandling),
}
// Get the area id and ramp id
let area = 0;
let ramp = 0;
let path = 0;
if(body.rgResult?.path)
{
if(body.rgResult?.path >= 0 && body.rgResult?.path <= 9){ // GID_PATH_C1
area = Number(0);
ramp = Number(Math.floor(Math.random() * 4));
}
else if(body.rgResult?.path >= 10 && body.rgResult?.path <= 15){ // GID_PATH_N9
area = Number(1);
ramp = Number(Math.floor(Math.random() * 2) + 4);
}
else if(body.rgResult?.path >= 16 && body.rgResult?.path <= 17){ // GID_PATH_WTEAST
area = Number(2);
ramp = Number(Math.floor(Math.random() * 2) + 6);
}
else if(body.rgResult?.path >= 18 && body.rgResult?.path <= 19){ // GID_PATH_WT_UP_DOWN
area = Number(3);
ramp = Number(Math.floor(Math.random() * 2) + 8);
}
else if(body.rgResult?.path >= 20 && body.rgResult?.path <= 26){ // GID_PATH_WG
area = Number(4);
ramp = Number(Math.floor(Math.random() * 4) + 10);
}
else if(body.rgResult?.path >= 27 && body.rgResult?.path <= 33){ // GID_PATH_KG
area = Number(5);
ramp = Number(Math.floor(Math.random() * 4) + 14);
}
else if(body.rgResult?.path >= 34 && body.rgResult?.path <= 37){ // GID_PATH_YS
area = Number(6);
ramp = Number(Math.floor(Math.random() * 3) + 18);
}
else if(body.rgResult?.path >= 38 && body.rgResult?.path <= 48){ // GID_PATH_KG_SHINYAMASHITA_MINATOMIRAI
area = Number(7);
ramp = Number(Math.floor(Math.random() * 4) + 21);
}
else if(body.rgResult?.path === 49){ // GID_PATH_NGR
area = Number(8);
ramp = Number(25);
}
else if(body.rgResult?.path >= 50 && body.rgResult?.path <= 53){ // GID_PATH_OS
area = Number(9);
ramp = Number(26);
}
else if(body.rgResult?.path >= 54 && body.rgResult?.path <= 55){ // GID_PATH_KB
area = Number(10);
ramp = Number(Math.floor(Math.random() * 2) + 27);
}
else if(body.rgResult?.path >= 58 && body.rgResult?.path <= 61){ // GID_PATH_FK
area = Number(11);
ramp = Number(Math.floor(Math.random() * 4) + 29);
}
else if(body.rgResult?.path >= 62 && body.rgResult?.path <= 63){ // GID_PATH_HK
area = Number(12);
ramp = Number(Math.floor(Math.random() * 2) + 33);
}
else if(body.rgResult?.path >= 64 && body.rgResult?.path <= 65){ // GID_PATH_TP
area = Number(13);
ramp = Number(Math.floor(Math.random() * 2) + 35);
}
else if(body.rgResult?.path >= 56 && body.rgResult?.path <= 57){ // GID_PATH_HS
area = Number(18);
ramp = Number(Math.floor(Math.random() * 2) + 27);
}
path = Number(body.rgResult.path);
}
// Get the available crown holder data
let carCrowns = await prisma.carCrown.count({
where: {
area: area
}
});
// Crown holder data available
if(carCrowns !== 0)
{
// Update it to the new one
let areaVal = Number(area);
await prisma.carCrown.update({
where: {
area: areaVal
},
data: {
...dataCrown,
area: area,
ramp: ramp,
path: path
}
});
}
// Crown holder data not available or still default crown holder data
else
{
await prisma.carCrown.create({
data: {
...dataCrown,
area: area,
ramp: ramp,
path: path
}
});
}
}
}

View File

@ -0,0 +1,573 @@
import { Config } from "../../config";
// Import Proto
import * as wm from "../../wmmt/wm.proto";
// Global Variable
let date = Math.floor(new Date().getTime() / 1000);
let playedPlace = wm.wm.protobuf.Place.create({
placeId: Config.getConfig().placeId,
regionId: Config.getConfig().regionId,
shopName: Config.getConfig().shopName,
country: Config.getConfig().country
});
export async function DefaultGhostCarBMW()
{
let cars = wm.wm.protobuf.Car.create({
carId: 999999999, // Don't change this
name: '',
regionId: 18, // IDN (福井)
manufacturer: 0,
model: 71, // Z4 Safty (yes.. safty)
visualModel: 100, // Z4 Safty (yes.. safty)
defaultColor: 0,
customColor: 0,
wheel: 20,
wheelColor: 0,
aero: 0,
bonnet: 0,
wing: 0,
mirror: 0,
neon: 0,
trunk: 0,
plate: 0,
plateColor: 0,
plateNumber: 0,
tunePower: 18,
tuneHandling: 16,
rivalMarker: 32,
aura: 551,
windowSticker: true,
windowStickerString: '',
windowStickerFont: 0,
title: 'Wangan Beginner',
level: 65, // SSSSS
lastPlayedAt: date,
country: 'JPN',
lastPlayedPlace: playedPlace
});
return { cars };
}
export async function DefaultGhostCarChevrolet()
{
let cars = wm.wm.protobuf.Car.create({
carId: 999999999, // Don't change this
name: '',
regionId: 18, // IDN (福井)
manufacturer: 1,
model: 66, // Corvette C6 Taxi
visualModel: 1, // Corvette C6 Taxi
defaultColor: 0,
customColor: 0,
wheel: 20,
wheelColor: 0,
aero: 0,
bonnet: 0,
wing: 0,
mirror: 0,
neon: 0,
trunk: 0,
plate: 0,
plateColor: 0,
plateNumber: 0,
tunePower: 18,
tuneHandling: 16,
rivalMarker: 32,
aura: 551,
windowSticker: true,
windowStickerString: '',
windowStickerFont: 0,
title: 'Wangan Beginner',
level: 65, // SSSSS
lastPlayedAt: date,
country: 'JPN',
lastPlayedPlace: playedPlace
});
return { cars };
}
export async function DefaultGhostCarMazda()
{
let cars = wm.wm.protobuf.Car.create({
carId: 999999999, // Don't change this
name: '',
regionId: 18, // IDN (福井)
manufacturer: 2,
model: 9, // RX-7
visualModel: 6, // RX-7
defaultColor: 0,
customColor: 0,
wheel: 20,
wheelColor: 0,
aero: 0,
bonnet: 0,
wing: 0,
mirror: 0,
neon: 0,
trunk: 0,
plate: 0,
plateColor: 0,
plateNumber: 0,
tunePower: 18,
tuneHandling: 16,
rivalMarker: 32,
aura: 551,
windowSticker: true,
windowStickerString: '',
windowStickerFont: 0,
title: 'Wangan Beginner',
level: 65, // SSSSS
lastPlayedAt: date,
country: 'JPN',
lastPlayedPlace: playedPlace
});
return { cars };
}
export async function DefaultGhostCarMercedes()
{
let cars = wm.wm.protobuf.Car.create({
carId: 999999999, // Don't change this
name: '',
regionId: 18, // IDN (福井)
manufacturer: 3,
model: 87, // SLS AMG
visualModel: 107, // SLS AMG
defaultColor: 0,
customColor: 0,
wheel: 20,
wheelColor: 0,
aero: 0,
bonnet: 0,
wing: 0,
mirror: 0,
neon: 0,
trunk: 0,
plate: 0,
plateColor: 0,
plateNumber: 0,
tunePower: 18,
tuneHandling: 16,
rivalMarker: 32,
aura: 551,
windowSticker: true,
windowStickerString: '',
windowStickerFont: 0,
title: 'Wangan Beginner',
level: 65, // SSSSS
lastPlayedAt: date,
country: 'JPN',
lastPlayedPlace: playedPlace
});
return { cars };
}
export async function DefaultGhostCarMitsubishi()
{
let cars = wm.wm.protobuf.Car.create({
carId: 999999999, // Don't change this
name: ' ',
regionId: 18, // IDN (福井)
manufacturer: 4,
model: 22, // EVO IX
visualModel: 15, // EVO IX
defaultColor: 0,
customColor: 0,
wheel: 20,
wheelColor: 0,
aero: 0,
bonnet: 0,
wing: 0,
mirror: 0,
neon: 0,
trunk: 0,
plate: 0,
plateColor: 0,
plateNumber: 0,
tunePower: 18,
tuneHandling: 16,
rivalMarker: 32,
aura: 551,
windowSticker: true,
windowStickerString: '',
windowStickerFont: 0,
title: 'Wangan Beginner',
level: 65, // SSSSS
lastPlayedAt: date,
country: 'JPN',
lastPlayedPlace: playedPlace
});
return { cars };
}
export async function DefaultGhostCarNissan()
{
let cars = wm.wm.protobuf.Car.create({
carId: 999999999, // Don't change this
name: '',
regionId: 18, // IDN (福井)
manufacturer: 5,
model: 27, // R34 nur
visualModel: 30, // R34 nur
defaultColor: 0,
customColor: 0,
wheel: 20,
wheelColor: 0,
aero: 0,
bonnet: 0,
wing: 0,
mirror: 0,
neon: 0,
trunk: 0,
plate: 0,
plateColor: 0,
plateNumber: 0,
tunePower: 18,
tuneHandling: 16,
rivalMarker: 32,
aura: 551,
windowSticker: true,
windowStickerString: '',
windowStickerFont: 0,
title: 'Wangan Beginner',
level: 65, // SSSSS
lastPlayedAt: date,
country: 'JPN',
lastPlayedPlace: playedPlace
});
return { cars };
}
export async function DefaultGhostCarSubaru()
{
let cars = wm.wm.protobuf.Car.create({
carId: 999999999, // Don't change this
name: '',
regionId: 18, // IDN (福井)
manufacturer: 7,
model: 47, // ALCYONE SVX
visualModel: 54, // ALCYONE SVX
defaultColor: 0,
customColor: 0,
wheel: 20,
wheelColor: 0,
aero: 0,
bonnet: 0,
wing: 0,
mirror: 0,
neon: 0,
trunk: 0,
plate: 0,
plateColor: 0,
plateNumber: 0,
tunePower: 18,
tuneHandling: 16,
rivalMarker: 32,
aura: 551,
windowSticker: true,
windowStickerString: '',
windowStickerFont: 0,
title: 'Wangan Beginner',
level: 65, // SSSSS
lastPlayedAt: date,
country: 'JPN',
lastPlayedPlace: playedPlace
});
return { cars };
}
export async function DefaultGhostCarToyota()
{
let cars = wm.wm.protobuf.Car.create({
carId: 999999999, // Don't change this
name: '',
regionId: 18, // IDN (福井)
manufacturer: 8,
model: 122, // GR Supra (not honda supra motorbike)
visualModel: 145, // GR Supra (not honda supra motorbike)
defaultColor: 0,
customColor: 0,
wheel: 20,
wheelColor: 0,
aero: 0,
bonnet: 0,
wing: 0,
mirror: 0,
neon: 0,
trunk: 0,
plate: 0,
plateColor: 0,
plateNumber: 0,
tunePower: 18,
tuneHandling: 16,
rivalMarker: 32,
aura: 551,
windowSticker: true,
windowStickerString: '',
windowStickerFont: 0,
title: 'Wangan Beginner',
level: 65, // SSSSS
lastPlayedAt: date,
country: 'JPN',
lastPlayedPlace: playedPlace
});
return { cars };
}
export async function DefaultGhostCarAudi()
{
let cars = wm.wm.protobuf.Car.create({
carId: 999999999, // Don't change this
name: '',
regionId: 18, // IDN (福井)
manufacturer: 9,
model: 89, // R8
visualModel: 109, // R8
defaultColor: 0,
customColor: 0,
wheel: 20,
wheelColor: 0,
aero: 0,
bonnet: 0,
wing: 0,
mirror: 0,
neon: 0,
trunk: 0,
plate: 0,
plateColor: 0,
plateNumber: 0,
tunePower: 18,
tuneHandling: 16,
rivalMarker: 32,
aura: 551,
windowSticker: true,
windowStickerString: '',
windowStickerFont: 0,
title: 'Wangan Beginner',
level: 65, // SSSSS
lastPlayedAt: date,
country: 'JPN',
lastPlayedPlace: playedPlace
});
return { cars };
}
export async function DefaultGhostCarDodge()
{
let cars = wm.wm.protobuf.Car.create({
carId: 999999999, // Don't change this
name: '',
regionId: 18, // IDN (福井)
manufacturer: 10,
model: 91, // Viper SRT10
visualModel: 111, // Viper SRT10
defaultColor: 0,
customColor: 0,
wheel: 20,
wheelColor: 0,
aero: 0,
bonnet: 0,
wing: 0,
mirror: 0,
neon: 0,
trunk: 0,
plate: 0,
plateColor: 0,
plateNumber: 0,
tunePower: 18,
tuneHandling: 16,
rivalMarker: 32,
aura: 551,
windowSticker: true,
windowStickerString: '',
windowStickerFont: 0,
title: 'Wangan Beginner',
level: 65, // SSSSS
lastPlayedAt: date,
country: 'JPN',
lastPlayedPlace: playedPlace
});
return { cars };
}
export async function DefaultGhostCarLamborghini()
{
let cars = wm.wm.protobuf.Car.create({
carId: 999999999, // Don't change this
name: '',
regionId: 18, // IDN (福井)
manufacturer: 11,
model: 103, // MIURA
visualModel: 125, // MIURA
defaultColor: 0,
customColor: 0,
wheel: 20,
wheelColor: 0,
aero: 0,
bonnet: 0,
wing: 0,
mirror: 0,
neon: 0,
trunk: 0,
plate: 0,
plateColor: 0,
plateNumber: 0,
tunePower: 18,
tuneHandling: 16,
rivalMarker: 32,
aura: 551,
windowSticker: true,
windowStickerString: '',
windowStickerFont: 0,
title: 'Wangan Beginner',
level: 65, // SSSSS
lastPlayedAt: date,
country: 'JPN',
lastPlayedPlace: playedPlace
});
return { cars };
}
export async function DefaultGhostCarHonda()
{
let cars = wm.wm.protobuf.Car.create({
carId: 999999999, // Don't change this
name: '',
regionId: 18, // IDN (福井)
manufacturer: 12,
model: 105, // S660
visualModel: 130, // S660
defaultColor: 0,
customColor: 0,
wheel: 20,
wheelColor: 0,
aero: 0,
bonnet: 0,
wing: 0,
mirror: 0,
neon: 0,
trunk: 0,
plate: 0,
plateColor: 0,
plateNumber: 0,
tunePower: 18,
tuneHandling: 16,
rivalMarker: 32,
aura: 551,
windowSticker: true,
windowStickerString: '',
windowStickerFont: 0,
title: 'Wangan Beginner',
level: 65, // SSSSS
lastPlayedAt: date,
country: 'JPN',
lastPlayedPlace: playedPlace
});
return { cars };
}
export async function DefaultGhostCarAcura()
{
let cars = wm.wm.protobuf.Car.create({
carId: 999999999, // Don't change this
name: '',
regionId: 18, // IDN (福井)
manufacturer: 12, // Not Acura... Acura is ID 13
model: 107, // Honda NSX
visualModel: 128, // Honda NSX
defaultColor: 0,
customColor: 0,
wheel: 20,
wheelColor: 0,
aero: 0,
bonnet: 0,
wing: 0,
mirror: 0,
neon: 0,
trunk: 0,
plate: 0,
plateColor: 0,
plateNumber: 0,
tunePower: 18,
tuneHandling: 16,
rivalMarker: 32,
aura: 551,
windowSticker: true,
windowStickerString: '',
windowStickerFont: 0,
title: 'Wangan Beginner',
level: 65, // SSSSS
lastPlayedAt: date,
country: 'JPN',
lastPlayedPlace: playedPlace
});
return { cars };
}
export async function DefaultGhostCarPorsche()
{
let cars = wm.wm.protobuf.Car.create({
carId: 999999999, // Don't change this
name: '',
regionId: 18, // IDN (福井)
manufacturer: 14,
model: 121, // 718 CAYMAN S
visualModel: 144, // 718 CAYMAN S
defaultColor: 0,
customColor: 0,
wheel: 20,
wheelColor: 0,
aero: 0,
bonnet: 0,
wing: 0,
mirror: 0,
neon: 0,
trunk: 0,
plate: 0,
plateColor: 0,
plateNumber: 0,
tunePower: 18,
tuneHandling: 16,
rivalMarker: 32,
aura: 551,
windowSticker: true,
windowStickerString: '',
windowStickerFont: 0,
title: 'Wangan Beginner',
level: 65, // SSSSS
lastPlayedAt: date,
country: 'JPN',
lastPlayedPlace: playedPlace
});
return { cars };
}

View File

@ -0,0 +1,832 @@
import { prisma } from "../..";
import { Config } from "../../config";
// Import Proto
import { wm } from "../../wmmt/wm.proto";
// Import Util
import * as common from "../../util/common";
import * as ghost_stamp from "../ghost/ghost_stamp";
import * as ghost_get_area_from_path from "../ghost/ghost_util/ghost_get_area_from_path";
// Save ghost history battle
export async function saveGhostHistory(body: wm.protobuf.SaveGameResultRequest)
{
console.log('Saving Ghost Battle History');
let updateNewTrail: boolean = true;
let saveExGhostHistory: any = {};
// Get the car result for the car
let car = body?.car;
if(car)
{
saveExGhostHistory = {
carId: common.sanitizeInput(car.carId),
tunePower: common.sanitizeInput(car.tunePower),
tuneHandling: common.sanitizeInput(car.tuneHandling),
playedAt: common.sanitizeInputNotZero(body.playedAt),
playedShopName: Config.getConfig().shopName
}
}
// Get the rg result for the car
let rgResult = body?.rgResult;
if(rgResult)
{
if(rgResult.opponents)
{
// Get how many opponents available
for(let i=0; i<rgResult.opponents.length; i++)
{
// First opponent data
if(i == 0)
{
// Get first opponent carId
saveExGhostHistory.opponent1CarId = rgResult.opponents[0].carId;
// Get first opponent tunePower
saveExGhostHistory.opponent1TunePower = rgResult.opponents[0].tunePower;
// Get first opponent tunePower
saveExGhostHistory.opponent1TuneHandling = rgResult.opponents[0].tuneHandling;
// Get the advantage distance between first opponent and user
saveExGhostHistory.opponent1Result = rgResult.opponents[0].result;
}
// Second opponent data
else if(i == 1)
{
// Get second opponent carId
saveExGhostHistory.opponent2CarId = rgResult.opponents[1].carId;
// Get second opponent tunePower
saveExGhostHistory.opponent2TunePower = rgResult.opponents[1].tunePower;
// Get second opponent tuneHandling
saveExGhostHistory.opponent2TuneHandling = rgResult.opponents[1].tuneHandling;
// Get the advantage distance between second opponent and user
saveExGhostHistory.opponent2Result = rgResult.opponents[1].result;
}
// Third opponent data
else if(i == 2)
{
// Get third opponent carId
saveExGhostHistory.opponent3CarId = rgResult.opponents[2].carId;
// Get third opponent tunePower
saveExGhostHistory.opponent3TunePower = rgResult.opponents[2].tunePower;
// Get third opponent tuneHandling
saveExGhostHistory.opponent3TuneHandling = rgResult.opponents[2].tuneHandling;
// Get the advantage distance between third opponent and user
saveExGhostHistory.opponent3Result = rgResult.opponents[2].result;
}
}
}
// Get played Area
if(common.sanitizeInput(rgResult.path))
{
let getArea = await ghost_get_area_from_path.getArea(rgResult.path);
saveExGhostHistory.area = getArea.area
}
}
await prisma.ghostBattleRecord.create({
data: saveExGhostHistory
});
// Sending stamp to opponents
await ghost_stamp.sendStamp(body);
// Return the value to 'BASE_PATH/src/util/games/ghost.ts'
return { updateNewTrail }
}
// Save OCM ghost history battle
export async function saveOCMGhostHistory(body: wm.protobuf.SaveGameResultRequest)
{
let updateNewTrail: boolean = true;
let saveExGhostHistory: any = {};
// Get the car result for the car
let car = body?.car;
if(car)
{
saveExGhostHistory = {
carId: common.sanitizeInput(car.carId),
tunePower: common.sanitizeInput(car.tunePower),
tuneHandling: common.sanitizeInput(car.tuneHandling),
playedAt: common.sanitizeInputNotZero(body.playedAt),
playedShopName: Config.getConfig().shopName
}
}
// Get the rg result for the car
let rgResult = body?.rgResult;
if(rgResult)
{
if(rgResult.opponents)
{
// Get the advantage distance between first opponent and user
saveExGhostHistory.result = rgResult.opponents[0].result;
}
// Get played Area
if(common.sanitizeInput(rgResult.path))
{
let getArea = await ghost_get_area_from_path.getArea(rgResult.path);
saveExGhostHistory.area = getArea.area
}
}
// Get current date
let date = Math.floor(new Date().getTime() / 1000);
// Get currently active OCM event
let ocmEventDate = await prisma.oCMEvent.findFirst({
where: {
// qualifyingPeriodStartAt is less than equal current date
qualifyingPeriodStartAt: { lte: date },
// competitionEndAt is greater than equal current date
competitionEndAt: { gte: date },
},
orderBy:{
dbId: 'desc'
}
});
// ----------Get available OCM Record (Qualifying or Main Draw)----------
// Current date is OCM main draw
let countGBR;
if(ocmEventDate!.competitionStartAt < date && ocmEventDate!.competitionCloseAt > date)
{
// Set OCM Main draw value to true
saveExGhostHistory.ocmMainDraw = true
// Get the user's available OCM Battle Record data
countGBR = await prisma.oCMTally.findFirst({
where:{
carId: saveExGhostHistory.carId,
competitionId: ocmEventDate!.competitionId,
}
});
}
// Current date is OCM qualifying day
else
{
// Set OCM Main draw value to false
saveExGhostHistory.ocmMainDraw = false
// Get the user's available OCM Battle Record data
countGBR = await prisma.oCMGhostBattleRecord.findFirst({
where:{
carId: saveExGhostHistory.carId,
ocmMainDraw: saveExGhostHistory.ocmMainDraw,
area: saveExGhostHistory.area,
competitionId: ocmEventDate!.competitionId,
periodId: 0
}
});
}
// ----------------------------------------------------------------
// User have OCM Battle Record data available
if(countGBR)
{
// Check if the newest advantage distance is bigger than the older advantage distance
if(countGBR!.result < saveExGhostHistory.result)
{
console.log('OCM Ghost Tally found');
// Current date is OCM Main Draw
if(ocmEventDate!.competitionStartAt < date && ocmEventDate!.competitionCloseAt > date)
{
// Get OCM Period ID
let OCM_periodId = await prisma.oCMPeriod.findFirst({
where:{
competitionDbId: ocmEventDate!.dbId,
competitionId: ocmEventDate!.competitionId,
startAt:
{
lte: date, // competitionStartAt is less than equal current date
},
closeAt:
{
gte: date, // competitionCloseAt is greater than equal current date
}
},
select:{
periodId: true
}
});
let checkGhost = await prisma.oCMGhostBattleRecord.findFirst({
where:{
carId: saveExGhostHistory.carId,
competitionId: ocmEventDate!.competitionId,
}
});
if(checkGhost)
{
console.log('Updating OCM Ghost Battle Record entry');
// Get the user's available OCM Battle Record data
let getGBR = await prisma.oCMGhostBattleRecord.findFirst({
where:{
carId: saveExGhostHistory.carId,
area: saveExGhostHistory.area,
competitionId: ocmEventDate!.competitionId,
}
});
// Update ghost battle record
await prisma.oCMGhostBattleRecord.update({
where:{
dbId: getGBR!.dbId
},
data: {
...saveExGhostHistory,
competitionId: ocmEventDate!.competitionId,
periodId: OCM_periodId!.periodId
}
});
}
else
{
console.log('Creating new OCM Ghost Battle Record entry');
// Create new ghost battle record
await prisma.oCMGhostBattleRecord.create({
data: {
...saveExGhostHistory,
competitionId: ocmEventDate!.competitionId,
periodId: OCM_periodId!.periodId
}
});
}
console.log('Updating OCM Tally Record');
// Update the OCM Tally Record
await prisma.oCMTally.update({
where:{
dbId: countGBR.dbId
},
data: {
periodId: OCM_periodId!.periodId,
result: body.rgResult!.opponents![0].result,
tunePower: body.car?.tunePower!,
tuneHandling: body.car?.tuneHandling!
}
});
}
// Current date is OCM Qualifying
else
{
// Update ghost battle record
await prisma.oCMGhostBattleRecord.update({
where:{
dbId: countGBR.dbId
},
data: {
...saveExGhostHistory,
competitionId: ocmEventDate!.competitionId,
periodId: 0
}
});
}
}
// Newest advantage distance is smaller than the older advantage distance
else
{
console.log('Result record is lower than previous record');
// Don't update the User's OCM ghost trail
updateNewTrail = false;
}
}
// User don't have OCM Battle Record data available
else
{
console.log('OCM Ghost Battle Record not found');
console.log('Creating new OOCM Ghost Battle Record entry');
// Current date is OCM Main Draw
if(ocmEventDate!.competitionStartAt < date && ocmEventDate!.competitionCloseAt > date)
{
// Get OCM Period ID
let OCM_periodId = await prisma.oCMPeriod.findFirst({
where:{
competitionDbId: ocmEventDate!.dbId,
competitionId: ocmEventDate!.competitionId
},
orderBy:{
periodId: 'desc'
},
select:{
periodId: true
}
});
// Update ghost battle record
await prisma.oCMGhostBattleRecord.create({
data: {
...saveExGhostHistory,
competitionId: ocmEventDate!.competitionId,
periodId: OCM_periodId!.periodId
}
});
let ocmTallyfind = await prisma.oCMTally.findFirst({
where:{
carId: saveExGhostHistory.carId,
competitionId: ocmEventDate!.competitionId,
},
});
if(ocmTallyfind)
{
console.log('Updating OCM Tally Record');
// Update the OCM Tally Record
await prisma.oCMTally.update({
where:{
dbId: ocmTallyfind.dbId
},
data: {
periodId: OCM_periodId!.periodId,
result: body.rgResult!.opponents![0].result,
tunePower: body.car?.tunePower!,
tuneHandling: body.car?.tuneHandling!
}
});
}
}
// Current date is OCM Qualifying
else
{
// Update ghost battle record
await prisma.oCMGhostBattleRecord.create({
data: {
...saveExGhostHistory,
competitionId: ocmEventDate!.competitionId,
periodId: 0
}
});
}
}
// Return the value to 'BASE_PATH/src/util/games/ghost.ts'
return { updateNewTrail }
}
// Save VSORG ghost history battle
export async function saveVSORGGhostHistory(body: wm.protobuf.SaveGameResultRequest)
{
console.log('Saving VSORG Ghost Battle History');
// Get the ghost expedition result for the car
let expeditionResult = body.rgResult?.expeditionResult;
// Get current date
let date = Math.floor(new Date().getTime() / 1000);
// expeditionResult is set
if (expeditionResult)
{
// Expedition update data
let dataExpedition = {
ghostExpeditionId: common.sanitizeInput(expeditionResult.ghostExpeditionId),
sugorokuPoint: common.sanitizeInput(expeditionResult.sugorokuPoint),
earnedScore: common.sanitizeInput(expeditionResult.earnedScore),
score: common.sanitizeInput(expeditionResult.score),
}
let checkExpeditionData = await prisma.ghostExpedition.findFirst({
where:{
carId: body.carId
}
});
// Update the expedition data
if(checkExpeditionData)
{
await prisma.ghostExpedition.update({
where:{
dbId: checkExpeditionData.dbId
},
data: {
...dataExpedition
}
});
}
// Create the expedition data
else
{
await prisma.ghostExpedition.create({
data: {
carId: body.carId,
...dataExpedition
}
});
}
if(expeditionResult.earnedItems!.length !== 0)
{
console.log('User Item reward from VSORG available, continuing ...');
// Get current date
let date = Math.floor(new Date().getTime() / 1000);
for(let i=0; i<expeditionResult.earnedItems!.length; i++)
{
await prisma.userItem.create({
data: {
category: expeditionResult.earnedItems![i].category,
itemId: expeditionResult.earnedItems![i].itemId,
userId: body.car!.userId!,
earnedAt: date,
type: 0
}
});
}
}
if(expeditionResult.aftereventBonus!.length !== 0)
{
console.log('User Item after event reward from VSORG available, continuing ...');
// Get current date
let date = Math.floor(new Date().getTime() / 1000);
for(let i=0; i<expeditionResult.aftereventBonus!.length; i++)
{
/*
await prisma.userItem.create({
data: {
category: expeditionResult.earnedItems![i].category,
itemId: expeditionResult.earnedItems![i].itemId,
userId: body.car!.userId!,
earnedAt: date,
type: 0
}
});*/
}
}
}
let updateNewTrail: boolean = true;
let saveExGhostHistory: any = {};
// Get the car result for the car
let car = body?.car;
if(car)
{
saveExGhostHistory = {
carId: common.sanitizeInput(car.carId),
tunePower: common.sanitizeInput(car.tunePower),
tuneHandling: common.sanitizeInput(car.tuneHandling),
playedAt: common.sanitizeInputNotZero(body.playedAt),
playedShopName: Config.getConfig().shopName
}
}
// Get the rg result for the car
let rgResult = body?.rgResult;
if(rgResult)
{
if(rgResult.opponents)
{
// Get first opponent carId
saveExGhostHistory.opponent1CarId = rgResult.opponents[0].carId;
// Get first opponent tunePower
saveExGhostHistory.opponent1TunePower = rgResult.opponents[0].tunePower;
// Get first opponent tunePower
saveExGhostHistory.opponent1TuneHandling = rgResult.opponents[0].tuneHandling;
// Get the advantage distance between first opponent and user
saveExGhostHistory.opponent1Result = rgResult.opponents[0].result;
}
// Get played Area
if(common.sanitizeInput(rgResult.path))
{
let getArea = await ghost_get_area_from_path.getArea(rgResult.path);
saveExGhostHistory.area = getArea.area
}
}
await prisma.ghostBattleRecord.create({
data: saveExGhostHistory
});
let getArea = await ghost_get_area_from_path.getArea(rgResult!.path);
// Check if defeating Wanted car
let checkWantedCar = await prisma.ghostExpeditionWantedCar.findFirst({
where:{
carId: rgResult!.opponents![0].carId,
area: getArea.area
}
})
// Wanted car available
if(checkWantedCar)
{
if(rgResult!.opponents![0].result > 0)
{
console.log('Wanted Car Defeated');
await prisma.ghostExpeditionWantedCar.delete({
where:{
dbId: checkWantedCar.dbId
}
})
}
else
{
console.log('Lose from Wanted Car');
// Making wanted car
let dataWantedGhost = {
carId: common.sanitizeInput(rgResult!.opponents![0].carId),
bonus: checkWantedCar.bonus + 1,
defeatedMeCount: checkWantedCar.defeatedMeCount + 1
}
await prisma.ghostExpeditionWantedCar.update({
where:{
dbId: checkWantedCar.dbId
},
data: dataWantedGhost
})
}
}
// If lose the race maybe
else
{
if(rgResult!.opponents![0].result < 0)
{
// Making wanted car
let dataWantedGhost = {
carId: common.sanitizeInput(rgResult!.opponents![0].carId),
bonus: 0,
numOfHostages: 1,
defeatedMeCount: 1,
area: getArea.area
}
console.log('Creating Wanted Car');
await prisma.ghostExpeditionWantedCar.create({
data: dataWantedGhost
})
}
}
// Check full tune ticket piece
let checkFTTicketPiece = await prisma.userItem.findMany({
where:{
userId: body.car!.userId!,
category: 202,
itemId: 2
}
});
if(checkFTTicketPiece.length >= 6)
{
// Give full tune ticket :)
await prisma.userItem.create({
data:{
userId: body.car!.userId!,
category: 203,
itemId: 5,
type: 0,
earnedAt: date
}
});
// Remove full tune ticket piece :(
await prisma.userItem.deleteMany({
where:{
userId: body.car!.userId!,
category: 202,
itemId: 2,
}
});
}
// Sending stamp to opponents
await ghost_stamp.sendStamp(body);
// Return the value to 'BASE_PATH/src/util/games/ghost.ts'
return { updateNewTrail }
}
// Save VSORG ghost history battle but retiring
export async function saveVSORGGhostRetireHistory(body: wm.protobuf.SaveGameResultRequest)
{
console.log('Saving VSORG Retiring Ghost Battle History');
// Get the ghost result for the car
let ghostResult = body?.rgResult;
// Get current date
let date = Math.floor(new Date().getTime() / 1000);
// ghostResult is set
let dataGhost: any;
if (ghostResult)
{
dataGhost = {
rgPlayCount: common.sanitizeInput(ghostResult.rgPlayCount),
}
// Update the car properties
await prisma.car.update({
where: {
carId: body.carId
},
data: {
...dataGhost
}
});
let getArea = await ghost_get_area_from_path.getArea(ghostResult.path);
// Making wanted car
let dataWantedGhost = {
carId: common.sanitizeInput(ghostResult.opponents![0].carId),
bonus: 0,
numOfHostages: 1,
defeatedMeCount: 1,
area: getArea.area
}
let checkWantedCar = await prisma.ghostExpeditionWantedCar.findFirst({
where:{
carId: dataWantedGhost.carId
}
})
if(checkWantedCar)
{
console.log('Updating Wanted Car');
dataWantedGhost.bonus = checkWantedCar.bonus + 1;
dataWantedGhost.defeatedMeCount = checkWantedCar.defeatedMeCount + 1;
await prisma.ghostExpeditionWantedCar.update({
where:{
dbId: checkWantedCar.dbId
},
data: dataWantedGhost
})
}
else
{
console.log('Creating Wanted Car');
await prisma.ghostExpeditionWantedCar.create({
data: dataWantedGhost
})
}
}
// Get the ghost expedition result for the car
let expeditionResult = body.rgResult?.expeditionResult;
// expeditionResult is set
if (expeditionResult)
{
// Expedition update data
let dataExpedition = {
ghostExpeditionId: common.sanitizeInput(expeditionResult.ghostExpeditionId),
sugorokuPoint: common.sanitizeInput(expeditionResult.sugorokuPoint),
earnedScore: common.sanitizeInput(expeditionResult.earnedScore),
score: common.sanitizeInput(expeditionResult.score),
}
let checkExpeditionData = await prisma.ghostExpedition.findFirst({
where:{
carId: body.carId
}
});
// Update the expedition data
if(checkExpeditionData)
{
await prisma.ghostExpedition.update({
where:{
dbId: checkExpeditionData.dbId
},
data: {
...dataExpedition
}
});
}
// Create the expedition data
else
{
await prisma.ghostExpedition.create({
data: {
carId: body.carId,
...dataExpedition
}
});
}
if(expeditionResult.earnedItems!.length !== 0)
{
console.log('User Item reward from VSORG available, continuing ...');
for(let i=0; i<expeditionResult.earnedItems!.length; i++)
{
await prisma.userItem.create({
data: {
category: expeditionResult.earnedItems![i].category,
itemId: expeditionResult.earnedItems![i].itemId,
userId: body.car!.userId!,
earnedAt: date,
type: 0
}
});
}
}
if(expeditionResult.aftereventBonus!.length !== 0)
{
console.log('User Item after event reward from VSORG available, continuing ...');
for(let i=0; i<expeditionResult.aftereventBonus!.length; i++)
{
/*
await prisma.userItem.create({
data: {
category: expeditionResult.earnedItems![i].category,
itemId: expeditionResult.earnedItems![i].itemId,
userId: body.car!.userId!,
earnedAt: date,
type: 0
}
});*/
}
}
}
// Check full tune ticket piece
let checkFTTicketPiece = await prisma.userItem.findMany({
where:{
userId: body.car!.userId!,
category: 202,
itemId: 2
}
});
if(checkFTTicketPiece.length >= 6)
{
// Give full tune ticket :)
await prisma.userItem.create({
data:{
userId: body.car!.userId!,
category: 203,
itemId: 5,
type: 0,
earnedAt: date
}
});
// Remove full tune ticket piece :(
await prisma.userItem.deleteMany({
where:{
userId: body.car!.userId!,
category: 202,
itemId: 2,
}
});
}
}

View File

@ -381,8 +381,7 @@ export async function ocmTallying(body: wm.protobuf.LoadGhostCompetitionInfoRequ
}
if(i === 0)
{
if(i === 0){
console.log('Making OCM Top 1 Ghost Data');
// Create Top 1 ghost data
@ -588,10 +587,10 @@ export async function ocmGiveNamePlateReward(competitionId: number)
let participantLength = getCarParticipant.length;
// Participant is more than certain number (100 is default)
if(participantLength > 25)
// Participant is more than 100
if(participantLength > 100)
{
participantLength = 25;
participantLength = 100
}
// 16th - C1
@ -739,37 +738,8 @@ export async function ocmGiveNamePlateReward(competitionId: number)
})
}
}
// 20th - Kobe
else if(competitionId === 6)
{
// Participation Award (Gemstone)
for(let i=0; i<getCarParticipant.length; i++)
{
await prisma.carItem.create({
data:{
carId: getCarParticipant[i].carId,
category: 17,
itemId: 228,
amount: 1
}
})
}
// Ranking within the top 100 (Minotaur GP)
for(let i=0; i<participantLength; i++)
{
await prisma.carItem.create({
data:{
carId: getCarParticipant[i].carId,
category: 17,
itemId: 229,
amount: 1
}
})
}
}
// 7th - Fukutoshin
else if(competitionId === 7)
else if(competitionId === 6)
{
// Participation Award (Koi)
for(let i=0; i<getCarParticipant.length; i++)
@ -797,37 +767,8 @@ export async function ocmGiveNamePlateReward(competitionId: number)
})
}
}
// 21st - Hiroshima
else if(competitionId === 8)
{
// Participation Award (Ukiyo-e)
for(let i=0; i<getCarParticipant.length; i++)
{
await prisma.carItem.create({
data:{
carId: getCarParticipant[i].carId,
category: 17,
itemId: 234,
amount: 1
}
})
}
// Ranking within the top 100 (Cerberus GP)
for(let i=0; i<participantLength; i++)
{
await prisma.carItem.create({
data:{
carId: getCarParticipant[i].carId,
category: 17,
itemId: 235,
amount: 1
}
})
}
}
// 8th - Hakone
else if(competitionId === 9)
else if(competitionId === 7)
{
// Participation Award (Studs)
for(let i=0; i<getCarParticipant.length; i++)
@ -855,6 +796,64 @@ export async function ocmGiveNamePlateReward(competitionId: number)
})
}
}
// 20th - Kobe
else if(competitionId === 8)
{
// Participation Award (Gemstone)
for(let i=0; i<getCarParticipant.length; i++)
{
await prisma.carItem.create({
data:{
carId: getCarParticipant[i].carId,
category: 17,
itemId: 228,
amount: 1
}
})
}
// Ranking within the top 100 (Minotaur GP)
for(let i=0; i<participantLength; i++)
{
await prisma.carItem.create({
data:{
carId: getCarParticipant[i].carId,
category: 17,
itemId: 229,
amount: 1
}
})
}
}
// 21st - Hiroshima
else if(competitionId === 9)
{
// Participation Award (Ukiyo-e)
for(let i=0; i<getCarParticipant.length; i++)
{
await prisma.carItem.create({
data:{
carId: getCarParticipant[i].carId,
category: 17,
itemId: 234,
amount: 1
}
})
}
// Ranking within the top 100 (Cerberus GP)
for(let i=0; i<participantLength; i++)
{
await prisma.carItem.create({
data:{
carId: getCarParticipant[i].carId,
category: 17,
itemId: 235,
amount: 1
}
})
}
}
// 1st - C1
else if(competitionId === 10)
{

View File

@ -5,7 +5,7 @@ export async function OCMArea(competition_id: number)
let rampVal = 0;
let pathVal = 0;
// 16th - C1 Outbound
// 16th - C1
if(competition_id === 1)
{
// GID_RUNAREA_C1
@ -53,7 +53,7 @@ export async function OCMArea(competition_id: number)
// GID_PATH_NGR_MARUNOUCHI
pathVal = 49;
}
// 6th - C1 Inbound
// 6th - C1
else if(competition_id === 5)
{
// GID_RUNAREA_C1
@ -65,20 +65,8 @@ export async function OCMArea(competition_id: number)
// GID_PATH_C1IN_KANDABASHI02
pathVal = 1;
}
// 20th - Kobe
else if(competition_id === 6)
{
// GID_RUNAREA_KOBE
areaVal = 10;
// GID_RAMP_KOBE_NADAOOHASHI
rampVal = 28;
// GID_PATH_KB_NADA
pathVal = 55;
}
// 7th - Fukutoshin
else if(competition_id === 7)
else if(competition_id === 6)
{
// GID_RUNAREA_SUBTOKYO_3_4
areaVal = 2;
@ -89,20 +77,8 @@ export async function OCMArea(competition_id: number)
// GID_PATH_WTWEST_GAIEN
pathVal = 17;
}
// 21st - Hiroshima
else if(competition_id === 8)
{
// GID_RUNAREA_HIROSHIMA
areaVal = 18;
// GID_RAMP_HIROSHIMA_SHINONOME
rampVal = 37;
// GID_PATH_HS_SHINONOME
pathVal = 56;
}
// 8th - Hakone
else if(competition_id === 9)
else if(competition_id === 7)
{
// GID_RUNAREA_HAKONE
areaVal = 12;
@ -113,6 +89,30 @@ export async function OCMArea(competition_id: number)
// GID_PATH_HKFOR
pathVal = 62;
}
// 20th - Kobe
else if(competition_id === 8)
{
// GID_RUNAREA_KOBE
areaVal = 10;
// GID_RAMP_KOBE_NADAOOHASHI
rampVal = 28;
// GID_PATH_KB_NADA
pathVal = 55;
}
// 21st - Hiroshima
else if(competition_id === 9)
{
// GID_RUNAREA_HIROSHIMA
areaVal = 18;
// GID_RAMP_HIROSHIMA_SHINONOME
rampVal = 37;
// GID_PATH_HS_SHINONOME
pathVal = 56;
}
// 1st - C1 Outbound
else if(competition_id === 10)
{

View File

@ -4,7 +4,7 @@ import { prisma } from "../..";
import { wm } from "../../wmmt/wm.proto";
// Import Util
import * as ghost_get_area_from_path from "./ghost_util/ghost_get_area_from_path";
import * as ghost_get_area_from_path from "../ghost/ghost_util/ghost_get_area_from_path";
export async function sendStamp(body: wm.protobuf.SaveGameResultRequest)

View File

@ -1,4 +1,4 @@
import { prisma } from "../../..";
import { prisma } from "../..";
// Import Proto
import * as ghost_ocm_area from "./ghost_ocm_area";

View File

@ -1,8 +1,8 @@
import { prisma } from "../..";
import { Config } from "../../config";
import { prisma } from "..";
import { Config } from "../config";
//Import Proto
import * as wm from "../../wmmt/wm.proto";
import * as wm from "../wmmt/wm.proto";
// *** CONSTANTS ***

View File

@ -1,6 +1,5 @@
import { prisma } from "../..";
// Sends the server response to the client
export async function checkScratchCar(userId: number, visualModel: number)
{

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

11217
src/wmmt/service.proto.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

9270
src/wmmt/system.proto.js vendored

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More