0
0
mirror of https://github.com/sp-tarkov/server.git synced 2025-02-13 09:50:43 -05:00

Merge branch '3.8.1-DEV' of https://dev.sp-tarkov.com/SPT-AKI/Server into 3.9.0-DEV

This commit is contained in:
Dev 2024-04-29 21:50:12 +01:00
commit 267efdc7ea
11 changed files with 166 additions and 65 deletions

View File

@ -331,7 +331,7 @@
"bosssanitar": { "bosssanitar": {
"5efde6b4f5448336730dbd61": 1, "5efde6b4f5448336730dbd61": 1,
"5eff09cd30a7dc22fd1ddfed": 1 "5eff09cd30a7dc22fd1ddfed": 1
}, },
"bosstagilla": {}, "bosstagilla": {},
"bossknight": {}, "bossknight": {},
"bosszryachiy": {}, "bosszryachiy": {},
@ -399,11 +399,11 @@
"60098ad7c2240c0fe85c570a": 2 "60098ad7c2240c0fe85c570a": 2
}, },
"arenafighterevent": { "arenafighterevent": {
"5734758f24597738025ee253": 1 "5734758f24597738025ee253": 1
}, },
"arenafighter": { "arenafighter": {
"5734758f24597738025ee253": 1 "5734758f24597738025ee253": 1
}, },
"crazyassaultevent": {}, "crazyassaultevent": {},
"assaultgroup": {}, "assaultgroup": {},
"gifter": {}, "gifter": {},
@ -790,7 +790,7 @@
"lightIsActiveDayChancePercent": 35, "lightIsActiveDayChancePercent": 35,
"lightIsActiveNightChancePercent": 95, "lightIsActiveNightChancePercent": 95,
"laserIsActiveChancePercent": 95, "laserIsActiveChancePercent": 95,
"forceStock": true, "forceStock": true,
"weaponModLimits": { "weaponModLimits": {
"scopeLimit": 1, "scopeLimit": 1,
"lightLaserLimit": 1 "lightLaserLimit": 1
@ -1655,18 +1655,18 @@
"5bffdc370db834001d23eca8": 100, "5bffdc370db834001d23eca8": 100,
"54491bb74bdc2d09088b4567": 100 "54491bb74bdc2d09088b4567": 100
} }
}, }
"clothing": { },
"add": {}, "clothing": {
"edit": { "add": {},
"body": { "edit": {
"5cc0858d14c02e000c6bea66": 20, "body": {
"5cde95d97d6c8b647a3769b0": 20 "5cc0858d14c02e000c6bea66": 20,
}, "5cde95d97d6c8b647a3769b0": 20
"feet": { },
"5cc085bb14c02e000e67a5c5": 20, "feet": {
"5cde95ef7d6c8b04713c4f2d": 20 "5cc085bb14c02e000e67a5c5": 20,
} "5cde95ef7d6c8b04713c4f2d": 20
} }
} }
} }
@ -1775,6 +1775,7 @@
} }
}, },
"equipment": { "equipment": {
"add": {},
"edit": { "edit": {
"ArmorVest": { "ArmorVest": {
"5c0e5bab86f77461f55ed1f3": 135, "5c0e5bab86f77461f55ed1f3": 135,
@ -1841,6 +1842,7 @@
"max": 50 "max": 50
}, },
"equipment": { "equipment": {
"add": {},
"edit": { "edit": {
"FirstPrimaryWeapon": { "FirstPrimaryWeapon": {
"5c501a4d2e221602b412b540": 2 "5c501a4d2e221602b412b540": 2
@ -1948,6 +1950,7 @@
} }
}, },
"equipment": { "equipment": {
"add": {},
"edit": { "edit": {
"FirstPrimaryWeapon": { "FirstPrimaryWeapon": {
"65290f395ae2ae97b80fdf2d": 8, "65290f395ae2ae97b80fdf2d": 8,
@ -2652,4 +2655,4 @@
} }
} }
} }
} }

View File

@ -2502,14 +2502,15 @@
"backpackLoot": { "backpackLoot": {
"weights": { "weights": {
"0": 1, "0": 1,
"3": 5,
"4": 7,
"5": 6,
"8": 6,
"10": 5, "10": 5,
"12": 4, "12": 4,
"15": 4, "15": 4,
"20": 3, "20": 3,
"23": 1, "23": 1
"3": 2,
"5": 5,
"8": 6
}, },
"whitelist": [] "whitelist": []
}, },
@ -2593,7 +2594,7 @@
}, },
"stims": { "stims": {
"weights": { "weights": {
"0": 1, "0": 2,
"1": 2, "1": 2,
"2": 1 "2": 1
}, },
@ -2602,7 +2603,7 @@
"vestLoot": { "vestLoot": {
"weights": { "weights": {
"0": 1, "0": 1,
"1": 2, "1": 3,
"2": 3, "2": 3,
"3": 2, "3": 2,
"4": 1 "4": 1

View File

@ -2499,14 +2499,15 @@
"backpackLoot": { "backpackLoot": {
"weights": { "weights": {
"0": 1, "0": 1,
"3": 5,
"4": 7,
"5": 6,
"8": 6,
"10": 5, "10": 5,
"12": 4, "12": 4,
"15": 4, "15": 4,
"20": 3, "20": 3,
"23": 1, "23": 1
"3": 2,
"5": 5,
"8": 6
}, },
"whitelist": [] "whitelist": []
}, },
@ -2590,7 +2591,7 @@
}, },
"stims": { "stims": {
"weights": { "weights": {
"0": 1, "0": 2,
"1": 2, "1": 2,
"2": 1 "2": 1
}, },
@ -2599,7 +2600,7 @@
"vestLoot": { "vestLoot": {
"weights": { "weights": {
"0": 1, "0": 1,
"1": 2, "1": 3,
"2": 3, "2": 3,
"3": 2, "3": 2,
"4": 1 "4": 1

View File

@ -531,6 +531,8 @@
"pmcresponse-killer_negative_28": "Not to worry, i stashed your gear at your moms house", "pmcresponse-killer_negative_28": "Not to worry, i stashed your gear at your moms house",
"pmcresponse-killer_negative_29": "Were you even trying", "pmcresponse-killer_negative_29": "Were you even trying",
"pmcresponse-killer_negative_30": "I bet you actually paid 250 big ones for that new edition", "pmcresponse-killer_negative_30": "I bet you actually paid 250 big ones for that new edition",
"pmcresponse-killer_negative_31": "Get ratted",
"pmcresponse-killer_negative_32": "Rat attack",
"pmcresponse-killer_plead_1": "I was trying to extract a quest item and you were in my path", "pmcresponse-killer_plead_1": "I was trying to extract a quest item and you were in my path",
"pmcresponse-killer_plead_2": "I was looting barrel caches and you were in the way, sorry", "pmcresponse-killer_plead_2": "I was looting barrel caches and you were in the way, sorry",
"pmcresponse-killer_plead_3": "I need PMC kills, Im sure you understand", "pmcresponse-killer_plead_3": "I need PMC kills, Im sure you understand",

View File

@ -20138,7 +20138,12 @@
"y": 0, "y": 0,
"r": 0, "r": 0,
"isSearched": true "isSearched": true
} },
"upd": {
"FoodDrink": {
"HpPercent": 60
}
}
}, { }, {
"_id": "6613bb72b5b0ba138a0fa9e8", "_id": "6613bb72b5b0ba138a0fa9e8",
"_tpl": "590c5d4b86f774784e1b9c45", "_tpl": "590c5d4b86f774784e1b9c45",
@ -20938,7 +20943,12 @@
"y": 32, "y": 32,
"r": 0, "r": 0,
"isSearched": true "isSearched": true
} },
"upd": {
"FoodDrink": {
"HpPercent": 60
}
}
}, { }, {
"_id": "6613bb72b5b0ba138a0faa3c", "_id": "6613bb72b5b0ba138a0faa3c",
"_tpl": "5448fee04bdc2dbc018b4567", "_tpl": "5448fee04bdc2dbc018b4567",
@ -20949,7 +20959,12 @@
"y": 32, "y": 32,
"r": 0, "r": 0,
"isSearched": true "isSearched": true
} },
"upd": {
"FoodDrink": {
"HpPercent": 60
}
}
}, { }, {
"_id": "6613bb72b5b0ba138a0faa3d", "_id": "6613bb72b5b0ba138a0faa3d",
"_tpl": "5448fee04bdc2dbc018b4567", "_tpl": "5448fee04bdc2dbc018b4567",
@ -20960,7 +20975,12 @@
"y": 32, "y": 32,
"r": 0, "r": 0,
"isSearched": true "isSearched": true
} },
"upd": {
"FoodDrink": {
"HpPercent": 60
}
}
}, { }, {
"_id": "6613bb72b5b0ba138a0faa3e", "_id": "6613bb72b5b0ba138a0faa3e",
"_tpl": "57347da92459774491567cf5", "_tpl": "57347da92459774491567cf5",
@ -23798,7 +23818,12 @@
"y": 0, "y": 0,
"r": 0, "r": 0,
"isSearched": true "isSearched": true
} },
"upd": {
"FoodDrink": {
"HpPercent": 60
}
}
}, { }, {
"_id": "6613e1cf291a2e76b002699b", "_id": "6613e1cf291a2e76b002699b",
"_tpl": "590c5f0d86f77413997acfab", "_tpl": "590c5f0d86f77413997acfab",
@ -25430,7 +25455,12 @@
"y": 29, "y": 29,
"r": 0, "r": 0,
"isSearched": true "isSearched": true
} },
"upd": {
"FoodDrink": {
"HpPercent": 60
}
}
}, { }, {
"_id": "6613e1cf291a2e76b0026a3f", "_id": "6613e1cf291a2e76b0026a3f",
"_tpl": "5d02778e86f774203e7dedbe", "_tpl": "5d02778e86f774203e7dedbe",
@ -25668,7 +25698,12 @@
"y": 29, "y": 29,
"r": 0, "r": 0,
"isSearched": true "isSearched": true
} },
"upd": {
"FoodDrink": {
"HpPercent": 60
}
}
}, { }, {
"_id": "6613e1cf291a2e76b0026a59", "_id": "6613e1cf291a2e76b0026a59",
"_tpl": "5e8488fa988a8701445df1e4", "_tpl": "5e8488fa988a8701445df1e4",
@ -25839,7 +25874,12 @@
"y": 29, "y": 29,
"r": 0, "r": 0,
"isSearched": true "isSearched": true
} },
"upd": {
"FoodDrink": {
"HpPercent": 60
}
}
}, { }, {
"_id": "6613e1cf291a2e76b0026a68", "_id": "6613e1cf291a2e76b0026a68",
"_tpl": "544fb3364bdc2d34748b456a", "_tpl": "544fb3364bdc2d34748b456a",

View File

@ -127,6 +127,9 @@ export class HealthController
const consumedItemMaxResource = this.itemHelper.getItem(itemToConsume._tpl)[1]._props.MaxResource; const consumedItemMaxResource = this.itemHelper.getItem(itemToConsume._tpl)[1]._props.MaxResource;
if (consumedItemMaxResource > 1) if (consumedItemMaxResource > 1)
{ {
// Ensure item has a upd object
this.itemHelper.addUpdObjectToItem(itemToConsume);
if (itemToConsume.upd.FoodDrink === undefined) if (itemToConsume.upd.FoodDrink === undefined)
{ {
itemToConsume.upd.FoodDrink = { HpPercent: consumedItemMaxResource - request.count }; itemToConsume.upd.FoodDrink = { HpPercent: consumedItemMaxResource - request.count };

View File

@ -119,6 +119,10 @@ export class BotLootGenerator
const containersBotHasAvailable = this.getAvailableContainersBotCanStoreItemsIn(botInventory); const containersBotHasAvailable = this.getAvailableContainersBotCanStoreItemsIn(botInventory);
// This set is passed as a reference to fill up the containers that are already full, this aliviates
// generation of the bots by avoiding checking the slots of containers we already know are full
const containersIdFull = new Set<string>();
// Special items // Special items
this.addLootFromPool( this.addLootFromPool(
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.SPECIAL, botJsonTemplate), this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.SPECIAL, botJsonTemplate),
@ -127,6 +131,9 @@ export class BotLootGenerator
botInventory, botInventory,
botRole, botRole,
botItemLimits, botItemLimits,
undefined,
undefined,
containersIdFull,
); );
// Healing items / Meds // Healing items / Meds
@ -139,6 +146,7 @@ export class BotLootGenerator
null, null,
0, 0,
isPmc, isPmc,
containersIdFull,
); );
// Drugs // Drugs
@ -151,6 +159,7 @@ export class BotLootGenerator
null, null,
0, 0,
isPmc, isPmc,
containersIdFull,
); );
// Food // Food
@ -163,6 +172,7 @@ export class BotLootGenerator
null, null,
0, 0,
isPmc, isPmc,
containersIdFull,
); );
// Drink // Drink
@ -175,6 +185,7 @@ export class BotLootGenerator
null, null,
0, 0,
isPmc, isPmc,
containersIdFull,
); );
// Currency // Currency
@ -187,6 +198,7 @@ export class BotLootGenerator
null, null,
0, 0,
isPmc, isPmc,
containersIdFull,
); );
// Stims // Stims
@ -199,6 +211,7 @@ export class BotLootGenerator
botItemLimits, botItemLimits,
0, 0,
isPmc, isPmc,
containersIdFull,
); );
// Grenades // Grenades
@ -211,6 +224,7 @@ export class BotLootGenerator
null, null,
0, 0,
isPmc, isPmc,
containersIdFull,
); );
// Backpack - generate loot if they have one // Backpack - generate loot if they have one
@ -228,6 +242,7 @@ export class BotLootGenerator
botRole, botRole,
isPmc, isPmc,
botLevel, botLevel,
containersIdFull,
); );
} }
@ -240,6 +255,7 @@ export class BotLootGenerator
botItemLimits, botItemLimits,
this.pmcConfig.maxBackpackLootTotalRub, this.pmcConfig.maxBackpackLootTotalRub,
isPmc, isPmc,
containersIdFull,
); );
} }
@ -256,6 +272,7 @@ export class BotLootGenerator
botItemLimits, botItemLimits,
this.pmcConfig.maxVestLootTotalRub, this.pmcConfig.maxVestLootTotalRub,
isPmc, isPmc,
containersIdFull,
); );
} }
@ -269,6 +286,7 @@ export class BotLootGenerator
botItemLimits, botItemLimits,
this.pmcConfig.maxPocketLootTotalRub, this.pmcConfig.maxPocketLootTotalRub,
isPmc, isPmc,
containersIdFull,
); );
// Secure // Secure
@ -281,6 +299,7 @@ export class BotLootGenerator
null, null,
-1, -1,
isPmc, isPmc,
containersIdFull,
); );
} }
@ -373,6 +392,7 @@ export class BotLootGenerator
itemSpawnLimits: IItemSpawnLimitSettings = null, itemSpawnLimits: IItemSpawnLimitSettings = null,
totalValueLimitRub = 0, totalValueLimitRub = 0,
isPmc = false, isPmc = false,
containersIdFull = new Set<string>(),
): void ): void
{ {
// Loot pool has items // Loot pool has items
@ -465,6 +485,7 @@ export class BotLootGenerator
itemToAddTemplate._id, itemToAddTemplate._id,
itemWithChildrenToAdd, itemWithChildrenToAdd,
inventoryToAddItemsTo, inventoryToAddItemsTo,
containersIdFull,
); );
// Handle when item cannot be added // Handle when item cannot be added
@ -593,6 +614,7 @@ export class BotLootGenerator
botRole: string, botRole: string,
isPmc: boolean, isPmc: boolean,
botLevel: number, botLevel: number,
containersIdFull?: Set<string>,
): void ): void
{ {
const chosenWeaponType = this.randomUtil.getArrayValue([ const chosenWeaponType = this.randomUtil.getArrayValue([
@ -625,6 +647,7 @@ export class BotLootGenerator
generatedWeapon.weapon[0]._tpl, generatedWeapon.weapon[0]._tpl,
[...generatedWeapon.weapon], [...generatedWeapon.weapon],
botInventory, botInventory,
containersIdFull,
); );
if (result !== ItemAddedResult.SUCCESS) if (result !== ItemAddedResult.SUCCESS)

View File

@ -106,7 +106,11 @@ export class FenceBaseAssortGenerator
if (this.itemHelper.isOfBaseclass(rootItemDb._id, BaseClasses.AMMO_BOX)) if (this.itemHelper.isOfBaseclass(rootItemDb._id, BaseClasses.AMMO_BOX))
{ {
this.itemHelper.addCartridgesToAmmoBox(itemWithChildrenToAdd, rootItemDb); // Only add cartridges to box if box has no children
if (itemWithChildrenToAdd.length === 1)
{
this.itemHelper.addCartridgesToAmmoBox(itemWithChildrenToAdd, rootItemDb);
}
} }
// Ensure IDs are unique // Ensure IDs are unique

View File

@ -532,12 +532,17 @@ export class BotGeneratorHelper
rootItemTplId: string, rootItemTplId: string,
itemWithChildren: Item[], itemWithChildren: Item[],
inventory: Inventory, inventory: Inventory,
containersIdFull?: Set<string>,
): ItemAddedResult ): ItemAddedResult
{ {
/** Track how many containers are unable to be found */ /** Track how many containers are unable to be found */
let missingContainerCount = 0; let missingContainerCount = 0;
for (const equipmentSlotId of equipmentSlots) for (const equipmentSlotId of equipmentSlots)
{ {
if (containersIdFull?.has(equipmentSlotId))
{
continue;
}
// Get container to put item into // Get container to put item into
const container = inventory.items.find((item) => item.slotId === equipmentSlotId); const container = inventory.items.find((item) => item.slotId === equipmentSlotId);
if (!container) if (!container)
@ -583,8 +588,11 @@ export class BotGeneratorHelper
const totalSlotGridCount = containerTemplate[1]._props.Grids.length; const totalSlotGridCount = containerTemplate[1]._props.Grids.length;
for (const slotGrid of containerTemplate[1]._props.Grids) for (const slotGrid of containerTemplate[1]._props.Grids)
{ {
// Grid is empty, skip // Grid is empty, skip or item size is bigger than grid
if (slotGrid._props.cellsH === 0 || slotGrid._props.cellsV === 0) if (
(slotGrid._props.cellsH === 0 || slotGrid._props.cellsV === 0)
|| (itemSize[0] * itemSize[1] > slotGrid._props.cellsV * slotGrid._props.cellsH)
)
{ {
continue; continue;
} }
@ -592,12 +600,6 @@ export class BotGeneratorHelper
// Can't put item type in grid, skip all grids as we're assuming they have the same rules // Can't put item type in grid, skip all grids as we're assuming they have the same rules
if (!this.itemAllowedInContainer(slotGrid, rootItemTplId)) if (!this.itemAllowedInContainer(slotGrid, rootItemTplId))
{ {
// Only one possible slot and item is incompatible, exit function and inform caller
if (equipmentSlots.length === 1)
{
return ItemAddedResult.INCOMPATIBLE_ITEM;
}
// Multiple containers, maybe next one allows item, only break out of loop for this containers grids // Multiple containers, maybe next one allows item, only break out of loop for this containers grids
break; break;
} }
@ -653,15 +655,25 @@ export class BotGeneratorHelper
// If we've checked all grids in container and reached this point, there's no space for item // If we've checked all grids in container and reached this point, there's no space for item
if (currentGridCount >= totalSlotGridCount) if (currentGridCount >= totalSlotGridCount)
{ {
return ItemAddedResult.NO_SPACE; break;
} }
currentGridCount++;
currentGridCount++;
// No space in this grid, move to next container grid and try again // No space in this grid, move to next container grid and try again
} }
// if we got to this point, the item couldnt be placed on the container
if (containersIdFull)
{
// if the item was a one by one, we know it must be full. Or if the maps cant find a slot for a one by one
if ((itemSize[0] === 1 && itemSize[1] === 1))
{
containersIdFull.add(equipmentSlotId);
}
}
} }
return ItemAddedResult.UNKNOWN; return ItemAddedResult.NO_SPACE;
} }
/** /**

View File

@ -8,6 +8,7 @@ import { IUserDialogInfo } from "@spt-aki/models/eft/profile/IAkiProfile";
import { BaseClasses } from "@spt-aki/models/enums/BaseClasses"; import { BaseClasses } from "@spt-aki/models/enums/BaseClasses";
import { ILogger } from "@spt-aki/models/spt/utils/ILogger"; import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer"; import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
import { ItemFilterService } from "@spt-aki/services/ItemFilterService";
import { LocaleService } from "@spt-aki/services/LocaleService"; import { LocaleService } from "@spt-aki/services/LocaleService";
import { MailSendService } from "@spt-aki/services/MailSendService"; import { MailSendService } from "@spt-aki/services/MailSendService";
import { HashUtil } from "@spt-aki/utils/HashUtil"; import { HashUtil } from "@spt-aki/utils/HashUtil";
@ -29,7 +30,7 @@ export class GiveSptCommand implements ISptCommand
private static commandRegex = /^spt give (((([a-z]{2,5}) )?"(.+)"|\w+) )?([0-9]+)$/; private static commandRegex = /^spt give (((([a-z]{2,5}) )?"(.+)"|\w+) )?([0-9]+)$/;
private static maxAllowedDistance = 1.5; private static maxAllowedDistance = 1.5;
protected savedCommand: SavedCommand; protected savedCommand: Map<string, SavedCommand> = new Map<string, SavedCommand>();
public constructor( public constructor(
@inject("WinstonLogger") protected logger: ILogger, @inject("WinstonLogger") protected logger: ILogger,
@ -40,6 +41,7 @@ export class GiveSptCommand implements ISptCommand
@inject("MailSendService") protected mailSendService: MailSendService, @inject("MailSendService") protected mailSendService: MailSendService,
@inject("LocaleService") protected localeService: LocaleService, @inject("LocaleService") protected localeService: LocaleService,
@inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("DatabaseServer") protected databaseServer: DatabaseServer,
@inject("ItemFilterService") protected itemFilterService: ItemFilterService,
) )
{ {
} }
@ -76,7 +78,7 @@ export class GiveSptCommand implements ISptCommand
// This is a reply to a give request previously made pending a reply // This is a reply to a give request previously made pending a reply
if (result[1] === undefined) if (result[1] === undefined)
{ {
if (this.savedCommand === undefined) if (!this.savedCommand.has(sessionId))
{ {
this.mailSendService.sendUserMessageToPlayer( this.mailSendService.sendUserMessageToPlayer(
sessionId, sessionId,
@ -85,7 +87,8 @@ export class GiveSptCommand implements ISptCommand
); );
return request.dialogId; return request.dialogId;
} }
if (+result[6] > this.savedCommand.potentialItemNames.length) const savedCommand = this.savedCommand.get(sessionId);
if (+result[6] > savedCommand.potentialItemNames.length)
{ {
this.mailSendService.sendUserMessageToPlayer( this.mailSendService.sendUserMessageToPlayer(
sessionId, sessionId,
@ -94,16 +97,19 @@ export class GiveSptCommand implements ISptCommand
); );
return request.dialogId; return request.dialogId;
} }
item = this.savedCommand.potentialItemNames[+result[6] - 1]; item = savedCommand.potentialItemNames[+result[6] - 1];
quantity = this.savedCommand.quantity; quantity = savedCommand.quantity;
locale = this.savedCommand.locale; locale = savedCommand.locale;
isItemName = true; isItemName = true;
this.savedCommand = undefined; this.savedCommand.delete(sessionId);
} }
else else
{ {
// A new give request was entered, we need to ignore the old saved command // A new give request was entered, we need to ignore the old saved command
this.savedCommand = undefined; if (this.savedCommand.has(sessionId))
{
this.savedCommand.delete(sessionId);
}
isItemName = result[5] !== undefined; isItemName = result[5] !== undefined;
item = result[5] ? result[5] : result[2]; item = result[5] ? result[5] : result[2];
quantity = +result[6]; quantity = +result[6];
@ -134,9 +140,9 @@ export class GiveSptCommand implements ISptCommand
const closestItemsMatchedByName = closestMatch( const closestItemsMatchedByName = closestMatch(
item.toLowerCase(), item.toLowerCase(),
this.itemHelper.getItems().filter((i) => i._type !== "Node").map((i) => this.itemHelper.getItems().filter((i) => i._type !== "Node").filter((i) =>
localizedGlobal[`${i?._id} Name`]?.toLowerCase() !this.itemFilterService.isItemBlacklisted(i._id)
).filter((i) => i !== undefined), ).map((i) => localizedGlobal[`${i?._id} Name`]?.toLowerCase()).filter((i) => i !== undefined),
true, true,
) as string[]; ) as string[];
@ -156,7 +162,7 @@ export class GiveSptCommand implements ISptCommand
const slicedItems = closestItemsMatchedByName.slice(0, 10); const slicedItems = closestItemsMatchedByName.slice(0, 10);
// max 10 item names and map them // max 10 item names and map them
const itemList = slicedItems.map((itemName) => `${i++}. ${itemName}`).join("\n"); const itemList = slicedItems.map((itemName) => `${i++}. ${itemName}`).join("\n");
this.savedCommand = new SavedCommand(quantity, slicedItems, locale); this.savedCommand.set(sessionId, new SavedCommand(quantity, slicedItems, locale));
this.mailSendService.sendUserMessageToPlayer( this.mailSendService.sendUserMessageToPlayer(
sessionId, sessionId,
commandHandler, commandHandler,
@ -185,7 +191,7 @@ export class GiveSptCommand implements ISptCommand
// If item is an item name, we need to search using that item name and the locale which one we want otherwise // If item is an item name, we need to search using that item name and the locale which one we want otherwise
// item is just the tplId. // item is just the tplId.
const tplId = isItemName const tplId = isItemName
? this.itemHelper.getItems().find((i) => ? this.itemHelper.getItems().filter((i) => !this.itemFilterService.isItemBlacklisted(i._id)).find((i) =>
this.databaseServer.getTables().locales.global[locale][`${i?._id} Name`]?.toLowerCase() === item this.databaseServer.getTables().locales.global[locale][`${i?._id} Name`]?.toLowerCase() === item
)._id )._id
: item; : item;

View File

@ -1090,6 +1090,12 @@ export class ItemHelper
const cartridgeDetails = this.getItem(cartridgeTpl); const cartridgeDetails = this.getItem(cartridgeTpl);
const cartridgeMaxStackSize = cartridgeDetails[1]._props.StackMaxSize; const cartridgeMaxStackSize = cartridgeDetails[1]._props.StackMaxSize;
// Exit if ammo already exists in box
if (ammoBox.find((item) => item._tpl === cartridgeTpl))
{
return;
}
// Add new stack-size-correct items to ammo box // Add new stack-size-correct items to ammo box
let currentStoredCartridgeCount = 0; let currentStoredCartridgeCount = 0;
const maxPerStack = Math.min(ammoBoxMaxCartridgeCount, cartridgeMaxStackSize); const maxPerStack = Math.min(ammoBoxMaxCartridgeCount, cartridgeMaxStackSize);
@ -1667,7 +1673,7 @@ export class ItemHelper
if (warningMessageWhenMissing) if (warningMessageWhenMissing)
{ {
this.logger.warning(warningMessageWhenMissing); this.logger.debug(warningMessageWhenMissing);
} }
return true; return true;