feat: credit boosters (+ daily first win) #2324

Merged
Sainan merged 4 commits from daily-first-win into main 2025-06-27 08:20:37 -07:00
8 changed files with 47 additions and 42 deletions
Showing only changes of commit d4e4a29ca0 - Show all commits

View File

@ -1,16 +1,12 @@
import { getAccountForRequest } from "@/src/services/loginService";
import { RequestHandler } from "express"; import { RequestHandler } from "express";
const checkDailyMissionBonusController: RequestHandler = (_req, res) => { export const checkDailyMissionBonusController: RequestHandler = async (req, res) => {
const data = Buffer.from([ const account = await getAccountForRequest(req);
0x44, 0x61, 0x69, 0x6c, 0x79, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x6e, 0x75, 0x73, 0x3a, const today = Math.trunc(Date.now() / 86400000) * 86400;
0x31, 0x2d, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x50, 0x56, 0x50, 0x57, 0x69, 0x6e, 0x42, 0x6f, 0x6e, 0x75, 0x73, if (account.DailyFirstWinDate != today) {
0x3a, 0x31, 0x0a res.send("DailyMissionBonus:1-DailyPVPWinBonus:1\n");
]); } else {
res.writeHead(200, { res.send("DailyMissionBonus:0-DailyPVPWinBonus:1\n");
"Content-Type": "text/html", }
"Content-Length": data.length
});
res.end(data);
}; };
export { checkDailyMissionBonusController };

View File

@ -88,7 +88,7 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
AffiliationMods, AffiliationMods,
SyndicateXPItemReward, SyndicateXPItemReward,
ConquestCompletedMissionsCount ConquestCompletedMissionsCount
} = await addMissionRewards(inventory, missionReport, firstCompletion); } = await addMissionRewards(account, inventory, missionReport, firstCompletion);
if (missionReport.EndOfMatchUpload) { if (missionReport.EndOfMatchUpload) {
inventory.RewardSeed = generateRewardSeed(); inventory.RewardSeed = generateRewardSeed();

View File

@ -26,7 +26,7 @@ export const completeAllMissionsController: RequestHandler = async (req, res) =>
if (mission.Completes == 0) { if (mission.Completes == 0) {
mission.Completes++; mission.Completes++;
if (node.missionReward) { if (node.missionReward) {
addFixedLevelRewards(node.missionReward, inventory, MissionRewards); addFixedLevelRewards(node.missionReward, MissionRewards);
} }
} }
mission.Tier = 1; mission.Tier = 1;

View File

@ -25,7 +25,8 @@ const databaseAccountSchema = new Schema<IDatabaseAccountJson>(
LastLogin: { type: Date, default: 0 }, LastLogin: { type: Date, default: 0 },
LatestEventMessageDate: { type: Date, default: 0 }, LatestEventMessageDate: { type: Date, default: 0 },
LastLoginRewardDate: { type: Number, default: 0 }, LastLoginRewardDate: { type: Number, default: 0 },
LoginDays: { type: Number, default: 1 } LoginDays: { type: Number, default: 1 },
DailyFirstWinDate: { type: Number, default: 0 }
}, },
opts opts
); );

View File

