First pass at implementing Place of fame dogtag bonus, bonus is slight out from what is shown on client (0.0x out)

This commit is contained in:
Dev 2024-01-13 16:41:06 +00:00
parent 46ec7bf3ba
commit bf148dba4a
3 changed files with 68 additions and 2 deletions

View File

@ -34,7 +34,7 @@ export class InventoryCallbacks
) )
{} {}
/** Handle Move event */ /** Handle client/game/profile/items/moving Move event */
public moveItem(pmcData: IPmcData, body: IInventoryMoveRequestData, sessionID: string): IItemEventRouterResponse public moveItem(pmcData: IPmcData, body: IInventoryMoveRequestData, sessionID: string): IItemEventRouterResponse
{ {
return this.inventoryController.moveItem(pmcData, body, sessionID); return this.inventoryController.moveItem(pmcData, body, sessionID);

View File

@ -1,6 +1,7 @@
import { inject, injectable } from "tsyringe"; import { inject, injectable } from "tsyringe";
import { LootGenerator } from "@spt-aki/generators/LootGenerator"; import { LootGenerator } from "@spt-aki/generators/LootGenerator";
import { HideoutHelper } from "@spt-aki/helpers/HideoutHelper";
import { InventoryHelper } from "@spt-aki/helpers/InventoryHelper"; import { InventoryHelper } from "@spt-aki/helpers/InventoryHelper";
import { ItemHelper } from "@spt-aki/helpers/ItemHelper"; import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
import { PaymentHelper } from "@spt-aki/helpers/PaymentHelper"; import { PaymentHelper } from "@spt-aki/helpers/PaymentHelper";
@ -59,6 +60,7 @@ export class InventoryController
@inject("PresetHelper") protected presetHelper: PresetHelper, @inject("PresetHelper") protected presetHelper: PresetHelper,
@inject("InventoryHelper") protected inventoryHelper: InventoryHelper, @inject("InventoryHelper") protected inventoryHelper: InventoryHelper,
@inject("QuestHelper") protected questHelper: QuestHelper, @inject("QuestHelper") protected questHelper: QuestHelper,
@inject("HideoutHelper") protected hideoutHelper: HideoutHelper,
@inject("RagfairOfferService") protected ragfairOfferService: RagfairOfferService, @inject("RagfairOfferService") protected ragfairOfferService: RagfairOfferService,
@inject("ProfileHelper") protected profileHelper: ProfileHelper, @inject("ProfileHelper") protected profileHelper: ProfileHelper,
@inject("PaymentHelper") protected paymentHelper: PaymentHelper, @inject("PaymentHelper") protected paymentHelper: PaymentHelper,
@ -105,6 +107,7 @@ export class InventoryController
// Check for item in inventory before allowing internal transfer // Check for item in inventory before allowing internal transfer
const originalItemLocation = ownerInventoryItems.from.find((x) => x._id === moveRequest.item); const originalItemLocation = ownerInventoryItems.from.find((x) => x._id === moveRequest.item);
const originalLocationSlotId = originalItemLocation.slotId;
if (!originalItemLocation) if (!originalItemLocation)
{ {
// Internal item move but item never existed, possible dupe glitch // Internal item move but item never existed, possible dupe glitch
@ -116,6 +119,13 @@ export class InventoryController
{ {
return this.httpResponseUtil.appendErrorToOutput(output, moveResult.errorMessage); return this.httpResponseUtil.appendErrorToOutput(output, moveResult.errorMessage);
} }
// Item is moving into or out of place of fame dogtag slot
if (moveRequest.to.container.startsWith("dogtag")
|| originalLocationSlotId.startsWith("dogtag"))
{
this.hideoutHelper.applyPlaceOfFameDogtagBonus(pmcData);
}
} }
else else
{ {

View File

@ -4,7 +4,7 @@ import { InventoryHelper } from "@spt-aki/helpers/InventoryHelper";
import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper"; import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
import { IPmcData } from "@spt-aki/models/eft/common/IPmcData"; import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
import { HideoutArea, IHideoutImprovement, Production, Productive } from "@spt-aki/models/eft/common/tables/IBotBase"; import { HideoutArea, IHideoutImprovement, Production, Productive } from "@spt-aki/models/eft/common/tables/IBotBase";
import { Upd } from "@spt-aki/models/eft/common/tables/IItem"; import { Item, Upd } from "@spt-aki/models/eft/common/tables/IItem";
import { StageBonus } from "@spt-aki/models/eft/hideout/IHideoutArea"; import { StageBonus } from "@spt-aki/models/eft/hideout/IHideoutArea";
import { IHideoutContinuousProductionStartRequestData } from "@spt-aki/models/eft/hideout/IHideoutContinuousProductionStartRequestData"; import { IHideoutContinuousProductionStartRequestData } from "@spt-aki/models/eft/hideout/IHideoutContinuousProductionStartRequestData";
import { IHideoutProduction } from "@spt-aki/models/eft/hideout/IHideoutProduction"; import { IHideoutProduction } from "@spt-aki/models/eft/hideout/IHideoutProduction";
@ -1043,4 +1043,60 @@ export class HideoutHelper
} }
} }
} }
/**
* Add/remove bonus combat skill based on number of dogtags in place of fame hideout area
* @param pmcData Player profile
*/
public applyPlaceOfFameDogtagBonus(pmcData: IPmcData): void
{
const fameAreaProfile = pmcData.Hideout.Areas.find(area => area.type === HideoutAreas.PLACE_OF_FAME);
// Get hideout area 16 bonus array
const fameAreaDb = this.databaseServer.getTables().hideout.areas.find((area) => area.type === HideoutAreas.PLACE_OF_FAME);
// Get SkillGroupLevelingBoost object
const combatBoostBonusDb = fameAreaDb.stages[fameAreaProfile.level].bonuses.find(bonus => bonus.type === "SkillGroupLevelingBoost");
// Get SkillGroupLevelingBoost object in profile
const combatBonusProfile = pmcData.Bonuses.find(bonus => bonus.id === combatBoostBonusDb.id);
// Get all slotted dogtag items
const activeDogtags = pmcData.Inventory.items.filter(item => item?.slotId?.startsWith("dogtag"));
// Calculate bonus percent (apply hideoutManagement bonus)
const hideoutManagementSkill = this.profileHelper.getSkillFromProfile(pmcData, SkillTypes.HIDEOUT_MANAGEMENT);
const hideoutManagementSkillBonusPercent = 1 + (hideoutManagementSkill.Progress / 10000); // 5100 becomes 0.51, add 1 to it, 1.51
const bonus = this.getDogtagCombatSkillBonusPercent(pmcData, activeDogtags) * hideoutManagementSkillBonusPercent;
// Update bonus value to above calcualted value
combatBonusProfile.value = Number.parseFloat(bonus.toFixed(2));
}
/**
* Calculate the raw dogtag combat skill bonus for place of fame based on number of dogtags
* Reverse engineered from client code
* @param pmcData Player profile
* @param activeDogtags Active dogtags in place of fame dogtag slots
* @returns combat bonus
*/
protected getDogtagCombatSkillBonusPercent(pmcData: IPmcData, activeDogtags: Item[]): number
{
// Not own dogtag
// Side = opposite of player
let result = 0;
for (const dogtag of activeDogtags)
{
if (dogtag.upd.Dogtag.Side === pmcData.Info.Side
|| Number.parseInt(dogtag.upd.Dogtag.AccountId) === pmcData.aid
)
{
continue;
}
result += 0.01 * dogtag.upd.Dogtag.Level;
}
return result;
}
} }