Added further progress on cultist circle - now rewards items upon completion

Now handles `HideoutDeleteProductionCommand` event, Deletes sacrificed items on craft start
Set craft time to 30 secs for debugging
This commit is contained in:
Dev 2024-08-22 17:48:39 +01:00
parent eccf4ee969
commit 6d7c4d95b6
7 changed files with 109 additions and 17 deletions

View File

@ -5,6 +5,7 @@ import { IHandleQTEEventRequestData } from "@spt/models/eft/hideout/IHandleQTEEv
import { IHideoutCancelProductionRequestData } from "@spt/models/eft/hideout/IHideoutCancelProductionRequestData"; import { IHideoutCancelProductionRequestData } from "@spt/models/eft/hideout/IHideoutCancelProductionRequestData";
import { IHideoutCircleOfCultistProductionStartRequestData } from "@spt/models/eft/hideout/IHideoutCircleOfCultistProductionStartRequestData"; import { IHideoutCircleOfCultistProductionStartRequestData } from "@spt/models/eft/hideout/IHideoutCircleOfCultistProductionStartRequestData";
import { IHideoutContinuousProductionStartRequestData } from "@spt/models/eft/hideout/IHideoutContinuousProductionStartRequestData"; import { IHideoutContinuousProductionStartRequestData } from "@spt/models/eft/hideout/IHideoutContinuousProductionStartRequestData";
import { IHideoutDeleteProductionRequestData } from "@spt/models/eft/hideout/IHideoutDeleteProductionRequestData";
import { IHideoutImproveAreaRequestData } from "@spt/models/eft/hideout/IHideoutImproveAreaRequestData"; import { IHideoutImproveAreaRequestData } from "@spt/models/eft/hideout/IHideoutImproveAreaRequestData";
import { IHideoutPutItemInRequestData } from "@spt/models/eft/hideout/IHideoutPutItemInRequestData"; import { IHideoutPutItemInRequestData } from "@spt/models/eft/hideout/IHideoutPutItemInRequestData";
import { IHideoutScavCaseStartRequestData } from "@spt/models/eft/hideout/IHideoutScavCaseStartRequestData"; import { IHideoutScavCaseStartRequestData } from "@spt/models/eft/hideout/IHideoutScavCaseStartRequestData";
@ -190,14 +191,25 @@ export class HideoutCallbacks implements OnUpdate {
/** /**
* Handle client/game/profile/items/moving - HideoutCircleOfCultistProductionStart * Handle client/game/profile/items/moving - HideoutCircleOfCultistProductionStart
*/ */
circleOfCultistProductionStart( public circleOfCultistProductionStart(
pmcData: IPmcData, pmcData: IPmcData,
request: IHideoutCircleOfCultistProductionStartRequestData, request: IHideoutCircleOfCultistProductionStartRequestData,
sessionId: string, sessionId: string,
): IItemEventRouterResponse | PromiseLike<IItemEventRouterResponse> { ): IItemEventRouterResponse {
return this.hideoutController.circleOfCultistProductionStart(sessionId, pmcData, request); return this.hideoutController.circleOfCultistProductionStart(sessionId, pmcData, request);
} }
/**
* Handle client/game/profile/items/moving - HideoutDeleteProductionCommand
*/
hideoutDeleteProductionCommand(
pmcData: IPmcData,
request: IHideoutDeleteProductionRequestData,
sessionId: string,
): IItemEventRouterResponse {
return this.hideoutController.hideoutDeleteProductionCommand(sessionId, pmcData, request);
}
public async onUpdate(timeSinceLastRun: number): Promise<boolean> { public async onUpdate(timeSinceLastRun: number): Promise<boolean> {
if (timeSinceLastRun > this.hideoutConfig.runIntervalSeconds) { if (timeSinceLastRun > this.hideoutConfig.runIntervalSeconds) {
this.hideoutController.update(); this.hideoutController.update();

View File

@ -14,6 +14,7 @@ import { IHideoutArea, Stage } from "@spt/models/eft/hideout/IHideoutArea";
import { IHideoutCancelProductionRequestData } from "@spt/models/eft/hideout/IHideoutCancelProductionRequestData"; import { IHideoutCancelProductionRequestData } from "@spt/models/eft/hideout/IHideoutCancelProductionRequestData";
import { IHideoutCircleOfCultistProductionStartRequestData } from "@spt/models/eft/hideout/IHideoutCircleOfCultistProductionStartRequestData"; import { IHideoutCircleOfCultistProductionStartRequestData } from "@spt/models/eft/hideout/IHideoutCircleOfCultistProductionStartRequestData";
import { IHideoutContinuousProductionStartRequestData } from "@spt/models/eft/hideout/IHideoutContinuousProductionStartRequestData"; import { IHideoutContinuousProductionStartRequestData } from "@spt/models/eft/hideout/IHideoutContinuousProductionStartRequestData";
import { IHideoutDeleteProductionRequestData } from "@spt/models/eft/hideout/IHideoutDeleteProductionRequestData";
import { IHideoutImproveAreaRequestData } from "@spt/models/eft/hideout/IHideoutImproveAreaRequestData"; import { IHideoutImproveAreaRequestData } from "@spt/models/eft/hideout/IHideoutImproveAreaRequestData";
import { IHideoutProduction } from "@spt/models/eft/hideout/IHideoutProduction"; import { IHideoutProduction } from "@spt/models/eft/hideout/IHideoutProduction";
import { IHideoutPutItemInRequestData } from "@spt/models/eft/hideout/IHideoutPutItemInRequestData"; import { IHideoutPutItemInRequestData } from "@spt/models/eft/hideout/IHideoutPutItemInRequestData";
@ -1256,7 +1257,7 @@ export class HideoutController {
sessionId: string, sessionId: string,
pmcData: IPmcData, pmcData: IPmcData,
request: IHideoutCircleOfCultistProductionStartRequestData, request: IHideoutCircleOfCultistProductionStartRequestData,
): IItemEventRouterResponse | PromiseLike<IItemEventRouterResponse> { ): IItemEventRouterResponse {
// Sparse, just has id // Sparse, just has id
const cultistCraftData = this.databaseService.getHideout().production.cultistRecipes[0]; const cultistCraftData = this.databaseService.getHideout().production.cultistRecipes[0];
const sacrificedItems: Item[] = this.getSacrificedItems(pmcData); const sacrificedItems: Item[] = this.getSacrificedItems(pmcData);
@ -1264,19 +1265,74 @@ export class HideoutController {
// Create production in pmc profile // Create production in pmc profile
this.hideoutHelper.registerCircleOfCultistProduction(sessionId, pmcData, cultistCraftData._id, sacrificedItems); this.hideoutHelper.registerCircleOfCultistProduction(sessionId, pmcData, cultistCraftData._id, sacrificedItems);
// What items can be rewarded by completion of craft
// TODO - how do we use this? maybe this is done in a later event?
const cultistStashDbItem = this.itemHelper.getItem(ItemTpl.HIDEOUTAREACONTAINER_CIRCLEOFCULTISTS_STASH_1);
const rewardItemPool = cultistStashDbItem[1]._props.Grids[0]._props.filters[0].Filter;
const output = this.eventOutputHolder.getOutput(sessionId); const output = this.eventOutputHolder.getOutput(sessionId);
// TODO - is this necessary?
// Do the items remain in the sacrifice window for duration of craft?
// Remove sacrified items // Remove sacrified items
// for (const rootItem of inventoryRootItemsInCultistGrid) { const slotId = "CircleOfCultistsGrid1";
// this.inventoryHelper.removeItem(pmcData, rootItem._id, sessionId, output); for (const item of sacrificedItems) {
// } if (item.slotId === slotId) {
this.inventoryHelper.removeItem(pmcData, item._id, sessionId, output);
}
}
// What items can be rewarded by completion of craft
const cultistStashDbItem = this.itemHelper.getItem(ItemTpl.HIDEOUTAREACONTAINER_CIRCLEOFCULTISTS_STASH_1);
// TODO: create own reward item pool as this is for items the circle accepts as sacrifice, NOT reward pool
const rewardItemPool = cultistStashDbItem[1]._props.Grids[0]._props.filters[0].Filter;
// TODO, tie this into rouble cost of items sacrificed
const randomRewardItemCount = this.randomUtil.getInt(1, 4);
this.logger.warning(`cicle craft chose ${randomRewardItemCount} reward count`);
// Create array of rewards
const rewards: Item[][] = [];
const cultistCircleStashId = pmcData.Inventory.hideoutAreaStashes[HideoutAreas.CIRCLE_OF_CULTISTS];
for (let index = 0; index < randomRewardItemCount; index++) {
const itemTpl = this.randomUtil.getArrayValue(rewardItemPool);
const rewardItem: Item = {
_id: this.hashUtil.generate(),
_tpl: itemTpl,
parentId: cultistCircleStashId,
slotId: slotId,
upd: {
StackObjectsCount: 1,
SpawnedInSession: true,
},
};
rewards.push([rewardItem]);
}
// Get the container grid for cultist stash area
const containerGrid = this.inventoryHelper.getContainerSlotMap(cultistStashDbItem[1]._id);
const canAddToContainer = this.inventoryHelper.canPlaceItemsInContainer(
this.cloner.clone(containerGrid), // MUST clone grid before passing in as function modifies grid
rewards,
);
if (canAddToContainer) {
for (const itemToAdd of rewards) {
this.logger.warning(`Placing reward: ${itemToAdd[0]._tpl} in circle grid`);
this.inventoryHelper.placeItemInContainer(containerGrid, itemToAdd, cultistCircleStashId, slotId);
// Add item + mods to output and profile inventory
output.profileChanges[sessionId].items.new.push(...itemToAdd);
pmcData.Inventory.items.push(...itemToAdd);
}
}
return output;
}
public hideoutDeleteProductionCommand(
sessionId: string,
pmcData: IPmcData,
request: IHideoutDeleteProductionRequestData,
): IItemEventRouterResponse {
const output = this.eventOutputHolder.getOutput(sessionId);
delete pmcData.Hideout.Production[request.recipeId];
return output; return output;
} }

View File

@ -123,8 +123,8 @@ export class HideoutHelper {
recipeId: string, recipeId: string,
sacrificedItems: Item[], sacrificedItems: Item[],
): void { ): void {
// TODO: hard coded 5 hour craft + no fuel use, where can we get this data // TODO: hard coded 5 hour (18000) craft + no fuel use, where can we get this data
const cultistProduction = this.initProduction(recipeId, 18000, false, true); const cultistProduction = this.initProduction(recipeId, 30, false, true);
cultistProduction.GivenItemsInStart = sacrificedItems; cultistProduction.GivenItemsInStart = sacrificedItems;
// Add circle production to profile // Add circle production to profile
@ -397,9 +397,24 @@ export class HideoutHelper {
if (production.Progress < production.ProductionTime) { if (production.Progress < production.ProductionTime) {
production.Progress += timeElapsedSeconds; production.Progress += timeElapsedSeconds;
this.logger.warning(`circle craft progress is now ${production.Progress} of ${production.ProductionTime}`);
// Check if craft is complete
if (production.Progress >= production.ProductionTime) {
this.flagCultistCircleCraftAsComplete(production);
this.logger.warning(`circle craft complete, AvailableForFinish set ot true`);
}
return; return;
} }
// Craft in complete
this.flagCultistCircleCraftAsComplete(production);
this.logger.warning(`circle craft complete, AvailableForFinish set ot true`);
}
protected flagCultistCircleCraftAsComplete(production: Productive) {
// Craft is complete, flas as such // Craft is complete, flas as such
production.AvailableForFinish = true; production.AvailableForFinish = true;

View File

@ -1,4 +1,4 @@
export type IHideoutCircleOfCultistProductionStartRequestData = { export interface IHideoutCircleOfCultistProductionStartRequestData {
Action: "HideoutCircleOfCultistProductionStart"; Action: "HideoutCircleOfCultistProductionStart";
timestamp: number; timestamp: number;
}; }

View File

@ -0,0 +1,5 @@
export interface IHideoutDeleteProductionRequestData {
Action: "HideoutDeleteProductionCommand";
recipeId: string;
timestamp: number;
}

View File

@ -12,4 +12,5 @@ export enum HideoutEventActions {
HIDEOUT_IMPROVE_AREA = "HideoutImproveArea", HIDEOUT_IMPROVE_AREA = "HideoutImproveArea",
HIDEOUT_CANCEL_PRODUCTION_COMMAND = "HideoutCancelProductionCommand", HIDEOUT_CANCEL_PRODUCTION_COMMAND = "HideoutCancelProductionCommand",
HIDEOUT_CIRCLE_OF_CULTIST_PRODUCTION_START = "HideoutCircleOfCultistProductionStart", HIDEOUT_CIRCLE_OF_CULTIST_PRODUCTION_START = "HideoutCircleOfCultistProductionStart",
HIDEOUT_DELETE_PRODUCTION_COMMAND = "HideoutDeleteProductionCommand",
} }

View File

@ -26,6 +26,7 @@ export class HideoutItemEventRouter extends ItemEventRouterDefinition {
new HandledRoute(HideoutEventActions.HIDEOUT_IMPROVE_AREA, false), new HandledRoute(HideoutEventActions.HIDEOUT_IMPROVE_AREA, false),
new HandledRoute(HideoutEventActions.HIDEOUT_CANCEL_PRODUCTION_COMMAND, false), new HandledRoute(HideoutEventActions.HIDEOUT_CANCEL_PRODUCTION_COMMAND, false),
new HandledRoute(HideoutEventActions.HIDEOUT_CIRCLE_OF_CULTIST_PRODUCTION_START, false), new HandledRoute(HideoutEventActions.HIDEOUT_CIRCLE_OF_CULTIST_PRODUCTION_START, false),
new HandledRoute(HideoutEventActions.HIDEOUT_DELETE_PRODUCTION_COMMAND, false),
]; ];
} }
@ -63,6 +64,8 @@ export class HideoutItemEventRouter extends ItemEventRouterDefinition {
return this.hideoutCallbacks.cancelProduction(pmcData, body, sessionID); return this.hideoutCallbacks.cancelProduction(pmcData, body, sessionID);
case HideoutEventActions.HIDEOUT_CIRCLE_OF_CULTIST_PRODUCTION_START: case HideoutEventActions.HIDEOUT_CIRCLE_OF_CULTIST_PRODUCTION_START:
return this.hideoutCallbacks.circleOfCultistProductionStart(pmcData, body, sessionID); return this.hideoutCallbacks.circleOfCultistProductionStart(pmcData, body, sessionID);
case HideoutEventActions.HIDEOUT_DELETE_PRODUCTION_COMMAND:
return this.hideoutCallbacks.hideoutDeleteProductionCommand(pmcData, body, sessionID);
default: default:
throw new Error(`Unhandled event ${url} request: ${JSON.stringify(body)}`); throw new Error(`Unhandled event ${url} request: ${JSON.stringify(body)}`);
} }