@ -968,6 +968,7 @@ const droptableAliases: Record<string, string> = {
//TODO: return type of partial missioninventoryupdate response //TODO: return type of partial missioninventoryupdate response
export const addMissionRewards = async ( export const addMissionRewards = async (
account: TAccountDocument,
inventory: TInventoryDatabaseDocument, inventory: TInventoryDatabaseDocument,
{ {
wagerTier: wagerTier, wagerTier: wagerTier,
@ -1015,13 +1016,17 @@ export const addMissionRewards = async (
const fixedLevelRewards = getLevelKeyRewards(levelKeyName); const fixedLevelRewards = getLevelKeyRewards(levelKeyName);
//logger.debug(`fixedLevelRewards ${fixedLevelRewards}`); //logger.debug(`fixedLevelRewards ${fixedLevelRewards}`);
if (fixedLevelRewards.levelKeyRewards) { if (fixedLevelRewards.levelKeyRewards) {
addFixedLevelRewards(fixedLevelRewards.levelKeyRewards, inventory, MissionRewards, rewardInfo); missionCompletionCredits += addFixedLevelRewards(
fixedLevelRewards.levelKeyRewards,
MissionRewards,
rewardInfo
);
} }
if (fixedLevelRewards.levelKeyRewards2) { if (fixedLevelRewards.levelKeyRewards2) {
for (const reward of fixedLevelRewards.levelKeyRewards2) { for (const reward of fixedLevelRewards.levelKeyRewards2) {
//quest stage completion credit rewards //quest stage completion credit rewards
if (reward.rewardType == "RT_CREDITS") { if (reward.rewardType == "RT_CREDITS") {
missionCompletionCredits += reward.amount; // will be added to inventory in addCredits missionCompletionCredits += reward.amount;
continue; continue;
} }
MissionRewards.push({ MissionRewards.push({
@ -1050,12 +1055,11 @@ export const addMissionRewards = async (
) { ) {
const levelCreditReward = getLevelCreditRewards(node); const levelCreditReward = getLevelCreditRewards(node);
missionCompletionCredits += levelCreditReward; missionCompletionCredits += levelCreditReward;
inventory.RegularCredits += levelCreditReward;
logger.debug(`levelCreditReward ${levelCreditReward}`); logger.debug(`levelCreditReward ${levelCreditReward}`);
} }
if (node.missionReward) { if (node.missionReward) {
missionCompletionCredits += addFixedLevelRewards(node.missionReward, inventory, MissionRewards, rewardInfo); missionCompletionCredits += addFixedLevelRewards(node.missionReward, MissionRewards, rewardInfo);
} }
if (rewardInfo.sortieTag == "Mission1") { if (rewardInfo.sortieTag == "Mission1") {
@ -1165,7 +1169,9 @@ export const addMissionRewards = async (
combineInventoryChanges(inventoryChanges, inventoryChange.InventoryChanges); combineInventoryChanges(inventoryChanges, inventoryChange.InventoryChanges);
} }
const credits = addCredits(inventory, { inventory.RegularCredits += missionCompletionCredits;
const credits = await addCredits(account, inventory, {
missionCompletionCredits, missionCompletionCredits,
missionDropCredits: creditDrops ?? 0, missionDropCredits: creditDrops ?? 0,
rngRewardCredits: inventoryChanges.RegularCredits ?? 0 rngRewardCredits: inventoryChanges.RegularCredits ?? 0
@ -1390,46 +1396,47 @@ export const addMissionRewards = async (
//creditBonus is not entirely accurate. //creditBonus is not entirely accurate.
//TODO: consider ActiveBoosters //TODO: consider ActiveBoosters
export const addCredits = ( export const addCredits = async (
account: TAccountDocument,
inventory: TInventoryDatabaseDocument, inventory: TInventoryDatabaseDocument,
{ {
missionDropCredits, missionDropCredits,
missionCompletionCredits, missionCompletionCredits,
rngRewardCredits rngRewardCredits
}: { missionDropCredits: number; missionCompletionCredits: number; rngRewardCredits: number } }: { missionDropCredits: number; missionCompletionCredits: number; rngRewardCredits: number }
): IMissionCredits => { ): Promise<IMissionCredits> => {
const hasDailyCreditBonus = true;
const totalCredits = missionDropCredits + missionCompletionCredits + rngRewardCredits;
const finalCredits: IMissionCredits = { const finalCredits: IMissionCredits = {
MissionCredits: [missionDropCredits, missionDropCredits], MissionCredits: [missionDropCredits, missionDropCredits],
CreditBonus: [missionCompletionCredits, missionCompletionCredits], CreditsBonus: [missionCompletionCredits, missionCompletionCredits],
TotalCredits: [totalCredits, totalCredits] TotalCredits: [0, 0]
}; };
if (hasDailyCreditBonus) { const today = Math.trunc(Date.now() / 86400000) * 86400;
if (account.DailyFirstWinDate != today) {
account.DailyFirstWinDate = today;
await account.save();
logger.debug(`daily first win, doubling missionCompletionCredits (${missionCompletionCredits})`);
finalCredits.DailyMissionBonus = true;
inventory.RegularCredits += missionCompletionCredits; inventory.RegularCredits += missionCompletionCredits;
finalCredits.CreditBonus[1] *= 2; finalCredits.CreditsBonus[1] *= 2;
finalCredits.MissionCredits[1] *= 2;
finalCredits.TotalCredits[1] *= 2;
} }
if (!hasDailyCreditBonus) { const totalCredits = finalCredits.MissionCredits[1] + finalCredits.CreditsBonus[1] + rngRewardCredits;
return finalCredits; finalCredits.TotalCredits = [totalCredits, totalCredits];
}
return { ...finalCredits, DailyMissionBonus: true }; return finalCredits;
}; };
export const addFixedLevelRewards = ( export const addFixedLevelRewards = (
rewards: IMissionRewardExternal, rewards: IMissionRewardExternal,
inventory: TInventoryDatabaseDocument,
MissionRewards: IMissionReward[], MissionRewards: IMissionReward[],
rewardInfo?: IRewardInfo rewardInfo?: IRewardInfo
): number => { ): number => {
let missionBonusCredits = 0; let missionBonusCredits = 0;
if (rewards.credits) { if (rewards.credits) {
missionBonusCredits += rewards.credits; missionBonusCredits += rewards.credits;
inventory.RegularCredits += rewards.credits;
} }
if (rewards.items) { if (rewards.items) {
for (const item of rewards.items) { for (const item of rewards.items) {

View File

@ -331,7 +331,7 @@ export const giveKeyChainMissionReward = async (
const fixedLevelRewards = getLevelKeyRewards(missionName); const fixedLevelRewards = getLevelKeyRewards(missionName);
if (fixedLevelRewards.levelKeyRewards) { if (fixedLevelRewards.levelKeyRewards) {
const missionRewards: { StoreItem: string; ItemCount: number }[] = []; const missionRewards: { StoreItem: string; ItemCount: number }[] = [];
addFixedLevelRewards(fixedLevelRewards.levelKeyRewards, inventory, missionRewards); inventory.RegularCredits += addFixedLevelRewards(fixedLevelRewards.levelKeyRewards, missionRewards);
for (const reward of missionRewards) { for (const reward of missionRewards) {
await addItem(inventory, fromStoreItem(reward.StoreItem), reward.ItemCount); await addItem(inventory, fromStoreItem(reward.StoreItem), reward.ItemCount);

View File

@ -25,6 +25,7 @@ export interface IDatabaseAccount extends IDatabaseAccountRequiredFields {
LatestEventMessageDate: Date; LatestEventMessageDate: Date;
LastLoginRewardDate: number; LastLoginRewardDate: number;
LoginDays: number; LoginDays: number;
DailyFirstWinDate: number;
} }
// Includes virtual ID // Includes virtual ID

View File

@ -17,9 +17,9 @@ export interface IMissionReward {
} }
export interface IMissionCredits { export interface IMissionCredits {
MissionCredits: number[]; MissionCredits: [number, number];
CreditBonus: number[]; CreditsBonus: [number, number]; // "Credit Reward"; `CreditsBonus[1]` is `CreditsBonus[0] * 2` if DailyMissionBonus
TotalCredits: number[]; TotalCredits: [number, number];
DailyMissionBonus?: boolean; DailyMissionBonus?: boolean;
} }