Rework of post-raid scav/pmc profile handling:
Moved logic out of `updateProfileBaseStats()` and into separate functions for pmc/scav, left profile-agnostic code alone new functions `updatePmcProfileDataPostRaid` and `updateScavProfileDataPostRaid` scav - Only copy active quest progress from client profile to server scav profile scav - dont attempt to update trader standings, none exist on scav profile scav - dont transfer psot-raid limb damage to server profile Update quest status values similarly to PMC quests post raid to ensure they're consistent with existing quest data in profile Simplifies `migrateScavQuestProgressToPmcProfile` made various warnings debug instead
This commit is contained in:
parent
d2209114c9
commit
ddb9917c6b
@ -107,19 +107,20 @@ export class InraidController
|
||||
*/
|
||||
protected savePmcProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void
|
||||
{
|
||||
const serverProfile = this.saveServer.getProfile(sessionID);
|
||||
const locationName = serverProfile.inraid.location.toLowerCase();
|
||||
const serveProfile = this.saveServer.getProfile(sessionID);
|
||||
const locationName = serveProfile.inraid.location.toLowerCase();
|
||||
|
||||
const map: ILocationBase = this.databaseServer.getTables().locations[locationName].base;
|
||||
const mapHasInsuranceEnabled = map.Insurance;
|
||||
|
||||
let serverPmcData = serverProfile.characters.pmc;
|
||||
let serverPmcProfile = serveProfile.characters.pmc;
|
||||
const isDead = this.isPlayerDead(postRaidRequest.exit);
|
||||
const preRaidGear = this.inRaidHelper.getPlayerGear(serverPmcData.Inventory.items);
|
||||
const preRaidGear = this.inRaidHelper.getPlayerGear(serverPmcProfile.Inventory.items);
|
||||
|
||||
serverProfile.inraid.character = "pmc";
|
||||
serveProfile.inraid.character = "pmc";
|
||||
|
||||
serverPmcData = this.inRaidHelper.updateProfileBaseStats(serverPmcData, postRaidRequest, sessionID);
|
||||
this.inRaidHelper.updateProfileBaseStats(serverPmcProfile, postRaidRequest, sessionID);
|
||||
this.inRaidHelper.updatePmcProfileDataPostRaid(serverPmcProfile, postRaidRequest, sessionID);
|
||||
|
||||
// Check for exit status
|
||||
this.markOrRemoveFoundInRaidItems(postRaidRequest);
|
||||
@ -127,20 +128,20 @@ export class InraidController
|
||||
postRaidRequest.profile.Inventory.items = this.itemHelper.replaceIDs(
|
||||
postRaidRequest.profile,
|
||||
postRaidRequest.profile.Inventory.items,
|
||||
serverPmcData.InsuredItems,
|
||||
serverPmcProfile.InsuredItems,
|
||||
postRaidRequest.profile.Inventory.fastPanel,
|
||||
);
|
||||
this.inRaidHelper.addUpdToMoneyFromRaid(postRaidRequest.profile.Inventory.items);
|
||||
|
||||
// Purge profile of equipment/container items
|
||||
serverPmcData = this.inRaidHelper.setInventory(sessionID, serverPmcData, postRaidRequest.profile);
|
||||
serverPmcProfile = this.inRaidHelper.setInventory(sessionID, serverPmcProfile, postRaidRequest.profile);
|
||||
|
||||
this.healthHelper.saveVitality(serverPmcData, postRaidRequest.health, sessionID);
|
||||
this.healthHelper.saveVitality(serverPmcProfile, postRaidRequest.health, sessionID);
|
||||
|
||||
// Remove inventory if player died and send insurance items
|
||||
if (mapHasInsuranceEnabled)
|
||||
{
|
||||
this.insuranceService.storeLostGear(serverPmcData, postRaidRequest, preRaidGear, sessionID, isDead);
|
||||
this.insuranceService.storeLostGear(serverPmcProfile, postRaidRequest, preRaidGear, sessionID, isDead);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -151,7 +152,7 @@ export class InraidController
|
||||
if (locationName === "lighthouse" && postRaidRequest.profile.Info.Side.toLowerCase() === "usec")
|
||||
{
|
||||
// Decrement counter if it exists, don't go below 0
|
||||
const remainingCounter = serverPmcData?.Stats.Eft.OverallCounters.Items.find((x) =>
|
||||
const remainingCounter = serverPmcProfile?.Stats.Eft.OverallCounters.Items.find((x) =>
|
||||
x.Key.includes("UsecRaidRemainKills")
|
||||
);
|
||||
if (remainingCounter?.Value > 0)
|
||||
@ -164,12 +165,12 @@ export class InraidController
|
||||
{
|
||||
this.pmcChatResponseService.sendKillerResponse(
|
||||
sessionID,
|
||||
serverPmcData,
|
||||
serverPmcProfile,
|
||||
postRaidRequest.profile.Stats.Eft.Aggressor,
|
||||
);
|
||||
this.matchBotDetailsCacheService.clearCache();
|
||||
|
||||
serverPmcData = this.performPostRaidActionsWhenDead(postRaidRequest, serverPmcData, sessionID);
|
||||
serverPmcProfile = this.performPostRaidActionsWhenDead(postRaidRequest, serverPmcProfile, sessionID);
|
||||
}
|
||||
|
||||
const victims = postRaidRequest.profile.Stats.Eft.Victims.filter((x) =>
|
||||
@ -177,12 +178,12 @@ export class InraidController
|
||||
);
|
||||
if (victims?.length > 0)
|
||||
{
|
||||
this.pmcChatResponseService.sendVictimResponse(sessionID, victims, serverPmcData);
|
||||
this.pmcChatResponseService.sendVictimResponse(sessionID, victims, serverPmcProfile);
|
||||
}
|
||||
|
||||
if (mapHasInsuranceEnabled)
|
||||
{
|
||||
this.insuranceService.sendInsuredItems(serverPmcData, sessionID, map.Id);
|
||||
this.insuranceService.sendInsuredItems(serverPmcProfile, sessionID, map.Id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -274,39 +275,43 @@ export class InraidController
|
||||
*/
|
||||
protected savePlayerScavProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void
|
||||
{
|
||||
const pmcData = this.profileHelper.getPmcProfile(sessionID);
|
||||
let scavData = this.profileHelper.getScavProfile(sessionID);
|
||||
const serverPmcProfile = this.profileHelper.getPmcProfile(sessionID);
|
||||
const serverScavProfile = this.profileHelper.getScavProfile(sessionID);
|
||||
const isDead = this.isPlayerDead(postRaidRequest.exit);
|
||||
|
||||
this.saveServer.getProfile(sessionID).inraid.character = "scav";
|
||||
|
||||
scavData = this.inRaidHelper.updateProfileBaseStats(scavData, postRaidRequest, sessionID);
|
||||
this.inRaidHelper.updateProfileBaseStats(serverScavProfile, postRaidRequest, sessionID);
|
||||
this.inRaidHelper.updateScavProfileDataPostRaid(serverScavProfile, postRaidRequest, sessionID);
|
||||
|
||||
// Completing scav quests create ConditionCounters, these values need to be transported to the PMC profile
|
||||
if (this.profileHasConditionCounters(scavData))
|
||||
if (this.profileHasConditionCounters(serverScavProfile))
|
||||
{
|
||||
// Scav quest progress needs to be moved to pmc so player can see it in menu / hand them in
|
||||
this.migrateScavQuestProgressToPmcProfile(scavData, pmcData);
|
||||
this.migrateScavQuestProgressToPmcProfile(serverScavProfile, serverPmcProfile);
|
||||
}
|
||||
|
||||
// Check for exit status
|
||||
// Change loot FiR status based on exit status
|
||||
this.markOrRemoveFoundInRaidItems(postRaidRequest);
|
||||
|
||||
postRaidRequest.profile.Inventory.items = this.itemHelper.replaceIDs(
|
||||
postRaidRequest.profile,
|
||||
postRaidRequest.profile.Inventory.items,
|
||||
pmcData.InsuredItems,
|
||||
serverPmcProfile.InsuredItems,
|
||||
postRaidRequest.profile.Inventory.fastPanel,
|
||||
);
|
||||
|
||||
// Some items from client profile don't have upd objects when they're single stack items
|
||||
this.inRaidHelper.addUpdToMoneyFromRaid(postRaidRequest.profile.Inventory.items);
|
||||
|
||||
this.handlePostRaidPlayerScavProcess(scavData, sessionID, postRaidRequest, pmcData, isDead);
|
||||
// Reset hp/regenerate loot
|
||||
this.handlePostRaidPlayerScavProcess(serverScavProfile, sessionID, postRaidRequest, serverPmcProfile, isDead);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does provided profile contain any condition counters
|
||||
* @param profile Profile to check for condition counters
|
||||
* @returns
|
||||
* @returns Profile has condition counters
|
||||
*/
|
||||
protected profileHasConditionCounters(profile: IPmcData): boolean
|
||||
{
|
||||
@ -318,6 +323,11 @@ export class InraidController
|
||||
return profile.ConditionCounters.Counters.length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scav quest progress isnt transferred automatically from scav to pmc, we do this manually
|
||||
* @param scavProfile Scav profile with quest progress post-raid
|
||||
* @param pmcProfile Server pmc profile to copy scav quest progress into
|
||||
*/
|
||||
protected migrateScavQuestProgressToPmcProfile(scavProfile: IPmcData, pmcProfile: IPmcData): void
|
||||
{
|
||||
for (const quest of scavProfile.Quests)
|
||||
@ -329,17 +339,16 @@ export class InraidController
|
||||
continue;
|
||||
}
|
||||
|
||||
// Post-raid status is enum word e.g. `Started` but pmc quest status is number e.g. 2
|
||||
// Status values mismatch or statusTimers counts mismatch
|
||||
if (
|
||||
quest.status !== <any>QuestStatus[pmcQuest.status]
|
||||
quest.status !== pmcQuest.status
|
||||
|| Object.keys(quest.statusTimers).length !== Object.keys(pmcQuest.statusTimers).length
|
||||
)
|
||||
{
|
||||
this.logger.warning(
|
||||
this.logger.debug(
|
||||
`Quest: ${quest.qid} found in PMC profile has different status/statustimer. Scav: ${quest.status} vs PMC: ${pmcQuest.status}`,
|
||||
);
|
||||
pmcQuest.status = <any>QuestStatus[quest.status];
|
||||
pmcQuest.status = quest.status;
|
||||
|
||||
// Copy status timers over + fix bad enum key for each
|
||||
pmcQuest.statusTimers = quest.statusTimers;
|
||||
@ -357,7 +366,7 @@ export class InraidController
|
||||
// Loop over all scav counters and add into pmc profile
|
||||
for (const scavCounter of scavProfile.ConditionCounters.Counters)
|
||||
{
|
||||
this.logger.warning(
|
||||
this.logger.debug(
|
||||
`Processing counter: ${scavCounter.id} value:${scavCounter.value} quest:${scavCounter.qid}`,
|
||||
);
|
||||
const counterInPmcProfile = pmcProfile.ConditionCounters.Counters.find((x) => x.id === scavCounter.id);
|
||||
@ -369,14 +378,14 @@ export class InraidController
|
||||
continue;
|
||||
}
|
||||
|
||||
this.logger.warning(
|
||||
this.logger.debug(
|
||||
`Counter id: ${scavCounter.id} already exists in pmc profile! with value: ${counterInPmcProfile.value} for quest: ${counterInPmcProfile.qid}`,
|
||||
);
|
||||
|
||||
// Only adjust counter value if its changed
|
||||
if (counterInPmcProfile.value !== scavCounter.value)
|
||||
{
|
||||
this.logger.warning(`OVERWRITING with values: ${scavCounter.value} quest: ${scavCounter.qid}`);
|
||||
this.logger.debug(`OVERWRITING with values: ${scavCounter.value} quest: ${scavCounter.qid}`);
|
||||
counterInPmcProfile.value = scavCounter.value;
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import { SaveServer } from "@spt-aki/servers/SaveServer";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { ProfileFixerService } from "@spt-aki/services/ProfileFixerService";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { ProfileHelper } from "./ProfileHelper";
|
||||
|
||||
@injectable()
|
||||
export class InRaidHelper
|
||||
@ -35,6 +36,7 @@ export class InRaidHelper
|
||||
@inject("ItemHelper") protected itemHelper: ItemHelper,
|
||||
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
||||
@inject("InventoryHelper") protected inventoryHelper: InventoryHelper,
|
||||
@inject("ProfileHelper") protected profileHelper: ProfileHelper,
|
||||
@inject("QuestHelper") protected questHelper: QuestHelper,
|
||||
@inject("PaymentHelper") protected paymentHelper: PaymentHelper,
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@ -62,19 +64,16 @@ export class InRaidHelper
|
||||
*/
|
||||
public addUpdToMoneyFromRaid(items: Item[]): void
|
||||
{
|
||||
for (const item of items)
|
||||
for (const item of items.filter(x => this.paymentHelper.isMoneyTpl(x._tpl)))
|
||||
{
|
||||
if (this.paymentHelper.isMoneyTpl(item._tpl))
|
||||
if (!item.upd)
|
||||
{
|
||||
if (!item.upd)
|
||||
{
|
||||
item.upd = {};
|
||||
}
|
||||
item.upd = {};
|
||||
}
|
||||
|
||||
if (!item.upd.StackObjectsCount)
|
||||
{
|
||||
item.upd.StackObjectsCount = 1;
|
||||
}
|
||||
if (!item.upd.StackObjectsCount)
|
||||
{
|
||||
item.upd.StackObjectsCount = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -140,18 +139,44 @@ export class InRaidHelper
|
||||
profileData: IPmcData,
|
||||
saveProgressRequest: ISaveProgressRequestData,
|
||||
sessionID: string,
|
||||
): IPmcData
|
||||
{
|
||||
// remove old skill fatigue
|
||||
): void
|
||||
{
|
||||
// Remove skill fatigue values
|
||||
this.resetSkillPointsEarnedDuringRaid(saveProgressRequest.profile);
|
||||
|
||||
// set profile data
|
||||
// Set profile data
|
||||
profileData.Info.Level = saveProgressRequest.profile.Info.Level;
|
||||
profileData.Skills = saveProgressRequest.profile.Skills;
|
||||
profileData.Stats.Eft = saveProgressRequest.profile.Stats.Eft;
|
||||
profileData.Encyclopedia = saveProgressRequest.profile.Encyclopedia;
|
||||
profileData.ConditionCounters = saveProgressRequest.profile.ConditionCounters;
|
||||
|
||||
this.validateBackendCounters(saveProgressRequest, profileData);
|
||||
|
||||
profileData.SurvivorClass = saveProgressRequest.profile.SurvivorClass;
|
||||
|
||||
// Add experience points
|
||||
profileData.Info.Experience += profileData.Stats.Eft.TotalSessionExperience;
|
||||
profileData.Stats.Eft.TotalSessionExperience = 0;
|
||||
|
||||
this.setPlayerInRaidLocationStatusToNone(sessionID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the skill points earned in a raid to 0, ready for next raid
|
||||
* @param profile Profile to update
|
||||
*/
|
||||
protected resetSkillPointsEarnedDuringRaid(profile: IPmcData): void
|
||||
{
|
||||
for (const skill of profile.Skills.Common)
|
||||
{
|
||||
skill.PointsEarnedDuringSession = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Check counters are correct in profile */
|
||||
protected validateBackendCounters(saveProgressRequest: ISaveProgressRequestData, profileData: IPmcData): void
|
||||
{
|
||||
for (const backendCounterKey in saveProgressRequest.profile.BackendCounters)
|
||||
{
|
||||
// Skip counters with no id
|
||||
@ -178,33 +203,47 @@ export class InRaidHelper
|
||||
if (matchingPreRaidCounter.value !== postRaidValue)
|
||||
{
|
||||
this.logger.error(
|
||||
`Backendcounter: ${backendCounterKey} value is different post raid, old: ${matchingPreRaidCounter.value} new: ${postRaidValue}`,
|
||||
`Backendcounter: ${backendCounterKey} value is different post raid, old: ${matchingPreRaidCounter.value} new: ${postRaidValue}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.processFailedQuests(sessionID, profileData, profileData.Quests, saveProgressRequest.profile.Quests);
|
||||
profileData.Quests = saveProgressRequest.profile.Quests;
|
||||
/**
|
||||
* Update various serverPMC profile values; quests/limb hp/trader standing with values post-raic
|
||||
* @param pmcData Server PMC profile
|
||||
* @param saveProgressRequest Post-raid request data
|
||||
* @param sessionId Session id
|
||||
*/
|
||||
public updatePmcProfileDataPostRaid(pmcData: IPmcData, saveProgressRequest: ISaveProgressRequestData, sessionId: string): void
|
||||
{
|
||||
// Process failed quests then copy everything
|
||||
this.processFailedQuests(sessionId, pmcData, pmcData.Quests, saveProgressRequest.profile.Quests);
|
||||
pmcData.Quests = saveProgressRequest.profile.Quests;
|
||||
|
||||
// Transfer effects from request to profile
|
||||
this.transferPostRaidLimbEffectsToProfile(saveProgressRequest, profileData);
|
||||
// No need to do this for scav, old scav is deleted and new one generated
|
||||
this.transferPostRaidLimbEffectsToProfile(saveProgressRequest, pmcData);
|
||||
|
||||
this.applyTraderStandingAdjustments(profileData.TradersInfo, saveProgressRequest.profile.TradersInfo);
|
||||
// Trader standing only occur on pmc profile, scav kills are handled in handlePostRaidPlayerScavKarmaChanges()
|
||||
// Scav client data has standing values of 0 for all traders, DO NOT RUN ON SCAV RAIDS
|
||||
this.applyTraderStandingAdjustments(pmcData.TradersInfo, saveProgressRequest.profile.TradersInfo);
|
||||
|
||||
profileData.SurvivorClass = saveProgressRequest.profile.SurvivorClass;
|
||||
this.profileFixerService.checkForAndFixPmcProfileIssues(pmcData);
|
||||
}
|
||||
|
||||
// Add experience points
|
||||
profileData.Info.Experience += profileData.Stats.Eft.TotalSessionExperience;
|
||||
profileData.Stats.Eft.TotalSessionExperience = 0;
|
||||
/**
|
||||
* Update scav quest values on server profile with updated values post-raid
|
||||
* @param scavData Server scav profile
|
||||
* @param saveProgressRequest Post-raid request data
|
||||
* @param sessionId Session id
|
||||
*/
|
||||
public updateScavProfileDataPostRaid(scavData: IPmcData, saveProgressRequest: ISaveProgressRequestData, sessionId: string): void
|
||||
{
|
||||
// Only copy active quests into scav profile // Progress will later to copied over to PMC profile
|
||||
const existingActiveQuestIds = scavData.Quests.filter(x => x.status !== QuestStatus.AvailableForStart).map(x => x.qid);
|
||||
scavData.Quests = saveProgressRequest.profile.Quests.filter(x => existingActiveQuestIds.includes(x.qid));
|
||||
|
||||
this.setPlayerInRaidLocationStatusToNone(sessionID);
|
||||
|
||||
if (!saveProgressRequest.isPlayerScav)
|
||||
{
|
||||
this.profileFixerService.checkForAndFixPmcProfileIssues(profileData);
|
||||
}
|
||||
|
||||
return profileData;
|
||||
this.profileFixerService.checkForAndFixScavProfileIssues(scavData);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -250,14 +289,6 @@ export class InRaidHelper
|
||||
}
|
||||
}
|
||||
|
||||
protected resetSkillPointsEarnedDuringRaid(profile: IPmcData): void
|
||||
{
|
||||
for (const skill of profile.Skills.Common)
|
||||
{
|
||||
skill.PointsEarnedDuringSession = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Take body part effects from client profile and apply to server profile
|
||||
* @param saveProgressRequest post-raid request
|
||||
|
@ -185,7 +185,7 @@ export class SaveServer
|
||||
{
|
||||
const filePath = `${this.profileFilepath}${sessionID}.json`;
|
||||
|
||||
// run callbacks
|
||||
// Run pre-save callbacks before we save into json
|
||||
for (const callback in this.onBeforeSaveCallbacks)
|
||||
{
|
||||
const previous = this.profiles[sessionID];
|
||||
|
@ -162,6 +162,15 @@ export class ProfileFixerService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find issues in the scav profile data that may cause issues
|
||||
* @param scavProfile profile to check and fix
|
||||
*/
|
||||
public checkForAndFixScavProfileIssues(scavProfile: IPmcData): void
|
||||
{
|
||||
this.updateProfileQuestDataValues(scavProfile);
|
||||
}
|
||||
|
||||
protected addMissingGunStandContainerImprovements(pmcProfile: IPmcData): void
|
||||
{
|
||||
const weaponStandArea = pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.WEAPON_STAND);
|
||||
|
Loading…
Reference in New Issue
Block a user