chore: use ideal time when going backwards to satisfy constraints (#2438)
"Before next expected world state refresh" is now used as a bare minimum constraint. If it cannot be met, we align to the ideal second. Compromising when multiple constraints are in use to avoid having to go back like 7 years, as this would break navigation. Closes #2434 Reviewed-on: #2438 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
This commit is contained in:
parent
7aa1b12306
commit
98ed2b5ee4
@ -1033,75 +1033,124 @@ const pushVoidStorms = (arr: IVoidStorm[], hour: number): void => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const doesTimeSatsifyConstraints = (timeSecs: number): boolean => {
|
interface ITimeConstraint {
|
||||||
if (config.worldState?.eidolonOverride) {
|
//name: string;
|
||||||
|
isValidTime: (timeSecs: number) => boolean;
|
||||||
|
getIdealTimeBefore: (timeSecs: number) => number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const eidolonDayConstraint: ITimeConstraint = {
|
||||||
|
//name: "eidolon day",
|
||||||
|
isValidTime: (timeSecs: number): boolean => {
|
||||||
const eidolonEpoch = 1391992660;
|
const eidolonEpoch = 1391992660;
|
||||||
const eidolonCycle = Math.trunc((timeSecs - eidolonEpoch) / 9000);
|
const eidolonCycle = Math.trunc((timeSecs - eidolonEpoch) / 9000);
|
||||||
const eidolonCycleStart = eidolonEpoch + eidolonCycle * 9000;
|
const eidolonCycleStart = eidolonEpoch + eidolonCycle * 9000;
|
||||||
const eidolonCycleEnd = eidolonCycleStart + 9000;
|
const eidolonCycleEnd = eidolonCycleStart + 9000;
|
||||||
const eidolonCycleNightStart = eidolonCycleEnd - 3000;
|
const eidolonCycleNightStart = eidolonCycleEnd - 3000;
|
||||||
if (config.worldState.eidolonOverride == "day") {
|
return !isBeforeNextExpectedWorldStateRefresh(timeSecs * 1000, eidolonCycleNightStart * 1000);
|
||||||
if (
|
},
|
||||||
//timeSecs < eidolonCycleStart ||
|
getIdealTimeBefore: (timeSecs: number): number => {
|
||||||
isBeforeNextExpectedWorldStateRefresh(timeSecs * 1000, eidolonCycleNightStart * 1000)
|
const eidolonEpoch = 1391992660;
|
||||||
) {
|
const eidolonCycle = Math.trunc((timeSecs - eidolonEpoch) / 9000);
|
||||||
return false;
|
const eidolonCycleStart = eidolonEpoch + eidolonCycle * 9000;
|
||||||
}
|
return eidolonCycleStart;
|
||||||
} else {
|
|
||||||
if (
|
|
||||||
timeSecs < eidolonCycleNightStart ||
|
|
||||||
isBeforeNextExpectedWorldStateRefresh(timeSecs * 1000, eidolonCycleEnd * 1000)
|
|
||||||
) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (config.worldState?.vallisOverride) {
|
const eidolonNightConstraint: ITimeConstraint = {
|
||||||
|
//name: "eidolon night",
|
||||||
|
isValidTime: (timeSecs: number): boolean => {
|
||||||
|
const eidolonEpoch = 1391992660;
|
||||||
|
const eidolonCycle = Math.trunc((timeSecs - eidolonEpoch) / 9000);
|
||||||
|
const eidolonCycleStart = eidolonEpoch + eidolonCycle * 9000;
|
||||||
|
const eidolonCycleEnd = eidolonCycleStart + 9000;
|
||||||
|
const eidolonCycleNightStart = eidolonCycleEnd - 3000;
|
||||||
|
return (
|
||||||
|
timeSecs >= eidolonCycleNightStart &&
|
||||||
|
!isBeforeNextExpectedWorldStateRefresh(timeSecs * 1000, eidolonCycleEnd * 1000)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
getIdealTimeBefore: (timeSecs: number): number => {
|
||||||
|
const eidolonEpoch = 1391992660;
|
||||||
|
const eidolonCycle = Math.trunc((timeSecs - eidolonEpoch) / 9000);
|
||||||
|
const eidolonCycleStart = eidolonEpoch + eidolonCycle * 9000;
|
||||||
|
const eidolonCycleEnd = eidolonCycleStart + 9000;
|
||||||
|
const eidolonCycleNightStart = eidolonCycleEnd - 3000;
|
||||||
|
if (eidolonCycleNightStart > timeSecs) {
|
||||||
|
// Night hasn't started yet, but we need to return a time in the past.
|
||||||
|
return eidolonCycleNightStart - 9000;
|
||||||
|
}
|
||||||
|
return eidolonCycleNightStart;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const venusColdConstraint: ITimeConstraint = {
|
||||||
|
//name: "venus cold",
|
||||||
|
isValidTime: (timeSecs: number): boolean => {
|
||||||
const vallisEpoch = 1541837628;
|
const vallisEpoch = 1541837628;
|
||||||
const vallisCycle = Math.trunc((timeSecs - vallisEpoch) / 1600);
|
const vallisCycle = Math.trunc((timeSecs - vallisEpoch) / 1600);
|
||||||
const vallisCycleStart = vallisEpoch + vallisCycle * 1600;
|
const vallisCycleStart = vallisEpoch + vallisCycle * 1600;
|
||||||
const vallisCycleEnd = vallisCycleStart + 1600;
|
const vallisCycleEnd = vallisCycleStart + 1600;
|
||||||
const vallisCycleColdStart = vallisCycleStart + 400;
|
const vallisCycleColdStart = vallisCycleStart + 400;
|
||||||
if (config.worldState.vallisOverride == "cold") {
|
return (
|
||||||
if (
|
timeSecs >= vallisCycleColdStart &&
|
||||||
timeSecs < vallisCycleColdStart ||
|
!isBeforeNextExpectedWorldStateRefresh(timeSecs * 1000, vallisCycleEnd * 1000)
|
||||||
isBeforeNextExpectedWorldStateRefresh(timeSecs * 1000, vallisCycleEnd * 1000)
|
);
|
||||||
) {
|
},
|
||||||
return false;
|
getIdealTimeBefore: (timeSecs: number): number => {
|
||||||
}
|
const vallisEpoch = 1541837628;
|
||||||
} else {
|
const vallisCycle = Math.trunc((timeSecs - vallisEpoch) / 1600);
|
||||||
if (
|
const vallisCycleStart = vallisEpoch + vallisCycle * 1600;
|
||||||
//timeSecs < vallisCycleStart ||
|
const vallisCycleColdStart = vallisCycleStart + 400;
|
||||||
isBeforeNextExpectedWorldStateRefresh(timeSecs * 1000, vallisCycleColdStart * 1000)
|
if (vallisCycleColdStart > timeSecs) {
|
||||||
) {
|
// Cold hasn't started yet, but we need to return a time in the past.
|
||||||
return false;
|
return vallisCycleColdStart - 1600;
|
||||||
|
}
|
||||||
|
return vallisCycleColdStart;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const venusWarmConstraint: ITimeConstraint = {
|
||||||
|
//name: "venus warm",
|
||||||
|
isValidTime: (timeSecs: number): boolean => {
|
||||||
|
const vallisEpoch = 1541837628;
|
||||||
|
const vallisCycle = Math.trunc((timeSecs - vallisEpoch) / 1600);
|
||||||
|
const vallisCycleStart = vallisEpoch + vallisCycle * 1600;
|
||||||
|
const vallisCycleColdStart = vallisCycleStart + 400;
|
||||||
|
return !isBeforeNextExpectedWorldStateRefresh(timeSecs * 1000, vallisCycleColdStart * 1000);
|
||||||
|
},
|
||||||
|
getIdealTimeBefore: (timeSecs: number): number => {
|
||||||
|
const vallisEpoch = 1541837628;
|
||||||
|
const vallisCycle = Math.trunc((timeSecs - vallisEpoch) / 1600);
|
||||||
|
const vallisCycleStart = vallisEpoch + vallisCycle * 1600;
|
||||||
|
return vallisCycleStart;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getIdealTimeSatsifyingConstraints = (constraints: ITimeConstraint[]): number => {
|
||||||
|
let timeSecs = Math.trunc(Date.now() / 1000);
|
||||||
|
let allGood;
|
||||||
|
do {
|
||||||
|
allGood = true;
|
||||||
|
for (const constraint of constraints) {
|
||||||
|
if (!constraint.isValidTime(timeSecs)) {
|
||||||
|
//logger.debug(`${constraint.name} is not happy with ${timeSecs}`);
|
||||||
|
const prevTimeSecs = timeSecs;
|
||||||
|
const suggestion = constraint.getIdealTimeBefore(timeSecs);
|
||||||
|
timeSecs = suggestion;
|
||||||
|
do {
|
||||||
|
timeSecs += 60;
|
||||||
|
if (timeSecs >= prevTimeSecs || !constraint.isValidTime(timeSecs)) {
|
||||||
|
timeSecs = suggestion; // Can't find a compromise; just take the suggestion and try to compromise on another constraint.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (!constraints.every(constraint => constraint.isValidTime(timeSecs)));
|
||||||
|
allGood = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} while (!allGood);
|
||||||
|
return timeSecs;
|
||||||
if (config.worldState?.duviriOverride) {
|
|
||||||
const duviriMoods = ["sorrow", "fear", "joy", "anger", "envy"];
|
|
||||||
const desiredMood = duviriMoods.indexOf(config.worldState.duviriOverride);
|
|
||||||
if (desiredMood == -1) {
|
|
||||||
logger.warn(`ignoring invalid config value for worldState.duviriOverride`, {
|
|
||||||
value: config.worldState.duviriOverride,
|
|
||||||
valid_values: duviriMoods
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const moodIndex = Math.trunc(timeSecs / 7200);
|
|
||||||
const moodStart = moodIndex * 7200;
|
|
||||||
const moodEnd = moodStart + 7200;
|
|
||||||
if (
|
|
||||||
moodIndex % 5 != desiredMood ||
|
|
||||||
isBeforeNextExpectedWorldStateRefresh(timeSecs * 1000, moodEnd * 1000)
|
|
||||||
) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const getVarziaRotation = (week: number): string => {
|
const getVarziaRotation = (week: number): string => {
|
||||||
@ -1179,10 +1228,38 @@ const getAllVarziaManifests = (): IPrimeVaultTraderOffer[] => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getWorldState = (buildLabel?: string): IWorldState => {
|
export const getWorldState = (buildLabel?: string): IWorldState => {
|
||||||
let timeSecs = Math.round(Date.now() / 1000);
|
const constraints: ITimeConstraint[] = [];
|
||||||
while (!doesTimeSatsifyConstraints(timeSecs)) {
|
if (config.worldState?.eidolonOverride) {
|
||||||
timeSecs -= 60;
|
constraints.push(config.worldState.eidolonOverride == "day" ? eidolonDayConstraint : eidolonNightConstraint);
|
||||||
}
|
}
|
||||||
|
if (config.worldState?.vallisOverride) {
|
||||||
|
constraints.push(config.worldState.vallisOverride == "cold" ? venusColdConstraint : venusWarmConstraint);
|
||||||
|
}
|
||||||
|
if (config.worldState?.duviriOverride) {
|
||||||
|
const duviriMoods = ["sorrow", "fear", "joy", "anger", "envy"];
|
||||||
|
const desiredMood = duviriMoods.indexOf(config.worldState.duviriOverride);
|
||||||
|
if (desiredMood == -1) {
|
||||||
|
logger.warn(`ignoring invalid config value for worldState.duviriOverride`, {
|
||||||
|
value: config.worldState.duviriOverride,
|
||||||
|
valid_values: duviriMoods
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
constraints.push({
|
||||||
|
//name: `duviri ${config.worldState.duviriOverride}`,
|
||||||
|
isValidTime: (timeSecs: number): boolean => {
|
||||||
|
const moodIndex = Math.trunc(timeSecs / 7200);
|
||||||
|
return moodIndex % 5 == desiredMood;
|
||||||
|
},
|
||||||
|
getIdealTimeBefore: (timeSecs: number): number => {
|
||||||
|
let moodIndex = Math.trunc(timeSecs / 7200);
|
||||||
|
moodIndex -= ((moodIndex % 5) - desiredMood + 5) % 5; // while (moodIndex % 5 != desiredMood) --moodIndex;
|
||||||
|
const moodStart = moodIndex * 7200;
|
||||||
|
return moodStart;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const timeSecs = getIdealTimeSatsifyingConstraints(constraints);
|
||||||
const timeMs = timeSecs * 1000;
|
const timeMs = timeSecs * 1000;
|
||||||
const day = Math.trunc((timeMs - EPOCH) / 86400000);
|
const day = Math.trunc((timeMs - EPOCH) / 86400000);
|
||||||
const week = Math.trunc(day / 7);
|
const week = Math.trunc(day / 7);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user