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
|
export interface InsuredItem
|
||||||
{
|
{
|
||||||
|
/** Trader Id item was insured by */
|
||||||
tid: string
|
tid: string
|
||||||
itemId: 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 { PlayerRaidEndState } from "../../../models/enums/PlayerRaidEndState";
|
||||||
import { IPmcData } from "../common/IPmcData";
|
import { IPmcData } from "../common/IPmcData";
|
||||||
import { ISyncHealthRequestData } from "../health/ISyncHealthRequestData";
|
import { ISyncHealthRequestData } from "../health/ISyncHealthRequestData";
|
||||||
|
import { IInsuredItemsData } from "./IInsuredItemsData";
|
||||||
|
|
||||||
export interface ISaveProgressRequestData
|
export interface ISaveProgressRequestData
|
||||||
{
|
{
|
||||||
@ -8,4 +9,5 @@ export interface ISaveProgressRequestData
|
|||||||
profile: IPmcData
|
profile: IPmcData
|
||||||
isPlayerScav: boolean
|
isPlayerScav: boolean
|
||||||
health: ISyncHealthRequestData
|
health: ISyncHealthRequestData
|
||||||
|
insurance: IInsuredItemsData[]
|
||||||
}
|
}
|
@ -8,8 +8,8 @@ import { NotificationSendHelper } from "../helpers/NotificationSendHelper";
|
|||||||
import { SecureContainerHelper } from "../helpers/SecureContainerHelper";
|
import { SecureContainerHelper } from "../helpers/SecureContainerHelper";
|
||||||
import { TraderHelper } from "../helpers/TraderHelper";
|
import { TraderHelper } from "../helpers/TraderHelper";
|
||||||
import { IPmcData } from "../models/eft/common/IPmcData";
|
import { IPmcData } from "../models/eft/common/IPmcData";
|
||||||
import { InsuredItem } from "../models/eft/common/tables/IBotBase";
|
|
||||||
import { Item } from "../models/eft/common/tables/IItem";
|
import { Item } from "../models/eft/common/tables/IItem";
|
||||||
|
import { IInsuredItemsData } from "../models/eft/inRaid/IInsuredItemsData";
|
||||||
import { ISaveProgressRequestData } from "../models/eft/inRaid/ISaveProgressRequestData";
|
import { ISaveProgressRequestData } from "../models/eft/inRaid/ISaveProgressRequestData";
|
||||||
import { IUserDialogInfo } from "../models/eft/profile/IAkiProfile";
|
import { IUserDialogInfo } from "../models/eft/profile/IAkiProfile";
|
||||||
import { ConfigTypes } from "../models/enums/ConfigTypes";
|
import { ConfigTypes } from "../models/enums/ConfigTypes";
|
||||||
@ -21,6 +21,7 @@ import { ILogger } from "../models/spt/utils/ILogger";
|
|||||||
import { ConfigServer } from "../servers/ConfigServer";
|
import { ConfigServer } from "../servers/ConfigServer";
|
||||||
import { DatabaseServer } from "../servers/DatabaseServer";
|
import { DatabaseServer } from "../servers/DatabaseServer";
|
||||||
import { SaveServer } from "../servers/SaveServer";
|
import { SaveServer } from "../servers/SaveServer";
|
||||||
|
import { JsonUtil } from "../utils/JsonUtil";
|
||||||
import { RandomUtil } from "../utils/RandomUtil";
|
import { RandomUtil } from "../utils/RandomUtil";
|
||||||
import { TimeUtil } from "../utils/TimeUtil";
|
import { TimeUtil } from "../utils/TimeUtil";
|
||||||
import { LocaleService } from "./LocaleService";
|
import { LocaleService } from "./LocaleService";
|
||||||
@ -38,6 +39,7 @@ export class InsuranceService
|
|||||||
@inject("SecureContainerHelper") protected secureContainerHelper: SecureContainerHelper,
|
@inject("SecureContainerHelper") protected secureContainerHelper: SecureContainerHelper,
|
||||||
@inject("RandomUtil") protected randomUtil: RandomUtil,
|
@inject("RandomUtil") protected randomUtil: RandomUtil,
|
||||||
@inject("ItemHelper") protected itemHelper: ItemHelper,
|
@inject("ItemHelper") protected itemHelper: ItemHelper,
|
||||||
|
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||||
@inject("TimeUtil") protected timeUtil: TimeUtil,
|
@inject("TimeUtil") protected timeUtil: TimeUtil,
|
||||||
@inject("SaveServer") protected saveServer: SaveServer,
|
@inject("SaveServer") protected saveServer: SaveServer,
|
||||||
@inject("TraderHelper") protected traderHelper: TraderHelper,
|
@inject("TraderHelper") protected traderHelper: TraderHelper,
|
||||||
@ -52,6 +54,11 @@ export class InsuranceService
|
|||||||
this.insuranceConfig = this.configServer.getConfig(ConfigTypes.INSURANCE);
|
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
|
public insuranceExists(sessionId: string): boolean
|
||||||
{
|
{
|
||||||
return this.insured[sessionId] !== undefined;
|
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 pmcData player profile to store gear in
|
||||||
* @param offraidData post-raid request object
|
* @param offraidData post-raid request object
|
||||||
* @param preRaidGear gear player wore prior to raid
|
* @param preRaidGear gear player wore prior to raid
|
||||||
@ -218,27 +225,136 @@ export class InsuranceService
|
|||||||
const equipmentToSendToPlayer = [];
|
const equipmentToSendToPlayer = [];
|
||||||
for (const insuredItem of pmcData.InsuredItems)
|
for (const insuredItem of pmcData.InsuredItems)
|
||||||
{
|
{
|
||||||
// Check insured item was on player during raid
|
// Skip insured items not on player when they started raid
|
||||||
if (preRaidGearHash[insuredItem.itemId])
|
const preRaidItem = preRaidGearHash[insuredItem.itemId];
|
||||||
|
if (!preRaidItem)
|
||||||
{
|
{
|
||||||
// This item exists in preRaidGear, meaning we brought it into the raid
|
continue;
|
||||||
// Check if item missing OR player died with item on
|
}
|
||||||
if (!offRaidGearHash[insuredItem.itemId] || playerDied)
|
|
||||||
{
|
// Skip items we should never return
|
||||||
equipmentToSendToPlayer.push({
|
if (this.insuranceConfig.blacklistedEquipment.includes(preRaidItem.slotId))
|
||||||
"pmcData": pmcData,
|
{
|
||||||
"insuredItem": insuredItem,
|
continue;
|
||||||
"item": preRaidGearHash[insuredItem.itemId],
|
}
|
||||||
"sessionID": sessionID
|
|
||||||
});
|
// 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,
|
||||||
|
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
|
// Process all insured items lost in-raid
|
||||||
for (const gear of equipmentToSendToPlayer)
|
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
|
* 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 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
|
const sessionId = gear.sessionID;
|
||||||
if (this.insuranceConfig.blacklistedEquipment.includes(actualItem.slotId))
|
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 = [
|
// init trader insurance array
|
||||||
"pocket1",
|
if (!this.insuranceTraderArrayExists(sessionId, traderId))
|
||||||
"pocket2",
|
|
||||||
"pocket3",
|
|
||||||
"pocket4"
|
|
||||||
];
|
|
||||||
|
|
||||||
// Check and correct the validity of the slotId
|
|
||||||
if (!("slotId" in actualItem) || pocketSlots.includes(actualItem.slotId))
|
|
||||||
{
|
{
|
||||||
actualItem.slotId = "hideout";
|
this.resetInsuranceTraderArray(sessionId, traderId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark root-level items for later
|
this.addInsuranceItemToArray(sessionId, traderId, itemToReturnToPlayer);
|
||||||
if (actualItem.parentId === pmcData.Inventory.equipment)
|
|
||||||
{
|
|
||||||
actualItem.slotId = "hideout";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear the location attribute of the item in the container.
|
// Remove item from insured items array as its been processed
|
||||||
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
|
|
||||||
pmcData.InsuredItems = pmcData.InsuredItems.filter((item) =>
|
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
|
public addInsuranceItemToArray(sessionId: string, traderId: string, itemToAdd: Item): void
|
||||||
{
|
{
|
||||||
|
|
||||||
this.insured[sessionId][traderId].push(itemToAdd);
|
this.insured[sessionId][traderId].push(itemToAdd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user