feat(ett)
This commit is contained in:
parent
65a1ff3e0b
commit
d59cba0752
8 changed files with 10351 additions and 0 deletions
5
user/mods/expandedtasktext/README.md
Normal file
5
user/mods/expandedtasktext/README.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
Expanded Task Text
|
||||
|
||||
Yes a config exists, yes its empty, yes it will be used in the future.
|
||||
|
||||
Expands information about tasks, for now just required and optional keys. More information will come in the future. :)
|
||||
7
user/mods/expandedtasktext/config/config.json
Normal file
7
user/mods/expandedtasktext/config/config.json
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"ShowCollectorRequirements": true,
|
||||
"ShowLightKeeperRequirements": true,
|
||||
"ShowGunsmithRequiredParts": true,
|
||||
"ShowNextQuestInChain": true,
|
||||
"ShowTimeUntilNextQuest": true
|
||||
}
|
||||
339
user/mods/expandedtasktext/db/GunsmithLocaleEN.json
Normal file
339
user/mods/expandedtasktext/db/GunsmithLocaleEN.json
Normal file
|
|
@ -0,0 +1,339 @@
|
|||
{
|
||||
"5ac23c6186f7741247042bad": {
|
||||
"QuestName": "Gunsmith Part 1",
|
||||
"RequiredParts": [
|
||||
"55d45f484bdc2d972f8b456d",
|
||||
"56083a334bdc2dc8488b4571",
|
||||
"5cc9c20cd7f00c001336c65d"
|
||||
]
|
||||
},
|
||||
"5ac2426c86f774138762edfe": {
|
||||
"QuestName": "Gunsmith Part 2",
|
||||
"RequiredParts": [
|
||||
"57ffa9f4245977728561e844",
|
||||
"5c87ca002e221600114cb150",
|
||||
"55d482194bdc2d1d4e8b456b"
|
||||
]
|
||||
},
|
||||
"5ac2428686f77412450b42bf": {
|
||||
"QuestName": "Gunsmith Part 3",
|
||||
"RequiredParts": [
|
||||
"5a351711c4a282000b1521a4",
|
||||
"59c63b4486f7747afb151c1c",
|
||||
"5cc9c20cd7f00c001336c65d",
|
||||
"5926f34786f77469195bfe92",
|
||||
"5926f2e086f7745aae644231",
|
||||
"5926d33d86f77410de68ebc0"
|
||||
]
|
||||
},
|
||||
"639872f9decada40426d3447": {
|
||||
"QuestName": "Gunsmith Part 4",
|
||||
"RequiredParts": [
|
||||
"587df583245977373c4f1129",
|
||||
"6415d33eda439c6a97048b5b",
|
||||
"5dff772da3651922b360bf91",
|
||||
"5dff77c759400025ea5150cf",
|
||||
"5afd7ded5acfc40017541f5e",
|
||||
"5afd7e095acfc40017541f61",
|
||||
"5947f92f86f77427344a76b1",
|
||||
"55d4ae6c4bdc2d8b2f8b456e",
|
||||
"593d490386f7745ee97a1555"
|
||||
]
|
||||
},
|
||||
"5ae3267986f7742a413592fe": {
|
||||
"QuestName": "Gunsmith Part 5",
|
||||
"RequiredParts": [
|
||||
"5c0111ab0db834001966914d",
|
||||
"58272d7f2459774f6311ddfd",
|
||||
"5a788068c5856700137e4c8f",
|
||||
"5b7be4895acfc400170e2dd5",
|
||||
"5c87ca002e221600114cb150",
|
||||
"5b7be47f5acfc400170e2dd2",
|
||||
"5cc9c20cd7f00c001336c65d",
|
||||
"5a78813bc5856700186c4abe"
|
||||
]
|
||||
},
|
||||
"5ae3270f86f77445ba41d4dd": {
|
||||
"QuestName": "Gunsmith Part 6",
|
||||
"RequiredParts": [
|
||||
"59f8a37386f7747af3328f06",
|
||||
"59bffc1f86f77435b128b872",
|
||||
"59bffbb386f77435b379b9c2",
|
||||
"5947f92f86f77427344a76b1",
|
||||
"59d6272486f77466146386ff",
|
||||
"57cff947245977638e6f2a19",
|
||||
"5b7be4895acfc400170e2dd5",
|
||||
"5d2c76ed48f03532f2136169",
|
||||
"6477772ea8a38bb2050ed4db"
|
||||
]
|
||||
},
|
||||
"5ac244eb86f7741356335af1": {
|
||||
"QuestName": "Gunsmith Part 7",
|
||||
"RequiredParts": [
|
||||
"544a37c44bdc2d25388b4567",
|
||||
"59db7e1086f77448be30ddf3",
|
||||
"5fbbaa86f9986c4cff3fe5f6",
|
||||
"5a339805c4a2826c6e06d73d",
|
||||
"5c78f2792e221600106f4683",
|
||||
"55d35ee94bdc2d61338b4568",
|
||||
"55d6190f4bdc2d87028b4567",
|
||||
"56ea8d2fd2720b7c698b4570",
|
||||
"651a8e529829226ceb67c319",
|
||||
"5c7fb51d2e2216001219ce11"
|
||||
]
|
||||
},
|
||||
"5ae3277186f7745973054106": {
|
||||
"QuestName": "Gunsmith Part 8",
|
||||
"RequiredParts": [
|
||||
"59ecc3dd86f7746dc827481c",
|
||||
"59ecc28286f7746d7a68aa8c",
|
||||
"5649ae4a4bdc2d1b2b8b4588",
|
||||
"5649af884bdc2d1b2b8b4589",
|
||||
"5efaf417aeb21837e749c7f2",
|
||||
"5649ab884bdc2ded0b8b457f",
|
||||
"5c1bc4812e22164bef5cfde7",
|
||||
"5bed61680db834001d2c45ab",
|
||||
"5a5f1ce64f39f90b401987bc"
|
||||
]
|
||||
},
|
||||
"639872fa9b4fb827b200d8e5": {
|
||||
"QuestName": "Gunsmith Part 9",
|
||||
"RequiredParts": [
|
||||
"5c0009510db834001966907f",
|
||||
"5c00076d0db834001d23ee1f",
|
||||
"5c920e902e221644f31c3c99",
|
||||
"5cc9c20cd7f00c001336c65d",
|
||||
"5c6beec32e221601da3578f2",
|
||||
"587de4282459771bca0ec90b"
|
||||
]
|
||||
},
|
||||
"5ae327c886f7745c7b3f2f3f": {
|
||||
"QuestName": "Gunsmith Part 10",
|
||||
"RequiredParts": [
|
||||
"55d482194bdc2d1d4e8b456b",
|
||||
"5cbda392ae92155f3c17c39f",
|
||||
"5c87ca002e221600114cb150",
|
||||
"5d2c76ed48f03532f2136169",
|
||||
"5947f92f86f77427344a76b1",
|
||||
"59bffc1f86f77435b128b872",
|
||||
"59bffbb386f77435b379b9c2",
|
||||
"5ac78eaf5acfc4001926317a",
|
||||
"5b222d405acfc400153af4fe",
|
||||
"6477772ea8a38bb2050ed4db"
|
||||
]
|
||||
},
|
||||
"639872fc93ae507d5858c3a6": {
|
||||
"QuestName": "Gunsmith Part 11",
|
||||
"RequiredParts": [
|
||||
"5fbb978207e8a97d1f0902d3",
|
||||
"5f6340d3ca442212f4047eb2",
|
||||
"5a7ad2e851dfba0016153692",
|
||||
"5fbbc383d5cb881a7363194a",
|
||||
"5a32a064c4a28200741e22de",
|
||||
"5fb655b748c711690e3a8d5a",
|
||||
"5649be884bdc2d79388b4577",
|
||||
"5fbbaa86f9986c4cff3fe5f6"
|
||||
]
|
||||
},
|
||||
"5b47799d86f7746c5d6a5fd8": {
|
||||
"QuestName": "Gunsmith Part 12",
|
||||
"RequiredParts": [
|
||||
"5b07db875acfc40dc528a5f6",
|
||||
"5b3a16655acfc40016387a2a",
|
||||
"5b07dd285acfc4001754240d",
|
||||
"64806bdd26c80811d408d37a"
|
||||
]
|
||||
},
|
||||
"5ac244c486f77413e12cf945": {
|
||||
"QuestName": "Gunsmith Part 13",
|
||||
"RequiredParts": [
|
||||
"59bffc1f86f77435b128b872",
|
||||
"59bffbb386f77435b379b9c2",
|
||||
"5c0102b20db834001d23eebc",
|
||||
"5c7fc87d2e221644f31c0298",
|
||||
"5aa66be6e5b5b0214e506e97",
|
||||
"5c86592b2e2216000e69e77c",
|
||||
"5c1780312e221602b66cc189",
|
||||
"5c17804b2e2216152006c02f",
|
||||
"6113c3586c780c1e710c90bc"
|
||||
]
|
||||
},
|
||||
"639872fe8871e1272b10ccf6": {
|
||||
"QuestName": "Gunsmith Part 14",
|
||||
"RequiredParts": [
|
||||
"55d4887d4bdc2d962f8b4570",
|
||||
"5c6d10fa2e221600106f3f23",
|
||||
"6269220d70b6c02e665f2635",
|
||||
"5d15cf3bd7ad1a67e71518b2",
|
||||
"5947eab886f77475961d96c5",
|
||||
"5bb20d92d4351e00853263eb",
|
||||
"5c7fb51d2e2216001219ce11",
|
||||
"5ea17bbc09aa976f2e7a51cd",
|
||||
"5b7be4895acfc400170e2dd5",
|
||||
"5fce0cf655375d18a253eff0",
|
||||
"5c06595c0db834001a66af6c",
|
||||
"5c18b9192e2216398b5a8104",
|
||||
"5bc09a30d4351e00367fb7c8",
|
||||
"558022b54bdc2dac148b458d"
|
||||
]
|
||||
},
|
||||
"5ae3280386f7742a41359364": {
|
||||
"QuestName": "Gunsmith Part 15",
|
||||
"RequiredParts": [
|
||||
"5a9eb32da2750c00171b3f9c",
|
||||
"5a7c74b3e899ef0014332c29",
|
||||
"544909bb4bdc2d6f028b4577",
|
||||
"5a9e81fba2750c00164f6b11",
|
||||
"5a69a2ed8dc32e000d46d1f1",
|
||||
"57a3459f245977764a01f703"
|
||||
]
|
||||
},
|
||||
"5ac242ab86f77412464f68b4": {
|
||||
"QuestName": "Gunsmith Part 16",
|
||||
"RequiredParts": [
|
||||
"5cc9c20cd7f00c001336c65d",
|
||||
"5aa66be6e5b5b0214e506e97",
|
||||
"5c86592b2e2216000e69e77c"
|
||||
]
|
||||
},
|
||||
"5b47749f86f7746c5d6a5fd4": {
|
||||
"QuestName": "Gunsmith Part 17",
|
||||
"RequiredParts": [
|
||||
"5e21ca18e4d47f0da15e77dd",
|
||||
"5947f92f86f77427344a76b1",
|
||||
"5648b4534bdc2d3d1c8b4580",
|
||||
"5649af884bdc2d1b2b8b4589",
|
||||
"5beec8b20db834001961942a",
|
||||
"5c0548ae0db834001966a3c2",
|
||||
"6130ca3fd92c473c77020dbd",
|
||||
"588226ef24597767af46e39c",
|
||||
"5b3a337e5acfc4704b4a19a0",
|
||||
"5f6372e2865db925d54f3869",
|
||||
"5f6339d53ada5942720e2dc3",
|
||||
"5fbbaa86f9986c4cff3fe5f6",
|
||||
"6477772ea8a38bb2050ed4db"
|
||||
]
|
||||
},
|
||||
"5b477b6f86f7747290681823": {
|
||||
"QuestName": "Gunsmith Part 18",
|
||||
"RequiredParts": [
|
||||
"57cff947245977638e6f2a19",
|
||||
"57cffb66245977632f391a99",
|
||||
"5b0e794b5acfc47a877359b2",
|
||||
"5b30ac585acfc433000eb79c",
|
||||
"59d6272486f77466146386ff",
|
||||
"5a9fbacda2750c00141e080f",
|
||||
"5c07dd120db834001c39092d",
|
||||
"5d2c76ed48f03532f2136169"
|
||||
]
|
||||
},
|
||||
"639873003693c63d86328f25": {
|
||||
"QuestName": "Gunsmith Part 19",
|
||||
"RequiredParts": [
|
||||
"6516b129609aaf354b34b3a8",
|
||||
"5b30ac585acfc433000eb79c",
|
||||
"6197b229af1f5202c57a9bea",
|
||||
"5dfcd0e547101c39625f66f9",
|
||||
"5dfce88fe9dc277128008b2e",
|
||||
"5947e98b86f774778f1448bc",
|
||||
"5e01e9e273d8eb11426f5bc3",
|
||||
"5e01ea19e9dc277128008c0b",
|
||||
"57c69dd424597774c03b7bbc",
|
||||
"57c5ac0824597754771e88a9"
|
||||
]
|
||||
},
|
||||
"5b477f7686f7744d1b23c4d2": {
|
||||
"QuestName": "Gunsmith Part 20",
|
||||
"RequiredParts": [
|
||||
"5aaf8a0be5b5b00015693243",
|
||||
"5addbf175acfc408fb13965b",
|
||||
"5addbfbb5acfc400194dbcf7",
|
||||
"5aa66be6e5b5b0214e506e97",
|
||||
"5c86592b2e2216000e69e77c",
|
||||
"58d399e486f77442e0016fe7",
|
||||
"58d39d3d86f77445bb794ae7",
|
||||
"57fd23e32459772d0805bcf1",
|
||||
"5addbfef5acfc400185c2857"
|
||||
]
|
||||
},
|
||||
"63987301e11ec11ff5504036": {
|
||||
"QuestName": "Gunsmith Part 21",
|
||||
"RequiredParts": [
|
||||
"5cde739cd7f00c0010373bd3",
|
||||
"5a339805c4a2826c6e06d73d",
|
||||
"5cde7afdd7f00c000d36b89d",
|
||||
"5649be884bdc2d79388b4577",
|
||||
"5fbbaa86f9986c4cff3fe5f6",
|
||||
"5cde7b43d7f00c000d36b93e",
|
||||
"5d1f819086f7744b355c219b",
|
||||
"5cff9e84d7ad1a049e54ed55",
|
||||
"61713cc4d8e3106d9806c109",
|
||||
"62850c28da09541f43158cca"
|
||||
]
|
||||
},
|
||||
"5b47825886f77468074618d3": {
|
||||
"QuestName": "Gunsmith Part 22",
|
||||
"RequiredParts": [
|
||||
"544a37c44bdc2d25388b4567",
|
||||
"5b30bc285acfc47a8608615d",
|
||||
"64806bdd26c80811d408d37a",
|
||||
"5b2cfa535acfc432ff4db7a0",
|
||||
"59db3a1d86f77429e05b4e92",
|
||||
"55d35ee94bdc2d61338b4568",
|
||||
"56ea8180d2720bf2698b456a",
|
||||
"57dbb57e2459774673234890",
|
||||
"56eabcd4d2720b66698b4574",
|
||||
"5a1ead28fcdbcb001912fa9f",
|
||||
"639c39807c1532d85b0162a9",
|
||||
"5a1eacb3fcdbcb09800872be",
|
||||
"591aef7986f774139d495f03"
|
||||
]
|
||||
},
|
||||
"64f83bb69878a0569d6ecfbe": {
|
||||
"QuestName": "Gunsmith Part 23",
|
||||
"RequiredParts": [
|
||||
"5d00ef6dd7ad1a0940739b16",
|
||||
"6065878ac9cf8012264142fd",
|
||||
"5bbdb8bdd4351e4502011460",
|
||||
"5f6340d3ca442212f4047eb2",
|
||||
"5a800961159bd4315e3a1657",
|
||||
"59f9d81586f7744c7506ee62",
|
||||
"5c87a07c2e2216001219d4a2",
|
||||
"6113cce3d92c473c770200c7",
|
||||
"5c6175362e221600133e3b94"
|
||||
]
|
||||
},
|
||||
"64f83bcdde58fc437700d8fa": {
|
||||
"QuestName": "Gunsmith Part 24",
|
||||
"RequiredParts": [
|
||||
"5d025cc1d7ad1a53845279ef",
|
||||
"5df8f535bb49d91fb446d6b0",
|
||||
"5d44069ca4b9361ebd26fc37",
|
||||
"5d1b5e94d7ad1a2b865a96b0",
|
||||
"5dfa3d2b0dee1b22f862eade",
|
||||
"6269220d70b6c02e665f2635",
|
||||
"5d2369418abbc306c62e0c80",
|
||||
"5b7be4895acfc400170e2dd5",
|
||||
"5b057b4f5acfc4771e1bd3e9",
|
||||
"5649a2464bdc2d91118b45a8",
|
||||
"577d128124597739d65d0e56",
|
||||
"577d141e24597739c5255e01",
|
||||
"5dfa3cd1b33c0951220c079b"
|
||||
]
|
||||
},
|
||||
"64f83bd983cfca080a362c82": {
|
||||
"QuestName": "Gunsmith Part 25",
|
||||
"RequiredParts": [
|
||||
"6491c6f6ef312a876705191b",
|
||||
"646371faf2404ab67905c8e9",
|
||||
"6492ef63cfcf7c89e701abf1",
|
||||
"6492d7847363b8a52206bc52",
|
||||
"5947f92f86f77427344a76b1",
|
||||
"5cf638cbd7f00c06595bc936",
|
||||
"5cf639aad7f00c065703d455",
|
||||
"5cc9c20cd7f00c001336c65d",
|
||||
"5a0c59791526d8dba737bba7",
|
||||
"5649ad3f4bdc2df8348b4585"
|
||||
]
|
||||
}
|
||||
}
|
||||
9537
user/mods/expandedtasktext/db/QuestInfo.json
Normal file
9537
user/mods/expandedtasktext/db/QuestInfo.json
Normal file
File diff suppressed because it is too large
Load diff
35
user/mods/expandedtasktext/package.json
Normal file
35
user/mods/expandedtasktext/package.json
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"name": "Expanded Task Text",
|
||||
"version": "1.6.4",
|
||||
"main": "src/mod.js",
|
||||
"license": "BY-NC-ND 4.0",
|
||||
"author": "Dirtbikercj, FriedEngineer",
|
||||
"sptVersion": "~3.11",
|
||||
"loadBefore": [],
|
||||
"loadAfter": [],
|
||||
"incompatibilities": [],
|
||||
"contributors": [],
|
||||
"scripts": {
|
||||
"lint": "npx @biomejs/biome lint ./",
|
||||
"lint:fix": "npx @biomejs/biome lint --write ./",
|
||||
"style": "npx @biomejs/biome format ./",
|
||||
"style:fix": "npx @biomejs/biome format --write ./",
|
||||
"format": "npx @biomejs/biome check --write ./",
|
||||
"setup": "npm i",
|
||||
"build": "node ./build.mjs",
|
||||
"buildinfo": "node ./build.mjs --verbose"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "1.8.3",
|
||||
"@types/node": "20.11",
|
||||
"@typescript-eslint/eslint-plugin": "7.2",
|
||||
"@typescript-eslint/parser": "7.2",
|
||||
"archiver": "^6.0",
|
||||
"eslint": "8.57",
|
||||
"fs-extra": "11.2",
|
||||
"ignore": "^5.2",
|
||||
"tsyringe": "4.8.0",
|
||||
"typescript": "5.4",
|
||||
"winston": "3.12"
|
||||
}
|
||||
}
|
||||
16
user/mods/expandedtasktext/src/IQuestInfoModel.ts
Normal file
16
user/mods/expandedtasktext/src/IQuestInfoModel.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
|
||||
export interface IQuestInfoModel
|
||||
{
|
||||
wikiLink: string;
|
||||
id: string;
|
||||
kappaRequired: boolean;
|
||||
lightkeeperRequired: boolean;
|
||||
objectives: IObjective[];
|
||||
}
|
||||
|
||||
export interface IObjective
|
||||
{
|
||||
id: string;
|
||||
requiredKeys: Record<string, string>[] | undefined;
|
||||
}
|
||||
81
user/mods/expandedtasktext/src/InstanceManager.ts
Normal file
81
user/mods/expandedtasktext/src/InstanceManager.ts
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
import * as fs from "node:fs";
|
||||
import * as path from "node:path";
|
||||
|
||||
import type { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import type { DatabaseServer } from "@spt/servers/DatabaseServer";
|
||||
import type { IDatabaseTables } from "@spt/models/spt/server/IDatabaseTables";
|
||||
import type { StaticRouterModService } from "@spt/services/mod/staticRouter/StaticRouterModService";
|
||||
import type { DependencyContainer } from "tsyringe";
|
||||
import type { CustomItemService } from "@spt/services/mod/CustomItemService";
|
||||
import type { ImageRouter } from "@spt/routers/ImageRouter";
|
||||
import type { PreSptModLoader } from "@spt/loaders/PreSptModLoader";
|
||||
import type { ConfigServer } from "@spt/servers/ConfigServer";
|
||||
import type { JsonUtil } from "@spt/utils/JsonUtil";
|
||||
import type { ProfileHelper } from "@spt/helpers/ProfileHelper";
|
||||
import type { RagfairPriceService } from "@spt/services/RagfairPriceService";
|
||||
import type { ImporterUtil } from "@spt/utils/ImporterUtil";
|
||||
import type { SaveServer } from "@spt/servers/SaveServer";
|
||||
import type { ItemHelper } from "@spt/helpers/ItemHelper";
|
||||
import type { HashUtil } from "@spt/utils/HashUtil";
|
||||
import type { FileSystem } from "@spt/utils/FileSystem"
|
||||
|
||||
export class InstanceManager
|
||||
{
|
||||
//#region Accessible in or after preAkiLoad
|
||||
public modName: string;
|
||||
public debug: boolean;
|
||||
// Useful Paths
|
||||
public modPath: string = path.join(process.cwd(), "user", "mods", "TarkovTools");
|
||||
public dbPath: string = path.join(process.cwd(), "user", "mods", "TarkovTools", "database");
|
||||
public profilePath: string = path.join(process.cwd(), "user", "profiles");
|
||||
public cachePath: string = path.join(path.dirname(__filename), "..", "config", "cache.json");
|
||||
|
||||
// Instances
|
||||
public container: DependencyContainer;
|
||||
public preSptModLoader: PreSptModLoader;
|
||||
public configServer: ConfigServer;
|
||||
public saveServer: SaveServer;
|
||||
public itemHelper: ItemHelper;
|
||||
public logger: ILogger;
|
||||
public staticRouter: StaticRouterModService;
|
||||
public vfs: FileSystem;
|
||||
//#endregion
|
||||
|
||||
//#region Accessible in or after postDBLoad
|
||||
public database: IDatabaseTables;
|
||||
public customItem: CustomItemService;
|
||||
public imageRouter: ImageRouter;
|
||||
public jsonUtil: JsonUtil;
|
||||
public profileHelper: ProfileHelper;
|
||||
public ragfairPriceService: RagfairPriceService;
|
||||
public importerUtil: ImporterUtil;
|
||||
public hashUtil: HashUtil;
|
||||
//#endregion
|
||||
|
||||
// Call at the start of the mods postDBLoad method
|
||||
public preSptLoad(container: DependencyContainer, mod: string): void
|
||||
{
|
||||
this.modName = mod;
|
||||
|
||||
this.container = container;
|
||||
this.preSptModLoader = container.resolve<PreSptModLoader>("PreSptModLoader");
|
||||
this.imageRouter = container.resolve<ImageRouter>("ImageRouter");
|
||||
this.configServer = container.resolve<ConfigServer>("ConfigServer");
|
||||
this.saveServer = container.resolve<SaveServer>("SaveServer");
|
||||
this.itemHelper = container.resolve<ItemHelper>("ItemHelper");
|
||||
this.logger = container.resolve<ILogger>("WinstonLogger");
|
||||
this.staticRouter = container.resolve<StaticRouterModService>("StaticRouterModService");
|
||||
this.vfs = container.resolve<FileSystem>("FileSystem");
|
||||
}
|
||||
|
||||
public postDBLoad(container: DependencyContainer): void
|
||||
{
|
||||
this.database = container.resolve<DatabaseServer>("DatabaseServer").getTables();
|
||||
this.customItem = container.resolve<CustomItemService>("CustomItemService");
|
||||
this.jsonUtil = container.resolve<JsonUtil>("JsonUtil");
|
||||
this.profileHelper = container.resolve<ProfileHelper>("ProfileHelper");
|
||||
this.ragfairPriceService = container.resolve<RagfairPriceService>("RagfairPriceService");
|
||||
this.importerUtil = container.resolve<ImporterUtil>("ImporterUtil");
|
||||
this.hashUtil = container.resolve<HashUtil>("HashUtil");
|
||||
}
|
||||
}
|
||||
331
user/mods/expandedtasktext/src/mod.ts
Normal file
331
user/mods/expandedtasktext/src/mod.ts
Normal file
|
|
@ -0,0 +1,331 @@
|
|||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
|
||||
import * as path from "node:path";
|
||||
import * as fs from "node:fs";
|
||||
import * as config from "../config/config.json";
|
||||
|
||||
import * as gsEN from "../db/GunsmithLocaleEN.json";
|
||||
|
||||
import type { DependencyContainer } from "tsyringe";
|
||||
import { InstanceManager } from "./InstanceManager";
|
||||
|
||||
import type { IPreSptLoadMod } from "@spt/models/external/IPreSptLoadMod";
|
||||
import type { IPostDBLoadMod } from "@spt/models/external/IPostDBLoadMod";
|
||||
import { LogTextColor } from "@spt/models/spt/logging/LogTextColor";
|
||||
import type { IDatabaseTables } from "@spt/models/spt/server/IDatabaseTables";
|
||||
import type { IQuest } from "@spt/models/eft/common/tables/IQuest";
|
||||
import type { ITrader } from "@spt/models/eft/common/tables/ITrader";
|
||||
import type { IObjective, IQuestInfoModel } from "./IQuestInfoModel";
|
||||
|
||||
|
||||
interface TimeGateUnlockRequirements
|
||||
{
|
||||
currentQuest: string,
|
||||
nextQuest: string,
|
||||
time: number
|
||||
}
|
||||
|
||||
class DExpandedTaskText implements IPostDBLoadMod, IPreSptLoadMod
|
||||
{
|
||||
private Instance: InstanceManager = new InstanceManager();
|
||||
private modName = "ExpandedTaskText";
|
||||
|
||||
private dbPath: string = path.join(path.dirname(__filename), "..", "db");
|
||||
|
||||
private tasks: Record<string, IQuest>;
|
||||
private locale: Record<string, Record<string, string>>;
|
||||
|
||||
private QuestInfo: IQuestInfoModel[];
|
||||
|
||||
private timeGateUnlocktimes: TimeGateUnlockRequirements[] = [];
|
||||
|
||||
public preSptLoad(container: DependencyContainer): void
|
||||
{
|
||||
this.Instance.preSptLoad(container, this.modName);
|
||||
}
|
||||
|
||||
public async postDBLoad(container: DependencyContainer): Promise<void>
|
||||
{
|
||||
const startTime = performance.now();
|
||||
|
||||
this.Instance.postDBLoad(container);
|
||||
|
||||
this.Instance.logger.log("Expanded Task Text is loading please wait...", LogTextColor.GREEN);
|
||||
|
||||
this.QuestInfo = await this.loadJsonFile<IQuestInfoModel[]>(path.join(this.dbPath, "QuestInfo.json"));
|
||||
|
||||
this.getAllTasks(this.Instance.database);
|
||||
this.updateAllBsgTasksText();
|
||||
|
||||
const endTime = performance.now();
|
||||
const startupTime = (endTime - startTime) / 1000;
|
||||
|
||||
this.Instance.logger.log(`Expanded Task Text startup took ${startupTime} seconds...`, LogTextColor.GREEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads and parses a config file from disk
|
||||
* @param fileName File name inside of config folder to load
|
||||
*/
|
||||
public async loadJsonFile<T>(filePath: string, readAsText = false): Promise<T>
|
||||
{
|
||||
const file = path.join(filePath);
|
||||
const string = await this.Instance.vfs.read(file);
|
||||
|
||||
return readAsText
|
||||
? string as T
|
||||
: JSON.parse(string) as T;
|
||||
}
|
||||
|
||||
private getAllTasks(database: IDatabaseTables): void
|
||||
{
|
||||
this.tasks = database.templates.quests;
|
||||
this.locale = database.locales.global;
|
||||
}
|
||||
|
||||
private getAllNextQuestsInChain(currentQuestId: string): string | undefined
|
||||
{
|
||||
const nextQuests: string[] = [];
|
||||
|
||||
// biome-ignore lint/complexity/noForEach: <explanation>
|
||||
Object.keys(this.tasks).forEach(key =>
|
||||
{
|
||||
if (this.tasks[key].conditions.AvailableForStart === undefined)
|
||||
{
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const conditionsAOS = this.tasks[key].conditions.AvailableForStart;
|
||||
|
||||
for (const condition in conditionsAOS)
|
||||
{
|
||||
if (conditionsAOS[condition]?.conditionType === "Quest" && conditionsAOS[condition]?.target === currentQuestId)
|
||||
{
|
||||
const nextQuestName = this.locale.en[`${key} name`];
|
||||
nextQuests.push(nextQuestName);
|
||||
|
||||
// Recursively find the next quests for the current quest
|
||||
const recursiveResults = this.getAllNextQuestsInChain(nextQuestName);
|
||||
nextQuests.push(...recursiveResults);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const resultString = nextQuests.join(", ");
|
||||
return resultString;
|
||||
}
|
||||
|
||||
private getAllTraderLoyalLevelItems(): Record<string, number>
|
||||
{
|
||||
const traders: Record<string, ITrader> = this.Instance.database.traders;
|
||||
const loyalLevelItems: Record<string, number> = {};
|
||||
|
||||
for (const trader in traders)
|
||||
{
|
||||
for (const assortItem in traders[trader]?.assort?.loyal_level_items)
|
||||
{
|
||||
loyalLevelItems[assortItem] = traders[trader].assort.loyal_level_items[assortItem];
|
||||
}
|
||||
}
|
||||
|
||||
return loyalLevelItems;
|
||||
}
|
||||
|
||||
private getAndBuildPartsList(taskId: string): string
|
||||
{
|
||||
const partIds: string[] = gsEN[taskId]?.RequiredParts;
|
||||
const localizedParts: string[] = [];
|
||||
|
||||
const traders: Record<string, ITrader> = this.Instance.database.traders;
|
||||
|
||||
const loyalLevelItems: Record<string, number> = this.getAllTraderLoyalLevelItems();
|
||||
|
||||
if (partIds.length === 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
for (const part of partIds)
|
||||
{
|
||||
let partString = this.locale.en[`${part} Name`];
|
||||
|
||||
for (const trader in traders)
|
||||
{
|
||||
for (let i = 0; i < traders[trader]?.assort?.items.length; i++)
|
||||
{
|
||||
if (part === traders[trader].assort.items[i]._tpl && loyalLevelItems[traders[trader].assort.items[i]._id] !== undefined)
|
||||
{
|
||||
partString += `\n Sold by (${this.locale.en[`${trader} Nickname`]} LL ${loyalLevelItems[traders[trader].assort.items[i]._id]})`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
localizedParts.push(partString);
|
||||
}
|
||||
|
||||
return localizedParts.join("\n\n");
|
||||
}
|
||||
|
||||
private buildKeyText(objectives: IObjective[], localeId: string): string | undefined
|
||||
{
|
||||
let keyDesc = "";
|
||||
|
||||
for (const obj of objectives)
|
||||
{
|
||||
if (obj.requiredKeys === undefined) continue;
|
||||
|
||||
const objDesc = this.locale[localeId][`${obj.id}`];
|
||||
let keys = "";
|
||||
|
||||
for (const keysInObj in obj.requiredKeys)
|
||||
{
|
||||
for (const key in obj.requiredKeys[keysInObj])
|
||||
{
|
||||
const localeKey = `${obj.requiredKeys[keysInObj][key]["id"]} Name`
|
||||
const localEntry = this.locale[localeId][localeKey];
|
||||
|
||||
if (localeKey === undefined || localEntry === undefined) continue;
|
||||
|
||||
keys += ` ${localEntry}\n`;
|
||||
}
|
||||
}
|
||||
|
||||
if (keys.length === 0) continue;
|
||||
|
||||
keyDesc += `${objDesc}\n Requires key(s):\n${keys}`
|
||||
}
|
||||
|
||||
return keyDesc;
|
||||
}
|
||||
|
||||
private updateAllBsgTasksText()
|
||||
{
|
||||
const questInfo = this.QuestInfo;
|
||||
const modifiedQuestIds = [];
|
||||
|
||||
for (const info of questInfo)
|
||||
{
|
||||
for (const localeID in this.locale)
|
||||
{
|
||||
const originalDesc = this.locale[localeID][`${info.id} description`];
|
||||
let keyDesc: string = this.buildKeyText(info.objectives, localeID);
|
||||
let collector: string;
|
||||
let lightKeeper: string;
|
||||
let durability: string;
|
||||
let requiredParts: string;
|
||||
let timeUntilNext: string;
|
||||
let leadsTo: string;
|
||||
|
||||
modifiedQuestIds.push(info.id);
|
||||
|
||||
if (config.ShowCollectorRequirements && info.kappaRequired)
|
||||
{
|
||||
collector = "This quest is required for Collector \n \n";
|
||||
}
|
||||
|
||||
|
||||
if (config.ShowLightKeeperRequirements && info.lightkeeperRequired)
|
||||
{
|
||||
lightKeeper = "This quest is required for Lightkeeper \n \n";
|
||||
}
|
||||
|
||||
|
||||
const nextQuest: string = this.getAllNextQuestsInChain(info.id);
|
||||
|
||||
if (nextQuest.length > 0 && config.ShowNextQuestInChain)
|
||||
{
|
||||
leadsTo = `Leads to: ${nextQuest} \n \n`;
|
||||
}
|
||||
else if (config.ShowNextQuestInChain)
|
||||
{
|
||||
leadsTo = "Leads to: Nothing \n \n";
|
||||
}
|
||||
else
|
||||
{
|
||||
leadsTo = "";
|
||||
}
|
||||
|
||||
if (gsEN[info.id]?.RequiredParts !== undefined && config.ShowGunsmithRequiredParts)
|
||||
{
|
||||
durability = "Required Durability: 60 \n";
|
||||
requiredParts = `${this.getAndBuildPartsList(info.id)} \n \n`;
|
||||
}
|
||||
|
||||
if (config.ShowTimeUntilNextQuest)
|
||||
{
|
||||
for (const req of this.timeGateUnlocktimes)
|
||||
{
|
||||
if (req.currentQuest === info.id)
|
||||
{
|
||||
timeUntilNext = `Hours until ${this.locale.en[`${req.nextQuest} name`]} unlocks after completion: ${req.time} \n \n`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (keyDesc === undefined)
|
||||
{
|
||||
keyDesc = "";
|
||||
}
|
||||
|
||||
if (collector === undefined)
|
||||
{
|
||||
collector = "";
|
||||
}
|
||||
|
||||
if (lightKeeper === undefined)
|
||||
{
|
||||
lightKeeper = "";
|
||||
}
|
||||
|
||||
if (requiredParts === undefined)
|
||||
{
|
||||
requiredParts = "";
|
||||
}
|
||||
|
||||
if (durability === undefined)
|
||||
{
|
||||
durability = "";
|
||||
}
|
||||
|
||||
if (timeUntilNext === undefined)
|
||||
{
|
||||
timeUntilNext = "";
|
||||
}
|
||||
|
||||
// biome-ignore lint/style/useTemplate: <>
|
||||
this.locale[localeID][`${info.id} description`] = collector + lightKeeper + leadsTo + timeUntilNext + (keyDesc.length > 0 ? `${keyDesc} \n` : "") + durability + requiredParts + originalDesc;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle leads to for custom traders
|
||||
for (const quest in this.Instance.database.templates.quests)
|
||||
{
|
||||
if (modifiedQuestIds.includes(quest)) continue;
|
||||
|
||||
for (const localeId in this.locale)
|
||||
{
|
||||
const originalDesc = this.locale[localeId][`${quest} description`];
|
||||
let leadsTo: string;
|
||||
|
||||
const nextQuest: string = this.getAllNextQuestsInChain(quest);
|
||||
|
||||
if (nextQuest.length > 0 && config.ShowNextQuestInChain)
|
||||
{
|
||||
leadsTo = `Leads to: ${nextQuest} \n \n`;
|
||||
}
|
||||
else if (config.ShowNextQuestInChain)
|
||||
{
|
||||
leadsTo = "Leads to: Nothing \n \n";
|
||||
}
|
||||
else
|
||||
{
|
||||
leadsTo = "";
|
||||
}
|
||||
|
||||
this.locale[localeId][`${quest} description`] = leadsTo + originalDesc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { mod: new DExpandedTaskText() }
|
||||
Loading…
Add table
Add a link
Reference in a new issue