Fixed issue that would cause repeatable completion quests to get stuck in an infinite loop
Improved performance of completion quests picking items to return
This commit is contained in:
parent
f46694a169
commit
f04382c9bb
@ -28,6 +28,7 @@ import { inject, injectable } from "tsyringe";
|
|||||||
@injectable()
|
@injectable()
|
||||||
export class RepeatableQuestGenerator {
|
export class RepeatableQuestGenerator {
|
||||||
protected questConfig: IQuestConfig;
|
protected questConfig: IQuestConfig;
|
||||||
|
protected maxRandomNumberAttempts = 6;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@inject("PrimaryLogger") protected logger: ILogger,
|
@inject("PrimaryLogger") protected logger: ILogger,
|
||||||
@ -516,24 +517,44 @@ export class RepeatableQuestGenerator {
|
|||||||
|
|
||||||
// Draw items to ask player to retrieve
|
// Draw items to ask player to retrieve
|
||||||
let isAmmo = 0;
|
let isAmmo = 0;
|
||||||
const randomNumbersUsed = [];
|
|
||||||
|
// Store the indexes of items we are asking player to provide
|
||||||
|
const usedItemIndexes = new Set();
|
||||||
for (let i = 0; i < distinctItemsToRetrieveCount; i++) {
|
for (let i = 0; i < distinctItemsToRetrieveCount; i++) {
|
||||||
let randomNumber = this.randomUtil.randInt(itemSelection.length);
|
let chosenItemIndex = this.randomUtil.randInt(itemSelection.length);
|
||||||
while (randomNumbersUsed.includes(randomNumber) && randomNumbersUsed.length !== itemSelection.length) {
|
let found = false;
|
||||||
randomNumber = this.randomUtil.randInt(itemSelection.length);
|
|
||||||
|
for (let i = 0; i < this.maxRandomNumberAttempts; i++) {
|
||||||
|
if (usedItemIndexes.has(chosenItemIndex)) {
|
||||||
|
chosenItemIndex = this.randomUtil.randInt(itemSelection.length);
|
||||||
|
} else {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
randomNumbersUsed.push(randomNumber);
|
if (!found) {
|
||||||
|
this.logger.error(
|
||||||
|
this.localisationService.getText("repeatable-no_reward_item_found_in_price_range", {
|
||||||
|
minPrice: 0,
|
||||||
|
roublesBudget: roublesBudget,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
const itemSelected = itemSelection[randomNumber];
|
return undefined;
|
||||||
|
}
|
||||||
|
usedItemIndexes.add(chosenItemIndex);
|
||||||
|
|
||||||
|
const itemSelected = itemSelection[chosenItemIndex];
|
||||||
const itemUnitPrice = this.itemHelper.getItemPrice(itemSelected[0]);
|
const itemUnitPrice = this.itemHelper.getItemPrice(itemSelected[0]);
|
||||||
let minValue = completionConfig.minRequestedAmount;
|
let minValue = completionConfig.minRequestedAmount;
|
||||||
let maxValue = completionConfig.maxRequestedAmount;
|
let maxValue = completionConfig.maxRequestedAmount;
|
||||||
if (this.itemHelper.isOfBaseclass(itemSelected[0], BaseClasses.AMMO)) {
|
if (this.itemHelper.isOfBaseclass(itemSelected[0], BaseClasses.AMMO)) {
|
||||||
// Prevent multiple ammo requirements from being picked, stop after 6 attempts
|
// Prevent multiple ammo requirements from being picked
|
||||||
if (isAmmo > 0 && isAmmo < 6) {
|
if (isAmmo > 0 && isAmmo < this.maxRandomNumberAttempts) {
|
||||||
isAmmo++;
|
isAmmo++;
|
||||||
i--;
|
i--;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
isAmmo++;
|
isAmmo++;
|
||||||
@ -542,21 +563,23 @@ export class RepeatableQuestGenerator {
|
|||||||
}
|
}
|
||||||
let value = minValue;
|
let value = minValue;
|
||||||
|
|
||||||
// get the value range within budget
|
// Get the value range within budget
|
||||||
maxValue = Math.min(maxValue, Math.floor(roublesBudget / itemUnitPrice));
|
maxValue = Math.min(maxValue, Math.floor(roublesBudget / itemUnitPrice));
|
||||||
if (maxValue > minValue) {
|
if (maxValue > minValue) {
|
||||||
// if it doesn't blow the budget we have for the request, draw a random amount of the selected
|
// If it doesn't blow the budget we have for the request, draw a random amount of the selected
|
||||||
// item type to be requested
|
// Item type to be requested
|
||||||
value = this.randomUtil.randInt(minValue, maxValue + 1);
|
value = this.randomUtil.randInt(minValue, maxValue + 1);
|
||||||
}
|
}
|
||||||
roublesBudget -= value * itemUnitPrice;
|
roublesBudget -= value * itemUnitPrice;
|
||||||
|
|
||||||
// push a CompletionCondition with the item and the amount of the item
|
// Push a CompletionCondition with the item and the amount of the item
|
||||||
quest.conditions.AvailableForFinish.push(this.generateCompletionAvailableForFinish(itemSelected[0], value));
|
quest.conditions.AvailableForFinish.push(this.generateCompletionAvailableForFinish(itemSelected[0], value));
|
||||||
|
|
||||||
if (roublesBudget > 0) {
|
if (roublesBudget > 0) {
|
||||||
// reduce the list possible items to fulfill the new budget constraint
|
// Reduce the list possible items to fulfill the new budget constraint
|
||||||
itemSelection = itemSelection.filter((x) => this.itemHelper.getItemPrice(x[0]) < roublesBudget);
|
itemSelection = itemSelection.filter(
|
||||||
|
(dbItem) => this.itemHelper.getItemPrice(dbItem[0]) < roublesBudget,
|
||||||
|
);
|
||||||
if (itemSelection.length === 0) {
|
if (itemSelection.length === 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user