0
0
mirror of https://github.com/sp-tarkov/server.git synced 2025-02-13 05:50:44 -05:00
- Removes a test for a class that was removed
- Changes the command for type checking from `lint:types` to
`type-check`

---------

Co-authored-by: Chomp <27521899+chompDev@users.noreply.github.com>
This commit is contained in:
Jesse 2025-01-09 21:25:53 +01:00 committed by GitHub
parent 6283635be6
commit dcbb5c1d5f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
31 changed files with 150 additions and 155 deletions

View File

@ -38,5 +38,5 @@ jobs:
working-directory: ./project working-directory: ./project
- name: Run Type Check - name: Run Type Check
run: npm run lint:types run: npm run type-check
working-directory: ./project working-directory: ./project

View File

@ -60,7 +60,14 @@
}, },
"overrides": [ "overrides": [
{ {
"include": ["tests/*"] "include": ["tests/*"],
"linter": {
"rules": {
"suspicious": {
"noExplicitAny": "off"
}
}
}
} }
] ]
} }

View File

@ -83,10 +83,12 @@ export class DialogueController {
// Add any friends the user has after the chatbots // Add any friends the user has after the chatbots
const profile = this.profileHelper.getFullProfile(sessionID); const profile = this.profileHelper.getFullProfile(sessionID);
for (const friendId of profile?.friends) { if (profile?.friends) {
const friendProfile = this.profileHelper.getChatRoomMemberFromSessionId(friendId); for (const friendId of profile.friends) {
if (friendProfile) { const friendProfile = this.profileHelper.getChatRoomMemberFromSessionId(friendId);
friends.push(friendProfile); if (friendProfile) {
friends.push(friendProfile);
}
} }
} }

View File

@ -256,6 +256,7 @@ export class GameController {
// Hideout Improvement property changed name // Hideout Improvement property changed name
if ((fullProfile.characters.pmc.Hideout as any).Improvement) { if ((fullProfile.characters.pmc.Hideout as any).Improvement) {
fullProfile.characters.pmc.Hideout.Improvements = (fullProfile.characters.pmc.Hideout as any).Improvement; fullProfile.characters.pmc.Hideout.Improvements = (fullProfile.characters.pmc.Hideout as any).Improvement;
// biome-ignore lint/performance/noDelete: Delete is fine here, as we're seeking to remove these entirely
delete (fullProfile.characters.pmc.Hideout as any).Improvement; delete (fullProfile.characters.pmc.Hideout as any).Improvement;
this.logger.warning(`Migration: Moved Hideout Improvement data to new property 'Improvements'`); this.logger.warning(`Migration: Moved Hideout Improvement data to new property 'Improvements'`);
} }
@ -273,12 +274,14 @@ export class GameController {
// Remove PMC 'ragfair' from trader list // Remove PMC 'ragfair' from trader list
if (fullProfile.characters.pmc.TradersInfo.ragfair) { if (fullProfile.characters.pmc.TradersInfo.ragfair) {
this.logger.warning("Migration: deleting: ragfair traderinfo object from PMC"); this.logger.warning("Migration: deleting: ragfair traderinfo object from PMC");
// biome-ignore lint/performance/noDelete: Delete is fine here, as we're seeking to remove these entirely
delete fullProfile.characters.pmc.TradersInfo.ragfair; delete fullProfile.characters.pmc.TradersInfo.ragfair;
} }
// Remove SCAV 'ragfair' from trader list // Remove SCAV 'ragfair' from trader list
if (fullProfile.characters.scav.TradersInfo.ragfair) { if (fullProfile.characters.scav.TradersInfo.ragfair) {
this.logger.warning("Migration: deleting: ragfair traderinfo object from PMC"); this.logger.warning("Migration: deleting: ragfair traderinfo object from PMC");
// biome-ignore lint/performance/noDelete: Delete is fine here, as we're seeking to remove these entirely
delete fullProfile.characters.scav.TradersInfo.ragfair; delete fullProfile.characters.scav.TradersInfo.ragfair;
} }
@ -561,6 +564,7 @@ export class GameController {
protected checkForAndRemoveUndefinedDialogs(fullProfile: ISptProfile): void { protected checkForAndRemoveUndefinedDialogs(fullProfile: ISptProfile): void {
const undefinedDialog = fullProfile.dialogues.undefined; const undefinedDialog = fullProfile.dialogues.undefined;
if (undefinedDialog) { if (undefinedDialog) {
// biome-ignore lint/performance/noDelete: Delete is fine here, as we're seeking to delete undefined dialogs.
delete fullProfile.dialogues.undefined; delete fullProfile.dialogues.undefined;
} }
} }

View File

@ -250,6 +250,7 @@ export class HealthController {
// Remove empty effect object // Remove empty effect object
if (Object.keys(pmcData.Health.BodyParts[bodyPartKey].Effects).length === 0) { if (Object.keys(pmcData.Health.BodyParts[bodyPartKey].Effects).length === 0) {
// biome-ignore lint/performance/noDelete: Delete is fine here as we entirely want to get rid of the effect.
delete pmcData.Health.BodyParts[bodyPartKey].Effects; delete pmcData.Health.BodyParts[bodyPartKey].Effects;
} }
} }

View File

@ -1229,6 +1229,7 @@ export class HideoutController {
if (hasMildPain) { if (hasMildPain) {
// Already has mild pain, remove mild and add severe // Already has mild pain, remove mild and add severe
// biome-ignore lint/performance/noDelete: Deleting is fine here, we're removing the effect to replace it with another.
delete pmcData.Health.BodyParts.Chest.Effects.MildMusclePain; delete pmcData.Health.BodyParts.Chest.Effects.MildMusclePain;
pmcData.Health.BodyParts.Chest.Effects.SevereMusclePain = { pmcData.Health.BodyParts.Chest.Effects.SevereMusclePain = {

View File

@ -282,7 +282,7 @@ export class InventoryController {
// Remove FiR status from destination stack when source stack has no FiR but destination does // Remove FiR status from destination stack when source stack has no FiR but destination does
if (!sourceItem.upd.SpawnedInSession && destinationItem.upd.SpawnedInSession) { if (!sourceItem.upd.SpawnedInSession && destinationItem.upd.SpawnedInSession) {
delete destinationItem.upd.SpawnedInSession; destinationItem.upd.SpawnedInSession = false;
} }
destinationItem.upd.StackObjectsCount += sourceItem.upd.StackObjectsCount; // Add source stackcount to destination destinationItem.upd.StackObjectsCount += sourceItem.upd.StackObjectsCount; // Add source stackcount to destination
@ -408,6 +408,7 @@ export class InventoryController {
if (request.to.location) { if (request.to.location) {
itemOne.location = request.to.location; itemOne.location = request.to.location;
} else { } else {
// biome-ignore lint/performance/noDelete: Delete is fine here as we entirely want to get rid of the location.
delete itemOne.location; delete itemOne.location;
} }
@ -416,6 +417,7 @@ export class InventoryController {
if (request.to2.location) { if (request.to2.location) {
itemTwo.location = request.to2.location; itemTwo.location = request.to2.location;
} else { } else {
// biome-ignore lint/performance/noDelete: Delete is fine here as we entirely want to get rid of the location.
delete itemTwo.location; delete itemTwo.location;
} }
@ -721,6 +723,7 @@ export class InventoryController {
if (change.location) { if (change.location) {
inventoryItem.location = change.location; inventoryItem.location = change.location;
} else { } else {
// biome-ignore lint/performance/noDelete: Delete is fine here as we entirely want to get rid of the location.
delete inventoryItem.location; delete inventoryItem.location;
} }
} }

View File

@ -571,9 +571,12 @@ export class BotWeaponGenerator {
} }
// Inner join the weapons allowed + passed in cartridge pool to get compatible cartridges // Inner join the weapons allowed + passed in cartridge pool to get compatible cartridges
const compatibleCartridges = Object.keys(cartridgePoolForWeapon) const compatibleCartridges = {};
.filter((cartridge) => compatibleCartridgesInTemplate.includes(cartridge)) for (const cartridge of Object.keys(cartridgePoolForWeapon)) {
.reduce((acc, key) => ({ ...acc, [key]: cartridgePoolForWeapon[key] }), {}); if (compatibleCartridgesInTemplate.includes(cartridge)) {
compatibleCartridges[cartridge] = cartridgePoolForWeapon[cartridge];
}
}
if (!compatibleCartridges) { if (!compatibleCartridges) {
// No compatible cartridges, use default // No compatible cartridges, use default

View File

@ -397,9 +397,9 @@ export class LootGenerator {
const presetAndMods: IItem[] = this.itemHelper.replaceIDs(chosenPreset._items); const presetAndMods: IItem[] = this.itemHelper.replaceIDs(chosenPreset._items);
this.itemHelper.remapRootItemId(presetAndMods); this.itemHelper.remapRootItemId(presetAndMods);
// Add chosen preset tpl to result array // Add chosen preset tpl to result array
presetAndMods.forEach((item) => { for (const item of presetAndMods) {
result.push(item); result.push(item);
}); }
if (itemLimitCount) { if (itemLimitCount) {
// Increment item count as item has been chosen and its inside itemLimitCount dictionary // Increment item count as item has been chosen and its inside itemLimitCount dictionary

View File

@ -403,7 +403,9 @@ export class RagfairOfferGenerator {
this.itemHelper.reparentItemAndChildren(clonedAssort[0], clonedAssort); this.itemHelper.reparentItemAndChildren(clonedAssort[0], clonedAssort);
// Clear unnecessary properties // Clear unnecessary properties
// biome-ignore lint/performance/noDelete: Deleting is fine here, we're getting rid of unecessary properties.
delete clonedAssort[0].parentId; delete clonedAssort[0].parentId;
// biome-ignore lint/performance/noDelete: Deleting is fine here, we're getting rid of unecessary properties.
delete clonedAssort[0].slotId; delete clonedAssort[0].slotId;
assortSingleOfferProcesses.push( assortSingleOfferProcesses.push(

View File

@ -309,20 +309,22 @@ export class RepeatableQuestRewardGenerator {
itemsToReturn.push({ item: chosenItemFromPool, stackSize: rewardItemStackCount }); itemsToReturn.push({ item: chosenItemFromPool, stackSize: rewardItemStackCount });
const itemCost = this.presetHelper.getDefaultPresetOrItemPrice(chosenItemFromPool._id); const itemCost = this.presetHelper.getDefaultPresetOrItemPrice(chosenItemFromPool._id);
itemRewardBudget -= rewardItemStackCount * itemCost; const calculatedItemRewardBudget = itemRewardBudget - rewardItemStackCount * itemCost;
this.logger.debug(`Added item: ${chosenItemFromPool._id} with price: ${rewardItemStackCount * itemCost}`); this.logger.debug(`Added item: ${chosenItemFromPool._id} with price: ${rewardItemStackCount * itemCost}`);
// If we still have budget narrow down possible items // If we still have budget narrow down possible items
if (itemRewardBudget > 0) { if (calculatedItemRewardBudget > 0) {
// Filter possible reward items to only items with a price below the remaining budget // Filter possible reward items to only items with a price below the remaining budget
exhausableItemPool = new ExhaustableArray( exhausableItemPool = new ExhaustableArray(
this.filterRewardPoolWithinBudget(itemPool, itemRewardBudget, 0), this.filterRewardPoolWithinBudget(itemPool, calculatedItemRewardBudget, 0),
this.randomUtil, this.randomUtil,
this.cloner, this.cloner,
); );
if (!exhausableItemPool.hasValues()) { if (!exhausableItemPool.hasValues()) {
this.logger.debug(`Reward pool empty with: ${itemRewardBudget} roubles of budget remaining`); this.logger.debug(
`Reward pool empty with: ${calculatedItemRewardBudget} roubles of budget remaining`,
);
break; // No reward items left, exit break; // No reward items left, exit
} }
} }

View File

@ -321,6 +321,7 @@ export class ScavCaseRewardGenerator {
// Clean up upd object if it wasn't used // Clean up upd object if it wasn't used
if (!rootItem.upd) { if (!rootItem.upd) {
// biome-ignore lint/performance/noDelete: Delete is fine here, we're cleaning up this object without leaving an undefined.
delete rootItem.upd; delete rootItem.upd;
} }

View File

@ -293,6 +293,7 @@ export class HealthHelper {
for (const bodyPart in bodyPartsWithEffects) { for (const bodyPart in bodyPartsWithEffects) {
// clear effects from profile bodyPart // clear effects from profile bodyPart
if (deleteExistingEffects) { if (deleteExistingEffects) {
// biome-ignore lint/performance/noDelete: Delete is fine here as we entirely want to get rid of the effect.
delete pmcData.Health.BodyParts[bodyPart].Effects; delete pmcData.Health.BodyParts[bodyPart].Effects;
} }
@ -339,6 +340,7 @@ export class HealthHelper {
// Delete empty property to prevent client bugs // Delete empty property to prevent client bugs
if (this.isEmpty(profileBodyPart.Effects)) { if (this.isEmpty(profileBodyPart.Effects)) {
// biome-ignore lint/performance/noDelete: Delete is fine here, we're removing an empty property to prevent game bugs.
delete profileBodyPart.Effects; delete profileBodyPart.Effects;
} }
} }

View File

@ -180,8 +180,11 @@ export class HideoutHelper {
break; break;
case BonusType.TEXT_BONUS: case BonusType.TEXT_BONUS:
// Delete values before they're added to profile // Delete values before they're added to profile
// biome-ignore lint/performance/noDelete: Delete is fine here as we entirely want to get rid of the data.
delete bonus.passive; delete bonus.passive;
// biome-ignore lint/performance/noDelete: Delete is fine here as we entirely want to get rid of the data.
delete bonus.production; delete bonus.production;
// biome-ignore lint/performance/noDelete: Delete is fine here as we entirely want to get rid of the data.
delete bonus.visible; delete bonus.visible;
break; break;
} }
@ -781,6 +784,7 @@ export class HideoutHelper {
} }
// Filter ran out / used up // Filter ran out / used up
// biome-ignore lint/performance/noDelete: Delete is fine here, as we're seeking to entirely delete the water filter.
delete waterFilterArea.slots[i].item; delete waterFilterArea.slots[i].item;
// Update remaining resources to be subtracted // Update remaining resources to be subtracted
filterDrainRate = Math.abs(resourceValue); filterDrainRate = Math.abs(resourceValue);
@ -919,6 +923,7 @@ export class HideoutHelper {
break; // Break here to avoid updating all filters break; // Break here to avoid updating all filters
} }
// biome-ignore lint/performance/noDelete: Delete is fine here, as we're seeking to entirely delete the air filter.
delete airFilterArea.slots[i].item; delete airFilterArea.slots[i].item;
// Update remaining resources to be subtracted // Update remaining resources to be subtracted
filterDrainRate = Math.abs(resourceValue); filterDrainRate = Math.abs(resourceValue);

View File

@ -118,7 +118,9 @@ export class InRaidHelper {
}); });
for (const item of itemsToRemovePropertyFrom) { for (const item of itemsToRemovePropertyFrom) {
delete item.upd.SpawnedInSession; if (item.upd) {
item.upd.SpawnedInSession = false;
}
} }
} }

View File

@ -177,10 +177,14 @@ export class InventoryHelper {
// Ensure item has upd object // Ensure item has upd object
this.itemHelper.addUpdObjectToItem(item); this.itemHelper.addUpdObjectToItem(item);
if (!item.upd) {
item.upd = {};
}
if (foundInRaid) { if (foundInRaid) {
item.upd.SpawnedInSession = foundInRaid; item.upd.SpawnedInSession = foundInRaid;
} else { } else {
delete item.upd.SpawnedInSession; item.upd.SpawnedInSession = false;
} }
} }
} }
@ -191,14 +195,17 @@ export class InventoryHelper {
*/ */
protected removeTraderRagfairRelatedUpdProperties(upd: IUpd): void { protected removeTraderRagfairRelatedUpdProperties(upd: IUpd): void {
if (upd.UnlimitedCount !== undefined) { if (upd.UnlimitedCount !== undefined) {
// biome-ignore lint/performance/noDelete: Delete is fine here since we're attempting to remove this fully here.
delete upd.UnlimitedCount; delete upd.UnlimitedCount;
} }
if (upd.BuyRestrictionCurrent !== undefined) { if (upd.BuyRestrictionCurrent !== undefined) {
// biome-ignore lint/performance/noDelete: Delete is fine here since we're attempting to remove this fully here.
delete upd.BuyRestrictionCurrent; delete upd.BuyRestrictionCurrent;
} }
if (upd.BuyRestrictionMax !== undefined) { if (upd.BuyRestrictionMax !== undefined) {
// biome-ignore lint/performance/noDelete: Delete is fine here since we're attempting to remove this fully here.
delete upd.BuyRestrictionMax; delete upd.BuyRestrictionMax;
} }
} }
@ -997,6 +1004,7 @@ export class InventoryHelper {
} else { } else {
// No location in request, delete it // No location in request, delete it
if (itemToMove.location) { if (itemToMove.location) {
// biome-ignore lint/performance/noDelete: Delete is fine here as we're trying to remove the entire data property.
delete itemToMove.location; delete itemToMove.location;
} }
} }
@ -1059,6 +1067,7 @@ export class InventoryHelper {
} else { } else {
// Moved from slot with location to one without, clean up // Moved from slot with location to one without, clean up
if (matchingInventoryItem.location) { if (matchingInventoryItem.location) {
// biome-ignore lint/performance/noDelete: Delete is fine here as we're trying to remove the entire data property.
delete matchingInventoryItem.location; delete matchingInventoryItem.location;
} }
} }

View File

@ -1194,6 +1194,7 @@ export class ItemHelper {
// In live no ammo box has the first cartridge item with a location // In live no ammo box has the first cartridge item with a location
if (location === 0) { if (location === 0) {
// biome-ignore lint/performance/noDelete: Delete is fine here as we entirely want to get rid of the location.
delete cartridgeItemToAdd.location; delete cartridgeItemToAdd.location;
} }
@ -1366,6 +1367,7 @@ export class ItemHelper {
// Only one cartridge stack added, remove location property as its only used for 2 or more stacks // Only one cartridge stack added, remove location property as its only used for 2 or more stacks
if (location === 1) { if (location === 1) {
// biome-ignore lint/performance/noDelete: Delete is fine here as we entirely want to get rid of the location.
delete magazineWithChildCartridges[1].location; delete magazineWithChildCartridges[1].location;
} }
} }
@ -1706,6 +1708,7 @@ export class ItemHelper {
if (!parentExists && item.parentId !== rootId && item.slotId !== "hideout") { if (!parentExists && item.parentId !== rootId && item.slotId !== "hideout") {
item.parentId = rootId; item.parentId = rootId;
item.slotId = "hideout"; item.slotId = "hideout";
// biome-ignore lint/performance/noDelete: Delete is fine here as we entirely want to get rid of the location.
delete item.location; delete item.location;
} }
} }
@ -1800,7 +1803,10 @@ export class ItemHelper {
*/ */
public removeSpawnedInSessionPropertyFromItems(items: IItem[]): void { public removeSpawnedInSessionPropertyFromItems(items: IItem[]): void {
for (const item of items) { for (const item of items) {
delete item.upd.SpawnedInSession; if (item.upd) {
// biome-ignore lint/performance/noDelete: Delete is fine here as we're removing the entire property.
delete item.upd.SpawnedInSession;
}
} }
} }
} }

View File

@ -253,6 +253,7 @@ export class QuestHelper {
existingQuest.completedConditions = []; existingQuest.completedConditions = [];
if (existingQuest.availableAfter) { if (existingQuest.availableAfter) {
// biome-ignore lint/performance/noDelete: Delete is fine here as we're trying to remove the entire data property.
delete existingQuest.availableAfter; delete existingQuest.availableAfter;
} }

View File

@ -1 +1,2 @@
// biome-ignore lint/complexity/noBannedTypes: Empty request is empty, this is fine.
export type IEmptyRequestData = {}; export type IEmptyRequestData = {};

View File

@ -1,23 +0,0 @@
import { ISkills } from "@spt/models/eft/common/tables/IBotBase";
export interface IPlayerIncrementSkillLevelRequestData {
_id: string;
experience: number;
quests: any[];
ragFairOffers: any[];
builds: any[];
items: Items;
production: Production;
skills: ISkills;
traderRelations: TraderRelations;
}
export interface Items {
new: any[];
change: any[];
del: any[];
}
export type Production = {};
export type TraderRelations = {};

View File

@ -227,10 +227,13 @@ export interface IEffects {
RightLeg: IRightLeg; RightLeg: IRightLeg;
} }
// biome-ignore lint/complexity/noBannedTypes: Not sure of typing on these for now.
export type IHead = {}; export type IHead = {};
// biome-ignore lint/complexity/noBannedTypes: Not sure of typing on these for now.
export type IChest = {}; export type IChest = {};
// biome-ignore lint/complexity/noBannedTypes: Not sure of typing on these for now.
export type IStomach = {}; export type IStomach = {};
export interface ILeftArm { export interface ILeftArm {

View File

@ -20,7 +20,7 @@ export interface ISearchRequestData {
handbookId: string; handbookId: string;
linkedSearchId: string; linkedSearchId: string;
neededSearchId: string; neededSearchId: string;
buildItems: BuildItems; buildItems: Record<string, number>;
buildCount: number; buildCount: number;
tm: number; tm: number;
reload: number; reload: number;
@ -31,5 +31,3 @@ export enum OfferOwnerType {
TRADEROWNERTYPE = 1, TRADEROWNERTYPE = 1,
PLAYEROWNERTYPE = 2, PLAYEROWNERTYPE = 2,
} }
export type BuildItems = {};

View File

@ -82,7 +82,7 @@ export class BotEquipmentModPoolService {
// Check item added into array for slots, need to iterate over those // Check item added into array for slots, need to iterate over those
const subItemDetails = this.itemHelper.getItem(itemToAdd)[1]; const subItemDetails = this.itemHelper.getItem(itemToAdd)[1];
const hasSubItemsToAdd = subItemDetails?._props?.Slots?.length ?? 0 > 0; const hasSubItemsToAdd = (subItemDetails?._props?.Slots?.length ?? 0) > 0;
if (hasSubItemsToAdd && !pool[subItemDetails._id]) { if (hasSubItemsToAdd && !pool[subItemDetails._id]) {
// Recursive call // Recursive call
this.generatePool([subItemDetails], poolType); this.generatePool([subItemDetails], poolType);

View File

@ -165,6 +165,7 @@ export class FenceService {
} }
// Clean up the items // Clean up the items
// biome-ignore lint/performance/noDelete: Delete is fine here as we're getting rid of the items before updating.
delete root.location; delete root.location;
const createAssort: ICreateFenceAssortsResult = { sptItems: [], barter_scheme: {}, loyal_level_items: {} }; const createAssort: ICreateFenceAssortsResult = { sptItems: [], barter_scheme: {}, loyal_level_items: {} };
@ -1115,6 +1116,8 @@ export class FenceService {
continue; continue;
} }
let armorWithMods = armorItemAndMods;
const modItemDbDetails = this.itemHelper.getItem(plateTpl)[1]; const modItemDbDetails = this.itemHelper.getItem(plateTpl)[1];
// Chance to remove plate // Chance to remove plate
@ -1122,7 +1125,7 @@ export class FenceService {
this.traderConfig.fence.chancePlateExistsInArmorPercent[modItemDbDetails._props?.armorClass ?? "3"]; this.traderConfig.fence.chancePlateExistsInArmorPercent[modItemDbDetails._props?.armorClass ?? "3"];
if (!this.randomUtil.getChance100(plateExistsChance)) { if (!this.randomUtil.getChance100(plateExistsChance)) {
// Remove plate from armor // Remove plate from armor
armorItemAndMods = armorItemAndMods.filter( armorWithMods = armorItemAndMods.filter(
(item) => item.slotId.toLowerCase() !== plateSlot._name.toLowerCase(), (item) => item.slotId.toLowerCase() !== plateSlot._name.toLowerCase(),
); );
@ -1135,13 +1138,13 @@ export class FenceService {
); );
// Find items mod to apply dura changes to // Find items mod to apply dura changes to
const modItemToAdjust = armorItemAndMods.find( const modItemToAdjust = armorWithMods.find(
(mod) => mod.slotId.toLowerCase() === plateSlot._name.toLowerCase(), (mod) => mod.slotId.toLowerCase() === plateSlot._name.toLowerCase(),
); );
if (!modItemToAdjust) { if (!modItemToAdjust) {
this.logger.warning( this.logger.warning(
`Unable to randomise armor items ${armorItemAndMods[0]._tpl} ${plateSlot._name} slot as it cannot be found, skipping`, `Unable to randomise armor items ${armorWithMods[0]._tpl} ${plateSlot._name} slot as it cannot be found, skipping`,
); );
continue; continue;
} }

View File

@ -29,7 +29,9 @@ export class ItemFilterService {
*/ */
public isItemBlacklisted(tpl: string): boolean { public isItemBlacklisted(tpl: string): boolean {
if (this.itemBlacklistCache.size === 0) { if (this.itemBlacklistCache.size === 0) {
this.itemConfig.blacklist.forEach((item) => this.itemBlacklistCache.add(item)); for (const item of this.itemConfig.blacklist) {
this.itemBlacklistCache.add(item);
}
} }
return this.itemBlacklistCache.has(tpl); return this.itemBlacklistCache.has(tpl);
@ -42,7 +44,9 @@ export class ItemFilterService {
*/ */
public isLootableItemBlacklisted(tpl: string): boolean { public isLootableItemBlacklisted(tpl: string): boolean {
if (this.lootableItemBlacklistCache.size === 0) { if (this.lootableItemBlacklistCache.size === 0) {
this.itemConfig.lootableItemBlacklist.forEach((item) => this.itemBlacklistCache.add(item)); for (const item of this.itemConfig.lootableItemBlacklist) {
this.itemBlacklistCache.add(item);
}
} }
return this.lootableItemBlacklistCache.has(tpl); return this.lootableItemBlacklistCache.has(tpl);

View File

@ -350,11 +350,13 @@ export class MailSendService {
// Clean up empty system data // Clean up empty system data
if (!message.systemData) { if (!message.systemData) {
// biome-ignore lint/performance/noDelete: Delete is fine here as we're trying to remove the entire data property.
delete message.systemData; delete message.systemData;
} }
// Clean up empty template id // Clean up empty template id
if (!message.templateId) { if (!message.templateId) {
// biome-ignore lint/performance/noDelete: Delete is fine here as we're trying to remove the entire data property.
delete message.templateId; delete message.templateId;
} }
@ -458,6 +460,7 @@ export class MailSendService {
// Remove empty data property if no rewards // Remove empty data property if no rewards
if (itemsToSendToPlayer.data.length === 0) { if (itemsToSendToPlayer.data.length === 0) {
// biome-ignore lint/performance/noDelete: Delete is fine here as we're trying to remove the empty data property.
delete itemsToSendToPlayer.data; delete itemsToSendToPlayer.data;
} }
} }

View File

@ -83,25 +83,27 @@ export class ProfileFixerService {
*/ */
public checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void { public checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void {
for (const traderDialogues of Object.values(fullProfile.dialogues)) { for (const traderDialogues of Object.values(fullProfile.dialogues)) {
for (const message of traderDialogues?.messages) { if (traderDialogues?.messages) {
// Skip any messages without attached items for (const message of traderDialogues.messages) {
if (!message.items?.data || !message.items?.stash) { // Skip any messages without attached items
continue; if (!message.items?.data || !message.items?.stash) {
} continue;
}
// Skip any messages that don't have a stashId collision with the player's equipment ID // Skip any messages that don't have a stashId collision with the player's equipment ID
if (message.items?.stash !== fullProfile.characters?.pmc?.Inventory?.equipment) { if (message.items?.stash !== fullProfile.characters?.pmc?.Inventory?.equipment) {
continue; continue;
} }
// Otherwise we need to generate a new unique stash ID for this message's attachments // Otherwise we need to generate a new unique stash ID for this message's attachments
message.items.stash = this.hashUtil.generate(); message.items.stash = this.hashUtil.generate();
message.items.data = this.itemHelper.adoptOrphanedItems(message.items.stash, message.items.data); message.items.data = this.itemHelper.adoptOrphanedItems(message.items.stash, message.items.data);
// Because `adoptOrphanedItems` sets the slotId to `hideout`, we need to re-set it to `main` to work with mail // Because `adoptOrphanedItems` sets the slotId to `hideout`, we need to re-set it to `main` to work with mail
for (const item of message.items.data) { for (const item of message.items.data) {
if (item.slotId === "hideout") { if (item.slotId === "hideout") {
item.slotId = "main"; item.slotId = "main";
}
} }
} }
} }
@ -325,15 +327,25 @@ export class ProfileFixerService {
const productionRewards = quest.rewards.Started?.filter( const productionRewards = quest.rewards.Started?.filter(
(reward) => reward.type === QuestRewardType.PRODUCTIONS_SCHEME, (reward) => reward.type === QuestRewardType.PRODUCTIONS_SCHEME,
); );
productionRewards?.forEach((reward) => this.verifyQuestProductionUnlock(pmcProfile, reward, quest));
if (productionRewards) {
for (const reward of productionRewards) {
this.verifyQuestProductionUnlock(pmcProfile, reward, quest);
}
}
} }
// For successful quests, check for unlocks in the `Success` rewards // For successful quests, check for unlocks in the `Success` rewards
if (profileQuest.status == QuestStatus.Success) { if (profileQuest.status === QuestStatus.Success) {
const productionRewards = quest.rewards.Success?.filter( const productionRewards = quest.rewards.Success?.filter(
(reward) => reward.type === QuestRewardType.PRODUCTIONS_SCHEME, (reward) => reward.type === QuestRewardType.PRODUCTIONS_SCHEME,
); );
productionRewards?.forEach((reward) => this.verifyQuestProductionUnlock(pmcProfile, reward, quest));
if (productionRewards) {
for (const reward of productionRewards) {
this.verifyQuestProductionUnlock(pmcProfile, reward, quest);
}
}
} }
} }

View File

@ -250,6 +250,7 @@ export class RagfairOfferService {
if (firstOfferItem.upd.StackObjectsCount > firstOfferItem.upd.OriginalStackObjectsCount) { if (firstOfferItem.upd.StackObjectsCount > firstOfferItem.upd.OriginalStackObjectsCount) {
playerOffer.items[0].upd.StackObjectsCount = firstOfferItem.upd.OriginalStackObjectsCount; playerOffer.items[0].upd.StackObjectsCount = firstOfferItem.upd.OriginalStackObjectsCount;
} }
// biome-ignore lint/performance/noDelete: Delete is fine here as we entirely want to get rid of the data.
delete playerOffer.items[0].upd.OriginalStackObjectsCount; delete playerOffer.items[0].upd.OriginalStackObjectsCount;
// Remove player offer from flea // Remove player offer from flea
this.ragfairOfferHandler.removeOffer(playerOffer); this.ragfairOfferHandler.removeOffer(playerOffer);

View File

@ -68,7 +68,7 @@ export class RagfairTaxService {
const requirementsPrice = requirementsValue * (sellInOnePiece ? 1 : offerItemCount); const requirementsPrice = requirementsValue * (sellInOnePiece ? 1 : offerItemCount);
const itemTaxMult = globals.config.RagFair.communityItemTax / 100.0; const itemTaxMult = globals.config.RagFair.communityItemTax / 100.0;
const requirementTaxMult = globals!.config.RagFair.communityRequirementTax / 100.0; const requirementTaxMult = globals.config.RagFair.communityRequirementTax / 100.0;
let itemPriceMult = Math.log10(itemWorth / requirementsPrice); let itemPriceMult = Math.log10(itemWorth / requirementsPrice);
let requirementPriceMult = Math.log10(requirementsPrice / itemWorth); let requirementPriceMult = Math.log10(requirementsPrice / itemWorth);
@ -144,39 +144,34 @@ export class RagfairTaxService {
} }
} }
if ("Dogtag" in item.upd!) { const upd = item.upd ?? {};
worth *= item.upd!.Dogtag!.Level;
}
if ("Key" in item.upd! && (itemTemplate._props.MaximumNumberOfUsage ?? 0) > 0) { if (upd.Dogtag) {
worth *= upd.Dogtag.Level;
}
if (upd.Key && (itemTemplate._props?.MaximumNumberOfUsage ?? 0) > 0) {
worth = worth =
(worth / itemTemplate._props.MaximumNumberOfUsage!) * (worth / (itemTemplate._props?.MaximumNumberOfUsage ?? 1)) *
(itemTemplate._props.MaximumNumberOfUsage! - item.upd!.Key!.NumberOfUsages); ((itemTemplate._props?.MaximumNumberOfUsage ?? 1) - upd.Key.NumberOfUsages);
} }
if (upd.Resource && (itemTemplate._props?.MaxResource ?? 0) > 0) {
if ("Resource" in item.upd! && itemTemplate._props.MaxResource! > 0) { worth = worth * 0.1 + ((worth * 0.9) / (itemTemplate._props?.MaxResource ?? 1)) * upd.Resource.Value;
worth = worth * 0.1 + ((worth * 0.9) / itemTemplate._props.MaxResource!) * item.upd.Resource!.Value;
} }
if (upd.SideEffect && (itemTemplate._props?.MaxResource ?? 0) > 0) {
if ("SideEffect" in item.upd! && itemTemplate._props.MaxResource! > 0) { worth = worth * 0.1 + ((worth * 0.9) / (itemTemplate._props?.MaxResource ?? 1)) * upd.SideEffect.Value;
worth = worth * 0.1 + ((worth * 0.9) / itemTemplate._props.MaxResource!) * item.upd.SideEffect!.Value;
} }
if (upd.MedKit && (itemTemplate._props?.MaxHpResource ?? 0) > 0) {
if ("MedKit" in item.upd! && itemTemplate._props.MaxHpResource! > 0) { worth = (worth / (itemTemplate._props?.MaxHpResource ?? 1)) * upd.MedKit.HpResource;
worth = (worth / itemTemplate._props.MaxHpResource!) * item.upd.MedKit!.HpResource;
} }
if (upd.FoodDrink && (itemTemplate._props?.MaxResource ?? 0) > 0) {
if ("FoodDrink" in item.upd! && itemTemplate._props.MaxResource! > 0) { worth = (worth / (itemTemplate._props?.MaxResource ?? 1)) * upd.FoodDrink.HpPercent;
worth = (worth / itemTemplate._props.MaxResource!) * item.upd.FoodDrink!.HpPercent;
} }
if (upd.Repairable && Number(itemTemplate._props?.armorClass ?? 0) > 0) {
if ("Repairable" in item.upd! && <number>itemTemplate._props.armorClass > 0) { const num2 = 0.01 * 0.0 ** upd.Repairable.MaxDurability;
const num2 = 0.01 * 0.0 ** item.upd.Repairable!.MaxDurability;
worth = worth =
worth * (item.upd.Repairable!.MaxDurability / itemTemplate._props.Durability! - num2) - worth * (upd.Repairable.MaxDurability / (itemTemplate._props?.Durability ?? 1) - num2) -
Math.floor( Math.floor(
itemTemplate._props.RepairCost! * (itemTemplate._props?.RepairCost ?? 0) * (upd.Repairable.MaxDurability - upd.Repairable.Durability),
(item.upd.Repairable!.MaxDurability - item.upd.Repairable!.Durability),
); );
} }

View File

@ -350,14 +350,16 @@ export class ItemTplGenerator {
} }
private cleanCaliber(ammoCaliber: string): string { private cleanCaliber(ammoCaliber: string): string {
ammoCaliber = ammoCaliber.replace("CALIBER", ""); let ammoCaliberToClean = ammoCaliber;
ammoCaliber = ammoCaliber.replace("PARA", "");
ammoCaliber = ammoCaliber.replace("NATO", ""); ammoCaliberToClean = ammoCaliberToClean.replace("CALIBER", "");
ammoCaliberToClean = ammoCaliberToClean.replace("PARA", "");
ammoCaliberToClean = ammoCaliberToClean.replace("NATO", "");
// Special case for 45ACP // Special case for 45ACP
ammoCaliber = ammoCaliber.replace("1143X23ACP", "45ACP"); ammoCaliberToClean = ammoCaliberToClean.replace("1143X23ACP", "45ACP");
return ammoCaliber; return ammoCaliberToClean;
} }
private getAmmoBoxPrefix(item: ITemplateItem): string { private getAmmoBoxPrefix(item: ITemplateItem): string {

View File

@ -1,55 +0,0 @@
import "reflect-metadata";
import { Queue } from "@spt/utils/collections/queue/Queue";
import { describe, expect, it } from "vitest";
describe("LinkedList", () => {
describe("enqueue", () => {
const queue = new Queue<number>();
queue.enqueue(420);
queue.enqueue(69);
queue.enqueue(8008135);
queue.enqueue(1337);
it("adds elements to the end of the queue", () => {
expect(queue.peek()).toEqual(420);
expect(queue.length).toEqual(4);
});
});
describe("enqueueAll", () => {
const queue = new Queue<number>();
queue.enqueueAll([420, 69, 8008135, 1337]);
it("iterates the array and adds each element to the end of the queue", () => {
expect(queue.peek()).toEqual(420);
expect(queue.length).toEqual(4);
});
});
describe("dequeue", () => {
const queue = new Queue<number>();
queue.enqueueAll([420, 69, 8008135, 1337]);
it("removes the first element and return it's value", () => {
expect(queue.dequeue()).toEqual(420);
expect(queue.peek()).toEqual(69);
expect(queue.length).toEqual(3);
expect(queue.dequeue()).toEqual(69);
expect(queue.peek()).toEqual(8008135);
expect(queue.length).toEqual(2);
expect(queue.dequeue()).toEqual(8008135);
expect(queue.peek()).toEqual(1337);
expect(queue.length).toEqual(1);
expect(queue.dequeue()).toEqual(1337);
expect(queue.peek()).toEqual(undefined);
expect(queue.length).toEqual(0);
expect(queue.dequeue()).toEqual(undefined);
expect(queue.peek()).toEqual(undefined);
expect(queue.length).toEqual(0);
});
});
});