Improve handling of how reward items have their stack count randomised

Separated out how weapons are chosen as rewards

Lowered chance of skill reward

Added additional reward types to most traders
This commit is contained in:
Dev 2023-11-19 13:21:34 +00:00
parent 8cb4833001
commit 1def90e9d6
3 changed files with 122 additions and 80 deletions

View File

@ -149,7 +149,7 @@
"items": [2, 4, 5, 5, 5, 5, 5],
"reputation": [0.01, 0.01, 0.02, 0.02, 0.03, 0.03, 0.03],
"rewardSpread": 0.5,
"skillRewardChance": [0, 0.01, 0.05, 0.1, 0.15, 0.2, 0.2],
"skillRewardChance": [0, 0.01, 0.05, 0.1, 0.1, 0.15, 0.15],
"skillPointReward": [10, 15, 20, 25, 30, 35, 40]
},
"locations": {
@ -172,10 +172,11 @@
"543be6564bdc2df4348b4568",
"5485a8684bdc2da71d8b4567",
"590c745b86f7743cc433c5f2",
"5422acb9af1c889c16000029",
"57864c322459775490116fbf",
"57864a66245977548f04a81f"
]
],
"rewardCanBeWeapon": true,
"weaponRewardChancePercent": 20
}, {
"traderId": "54cb57776803fa99248b456e",
"name": "therapist",
@ -189,8 +190,11 @@
"57864c8c245977548867e7f1",
"5448e8d04bdc2ddf718b4569",
"57864e4c24597754843f8723",
"57864ee62459775490116fc1"
]
"57864ee62459775490116fc1",
"543be5664bdc2dd4348b4569"
],
"rewardCanBeWeapon": false,
"weaponRewardChancePercent": 0
}, {
"traderId": "58330581ace78e27b8b10cee",
"name": "skier",
@ -199,7 +203,6 @@
"5a341c4086f77401f2541505",
"5448e8d64bdc2dce718b4568",
"5448e8d04bdc2ddf718b4569",
"5422acb9af1c889c16000029",
"55818ad54bdc2ddc698b4569",
"57864a3d24597754843f8721",
"5a341c4686f77469e155819e",
@ -211,19 +214,26 @@
"590c745b86f7743cc433c5f2",
"57864a66245977548f04a81f",
"5c164d2286f774194c5e69fa"
]
],
"rewardCanBeWeapon": true,
"weaponRewardChancePercent": 20
}, {
"traderId": "5935c25fb3acc3127c3d8cd9",
"name": "peacekeeper",
"questTypes": ["Completion", "Exploration", "Elimination"],
"rewardBaseWhitelist": [
"5422acb9af1c889c16000029",
"543be6564bdc2df4348b4568",
"5448e5284bdc2dcb718b4567",
"5485a8684bdc2da71d8b4567",
"57864a3d24597754843f8721",
"55818af64bdc2d5b648b4570"
]
"55818af64bdc2d5b648b4570",
"57864e4c24597754843f8723",
"57864a66245977548f04a81f",
"57864ee62459775490116fc1",
"590c745b86f7743cc433c5f2"
],
"rewardCanBeWeapon": true,
"weaponRewardChancePercent": 20
}, {
"traderId": "5a7c2eca46aef81a7ca2145d",
"name": "mechanic",
@ -234,10 +244,16 @@
"55818b164bdc2ddc698b456c",
"55818a684bdc2ddd698b456d",
"550aa4cd4bdc2dd8348b456c",
"5422acb9af1c889c16000029",
"5485a8684bdc2da71d8b4567",
"55818b224bdc2dde698b456f"
]
"55818b224bdc2dde698b456f",
"57864a66245977548f04a81f",
"55818af64bdc2d5b648b4570",
"550aa4dd4bdc2dc9348b4569",
"55818a594bdc2db9688b456a",
"55818a104bdc2db9688b4569"
],
"rewardCanBeWeapon": true,
"weaponRewardChancePercent": 20
}, {
"traderId": "5ac3b934156ae10c4430e83c",
"name": "ragman",
@ -251,7 +267,9 @@
"5448e53e4bdc2d60728b4567",
"5448e5284bdc2dcb718b4567",
"57864a66245977548f04a81f"
]
],
"rewardCanBeWeapon": false,
"weaponRewardChancePercent": 0
}, {
"traderId": "5c0647fdd443bc2504c2d371",
"name": "jaeger",
@ -268,7 +286,9 @@
"5795f317245977243854e041",
"5d650c3e815116009f6201d2",
"57864ada245977548638de91"
]
],
"rewardCanBeWeapon": false,
"weaponRewardChancePercent": 0
}
],
"questConfig": {
@ -799,7 +819,7 @@
"items": [4, 5, 5, 6, 6, 7, 7],
"reputation": [0.02, 0.03, 0.04, 0.04, 0.05, 0.05, 0.05],
"rewardSpread": 0.5,
"skillRewardChance": [0, 0.05, 0.1, 0.15, 0.25, 0.3, 0.3],
"skillRewardChance": [0, 0.05, 0.1, 0.15, 0.2, 0.2, 0.2],
"skillPointReward": [25, 35, 45, 50, 55, 60, 65]
},
"locations": {
@ -822,10 +842,11 @@
"543be6564bdc2df4348b4568",
"5485a8684bdc2da71d8b4567",
"590c745b86f7743cc433c5f2",
"5422acb9af1c889c16000029",
"57864c322459775490116fbf",
"57864a66245977548f04a81f"
]
],
"rewardCanBeWeapon": true,
"weaponRewardChancePercent": 25
}, {
"traderId": "54cb57776803fa99248b456e",
"name": "therapist",
@ -839,8 +860,11 @@
"57864c8c245977548867e7f1",
"5448e8d04bdc2ddf718b4569",
"57864e4c24597754843f8723",
"57864ee62459775490116fc1"
]
"57864ee62459775490116fc1",
"543be5664bdc2dd4348b4569"
],
"rewardCanBeWeapon": false,
"weaponRewardChancePercent": 0
}, {
"traderId": "58330581ace78e27b8b10cee",
"name": "skier",
@ -849,7 +873,6 @@
"5a341c4086f77401f2541505",
"5448e8d64bdc2dce718b4568",
"5448e8d04bdc2ddf718b4569",
"5422acb9af1c889c16000029",
"55818ad54bdc2ddc698b4569",
"57864a3d24597754843f8721",
"5a341c4686f77469e155819e",
@ -861,19 +884,26 @@
"590c745b86f7743cc433c5f2",
"57864a66245977548f04a81f",
"5c164d2286f774194c5e69fa"
]
],
"rewardCanBeWeapon": true,
"weaponRewardChancePercent": 25
}, {
"traderId": "5935c25fb3acc3127c3d8cd9",
"name": "peacekeeper",
"questTypes": ["Completion", "Exploration", "Elimination"],
"rewardBaseWhitelist": [
"5422acb9af1c889c16000029",
"543be6564bdc2df4348b4568",
"5448e5284bdc2dcb718b4567",
"5485a8684bdc2da71d8b4567",
"57864a3d24597754843f8721",
"55818af64bdc2d5b648b4570"
]
"55818af64bdc2d5b648b4570",
"57864e4c24597754843f8723",
"57864a66245977548f04a81f",
"57864ee62459775490116fc1",
"590c745b86f7743cc433c5f2"
],
"rewardCanBeWeapon": true,
"weaponRewardChancePercent": 25
}, {
"traderId": "5a7c2eca46aef81a7ca2145d",
"name": "mechanic",
@ -884,10 +914,16 @@
"55818b164bdc2ddc698b456c",
"55818a684bdc2ddd698b456d",
"550aa4cd4bdc2dd8348b456c",
"5422acb9af1c889c16000029",
"5485a8684bdc2da71d8b4567",
"55818b224bdc2dde698b456f"
]
"55818b224bdc2dde698b456f",
"57864a66245977548f04a81f",
"55818af64bdc2d5b648b4570",
"550aa4dd4bdc2dc9348b4569",
"55818a594bdc2db9688b456a",
"55818a104bdc2db9688b4569"
],
"rewardCanBeWeapon": true,
"weaponRewardChancePercent": 25
}, {
"traderId": "5ac3b934156ae10c4430e83c",
"name": "ragman",
@ -901,7 +937,9 @@
"5448e53e4bdc2d60728b4567",
"5448e5284bdc2dcb718b4567",
"57864a66245977548f04a81f"
]
],
"rewardCanBeWeapon": false,
"weaponRewardChancePercent": 0
}, {
"traderId": "5c0647fdd443bc2504c2d371",
"name": "jaeger",
@ -918,14 +956,16 @@
"5795f317245977243854e041",
"5d650c3e815116009f6201d2",
"57864ada245977548638de91"
]
],
"rewardCanBeWeapon": false,
"weaponRewardChancePercent": 0
}
],
"questConfig": {
"Exploration": {
"possibleSkillRewards": ["Endurance", "Strength", "Vitality"],
"maxExtracts": 25,
"maxExtractsWithSpecificExit": 12,
"possibleSkillRewards": ["Endurance", "Strength", "Vitality"],
"specificExits": {
"probability": 0.4,
"passageRequirementWhitelist": [
@ -1538,9 +1578,10 @@
"55818a594bdc2db9688b456a",
"57864c8c245977548867e7f1",
"5448ecbe4bdc2d60728b4568",
"5422acb9af1c889c16000029",
"57864bb7245977548b3b66c2"
]
],
"rewardCanBeWeapon": true,
"weaponRewardChancePercent": 10
}
],
"questConfig": {

View File

@ -907,13 +907,23 @@ export class RepeatableQuestGenerator
}
rewardIndex++;
const traderWhitelistDetails = repeatableConfig.traderWhitelist.find((x) => x.traderId === traderId);
if (traderWhitelistDetails.rewardCanBeWeapon && this.randomUtil.getChance100(traderWhitelistDetails.weaponRewardChancePercent))
{
// Add a random default preset weapon as reward
const defaultPresets = Object.values(this.presetHelper.getDefaultPresets());
const defaultPreset = this.randomUtil.getArrayValue(defaultPresets);
// use _encyclopedia as its always the base items _tpl, items[0] isnt guaranteed to be base item
rewards.Success.push(this.generateRewardItem(defaultPreset._encyclopedia, 1, rewardIndex, defaultPreset._items));
rewardIndex++;
}
if (rewardItemPool.length > 0)
{
let weaponRewardCount = 0;
for (let i = 0; i < rewardNumItems - 1; i++)
for (let i = 0; i < rewardNumItems; i++)
{
let itemCount = 1;
let children: Item[] = null;
let rewardItemStackCount = 1;
const itemSelected = rewardItemPool[this.randomUtil.randInt(rewardItemPool.length)];
if (this.itemHelper.isOfBaseclass(itemSelected._id, BaseClasses.AMMO))
{
@ -924,54 +934,23 @@ export class RepeatableQuestGenerator
}
// Randomise the cartridge count returned
itemCount = this.randomUtil.randInt(
rewardItemStackCount = this.randomUtil.randInt(
repeatableConfig.rewardAmmoStackMinSize,
itemSelected._props.StackMaxSize,
);
}
else if (this.itemHelper.isOfBaseclass(itemSelected._id, BaseClasses.WEAPON))
{
if (weaponRewardCount >= 1)
{
// Limit weapon rewards to 1 per daily
rewardItemPool = rewardItemPool.filter((x) =>
!this.itemHelper.isOfBaseclass(x._id, BaseClasses.WEAPON)
);
if (rewardItemPool.length === 0)
{
// No rewards left, break out of loop
break;
}
// Another weapon chosen, skip
continue;
}
let defaultPreset = this.presetHelper.getDefaultPreset(itemSelected._id);
if (!defaultPreset)
{
// No default for chosen weapon found, get any random default weapon preset
const defaultPresets = Object.values(this.presetHelper.getDefaultPresets());
defaultPreset = this.randomUtil.getArrayValue(defaultPresets);
}
children = this.ragfairServerHelper.reparentPresets(defaultPreset._items[0], defaultPreset._items);
weaponRewardCount++;
}
// 25% chance to double reward stack (item should be stackable and not weapon)
if (this.increaseRewardItemStackSize(itemSelected))
if (this.canIncreaseRewardItemStackSize(itemSelected, 70000))
{
itemCount = 2;
rewardItemStackCount = this.getRandomisedRewardItemStackSizeByPrice(itemSelected);
}
rewards.Success.push(this.generateRewardItem(itemSelected._id, itemCount, rewardIndex, children));
rewards.Success.push(this.generateRewardItem(itemSelected._id, rewardItemStackCount, rewardIndex));
rewardIndex++;
const itemCost = (this.itemHelper.isOfBaseclass(itemSelected._id, BaseClasses.WEAPON))
? this.itemHelper.getItemMaxPrice(children[0]._tpl) // use if preset is not default : this.itemHelper.getWeaponPresetPrice(children[0], children, this.itemHelper.getStaticItemPrice(itemSelected._id))
: this.itemHelper.getStaticItemPrice(itemSelected._id);
roublesBudget -= itemCount * itemCost;
const itemCost = this.itemHelper.getStaticItemPrice(itemSelected._id);
roublesBudget -= rewardItemStackCount * itemCost;
// If we still have budget narrow down possible items
if (roublesBudget > 0)
@ -1018,15 +997,34 @@ export class RepeatableQuestGenerator
/**
* Should reward item have stack size increased (25% chance)
* @param item Item to possibly increase stack size of
* @param maxRoublePriceToStack Maximum rouble price an item can be to still be chosen for stacking
* @returns True if it should
*/
protected increaseRewardItemStackSize(item: ITemplateItem): boolean
protected canIncreaseRewardItemStackSize(item: ITemplateItem, maxRoublePriceToStack: number): boolean
{
return item._props.StackMaxSize > 1
&& !this.itemHelper.isOfBaseclass(item._id, BaseClasses.WEAPON)
return this.itemHelper.getStaticItemPrice(item._id) < maxRoublePriceToStack
&& !this.itemHelper.isOfBaseclasses(item._id, [BaseClasses.WEAPON, BaseClasses.AMMO])
&& this.randomUtil.getChance100(25);
}
/**
* Get a randomised number a reward items stack size should be based on its handbook price
* @param item Reward item to get stack size for
* @returns Stack size value
*/
protected getRandomisedRewardItemStackSizeByPrice(item: ITemplateItem): number
{
const rewardItemPrice = this.itemHelper.getStaticItemPrice(item._id);
if (rewardItemPrice < 3000) {
return this.randomUtil.getArrayValue([2, 3, 4]);
}
else if (rewardItemPrice < 10000) {
return this.randomUtil.getArrayValue([2, 3]);
}
return 2;
}
/**
* Select a number of items that have a colelctive value of the passed in parameter
* @param repeatableConfig Config
@ -1071,19 +1069,20 @@ export class RepeatableQuestGenerator
* @param {integer} index All rewards will be appended to a list, for unknown reasons the client wants the index
* @returns {object} Object of "Reward"-item-type
*/
protected generateRewardItem(tpl: string, value: number, index: number, preset = null): IReward
protected generateRewardItem(tpl: string, value: number, index: number, preset: Item[] = null): IReward
{
const id = this.objectId.generate();
const rewardItem: IReward = { target: id, value: value, type: "Item", index: index };
const rootItem = { _id: id, _tpl: tpl, upd: { StackObjectsCount: value, SpawnedInSession: true } };
if (preset)
{
const rootItem = preset.find(x => x._tpl === tpl);
rewardItem.target = rootItem._id; // Target property and root items id must match
rewardItem.items = this.ragfairServerHelper.reparentPresets(rootItem, preset);
}
else
{
const rootItem = { _id: id, _tpl: tpl, upd: { StackObjectsCount: value, SpawnedInSession: true } };
rewardItem.items = [rootItem];
}
return rewardItem;

View File

@ -77,6 +77,8 @@ export interface ITraderWhitelist
traderId: string;
questTypes: string[];
rewardBaseWhitelist: string[];
rewardCanBeWeapon: boolean
weaponRewardChancePercent: number
}
export interface IRepeatableQuestTypesConfig