Persist durability changes + faceshield hit values incurred during a raid (!110)
Fixes insured items comin back full durability Co-authored-by: CWX <CWX@noreply.dev.sp-tarkov.com> Co-authored-by: Dev <dev@dev.sp-tarkov.com> Reviewed-on: https://dev.sp-tarkov.com/SPT-AKI/Server/pulls/110
This commit is contained in:
parent
9dd2d3cd04
commit
a962823192
@ -341,6 +341,7 @@ export interface BackendCounter
|
||||
|
||||
export interface InsuredItem
|
||||
{
|
||||
/** Trader Id item was insured by */
|
||||
tid: string
|
||||
itemId: string
|
||||
}
|
||||
|
7
project/src/models/eft/inRaid/IInsuredItemsData.ts
Normal file
7
project/src/models/eft/inRaid/IInsuredItemsData.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export interface IInsuredItemsData
|
||||
{
|
||||
id: string
|
||||
durability?: number
|
||||
maxDurability?: number
|
||||
hits?: number
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
import { PlayerRaidEndState } from "../../../models/enums/PlayerRaidEndState";
|
||||
import { IPmcData } from "../common/IPmcData";
|
||||
import { ISyncHealthRequestData } from "../health/ISyncHealthRequestData";
|
||||
import { IInsuredItemsData } from "./IInsuredItemsData";
|
||||
|
||||
export interface ISaveProgressRequestData
|
||||
{
|
||||
@ -8,4 +9,5 @@ export interface ISaveProgressRequestData
|
||||
profile: IPmcData
|
||||
isPlayerScav: boolean
|
||||
health: ISyncHealthRequestData
|
||||
insurance: IInsuredItemsData[]
|
||||
}
|
@ -8,8 +8,8 @@ import { NotificationSendHelper } from "../helpers/NotificationSendHelper";
|
||||
import { SecureContainerHelper } from "../helpers/SecureContainerHelper";
|
||||
import { TraderHelper } from "../helpers/TraderHelper";
|
||||
import { IPmcData } from "../models/eft/common/IPmcData";
|
||||
import { InsuredItem } from "../models/eft/common/tables/IBotBase";
|
||||
import { Item } from "../models/eft/common/tables/IItem";
|
||||
import { IInsuredItemsData } from "../models/eft/inRaid/IInsuredItemsData";
|
||||
import { ISaveProgressRequestData } from "../models/eft/inRaid/ISaveProgressRequestData";
|
||||
import { IUserDialogInfo } from "../models/eft/profile/IAkiProfile";
|
||||
import { ConfigTypes } from "../models/enums/ConfigTypes";
|
||||
@ -21,6 +21,7 @@ import { ILogger } from "../models/spt/utils/ILogger";
|
||||
import { ConfigServer } from "../servers/ConfigServer";
|
||||
import { DatabaseServer } from "../servers/DatabaseServer";
|
||||
import { SaveServer } from "../servers/SaveServer";
|
||||
import { JsonUtil } from "../utils/JsonUtil";
|
||||
import { RandomUtil } from "../utils/RandomUtil";
|
||||
import { TimeUtil } from "../utils/TimeUtil";
|
||||
import { LocaleService } from "./LocaleService";
|
||||
@ -38,6 +39,7 @@ export class InsuranceService
|
||||
@inject("SecureContainerHelper") protected secureContainerHelper: SecureContainerHelper,
|
||||
@inject("RandomUtil") protected randomUtil: RandomUtil,
|
||||
@inject("ItemHelper") protected itemHelper: ItemHelper,
|
||||
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||
@inject("TimeUtil") protected timeUtil: TimeUtil,
|
||||
@inject("SaveServer") protected saveServer: SaveServer,
|
||||
@inject("TraderHelper") protected traderHelper: TraderHelper,
|
||||
@ -52,6 +54,11 @@ export class InsuranceService
|
||||
this.insuranceConfig = this.configServer.getConfig(ConfigTypes.INSURANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does player have insurance array
|
||||
* @param sessionId Player id
|
||||
* @returns True if exists
|
||||
*/
|
||||
public insuranceExists(sessionId: string): boolean
|
||||
{
|
||||
return this.insured[sessionId] !== undefined;
|
||||
@ -203,7 +210,7 @@ export class InsuranceService
|
||||
}
|
||||
|
||||
/**
|
||||
* Store lost gear post-raid inside profile
|
||||
* Store lost gear post-raid inside profile, ready for later code to pick it up and mail it
|
||||
* @param pmcData player profile to store gear in
|
||||
* @param offraidData post-raid request object
|
||||
* @param preRaidGear gear player wore prior to raid
|
||||
@ -218,27 +225,136 @@ export class InsuranceService
|
||||
const equipmentToSendToPlayer = [];
|
||||
for (const insuredItem of pmcData.InsuredItems)
|
||||
{
|
||||
// Check insured item was on player during raid
|
||||
if (preRaidGearHash[insuredItem.itemId])
|
||||
// Skip insured items not on player when they started raid
|
||||
const preRaidItem = preRaidGearHash[insuredItem.itemId];
|
||||
if (!preRaidItem)
|
||||
{
|
||||
// This item exists in preRaidGear, meaning we brought it into the raid
|
||||
// Check if item missing OR player died with item on
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip items we should never return
|
||||
if (this.insuranceConfig.blacklistedEquipment.includes(preRaidItem.slotId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if item missing in post-raid gear OR player died
|
||||
// Catches both events: player died with item on + player survied but dropped item in raid
|
||||
if (!offRaidGearHash[insuredItem.itemId] || playerDied)
|
||||
{
|
||||
equipmentToSendToPlayer.push({
|
||||
"pmcData": pmcData,
|
||||
"insuredItem": insuredItem,
|
||||
"item": preRaidGearHash[insuredItem.itemId],
|
||||
"sessionID": sessionID
|
||||
pmcData: pmcData,
|
||||
itemToReturnToPlayer: this.getInsuredItemDetails(pmcData, preRaidItem, offraidData.insurance.find(x => x.id === insuredItem.itemId)),
|
||||
traderId: insuredItem.tid,
|
||||
sessionID: sessionID
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process all insured items lost in-raid
|
||||
for (const gear of equipmentToSendToPlayer)
|
||||
{
|
||||
this.addGearToSend(gear.pmcData, gear.insuredItem, gear.item, gear.sessionID);
|
||||
this.addGearToSend(gear);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Take preraid item and update properties to ensure its ready to be given to player in insurance return mail
|
||||
* @param pmcData Player profile
|
||||
* @param insuredItem Insured items properties
|
||||
* @param preRaidItem Insured item as it was pre-raid
|
||||
* @param insuredItemFromClient Item data when player left raid (durability values)
|
||||
* @returns Item object
|
||||
*/
|
||||
protected getInsuredItemDetails(pmcData: IPmcData, preRaidItem: Item, insuredItemFromClient: IInsuredItemsData): Item
|
||||
{
|
||||
// Get baseline item to return, clone pre raid item
|
||||
const itemToReturn: Item = this.jsonUtil.clone(preRaidItem);
|
||||
|
||||
// Add upd if it doesnt exist
|
||||
if (!itemToReturn.upd)
|
||||
{
|
||||
itemToReturn.upd = {};
|
||||
}
|
||||
|
||||
// Check for slotid values that need to be updated and adjust
|
||||
this.updateSlotIdValue(pmcData.Inventory.equipment, itemToReturn);
|
||||
|
||||
// Remove location property
|
||||
if (itemToReturn.slotId === "hideout" && "location" in itemToReturn)
|
||||
{
|
||||
delete itemToReturn.location;
|
||||
}
|
||||
|
||||
// Remove found in raid status when upd exists + SpawnedInSession value exists
|
||||
if ("upd" in itemToReturn && "SpawnedInSession" in itemToReturn.upd)
|
||||
{
|
||||
itemToReturn.upd.SpawnedInSession = false;
|
||||
}
|
||||
|
||||
// Client item has durability values, Ensure values persist into server data
|
||||
if (insuredItemFromClient.durability)
|
||||
{
|
||||
// Item didnt have Repairable object pre-raid, add it
|
||||
if (!itemToReturn.upd.Repairable)
|
||||
{
|
||||
itemToReturn.upd.Repairable = {
|
||||
Durability: insuredItemFromClient.durability,
|
||||
MaxDurability: insuredItemFromClient.maxDurability
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
itemToReturn.upd.Repairable.Durability = insuredItemFromClient.durability;
|
||||
itemToReturn.upd.Repairable.MaxDurability = insuredItemFromClient.maxDurability;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Client item has FaceShield values, Ensure values persist into server data
|
||||
if (insuredItemFromClient?.hits)
|
||||
{
|
||||
// Item didnt have faceshield object pre-raid, add it
|
||||
if (!itemToReturn.upd.FaceShield)
|
||||
{
|
||||
itemToReturn.upd.FaceShield = {
|
||||
Hits: insuredItemFromClient.hits
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
itemToReturn.upd.FaceShield.Hits = insuredItemFromClient.hits;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return itemToReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset slotId property to "hideout" when necessary (used to be in )
|
||||
* @param pmcData Players pmcData.Inventory.equipment value
|
||||
* @param itemToReturn item we will send to player as insurance return
|
||||
*/
|
||||
protected updateSlotIdValue(playerBaseInventoryEquipmentId: string, itemToReturn: Item): void
|
||||
{
|
||||
const pocketSlots = [
|
||||
"pocket1",
|
||||
"pocket2",
|
||||
"pocket3",
|
||||
"pocket4"
|
||||
];
|
||||
|
||||
// Some pockets can lose items with player death, some don't
|
||||
if (!("slotId" in itemToReturn) || pocketSlots.includes(itemToReturn.slotId))
|
||||
{
|
||||
itemToReturn.slotId = "hideout";
|
||||
}
|
||||
|
||||
// Mark root-level items for later processing
|
||||
if (itemToReturn.parentId === playerBaseInventoryEquipmentId)
|
||||
{
|
||||
itemToReturn.slotId = "hideout";
|
||||
}
|
||||
}
|
||||
|
||||
@ -260,67 +376,36 @@ export class InsuranceService
|
||||
|
||||
/**
|
||||
* Add gear item to InsuredItems array in player profile
|
||||
* @param pmcData profile to store item in
|
||||
* @param insuredItem Item to store in profile
|
||||
* @param actualItem item to store
|
||||
* @param sessionID Session id
|
||||
* @param pmcData Player profile
|
||||
* @param itemToReturnToPlayer item to store
|
||||
* @param traderId Id of trader item was insured with
|
||||
*/
|
||||
protected addGearToSend(pmcData: IPmcData, insuredItem: InsuredItem, actualItem: Item, sessionID: string): void
|
||||
protected addGearToSend(gear: { sessionID: string; pmcData: IPmcData; itemToReturnToPlayer: Item; traderId: string}): void
|
||||
{
|
||||
// Skip items defined in config
|
||||
if (this.insuranceConfig.blacklistedEquipment.includes(actualItem.slotId))
|
||||
const sessionId = gear.sessionID;
|
||||
const pmcData = gear.pmcData;
|
||||
const itemToReturnToPlayer = gear.itemToReturnToPlayer;
|
||||
const traderId = gear.traderId;
|
||||
|
||||
// Ensure insurance array is init
|
||||
if (!this.insuranceExists(sessionId))
|
||||
{
|
||||
return;
|
||||
this.resetInsurance(sessionId);
|
||||
}
|
||||
|
||||
const pocketSlots = [
|
||||
"pocket1",
|
||||
"pocket2",
|
||||
"pocket3",
|
||||
"pocket4"
|
||||
];
|
||||
|
||||
// Check and correct the validity of the slotId
|
||||
if (!("slotId" in actualItem) || pocketSlots.includes(actualItem.slotId))
|
||||
// init trader insurance array
|
||||
if (!this.insuranceTraderArrayExists(sessionId, traderId))
|
||||
{
|
||||
actualItem.slotId = "hideout";
|
||||
this.resetInsuranceTraderArray(sessionId, traderId);
|
||||
}
|
||||
|
||||
// Mark root-level items for later
|
||||
if (actualItem.parentId === pmcData.Inventory.equipment)
|
||||
{
|
||||
actualItem.slotId = "hideout";
|
||||
}
|
||||
this.addInsuranceItemToArray(sessionId, traderId, itemToReturnToPlayer);
|
||||
|
||||
// Clear the location attribute of the item in the container.
|
||||
if (actualItem.slotId === "hideout" && "location" in actualItem)
|
||||
{
|
||||
delete actualItem.location;
|
||||
}
|
||||
|
||||
// Remove found in raid status
|
||||
if ("upd" in actualItem && "SpawnedInSession" in actualItem.upd)
|
||||
{
|
||||
actualItem.upd.SpawnedInSession = false;
|
||||
}
|
||||
|
||||
// Mark to add to insurance
|
||||
if (!this.insuranceExists(sessionID))
|
||||
{
|
||||
this.resetInsurance(sessionID);
|
||||
}
|
||||
|
||||
if (!this.insuranceTraderArrayExists(sessionID, insuredItem.tid))
|
||||
{
|
||||
this.resetInsuranceTraderArray(sessionID, insuredItem.tid);
|
||||
}
|
||||
|
||||
this.addInsuranceItemToArray(sessionID, insuredItem.tid, actualItem);
|
||||
|
||||
// Remove processed item from array
|
||||
// Remove item from insured items array as its been processed
|
||||
pmcData.InsuredItems = pmcData.InsuredItems.filter((item) =>
|
||||
{
|
||||
return item.itemId !== insuredItem.itemId;
|
||||
return item.itemId !== itemToReturnToPlayer._id;
|
||||
});
|
||||
}
|
||||
|
||||
@ -353,6 +438,7 @@ export class InsuranceService
|
||||
*/
|
||||
public addInsuranceItemToArray(sessionId: string, traderId: string, itemToAdd: Item): void
|
||||
{
|
||||
|
||||
this.insured[sessionId][traderId].push(itemToAdd);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user