feat: archon hunt rewards #1713
@ -53,6 +53,9 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
|
|||||||
logger.debug("mission report:", missionReport);
|
logger.debug("mission report:", missionReport);
|
||||||
|
|
||||||
const inventory = await getInventory(accountId);
|
const inventory = await getInventory(accountId);
|
||||||
|
const firstCompletion = missionReport.SortieId
|
||||||
|
? inventory.CompletedSorties.indexOf(missionReport.SortieId) == -1
|
||||||
|
: false;
|
||||||
const inventoryUpdates = await addMissionInventoryUpdates(inventory, missionReport);
|
const inventoryUpdates = await addMissionInventoryUpdates(inventory, missionReport);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@ -69,7 +72,7 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { MissionRewards, inventoryChanges, credits, AffiliationMods, SyndicateXPItemReward } =
|
const { MissionRewards, inventoryChanges, credits, AffiliationMods, SyndicateXPItemReward } =
|
||||||
await addMissionRewards(inventory, missionReport);
|
await addMissionRewards(inventory, missionReport, firstCompletion);
|
||||||
|
|
||||||
await inventory.save();
|
await inventory.save();
|
||||||
const inventoryResponse = await getInventoryResponse(inventory, true);
|
const inventoryResponse = await getInventoryResponse(inventory, true);
|
||||||
|
@ -91,7 +91,8 @@ import {
|
|||||||
ICrewMemberSkill,
|
ICrewMemberSkill,
|
||||||
ICrewMemberSkillEfficiency,
|
ICrewMemberSkillEfficiency,
|
||||||
ICrewMemberDatabase,
|
ICrewMemberDatabase,
|
||||||
ICrewMemberClient
|
ICrewMemberClient,
|
||||||
|
ISortieRewardAttenuation
|
||||||
} from "../../types/inventoryTypes/inventoryTypes";
|
} from "../../types/inventoryTypes/inventoryTypes";
|
||||||
import { IOid } from "../../types/commonTypes";
|
import { IOid } from "../../types/commonTypes";
|
||||||
import {
|
import {
|
||||||
@ -1276,6 +1277,14 @@ lastSortieRewardSchema.set("toJSON", {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const sortieRewardAttenutationSchema = new Schema<ISortieRewardAttenuation>(
|
||||||
|
{
|
||||||
|
Tag: String,
|
||||||
|
Atten: Number
|
||||||
|
},
|
||||||
|
{ _id: false }
|
||||||
|
);
|
||||||
|
|
||||||
const lockedWeaponGroupSchema = new Schema<ILockedWeaponGroupDatabase>(
|
const lockedWeaponGroupSchema = new Schema<ILockedWeaponGroupDatabase>(
|
||||||
{
|
{
|
||||||
s: Schema.Types.ObjectId,
|
s: Schema.Types.ObjectId,
|
||||||
@ -1495,6 +1504,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
|
|||||||
CompletedSorties: [String],
|
CompletedSorties: [String],
|
||||||
LastSortieReward: { type: [lastSortieRewardSchema], default: undefined },
|
LastSortieReward: { type: [lastSortieRewardSchema], default: undefined },
|
||||||
LastLiteSortieReward: { type: [lastSortieRewardSchema], default: undefined },
|
LastLiteSortieReward: { type: [lastSortieRewardSchema], default: undefined },
|
||||||
|
SortieRewardAttenuation: { type: [sortieRewardAttenutationSchema], default: undefined },
|
||||||
|
|
||||||
// Resource Extractor Drones
|
// Resource Extractor Drones
|
||||||
Drones: [droneSchema],
|
Drones: [droneSchema],
|
||||||
|
@ -412,7 +412,9 @@ export const addMissionInventoryUpdates = async (
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "SortieId": {
|
case "SortieId": {
|
||||||
|
if (inventory.CompletedSorties.indexOf(value) == -1) {
|
||||||
inventory.CompletedSorties.push(value);
|
inventory.CompletedSorties.push(value);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "SeasonChallengeCompletions": {
|
case "SeasonChallengeCompletions": {
|
||||||
@ -569,7 +571,8 @@ export const addMissionRewards = async (
|
|||||||
RegularCredits: creditDrops,
|
RegularCredits: creditDrops,
|
||||||
VoidTearParticipantsCurrWave: voidTearWave,
|
VoidTearParticipantsCurrWave: voidTearWave,
|
||||||
StrippedItems: strippedItems
|
StrippedItems: strippedItems
|
||||||
}: IMissionInventoryUpdateRequest
|
}: IMissionInventoryUpdateRequest,
|
||||||
|
firstCompletion: boolean
|
||||||
): Promise<AddMissionRewardsReturnType> => {
|
): Promise<AddMissionRewardsReturnType> => {
|
||||||
if (!rewardInfo) {
|
if (!rewardInfo) {
|
||||||
//TODO: if there is a case where you can have credits collected during a mission but no rewardInfo, add credits needs to be handled earlier
|
//TODO: if there is a case where you can have credits collected during a mission but no rewardInfo, add credits needs to be handled earlier
|
||||||
@ -583,22 +586,12 @@ export const addMissionRewards = async (
|
|||||||
}
|
}
|
||||||
|
|
||||||
//TODO: check double reward merging
|
//TODO: check double reward merging
|
||||||
const MissionRewards: IMissionReward[] = getRandomMissionDrops(rewardInfo, wagerTier);
|
const MissionRewards: IMissionReward[] = getRandomMissionDrops(inventory, rewardInfo, wagerTier, firstCompletion);
|
||||||
logger.debug("random mission drops:", MissionRewards);
|
logger.debug("random mission drops:", MissionRewards);
|
||||||
const inventoryChanges: IInventoryChanges = {};
|
const inventoryChanges: IInventoryChanges = {};
|
||||||
const AffiliationMods: IAffiliationMods[] = [];
|
const AffiliationMods: IAffiliationMods[] = [];
|
||||||
let SyndicateXPItemReward;
|
let SyndicateXPItemReward;
|
||||||
|
|
||||||
if (rewardInfo.sortieTag == "Final") {
|
|
||||||
inventory.LastSortieReward = [
|
|
||||||
{
|
|
||||||
SortieId: new Types.ObjectId(rewardInfo.sortieId!.split("_")[1]),
|
|
||||||
StoreItem: MissionRewards[0].StoreItem,
|
|
||||||
Manifest: "/Lotus/Types/Game/MissionDecks/SortieRewards"
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
let missionCompletionCredits = 0;
|
let missionCompletionCredits = 0;
|
||||||
//inventory change is what the client has not rewarded itself, also the client needs to know the credit changes for display
|
//inventory change is what the client has not rewarded itself, also the client needs to know the credit changes for display
|
||||||
if (levelKeyName) {
|
if (levelKeyName) {
|
||||||
@ -962,11 +955,78 @@ function getLevelCreditRewards(node: IRegion): number {
|
|||||||
//TODO: get dark sektor fixed credit rewards and railjack bonus
|
//TODO: get dark sektor fixed credit rewards and railjack bonus
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRandomMissionDrops(RewardInfo: IRewardInfo, tierOverride: number | undefined): IMissionReward[] {
|
function getRandomMissionDrops(
|
||||||
|
inventory: TInventoryDatabaseDocument,
|
||||||
|
RewardInfo: IRewardInfo,
|
||||||
|
tierOverride: number | undefined,
|
||||||
|
firstCompletion: boolean
|
||||||
|
): IMissionReward[] {
|
||||||
const drops: IMissionReward[] = [];
|
const drops: IMissionReward[] = [];
|
||||||
if (RewardInfo.sortieTag == "Final") {
|
if (RewardInfo.sortieTag == "Final" && firstCompletion) {
|
||||||
|
const arr = RewardInfo.sortieId!.split("_");
|
||||||
|
let sortieId = arr[1];
|
||||||
|
if (sortieId == "Lite") {
|
||||||
|
sortieId = arr[2];
|
||||||
|
|
||||||
|
// TODO: Some way to get from sortieId to reward to make this faster + more reliable at week rollover.
|
||||||
|
const boss = getWorldState().LiteSorties[0].Boss as
|
||||||
|
| "SORTIE_BOSS_AMAR"
|
||||||
|
| "SORTIE_BOSS_NIRA"
|
||||||
|
| "SORTIE_BOSS_BOREAL";
|
||||||
|
let crystalType = {
|
||||||
|
SORTIE_BOSS_AMAR: "/Lotus/StoreItems/Types/Gameplay/NarmerSorties/ArchonCrystalAmar",
|
||||||
|
SORTIE_BOSS_NIRA: "/Lotus/StoreItems/Types/Gameplay/NarmerSorties/ArchonCrystalNira",
|
||||||
|
SORTIE_BOSS_BOREAL: "/Lotus/StoreItems/Types/Gameplay/NarmerSorties/ArchonCrystalBoreal"
|
||||||
|
}[boss];
|
||||||
|
const attenTag = {
|
||||||
|
SORTIE_BOSS_AMAR: "NarmerSortieAmarCrystalRewards",
|
||||||
|
SORTIE_BOSS_NIRA: "NarmerSortieNiraCrystalRewards",
|
||||||
|
SORTIE_BOSS_BOREAL: "NarmerSortieBorealCrystalRewards"
|
||||||
|
}[boss];
|
||||||
|
const attenIndex = inventory.SortieRewardAttenuation?.findIndex(x => x.Tag == attenTag) ?? -1;
|
||||||
|
const mythicProbability =
|
||||||
|
0.2 + (inventory.SortieRewardAttenuation?.find(x => x.Tag == attenTag)?.Atten ?? 0);
|
||||||
|
if (Math.random() < mythicProbability) {
|
||||||
|
crystalType += "Mythic";
|
||||||
|
if (attenIndex != -1) {
|
||||||
|
inventory.SortieRewardAttenuation!.splice(attenIndex, 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (attenIndex == -1) {
|
||||||
|
inventory.SortieRewardAttenuation ??= [];
|
||||||
|
inventory.SortieRewardAttenuation.push({
|
||||||
|
Tag: attenTag,
|
||||||
|
Atten: 0.2
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
inventory.SortieRewardAttenuation![attenIndex].Atten += 0.2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drops.push({ StoreItem: crystalType, ItemCount: 1 });
|
||||||
|
|
||||||
|
const drop = getRandomRewardByChance(
|
||||||
|
ExportRewards["/Lotus/Types/Game/MissionDecks/ArchonSortieRewards"][0]
|
||||||
|
)!;
|
||||||
|
drops.push({ StoreItem: drop.type, ItemCount: drop.itemCount });
|
||||||
|
inventory.LastLiteSortieReward = [
|
||||||
|
{
|
||||||
|
SortieId: new Types.ObjectId(sortieId),
|
||||||
|
StoreItem: drop.type,
|
||||||
|
Manifest: "/Lotus/Types/Game/MissionDecks/ArchonSortieRewards"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
} else {
|
||||||
const drop = getRandomRewardByChance(ExportRewards["/Lotus/Types/Game/MissionDecks/SortieRewards"][0])!;
|
const drop = getRandomRewardByChance(ExportRewards["/Lotus/Types/Game/MissionDecks/SortieRewards"][0])!;
|
||||||
drops.push({ StoreItem: drop.type, ItemCount: drop.itemCount });
|
drops.push({ StoreItem: drop.type, ItemCount: drop.itemCount });
|
||||||
|
inventory.LastSortieReward = [
|
||||||
|
{
|
||||||
|
SortieId: new Types.ObjectId(sortieId),
|
||||||
|
StoreItem: drop.type,
|
||||||
|
Manifest: "/Lotus/Types/Game/MissionDecks/SortieRewards"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (RewardInfo.periodicMissionTag?.startsWith("HardDaily")) {
|
if (RewardInfo.periodicMissionTag?.startsWith("HardDaily")) {
|
||||||
drops.push({
|
drops.push({
|
||||||
|
@ -285,6 +285,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
|
|||||||
CompletedSorties: string[];
|
CompletedSorties: string[];
|
||||||
LastSortieReward?: ILastSortieRewardClient[];
|
LastSortieReward?: ILastSortieRewardClient[];
|
||||||
LastLiteSortieReward?: ILastSortieRewardClient[];
|
LastLiteSortieReward?: ILastSortieRewardClient[];
|
||||||
|
SortieRewardAttenuation?: ISortieRewardAttenuation[];
|
||||||
Drones: IDroneClient[];
|
Drones: IDroneClient[];
|
||||||
StepSequencers: IStepSequencer[];
|
StepSequencers: IStepSequencer[];
|
||||||
ActiveAvatarImageType: string;
|
ActiveAvatarImageType: string;
|
||||||
@ -746,6 +747,11 @@ export interface ILastSortieRewardDatabase extends Omit<ILastSortieRewardClient,
|
|||||||
SortieId: Types.ObjectId;
|
SortieId: Types.ObjectId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ISortieRewardAttenuation {
|
||||||
|
Tag: string;
|
||||||
|
Atten: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ILibraryDailyTaskInfo {
|
export interface ILibraryDailyTaskInfo {
|
||||||
EnemyTypes: string[];
|
EnemyTypes: string[];
|
||||||
EnemyLocTag: string;
|
EnemyLocTag: string;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user