Improve selection of items to add mods for:
quest rewards bot loot gen map loot gen fence assort gen Updated `removeRandomModsOfItem()` to also skip slots with a _required prop
This commit is contained in:
parent
6a8e261af1
commit
cb18d251ba
@ -344,7 +344,7 @@ export class BotLootGenerator
|
|||||||
this.randomiseAmmoStackSize(isPmc, itemToAddTemplate, itemsToAdd[0]);
|
this.randomiseAmmoStackSize(isPmc, itemToAddTemplate, itemsToAdd[0]);
|
||||||
}
|
}
|
||||||
// Must add soft inserts/plates
|
// Must add soft inserts/plates
|
||||||
else if (this.itemHelper.itemCanRequireArmorInserts(itemToAddTemplate._id))
|
else if (this.itemHelper.itemRequiresSoftInserts(itemToAddTemplate._id))
|
||||||
{
|
{
|
||||||
itemsToAdd = this.itemHelper.addChildSlotItems(itemsToAdd, itemToAddTemplate, null, true);
|
itemsToAdd = this.itemHelper.addChildSlotItems(itemsToAdd, itemToAddTemplate, null, true);
|
||||||
}
|
}
|
||||||
|
@ -861,7 +861,7 @@ export class LocationGenerator
|
|||||||
);
|
);
|
||||||
itemWithMods.push(...magazineItem);
|
itemWithMods.push(...magazineItem);
|
||||||
}
|
}
|
||||||
else if (this.itemHelper.itemCanRequireArmorInserts(chosenTpl))
|
else if (this.itemHelper.armorItemCanHoldMods(chosenTpl))
|
||||||
{
|
{
|
||||||
itemWithMods.push({
|
itemWithMods.push({
|
||||||
_id: this.objectId.generate(),
|
_id: this.objectId.generate(),
|
||||||
@ -1071,8 +1071,9 @@ export class LocationGenerator
|
|||||||
// Replace existing magazine with above array
|
// Replace existing magazine with above array
|
||||||
items.splice(items.indexOf(items[0]), 1, ...magazineWithCartridges);
|
items.splice(items.indexOf(items[0]), 1, ...magazineWithCartridges);
|
||||||
}
|
}
|
||||||
else if (this.itemHelper.itemCanRequireArmorInserts(chosenTpl))
|
else if (this.itemHelper.armorItemCanHoldMods(chosenTpl))
|
||||||
{
|
{
|
||||||
|
// We make base item above, at start of function, no need to do it here
|
||||||
if (itemTemplate._props.Slots?.length > 0)
|
if (itemTemplate._props.Slots?.length > 0)
|
||||||
{
|
{
|
||||||
items = this.itemHelper.addChildSlotItems(items, itemTemplate, this.locationConfig.equipmentLootSettings.modSpawnChancePercent);
|
items = this.itemHelper.addChildSlotItems(items, itemTemplate, this.locationConfig.equipmentLootSettings.modSpawnChancePercent);
|
||||||
|
@ -105,11 +105,47 @@ export class ItemHelper
|
|||||||
* @param itemTpl item to check
|
* @param itemTpl item to check
|
||||||
* @returns Does item have the possibility ot need soft inserts
|
* @returns Does item have the possibility ot need soft inserts
|
||||||
*/
|
*/
|
||||||
public itemCanRequireArmorInserts(itemTpl: string): boolean
|
public armorItemCanHoldMods(itemTpl: string): boolean
|
||||||
{
|
{
|
||||||
return this.isOfBaseclasses(itemTpl, [BaseClasses.HEADWEAR, BaseClasses.VEST, BaseClasses.ARMOR]);
|
return this.isOfBaseclasses(itemTpl, [BaseClasses.HEADWEAR, BaseClasses.VEST, BaseClasses.ARMOR]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the provided item tpl require soft inserts to become a valid armor item
|
||||||
|
* @param itemTpl Item tpl to check
|
||||||
|
* @returns True if it needs armor inserts
|
||||||
|
*/
|
||||||
|
public itemRequiresSoftInserts(itemTpl: string): boolean
|
||||||
|
{
|
||||||
|
// not a slot that takes soft-inserts
|
||||||
|
if (!this.armorItemCanHoldMods(itemTpl))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check is an item
|
||||||
|
const itemDbDetails = this.getItem(itemTpl);
|
||||||
|
if (!itemDbDetails[0])
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Has no slots
|
||||||
|
if (!(itemDbDetails[1]._props.Slots ?? []).length)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if item has slots that match soft insert name ids
|
||||||
|
const softInsertSlotIds = ["groin", "soft_armor_back", "soft_armor_front", "soft_armor_left", "soft_armor_right", "shoulder_l", "shoulder_r", "collar"];
|
||||||
|
if (itemDbDetails[1]._props.Slots.find(slot => softInsertSlotIds.includes(slot._name.toLowerCase())))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the item price based on the handbook or as a fallback from the prices.json if the item is not
|
* Returns the item price based on the handbook or as a fallback from the prices.json if the item is not
|
||||||
* found in the handbook. If the price can't be found at all return 0
|
* found in the handbook. If the price can't be found at all return 0
|
||||||
|
@ -267,8 +267,8 @@ export class QuestHelper
|
|||||||
const mods: Item[] = [];
|
const mods: Item[] = [];
|
||||||
const rootItem = questReward.items[0];
|
const rootItem = questReward.items[0];
|
||||||
|
|
||||||
// Is armor item that needs inserts / plates
|
// Is armor item that may need inserts / plates
|
||||||
if (questReward.items.length === 1 && this.itemHelper.itemCanRequireArmorInserts(rootItem._tpl))
|
if (questReward.items.length === 1 && this.itemHelper.armorItemCanHoldMods(rootItem._tpl))
|
||||||
{
|
{
|
||||||
// Attempt to pull default preset from globals and add child items to reward
|
// Attempt to pull default preset from globals and add child items to reward
|
||||||
this.generateArmorRewardChildSlots(rootItem, questReward);
|
this.generateArmorRewardChildSlots(rootItem, questReward);
|
||||||
|
@ -403,7 +403,7 @@ export class FenceService
|
|||||||
protected createAssorts(assortCount: number, assorts: ITraderAssort, loyaltyLevel: number): void
|
protected createAssorts(assortCount: number, assorts: ITraderAssort, loyaltyLevel: number): void
|
||||||
{
|
{
|
||||||
const fenceAssort = this.databaseServer.getTables().traders[Traders.FENCE].assort;
|
const fenceAssort = this.databaseServer.getTables().traders[Traders.FENCE].assort;
|
||||||
const defaultWeaponPresets = this.presetHelper.getDefaultPresets();
|
const defaultPresets = this.presetHelper.getDefaultPresets();
|
||||||
const fenceAssortIds = Object.keys(fenceAssort.loyal_level_items);
|
const fenceAssortIds = Object.keys(fenceAssort.loyal_level_items);
|
||||||
const itemTypeCounts = this.initItemLimitCounter(this.traderConfig.fence.itemTypeLimits);
|
const itemTypeCounts = this.initItemLimitCounter(this.traderConfig.fence.itemTypeLimits);
|
||||||
|
|
||||||
@ -412,7 +412,7 @@ export class FenceService
|
|||||||
// Add presets
|
// Add presets
|
||||||
const maxPresetCount = Math.round(assortCount * (this.traderConfig.fence.maxPresetsPercent / 100));
|
const maxPresetCount = Math.round(assortCount * (this.traderConfig.fence.maxPresetsPercent / 100));
|
||||||
const randomisedPresetCount = this.randomUtil.getInt(0, maxPresetCount);
|
const randomisedPresetCount = this.randomUtil.getInt(0, maxPresetCount);
|
||||||
this.addPresets(randomisedPresetCount, defaultWeaponPresets, assorts, loyaltyLevel);
|
this.addPresets(randomisedPresetCount, defaultPresets, assorts, loyaltyLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected addItemAssorts(
|
protected addItemAssorts(
|
||||||
@ -481,7 +481,7 @@ export class FenceService
|
|||||||
rootItemToPush.upd.UnlimitedCount = false;
|
rootItemToPush.upd.UnlimitedCount = false;
|
||||||
|
|
||||||
// Need to add mods to armors so they dont show as red in the trade screen
|
// Need to add mods to armors so they dont show as red in the trade screen
|
||||||
if (this.itemHelper.itemCanRequireArmorInserts(rootItemToPush._tpl))
|
if (this.itemHelper.itemRequiresSoftInserts(rootItemToPush._tpl))
|
||||||
{
|
{
|
||||||
this.addModsToArmorModSlots(itemsToPush, itemDbDetails);
|
this.addModsToArmorModSlots(itemsToPush, itemDbDetails);
|
||||||
}
|
}
|
||||||
@ -594,25 +594,25 @@ export class FenceService
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add preset weapons to fence presets
|
* Add weapon/armor presets to fence
|
||||||
* @param assortCount how many assorts to add to assorts
|
* @param assortCount how many assorts to add to assorts
|
||||||
* @param defaultWeaponPresets a dictionary of default weapon presets
|
* @param defaultPresets a dictionary of default weapon presets
|
||||||
* @param assorts object to add presets to
|
* @param assorts object to add presets to
|
||||||
* @param loyaltyLevel loyalty level to requre item at
|
* @param loyaltyLevel loyalty level to requre item at
|
||||||
*/
|
*/
|
||||||
protected addPresets(
|
protected addPresets(
|
||||||
desiredPresetCount: number,
|
desiredPresetCount: number,
|
||||||
defaultWeaponPresets: Record<string, IPreset>,
|
defaultPresets: Record<string, IPreset>,
|
||||||
assorts: ITraderAssort,
|
assorts: ITraderAssort,
|
||||||
loyaltyLevel: number,
|
loyaltyLevel: number,
|
||||||
): void
|
): void
|
||||||
{
|
{
|
||||||
let presetCount = 0;
|
let presetCount = 0;
|
||||||
const presetKeys = Object.keys(defaultWeaponPresets);
|
const presetKeys = Object.keys(defaultPresets);
|
||||||
for (let index = 0; index < desiredPresetCount; index++)
|
for (let index = 0; index < desiredPresetCount; index++)
|
||||||
{
|
{
|
||||||
const presetId = presetKeys[this.randomUtil.getInt(0, presetKeys.length - 1)];
|
const presetId = presetKeys[this.randomUtil.getInt(0, presetKeys.length - 1)];
|
||||||
const preset = defaultWeaponPresets[presetId];
|
const preset = defaultPresets[presetId];
|
||||||
|
|
||||||
// Check we're under preset limit
|
// Check we're under preset limit
|
||||||
if (presetCount > desiredPresetCount)
|
if (presetCount > desiredPresetCount)
|
||||||
@ -626,12 +626,12 @@ export class FenceService
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct weapon + mods
|
// Construct preset + mods
|
||||||
const weaponAndMods: Item[] = this.itemHelper.replaceIDs(
|
const weaponAndMods: Item[] = this.itemHelper.replaceIDs(
|
||||||
null,
|
null,
|
||||||
this.jsonUtil.clone(defaultWeaponPresets[preset._id]._items),
|
this.jsonUtil.clone(defaultPresets[preset._id]._items),
|
||||||
);
|
);
|
||||||
this.removeRandomPartsOfWeapon(weaponAndMods);
|
this.removeRandomModsOfItem(weaponAndMods);
|
||||||
for (let i = 0; i < weaponAndMods.length; i++)
|
for (let i = 0; i < weaponAndMods.length; i++)
|
||||||
{
|
{
|
||||||
const mod = weaponAndMods[i];
|
const mod = weaponAndMods[i];
|
||||||
@ -676,42 +676,48 @@ export class FenceService
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove parts of a weapon prior to being listed on flea
|
* Remove parts of a weapon prior to being listed on flea
|
||||||
* @param weaponAndMods Weapon to remove parts from
|
* @param itemAndMods Weapon to remove parts from
|
||||||
*/
|
*/
|
||||||
protected removeRandomPartsOfWeapon(weaponAndMods: Item[]): void
|
protected removeRandomModsOfItem(itemAndMods: Item[]): void
|
||||||
{
|
{
|
||||||
// Items to be removed from inventory
|
// Items to be removed from inventory
|
||||||
const toDelete: string[] = [];
|
const toDelete: string[] = [];
|
||||||
|
|
||||||
// Loop over insurance items, find items to delete from player inventory
|
// Find mods to remove from item that could've been scavenged by other players in-raid
|
||||||
for (const weaponMod of weaponAndMods)
|
for (const itemMod of itemAndMods)
|
||||||
{
|
{
|
||||||
if (this.presetModItemWillBeRemoved(weaponMod, toDelete))
|
if (this.presetModItemWillBeRemoved(itemMod, toDelete))
|
||||||
{
|
{
|
||||||
// Skip if not an item
|
// Skip if not an item
|
||||||
const itemDbDetails = this.itemHelper.getItem(weaponMod._tpl);
|
const itemDbDetails = this.itemHelper.getItem(itemMod._tpl);
|
||||||
if (!itemDbDetails[0])
|
if (!itemDbDetails[0])
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is a mod and can't be edited in-raid
|
// Is a mod and can't be edited in-raid
|
||||||
if (weaponMod.slotId !== "hideout" && !itemDbDetails[1]._props.RaidModdable)
|
if (itemMod.slotId !== "hideout" && !itemDbDetails[1]._props.RaidModdable)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const slotDetails = itemDbDetails[1]._props.Slots.find(slot => slot._name === itemMod.slotId);
|
||||||
|
if (slotDetails?._required)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove item and its sub-items to prevent orphans
|
// Remove item and its sub-items to prevent orphans
|
||||||
toDelete.push(...this.itemHelper.findAndReturnChildrenByItems(weaponAndMods, weaponMod._id));
|
toDelete.push(...this.itemHelper.findAndReturnChildrenByItems(itemAndMods, itemMod._id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reverse loop and remove items
|
// Reverse loop and remove items
|
||||||
for (let index = weaponAndMods.length - 1; index >= 0; --index)
|
for (let index = itemAndMods.length - 1; index >= 0; --index)
|
||||||
{
|
{
|
||||||
if (toDelete.includes(weaponAndMods[index]._id))
|
if (toDelete.includes(itemAndMods[index]._id))
|
||||||
{
|
{
|
||||||
weaponAndMods.splice(index, 1);
|
itemAndMods.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -302,7 +302,7 @@ export class InsuranceService
|
|||||||
|
|
||||||
if (itemClientInsuranceData || itemIsSoftInsert)
|
if (itemClientInsuranceData || itemIsSoftInsert)
|
||||||
{
|
{
|
||||||
// Get baseline item to return, clone pre raid item
|
// Get baseline item to return, clone pre-raid item
|
||||||
const itemToReturn: Item = this.jsonUtil.clone(preRaidItem);
|
const itemToReturn: Item = this.jsonUtil.clone(preRaidItem);
|
||||||
|
|
||||||
// Add upd if it doesnt exist
|
// Add upd if it doesnt exist
|
||||||
@ -311,7 +311,7 @@ export class InsuranceService
|
|||||||
itemToReturn.upd = {};
|
itemToReturn.upd = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for slotid values that need to be updated and adjust
|
// Check for slotId values that need to be updated and adjust
|
||||||
this.updateSlotIdValue(pmcData.Inventory.equipment, itemToReturn);
|
this.updateSlotIdValue(pmcData.Inventory.equipment, itemToReturn);
|
||||||
|
|
||||||
// Remove location property
|
// Remove location property
|
||||||
|
Loading…
Reference in New Issue
Block a user