0
0
mirror of https://github.com/sp-tarkov/server.git synced 2025-02-13 08:30:44 -05:00

Merge branch 'master' of https://dev.sp-tarkov.com/SPT-AKI/Server into 3.8.0

# Conflicts:
#	project/assets/configs/core.json
This commit is contained in:
Dev 2023-11-13 17:06:19 +00:00
commit 206f0d672d
15 changed files with 31131 additions and 31098 deletions

View File

@ -144,9 +144,9 @@
"minPlayerLevel": 5, "minPlayerLevel": 5,
"rewardScaling": { "rewardScaling": {
"levels": [1, 10, 20, 30, 40, 50, 60], "levels": [1, 10, 20, 30, 40, 50, 60],
"experience": [1000, 12000, 42000, 89000, 177000, 300000, 500000], "experience": [1000, 5000, 11000, 59000, 147000, 250000, 450000],
"roubles": [15000, 40000, 75000, 100000, 140000, 170000, 210000], "roubles": [15000, 40000, 75000, 100000, 140000, 170000, 210000],
"items": [3, 4, 5, 5, 5, 5, 5], "items": [2, 4, 5, 5, 5, 5, 5],
"reputation": [0.01, 0.01, 0.02, 0.02, 0.03, 0.03, 0.03], "reputation": [0.01, 0.01, 0.02, 0.02, 0.03, 0.03, 0.03],
"rewardSpread": 0.5, "rewardSpread": 0.5,
"skillRewardChance": [0, 0.01, 0.05, 0.1, 0.15, 0.2, 0.25], "skillRewardChance": [0, 0.01, 0.05, 0.1, 0.15, 0.2, 0.25],
@ -709,7 +709,7 @@
"minPlayerLevel": 15, "minPlayerLevel": 15,
"rewardScaling": { "rewardScaling": {
"levels": [1, 10, 20, 30, 40, 50, 60], "levels": [1, 10, 20, 30, 40, 50, 60],
"experience": [5000, 25000, 60000, 130000, 240000, 390000, 750000], "experience": [5000, 25000, 40000, 110000, 220000, 370000, 720000],
"roubles": [50000, 150000, 300000, 425000, 550000, 675000, 850000], "roubles": [50000, 150000, 300000, 425000, 550000, 675000, 850000],
"items": [4, 5, 5, 6, 6, 7, 7], "items": [4, 5, 5, 6, 6, 7, 7],
"reputation": [0.02, 0.03, 0.04, 0.04, 0.05, 0.05, 0.05], "reputation": [0.02, 0.03, 0.04, 0.04, 0.05, 0.05, 0.05],
@ -1337,14 +1337,14 @@
"Pickup" "Pickup"
], ],
"resetTime": 86400, "resetTime": 86400,
"numQuests": 4, "numQuests": 1,
"minPlayerLevel": 1, "minPlayerLevel": 1,
"rewardScaling": { "rewardScaling": {
"levels": [1, 20, 45, 100], "levels": [1, 20, 45, 100],
"experience": [2000, 4000, 20000, 80000], "experience": [1000, 4000, 20000, 80000],
"roubles": [6000, 10000, 100000, 250000], "roubles": [6000, 10000, 100000, 250000],
"items": [2, 3, 4, 4], "items": [3, 3, 4, 4],
"reputation": [0.01, 0.02, 0.05, 0.05], "reputation": [0.02, 0.02, 0.05, 0.05],
"rewardSpread": 0.5, "rewardSpread": 0.5,
"skillRewardChance": [0, 0, 0, 0, 0, 0, 0], "skillRewardChance": [0, 0, 0, 0, 0, 0, 0],
"skillPointReward": [10, 15, 20, 25, 30, 35, 40] "skillPointReward": [10, 15, 20, 25, 30, 35, 40]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -189,7 +189,7 @@
"ragfair-unable_to_find_locale_by_key": "Unable to find EFT locale with key: %s", "ragfair-unable_to_find_locale_by_key": "Unable to find EFT locale with key: %s",
"ragfair-unable_to_adjust_stack_count_assort_not_found": "Trader: {{traderId}} flea offer: {{offerId}} could not have its stack count adjusted to match traders assort value (assort not found)", "ragfair-unable_to_adjust_stack_count_assort_not_found": "Trader: {{traderId}} flea offer: {{offerId}} could not have its stack count adjusted to match traders assort value (assort not found)",
"ragfair-unable_to_remove_offer_not_found_in_profile": "Unable to find offer: {{offerId}} in profile: {{profileId}} as offer is undefined, creating", "ragfair-unable_to_remove_offer_not_found_in_profile": "Unable to find offer: {{offerId}} in profile: {{profileId}} as offer is undefined, creating",
"ragfair-unable_to_find_item_price_for_item_in_flea_handbook": "Unable to find live-flea or handbook price for {{tplId}}, defaulting to 1, if this is a modded item contact the mod author", "ragfair-unable_to_find_item_price_for_item_in_flea_handbook": "Unable to find live-flea or handbook price for %s, defaulting to 1, if this is a modded item contact the mod author",
"ragfair-unable_to_find_preset_with_id": "Unable to find preset with id: %s, using existing price of existing weapon base", "ragfair-unable_to_find_preset_with_id": "Unable to find preset with id: %s, using existing price of existing weapon base",
"ragfair-unable_to_remove_offer_doesnt_exist": "Unable to remove offer with id: %s as it cannot be found in flea market", "ragfair-unable_to_remove_offer_doesnt_exist": "Unable to remove offer with id: %s as it cannot be found in flea market",
"repeatable-accepted_repeatable_quest_not_found_in_active_quests": "Accepted a repeatable quest: %s which could not be found in the activeQuests array. Please report this bug", "repeatable-accepted_repeatable_quest_not_found_in_active_quests": "Accepted a repeatable quest: %s which could not be found in the activeQuests array. Please report this bug",

File diff suppressed because it is too large Load Diff

View File

@ -84,6 +84,11 @@ export class InventoryCallbacks
return this.inventoryController.bindItem(pmcData, body, sessionID); return this.inventoryController.bindItem(pmcData, body, sessionID);
} }
public unbindItem(pmcData: IPmcData, body: IInventoryBindRequestData, sessionID: string): IItemEventRouterResponse
{
return this.inventoryController.unbindItem(pmcData, body, sessionID);
}
public examineItem(pmcData: IPmcData, body: IInventoryExamineRequestData, sessionID: string): IItemEventRouterResponse public examineItem(pmcData: IPmcData, body: IInventoryExamineRequestData, sessionID: string): IItemEventRouterResponse
{ {
return this.inventoryController.examineItem(pmcData, body, sessionID); return this.inventoryController.examineItem(pmcData, body, sessionID);

View File

@ -240,16 +240,16 @@ export class GameController
const trader = this.databaseServer.getTables().traders[traderKey]; const trader = this.databaseServer.getTables().traders[traderKey];
if (!trader?.base?.repair) if (!trader?.base?.repair)
{ {
this.logger.warning(`Trader ${trader.base._id} ${trader.base.name} is missing a repair object, adding in default values`); this.logger.warning(`Trader ${trader.base._id} ${trader.base.nickname} is missing a repair object, adding in default values`);
trader.base.repair = this.jsonUtil.clone(this.databaseServer.getTables().traders.ragfair.base.repair); trader.base.repair = this.jsonUtil.clone(this.databaseServer.getTables().traders.ragfair.base.repair);
return; return;
} }
if (trader?.base?.repair?.quality) if (trader.base.repair?.quality === undefined)
{ {
this.logger.warning(`Trader ${trader.base._id} ${trader.base.name} is missing a repair quality value, adding in default value`); this.logger.warning(`Trader ${trader.base._id} ${trader.base.nickname} is missing a repair quality value, adding in default value`);
trader.base.repair.quality = this.jsonUtil.clone(this.databaseServer.getTables().traders.ragfair.base.repair.quality); trader.base.repair.quality = this.databaseServer.getTables().traders.ragfair.base.repair.quality;
} }
} }
} }

