feat: credit boosters (+ daily first win) #2324
@ -1,16 +1,12 @@
|
||||
import { getAccountForRequest } from "@/src/services/loginService";
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
const checkDailyMissionBonusController: RequestHandler = (_req, res) => {
|
||||
const data = Buffer.from([
|
||||
0x44, 0x61, 0x69, 0x6c, 0x79, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x6e, 0x75, 0x73, 0x3a,
|
||||
0x31, 0x2d, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x50, 0x56, 0x50, 0x57, 0x69, 0x6e, 0x42, 0x6f, 0x6e, 0x75, 0x73,
|
||||
0x3a, 0x31, 0x0a
|
||||
]);
|
||||
res.writeHead(200, {
|
||||
"Content-Type": "text/html",
|
||||
"Content-Length": data.length
|
||||
});
|
||||
res.end(data);
|
||||
export const checkDailyMissionBonusController: RequestHandler = async (req, res) => {
|
||||
const account = await getAccountForRequest(req);
|
||||
const today = Math.trunc(Date.now() / 86400000) * 86400;
|
||||
if (account.DailyFirstWinDate != today) {
|
||||
res.send("DailyMissionBonus:1-DailyPVPWinBonus:1\n");
|
||||
} else {
|
||||
res.send("DailyMissionBonus:0-DailyPVPWinBonus:1\n");
|
||||
}
|
||||
};
|
||||
|
||||
export { checkDailyMissionBonusController };
|
||||
|
@ -88,7 +88,7 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
|
||||
AffiliationMods,
|
||||
SyndicateXPItemReward,
|
||||
ConquestCompletedMissionsCount
|
||||
} = await addMissionRewards(inventory, missionReport, firstCompletion);
|
||||
} = await addMissionRewards(account, inventory, missionReport, firstCompletion);
|
||||
|
||||
if (missionReport.EndOfMatchUpload) {
|
||||
inventory.RewardSeed = generateRewardSeed();
|
||||
|
@ -26,7 +26,7 @@ export const completeAllMissionsController: RequestHandler = async (req, res) =>
|
||||
if (mission.Completes == 0) {
|
||||
mission.Completes++;
|
||||
if (node.missionReward) {
|
||||
addFixedLevelRewards(node.missionReward, inventory, MissionRewards);
|
||||
addFixedLevelRewards(node.missionReward, MissionRewards);
|
||||
}
|
||||
}
|
||||
mission.Tier = 1;
|
||||
|
@ -23,9 +23,9 @@ export const setBoosterController: RequestHandler = async (req, res) => {
|
||||
res.status(400).send("Invalid ItemType provided.");
|
||||
return;
|
||||
}
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
const now = Math.trunc(Date.now() / 1000);
|
||||
for (const { ItemType, ExpiryDate } of requests) {
|
||||
if (ExpiryDate < now) {
|
||||
if (ExpiryDate <= now) {
|
||||
// remove expired boosters
|
||||
const index = boosters.findIndex(item => item.ItemType === ItemType);
|
||||
if (index !== -1) {
|
||||
|
@ -25,7 +25,8 @@ const databaseAccountSchema = new Schema<IDatabaseAccountJson>(
|
||||
LastLogin: { type: Date, default: 0 },
|
||||
LatestEventMessageDate: { type: Date, default: 0 },
|
||||
LastLoginRewardDate: { type: Number, default: 0 },
|
||||
LoginDays: { type: Number, default: 1 }
|
||||
LoginDays: { type: Number, default: 1 },
|
||||
DailyFirstWinDate: { type: Number, default: 0 }
|
||||
},
|
||||
opts
|
||||
);
|
||||
|
@ -968,6 +968,7 @@ const droptableAliases: Record<string, string> = {
|
||||
|
||||
//TODO: return type of partial missioninventoryupdate response
|
||||
export const addMissionRewards = async (
|
||||
account: TAccountDocument,
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
{
|
||||
wagerTier: wagerTier,
|
||||
@ -1015,13 +1016,17 @@ export const addMissionRewards = async (
|
||||
const fixedLevelRewards = getLevelKeyRewards(levelKeyName);
|
||||
//logger.debug(`fixedLevelRewards ${fixedLevelRewards}`);
|
||||
if (fixedLevelRewards.levelKeyRewards) {
|
||||
addFixedLevelRewards(fixedLevelRewards.levelKeyRewards, inventory, MissionRewards, rewardInfo);
|
||||
missionCompletionCredits += addFixedLevelRewards(
|
||||
fixedLevelRewards.levelKeyRewards,
|
||||
MissionRewards,
|
||||
rewardInfo
|
||||
);
|
||||
}
|
||||
if (fixedLevelRewards.levelKeyRewards2) {
|
||||
for (const reward of fixedLevelRewards.levelKeyRewards2) {
|
||||
//quest stage completion credit rewards
|
||||
if (reward.rewardType == "RT_CREDITS") {
|
||||
missionCompletionCredits += reward.amount; // will be added to inventory in addCredits
|
||||
missionCompletionCredits += reward.amount;
|
||||
continue;
|
||||
}
|
||||
MissionRewards.push({
|
||||
@ -1050,12 +1055,11 @@ export const addMissionRewards = async (
|
||||
) {
|
||||
const levelCreditReward = getLevelCreditRewards(node);
|
||||
missionCompletionCredits += levelCreditReward;
|
||||
inventory.RegularCredits += levelCreditReward;
|
||||
logger.debug(`levelCreditReward ${levelCreditReward}`);
|
||||
}
|
||||
|
||||
if (node.missionReward) {
|
||||
missionCompletionCredits += addFixedLevelRewards(node.missionReward, inventory, MissionRewards, rewardInfo);
|
||||
missionCompletionCredits += addFixedLevelRewards(node.missionReward, MissionRewards, rewardInfo);
|
||||
}
|
||||
|
||||
if (rewardInfo.sortieTag == "Mission1") {
|
||||
@ -1165,7 +1169,9 @@ export const addMissionRewards = async (
|
||||
combineInventoryChanges(inventoryChanges, inventoryChange.InventoryChanges);
|
||||
}
|
||||
|
||||
const credits = addCredits(inventory, {
|
||||
inventory.RegularCredits += missionCompletionCredits;
|
||||
|
||||
const credits = await addCredits(account, inventory, {
|
||||
missionCompletionCredits,
|
||||
missionDropCredits: creditDrops ?? 0,
|
||||
rngRewardCredits: inventoryChanges.RegularCredits ?? 0
|
||||
@ -1388,48 +1394,61 @@ export const addMissionRewards = async (
|
||||
};
|
||||
};
|
||||
|
||||
//creditBonus is not entirely accurate.
|
||||
//TODO: consider ActiveBoosters
|
||||
export const addCredits = (
|
||||
export const addCredits = async (
|
||||
account: TAccountDocument,
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
{
|
||||
missionDropCredits,
|
||||
missionCompletionCredits,
|
||||
rngRewardCredits
|
||||
}: { missionDropCredits: number; missionCompletionCredits: number; rngRewardCredits: number }
|
||||
): IMissionCredits => {
|
||||
const hasDailyCreditBonus = true;
|
||||
const totalCredits = missionDropCredits + missionCompletionCredits + rngRewardCredits;
|
||||
|
||||
): Promise<IMissionCredits> => {
|
||||
const finalCredits: IMissionCredits = {
|
||||
MissionCredits: [missionDropCredits, missionDropCredits],
|
||||
CreditBonus: [missionCompletionCredits, missionCompletionCredits],
|
||||
TotalCredits: [totalCredits, totalCredits]
|
||||
CreditsBonus: [missionCompletionCredits, missionCompletionCredits],
|
||||
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;
|
||||
finalCredits.CreditBonus[1] *= 2;
|
||||
finalCredits.MissionCredits[1] *= 2;
|
||||
finalCredits.TotalCredits[1] *= 2;
|
||||
finalCredits.CreditsBonus[1] *= 2;
|
||||
}
|
||||
|
||||
if (!hasDailyCreditBonus) {
|
||||
return finalCredits;
|
||||
const totalCredits = finalCredits.MissionCredits[1] + finalCredits.CreditsBonus[1] + rngRewardCredits;
|
||||
finalCredits.TotalCredits = [totalCredits, totalCredits];
|
||||
|
||||
if (config.worldState?.creditBoost) {
|
||||
inventory.RegularCredits += finalCredits.TotalCredits[1];
|
||||
finalCredits.TotalCredits[1] += finalCredits.TotalCredits[1];
|
||||
}
|
||||
return { ...finalCredits, DailyMissionBonus: true };
|
||||
const now = Math.trunc(Date.now() / 1000); // TOVERIFY: Should we maybe subtract mission time as to apply credit boosters that expired during mission?
|
||||
if ((inventory.Boosters.find(x => x.ItemType == "/Lotus/Types/Boosters/CreditBooster")?.ExpiryDate ?? 0) > now) {
|
||||
inventory.RegularCredits += finalCredits.TotalCredits[1];
|
||||
finalCredits.TotalCredits[1] += finalCredits.TotalCredits[1];
|
||||
}
|
||||
if ((inventory.Boosters.find(x => x.ItemType == "/Lotus/Types/Boosters/CreditBlessing")?.ExpiryDate ?? 0) > now) {
|
||||
inventory.RegularCredits += finalCredits.TotalCredits[1];
|
||||
finalCredits.TotalCredits[1] += finalCredits.TotalCredits[1];
|
||||
}
|
||||
|
||||
return finalCredits;
|
||||
};
|
||||
|
||||
export const addFixedLevelRewards = (
|
||||
rewards: IMissionRewardExternal,
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
MissionRewards: IMissionReward[],
|
||||
rewardInfo?: IRewardInfo
|
||||
): number => {
|
||||
let missionBonusCredits = 0;
|
||||
if (rewards.credits) {
|
||||
missionBonusCredits += rewards.credits;
|
||||
inventory.RegularCredits += rewards.credits;
|
||||
}
|
||||
if (rewards.items) {
|
||||
for (const item of rewards.items) {
|
||||
|
@ -331,7 +331,7 @@ export const giveKeyChainMissionReward = async (
|
||||
const fixedLevelRewards = getLevelKeyRewards(missionName);
|
||||
if (fixedLevelRewards.levelKeyRewards) {
|
||||
const missionRewards: { StoreItem: string; ItemCount: number }[] = [];
|
||||
addFixedLevelRewards(fixedLevelRewards.levelKeyRewards, inventory, missionRewards);
|
||||
inventory.RegularCredits += addFixedLevelRewards(fixedLevelRewards.levelKeyRewards, missionRewards);
|
||||
|
||||
for (const reward of missionRewards) {
|
||||
await addItem(inventory, fromStoreItem(reward.StoreItem), reward.ItemCount);
|
||||
|
@ -25,6 +25,7 @@ export interface IDatabaseAccount extends IDatabaseAccountRequiredFields {
|
||||
LatestEventMessageDate: Date;
|
||||
LastLoginRewardDate: number;
|
||||
LoginDays: number;
|
||||
DailyFirstWinDate: number;
|
||||
}
|
||||
|
||||
// Includes virtual ID
|
||||
|
@ -17,9 +17,9 @@ export interface IMissionReward {
|
||||
}
|
||||
|
||||
export interface IMissionCredits {
|
||||
MissionCredits: number[];
|
||||
CreditBonus: number[];
|
||||
TotalCredits: number[];
|
||||
MissionCredits: [number, number];
|
||||
CreditsBonus: [number, number]; // "Credit Reward"; `CreditsBonus[1]` is `CreditsBonus[0] * 2` if DailyMissionBonus
|
||||
TotalCredits: [number, number];
|
||||
DailyMissionBonus?: boolean;
|
||||
}
|
||||
|
||||
|
@ -2275,14 +2275,13 @@ function doAcquireBoosters() {
|
||||
const ExpiryDate = Date.now() / 1000 + 3 * 24 * 60 * 60; // default 3 days
|
||||
setBooster(uniqueName, ExpiryDate, () => {
|
||||
$("#acquire-type-Boosters").val("");
|
||||
updateInventory();
|
||||
});
|
||||
}
|
||||
|
||||
function doChangeBoosterExpiry(ItemType, ExpiryDateInput) {
|
||||
console.log("Changing booster expiry for", ItemType, "to", ExpiryDateInput.value);
|
||||
// cast local datetime string to unix timestamp
|
||||
const ExpiryDate = new Date(ExpiryDateInput.value).getTime() / 1000;
|
||||
const ExpiryDate = Math.trunc(new Date(ExpiryDateInput.value).getTime() / 1000);
|
||||
if (isNaN(ExpiryDate)) {
|
||||
ExpiryDateInput.addClass("is-invalid").focus();
|
||||
return false;
|
||||
|
Loading…
x
Reference in New Issue
Block a user