View File

@ -652,7 +652,7 @@ export class HideoutController
let counterHoursCrafting = pmcData.BackendCounters[HideoutController.nameBackendCountersCrafting]; let counterHoursCrafting = pmcData.BackendCounters[HideoutController.nameBackendCountersCrafting];
if (!counterHoursCrafting) if (!counterHoursCrafting)
{ {
pmcData.BackendCounters[HideoutController.nameBackendCountersCrafting] = { "id": HideoutController.nameBackendCountersCrafting, "value": 0 }; pmcData.BackendCounters[HideoutController.nameBackendCountersCrafting] = { id: HideoutController.nameBackendCountersCrafting, value: 0 };
counterHoursCrafting = pmcData.BackendCounters[HideoutController.nameBackendCountersCrafting]; counterHoursCrafting = pmcData.BackendCounters[HideoutController.nameBackendCountersCrafting];
} }
let hoursCrafting = counterHoursCrafting.value; let hoursCrafting = counterHoursCrafting.value;
@ -680,6 +680,12 @@ export class HideoutController
let prodId: string; let prodId: string;
for (const x of entries) for (const x of entries)
{ {
// Skip null production objects
if (!x[1])
{
continue;
}
if (this.hideoutHelper.isProductionType(x[1])) // Production or ScavCase if (this.hideoutHelper.isProductionType(x[1])) // Production or ScavCase
{ {
if ((x[1] as Production).RecipeId === request.recipeId) if ((x[1] as Production).RecipeId === request.recipeId)

View File

@ -518,6 +518,7 @@ export class InventoryController
/** /**
* Bind an inventory item to the quick access menu at bottom of player screen * Bind an inventory item to the quick access menu at bottom of player screen
* Handle bind event
* @param pmcData Player profile * @param pmcData Player profile
* @param bindRequest Reqeust object * @param bindRequest Reqeust object
* @param sessionID Session id * @param sessionID Session id
@ -527,17 +528,37 @@ export class InventoryController
{ {
for (const index in pmcData.Inventory.fastPanel) for (const index in pmcData.Inventory.fastPanel)
{ {
// Find item with existing item in it and remove existing binding, you cant have same item bound to more than 1 slot
if (pmcData.Inventory.fastPanel[index] === bindRequest.item) if (pmcData.Inventory.fastPanel[index] === bindRequest.item)
{ {
pmcData.Inventory.fastPanel[index] = ""; pmcData.Inventory.fastPanel[index] = "";
break;
} }
} }
// Create link between fast panel slot and requested item
pmcData.Inventory.fastPanel[bindRequest.index] = bindRequest.item; pmcData.Inventory.fastPanel[bindRequest.index] = bindRequest.item;
return this.eventOutputHolder.getOutput(sessionID); return this.eventOutputHolder.getOutput(sessionID);
} }
/**
* Unbind an inventory item from quick access menu at bottom of player screen
* Handle unbind event
* @param pmcData Player profile
* @param bindRequest Request object
* @param sessionID Session id
* @returns IItemEventRouterResponse
*/
public unbindItem(pmcData: IPmcData, request: IInventoryBindRequestData, sessionID: string): IItemEventRouterResponse
{
// Remove kvp from requested fast panel index
delete pmcData.Inventory.fastPanel[request.index];
return this.eventOutputHolder.getOutput(sessionID);
}
/** /**
* Handles examining an item * Handles examining an item

View File

@ -498,10 +498,10 @@ export class QuestController
protected removeQuestFromScavProfile(sessionId: string, questIdToRemove: string): void protected removeQuestFromScavProfile(sessionId: string, questIdToRemove: string): void
{ {
const fullProfile = this.profileHelper.getFullProfile(sessionId); const fullProfile = this.profileHelper.getFullProfile(sessionId);
const repeatableInScavProfile = fullProfile.characters.scav.Quests.find(x => x.qid === questIdToRemove); const repeatableInScavProfile = fullProfile.characters.scav.Quests?.find(x => x.qid === questIdToRemove);
if (!repeatableInScavProfile) if (!repeatableInScavProfile)
{ {
this.logger.warning(`Unable to remove quest: ${questIdToRemove} from profile as scav profile cannot be found`); this.logger.warning(`Unable to remove quest: ${questIdToRemove} from profile as scav quest cannot be found`);
return; return;
} }

View File

@ -231,6 +231,14 @@ export class HideoutHelper
{ {
// Craft value is null, get rid of it (could be from cancelling craft that needs cleaning up) // Craft value is null, get rid of it (could be from cancelling craft that needs cleaning up)
delete pmcData.Hideout.Production[prodId]; delete pmcData.Hideout.Production[prodId];
continue;
}
if (craft.Progress === undefined)
{
this.logger.warning(`Craft ${prodId} has an undefined progress value, defaulting to 0`);
craft.Progress = 0;
} }
// Craft complete, skip processing (Don't skip continious crafts like bitcoin farm) // Craft complete, skip processing (Don't skip continious crafts like bitcoin farm)

View File

@ -10,6 +10,7 @@ export enum ItemEventActions
TOGGLE = "Toggle", TOGGLE = "Toggle",
TAG = "Tag", TAG = "Tag",
BIND = "Bind", BIND = "Bind",
UNBIND = "Unbind",
EXAMINE = "Examine", EXAMINE = "Examine",
READ_ENCYCLOPEDIA = "ReadEncyclopedia", READ_ENCYCLOPEDIA = "ReadEncyclopedia",
APPLY_INVENTORY_CHANGES = "ApplyInventoryChanges", APPLY_INVENTORY_CHANGES = "ApplyInventoryChanges",

View File

@ -32,6 +32,7 @@ export class InventoryItemEventRouter extends ItemEventRouterDefinition
new HandledRoute(ItemEventActions.TOGGLE, false), new HandledRoute(ItemEventActions.TOGGLE, false),
new HandledRoute(ItemEventActions.TAG, false), new HandledRoute(ItemEventActions.TAG, false),
new HandledRoute(ItemEventActions.BIND, false), new HandledRoute(ItemEventActions.BIND, false),
new HandledRoute(ItemEventActions.UNBIND, false),
new HandledRoute(ItemEventActions.EXAMINE, false), new HandledRoute(ItemEventActions.EXAMINE, false),
new HandledRoute(ItemEventActions.READ_ENCYCLOPEDIA, false), new HandledRoute(ItemEventActions.READ_ENCYCLOPEDIA, false),
new HandledRoute(ItemEventActions.APPLY_INVENTORY_CHANGES, false), new HandledRoute(ItemEventActions.APPLY_INVENTORY_CHANGES, false),
@ -67,6 +68,8 @@ export class InventoryItemEventRouter extends ItemEventRouterDefinition
return this.inventoryCallbacks.tagItem(pmcData, body, sessionID); return this.inventoryCallbacks.tagItem(pmcData, body, sessionID);
case ItemEventActions.BIND: case ItemEventActions.BIND:
return this.inventoryCallbacks.bindItem(pmcData, body, sessionID); return this.inventoryCallbacks.bindItem(pmcData, body, sessionID);
case ItemEventActions.UNBIND:
return this.inventoryCallbacks.unbindItem(pmcData, body, sessionID);
case ItemEventActions.EXAMINE: case ItemEventActions.EXAMINE:
return this.inventoryCallbacks.examineItem(pmcData, body, sessionID); return this.inventoryCallbacks.examineItem(pmcData, body, sessionID);
case ItemEventActions.READ_ENCYCLOPEDIA: case ItemEventActions.READ_ENCYCLOPEDIA:

View File

@ -101,7 +101,7 @@ export class RagfairPriceService implements OnLoad
{ {
// Get dynamic price (templates/prices), if that doesnt exist get price from static array (templates/handbook) // Get dynamic price (templates/prices), if that doesnt exist get price from static array (templates/handbook)
let itemPrice = this.getDynamicPriceForItem(tplId) || this.getStaticPriceForItem(tplId); let itemPrice = this.getDynamicPriceForItem(tplId) || this.getStaticPriceForItem(tplId);
if (!itemPrice) if (itemPrice === undefined)
{ {
this.logger.warning(this.localisationService.getText("ragfair-unable_to_find_item_price_for_item_in_flea_handbook", tplId)); this.logger.warning(this.localisationService.getText("ragfair-unable_to_find_item_price_for_item_in_flea_handbook", tplId));
} }

View File

@ -1,9 +1,12 @@
import os from "node:os"; import os from "node:os";
import { inject, injectable, injectAll } from "tsyringe"; import { inject, injectAll, injectable } from "tsyringe";
import { OnLoad } from "@spt-aki/di/OnLoad"; import { OnLoad } from "@spt-aki/di/OnLoad";
import { OnUpdate } from "@spt-aki/di/OnUpdate"; import { OnUpdate } from "@spt-aki/di/OnUpdate";
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
import { ICoreConfig } from "@spt-aki/models/spt/config/ICoreConfig";
import { ILogger } from "@spt-aki/models/spt/utils/ILogger"; import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
import { LocalisationService } from "@spt-aki/services/LocalisationService"; import { LocalisationService } from "@spt-aki/services/LocalisationService";
import { EncodingUtil } from "@spt-aki/utils/EncodingUtil"; import { EncodingUtil } from "@spt-aki/utils/EncodingUtil";
import { TimeUtil } from "@spt-aki/utils/TimeUtil"; import { TimeUtil } from "@spt-aki/utils/TimeUtil";
@ -12,16 +15,20 @@ import { TimeUtil } from "@spt-aki/utils/TimeUtil";
export class App export class App
{ {
protected onUpdateLastRun = {}; protected onUpdateLastRun = {};
protected coreConfig: ICoreConfig;
constructor( constructor(
@inject("WinstonLogger") protected logger: ILogger, @inject("WinstonLogger") protected logger: ILogger,
@inject("TimeUtil") protected timeUtil: TimeUtil, @inject("TimeUtil") protected timeUtil: TimeUtil,
@inject("LocalisationService") protected localisationService: LocalisationService, @inject("LocalisationService") protected localisationService: LocalisationService,
@inject("ConfigServer") protected configServer: ConfigServer,
@inject("EncodingUtil") protected encodingUtil: EncodingUtil, @inject("EncodingUtil") protected encodingUtil: EncodingUtil,
@injectAll("OnLoad") protected onLoadComponents: OnLoad[], @injectAll("OnLoad") protected onLoadComponents: OnLoad[],
@injectAll("OnUpdate") protected onUpdateComponents: OnUpdate[] @injectAll("OnUpdate") protected onUpdateComponents: OnUpdate[]
) )
{ } {
this.coreConfig = this.configServer.getConfig(ConfigTypes.CORE);
}
public async load(): Promise<void> public async load(): Promise<void>
{ {
@ -33,6 +40,16 @@ export class App
this.logger.debug(`RAM: ${(os.totalmem() / 1024 / 1024 / 1024).toFixed(2)}GB`); this.logger.debug(`RAM: ${(os.totalmem() / 1024 / 1024 / 1024).toFixed(2)}GB`);
this.logger.debug(`PATH: ${this.encodingUtil.toBase64(process.argv[0])}`); this.logger.debug(`PATH: ${this.encodingUtil.toBase64(process.argv[0])}`);
this.logger.debug(`PATH: ${this.encodingUtil.toBase64(process.execPath)}`); this.logger.debug(`PATH: ${this.encodingUtil.toBase64(process.execPath)}`);
this.logger.debug(`Server: ${this.coreConfig.akiVersion}`);
if (this.coreConfig.buildTime)
{
this.logger.debug(`Date: ${this.coreConfig.buildTime}`);
}
if (this.coreConfig.commit)
{
this.logger.debug(`Commit: ${this.coreConfig.commit}`);
}
for (const onLoad of this.onLoadComponents) for (const onLoad of this.onLoadComponents)
{ {