返回提交历史
Modified
config-vanilla.json
+2
-0
Modified
src/services/configService.ts
+2
-0
Modified
src/services/missionInventoryUpdateService.ts
+107
-47
Modified
src/services/worldStateService.ts
+83
-2
Modified
src/types/worldStateTypes.ts
+8
-4
Modified
static/webui/index.html
+19
-0
Modified
static/webui/translations/de.js
+2
-0
Modified
static/webui/translations/en.js
+2
-0
Modified
static/webui/translations/es.js
+2
-0
Modified
static/webui/translations/fr.js
+2
-0
Modified
static/webui/translations/ru.js
+2
-0
Modified
static/webui/translations/uk.js
+2
-0
Modified
static/webui/translations/zh.js
+2
-0
XFEstudio/XFESpaceNinjaServer
feat: thermia fractures (#2670)
Re #1103 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/2670 Reviewed-by: Sainan <63328889+sainan@users.noreply.github.com> Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
7dc44e81
代码差异
13 个文件
+235
-53
@@ -86,6 +86,8 @@
86
86
"bellyOfTheBeastProgressOverride": 0,
87
87
"eightClaw": false,
88
88
"eightClawProgressOverride": 0,
89
"thermiaFracturesOverride": null,
90
"thermiaFracturesProgressOverride": 0,
89
91
"eidolonOverride": "",
90
92
"vallisOverride": "",
91
93
"duviriOverride": "",
@@ -98,6 +98,8 @@ export interface IConfig {
98
98
bellyOfTheBeastProgressOverride?: number;
99
99
eightClaw?: boolean;
100
100
eightClawProgressOverride?: number;
101
thermiaFracturesOverride?: boolean;
102
thermiaFracturesProgressOverride?: number;
101
103
eidolonOverride?: string;
102
104
vallisOverride?: string;
103
105
duviriOverride?: string;
@@ -640,7 +640,7 @@ export const addMissionInventoryUpdates = async (
640
640
}
641
641
642
642
const currentNode = inventoryUpdates.RewardInfo!.node;
643
let currentMissionKey;
643
let currentMissionKey: string | undefined;
644
644
if (currentNode == goal.Node) {
645
645
currentMissionKey = goal.MissionKeyName;
646
646
} else if (goal.ConcurrentNodes && goal.ConcurrentMissionKeyNames) {
@@ -651,15 +651,15 @@ export const addMissionInventoryUpdates = async (
651
651
}
652
652
}
653
653
}
654
if (currentMissionKey && currentMissionKey in goalMessagesByKey) {
655
let countBeforeUpload = goalProgress?.Count ?? 0;
656
let totalCount = countBeforeUpload + uploadProgress.Count;
657
if (goal.Best) {
658
countBeforeUpload = goalProgress?.Best ?? 0;
659
totalCount = uploadProgress.Best;
660
}
661
let reward;
654
const rewards = [];
655
let countBeforeUpload = goalProgress?.Count ?? 0;
656
let totalCount = countBeforeUpload + uploadProgress.Count;
657
if (goal.Best) {
658
countBeforeUpload = goalProgress?.Best ?? 0;
659
totalCount = uploadProgress.Best;
660
}
662
661
662
{
663
663
if (goal.InterimGoals && goal.InterimRewards) {
664
664
for (let i = 0; i < goal.InterimGoals.length; i++) {
665
665
if (
@@ -668,70 +668,95 @@ export const addMissionInventoryUpdates = async (
668
668
(!goalProgress || countBeforeUpload < goal.InterimGoals[i]) &&
669
669
goal.InterimRewards[i]
670
670
) {
671
reward = goal.InterimRewards[i];
671
rewards.push(goal.InterimRewards[i]);
672
672
break;
673
673
}
674
674
}
675
675
}
676
676
if (
677
!reward &&
678
677
goal.Goal &&
679
678
goal.Goal <= totalCount &&
680
679
(!goalProgress || countBeforeUpload < goal.Goal) &&
681
680
goal.Reward
682
681
) {
683
reward = goal.Reward;
682
rewards.push(goal.Reward);
684
683
}
685
684
if (
686
!reward &&
687
685
goal.BonusGoal &&
688
686
goal.BonusGoal <= totalCount &&
689
687
(!goalProgress || countBeforeUpload < goal.BonusGoal) &&
690
688
goal.BonusReward
691
689
) {
692
reward = goal.BonusReward;
690
rewards.push(goal.BonusReward);
693
691
}
694
if (reward) {
695
if (currentMissionKey in goalMessagesByKey) {
696
// Send reward via inbox
697
const info = goalMessagesByKey[currentMissionKey];
698
const message: IMessageCreationTemplate = {
699
sndr: info.sndr,
700
msg: info.msg,
701
sub: info.sub,
702
icon: info.icon,
703
highPriority: true
704
};
692
}
705
693
706
if (reward.items) {
707
message.att = reward.items.map(x => (isStoreItem(x) ? fromStoreItem(x) : x));
708
}
709
if (reward.countedItems) {
710
message.countedAtt = reward.countedItems;
711
}
712
if (reward.credits) {
713
message.RegularCredits = reward.credits;
714
}
715
if (info.arg) {
716
const args: Record<string, string | number> = {
717
PLAYER_NAME: account.DisplayName,
718
CREDIT_REWARD: reward.credits ?? 0
719
};
694
const messages: IMessageCreationTemplate[] = [];
695
const infos: {
696
sndr: string;
697
msg: string;
698
sub: string;
699
icon: string;
700
arg?: string[];
701
}[] = [];
720
702
721
info.arg.forEach(key => {
722
const value = args[key];
723
if (value) {
724
message.arg ??= [];
725
message.arg.push({ Key: key, Tag: value });
726
}
727
});
703
{
704
if (currentMissionKey && currentMissionKey in goalMessagesByKey) {
705
infos.push(goalMessagesByKey[currentMissionKey]);
706
} else if (goal.Tag in goalMessagesByTag) {
707
const combinedGoals = [...(goal.InterimGoals || []), goal.Goal, goal.BonusGoal];
708
combinedGoals.forEach((n, i) => {
709
if (n !== undefined && n > countBeforeUpload && n <= totalCount) {
710
infos.push(goalMessagesByTag[goal.Tag][i]);
728
711
}
712
});
713
}
714
}
729
715
730
await createMessage(inventory.accountOwnerId, [message]);
716
for (let i = 0; i < rewards.length; i++) {
717
if (infos[i]) {
718
const info = infos[i];
719
const reward = rewards[i];
720
const message: IMessageCreationTemplate = {
721
sndr: info.sndr,
722
msg: info.msg,
723
sub: info.sub,
724
icon: info.icon,
725
highPriority: true
726
};
727
if (reward.items) {
728
message.att = reward.items.map(x => (isStoreItem(x) ? fromStoreItem(x) : x));
729
}
730
if (reward.countedItems) {
731
message.countedAtt = reward.countedItems;
732
}
733
if (reward.credits) {
734
message.RegularCredits = reward.credits;
731
735
}
736
if (info.arg) {
737
const args: Record<string, string | number> = {
738
PLAYER_NAME: account.DisplayName,
739
CREDIT_REWARD: reward.credits ?? 0
740
};
741
742
for (let j = 0; j < info.arg.length; j++) {
743
const key = info.arg[j];
744
const value = args[key];
745
if (value) {
746
message.arg ??= [];
747
message.arg.push({
748
Key: key,
749
Tag: value
750
});
751
}
752
}
753
}
754
messages.push(message);
732
755
}
733
756
}
734
757
758
if (messages.length > 0) await createMessage(inventory.accountOwnerId, messages);
759
735
760
if (goalProgress) {
736
761
goalProgress.Best = Math.max(goalProgress.Best!, uploadProgress.Best);
737
762
goalProgress.Count += uploadProgress.Count;
@@ -2617,3 +2642,38 @@ const goalMessagesByKey: Record<string, { sndr: string; msg: string; sub: string
2617
2642
arg: ["PLAYER_NAME"]
2618
2643
}
2619
2644
};
2645
2646
const goalMessagesByTag: Record<string, { sndr: string; msg: string; sub: string; icon: string; arg?: string[] }[]> = {
2647
HeatFissure: [
2648
{
2649
sndr: "/Lotus/Language/Npcs/Eudico",
2650
msg: "/Lotus/Language/Messages/OrbHeistEventRewardAInboxMessageBody",
2651
sub: "/Lotus/Language/Messages/OrbHeistEventRewardAInboxMessageTitle",
2652
icon: "/Lotus/Interface/Icons/Npcs/Eudico.png"
2653
},
2654
{
2655
sndr: "/Lotus/Language/Npcs/Eudico",
2656
msg: "/Lotus/Language/Messages/OrbHeistEventRewardBInboxMessageBody",
2657
sub: "/Lotus/Language/Messages/OrbHeistEventRewardBInboxMessageTitle",
2658
icon: "/Lotus/Interface/Icons/Npcs/Eudico.png"
2659
},
2660
{
2661
sndr: "/Lotus/Language/Npcs/Eudico",
2662
msg: "/Lotus/Language/Messages/OrbHeistEventRewardCInboxMessageBody",
2663
sub: "/Lotus/Language/Messages/OrbHeistEventRewardCInboxMessageTitle",
2664
icon: "/Lotus/Interface/Icons/Npcs/Eudico.png"
2665
},
2666
{
2667
sndr: "/Lotus/Language/Npcs/Eudico",
2668
msg: "/Lotus/Language/Messages/OrbHeistEventRewardDInboxMessageBody",
2669
sub: "/Lotus/Language/Messages/OrbHeistEventRewardDInboxMessageTitle",
2670
icon: "/Lotus/Interface/Icons/Npcs/Eudico.png"
2671
},
2672
{
2673
sndr: "/Lotus/Language/Npcs/Eudico",
2674
msg: "/Lotus/Language/Messages/OrbHeistEventRewardEInboxMessageBody",
2675
sub: "/Lotus/Language/Messages/OrbHeistEventRewardEInboxMessageTitle",
2676
icon: "/Lotus/Interface/Icons/Npcs/Eudico.png"
2677
}
2678
]
2679
};
@@ -2629,6 +2629,87 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
2629
2629
);
2630
2630
}
2631
2631
2632
const thermiaFracturesCycleDay = day % 32;
2633
const isThermiaFracturesActive = thermiaFracturesCycleDay < 14;
2634
if (config.worldState?.thermiaFracturesOverride ?? isThermiaFracturesActive) {
2635
const activeStartDay = day - thermiaFracturesCycleDay;
2636
2637
const count = config.worldState?.thermiaFracturesProgressOverride ?? 0;
2638
const activation = config.worldState?.thermiaFracturesOverride ? 1740416400000 : getSortieTime(activeStartDay);
2639
const expiry = config.worldState?.thermiaFracturesOverride ? 2000000000000 : getSortieTime(activeStartDay + 14);
2640
2641
worldState.Goals.push({
2642
_id: { $oid: "5c7cb0d00000000000000000" },
2643
Activation: { $date: { $numberLong: activation.toString() } },
2644
Expiry: { $date: { $numberLong: expiry.toString() } },
2645
Node: "SolNode129",
2646
ScoreVar: "FissuresClosed",
2647
ScoreLocTag: "/Lotus/Language/G1Quests/HeatFissuresEventScore",
2648
Count: count,
2649
HealthPct: count / 100,
2650
Regions: [1],
2651
Desc: "/Lotus/Language/G1Quests/HeatFissuresEventName",
2652
ToolTip: "/Lotus/Language/G1Quests/HeatFissuresEventDesc",
2653
OptionalInMission: true,
2654
Tag: "HeatFissure",
2655
UpgradeIds: [{ $oid: "5c81cefa4c4566791728eaa7" }, { $oid: "5c81cefa4c4566791728eaa6" }],
2656
Personal: true,
2657
Community: true,
2658
Goal: 100,
2659
Reward: {
2660
items: ["/Lotus/StoreItems/Weapons/Corpus/LongGuns/CrpBFG/Vandal/VandalCrpBFG"]
2661
},
2662
InterimGoals: [5, 25, 50, 75],
2663
InterimRewards: [
2664
{ items: ["/Lotus/StoreItems/Upgrades/Skins/Clan/OrbBadgeItem"] },
2665
{
2666
items: [
2667
"/Lotus/StoreItems/Upgrades/Mods/DualSource/Shotgun/ShotgunMedicMod",
2668
"/Lotus/StoreItems/Upgrades/Mods/DualSource/Rifle/SerratedRushMod"
2669
]
2670
},
2671
{
2672
items: [
2673
"/Lotus/StoreItems/Upgrades/Mods/DualSource/Pistol/MultishotDodgeMod",
2674
"/Lotus/StoreItems/Upgrades/Mods/DualSource/Melee/CritDamageChargeSpeedMod"
2675
]
2676
},
2677
{ items: ["/Lotus/StoreItems/Upgrades/Skins/Sigils/OrbSigil"] }
2678
]
2679
});
2680
worldState.NodeOverrides.push({
2681
_id: { $oid: "5c7cb0d00000000000000000" },
2682
Activation: { $date: { $numberLong: activation.toString() } },
2683
Expiry: { $date: { $numberLong: expiry.toString() } },
2684
Node: "SolNode129",
2685
Faction: "FC_CORPUS",
2686
CustomNpcEncounters: ["/Lotus/Types/Gameplay/Venus/Encounters/Heists/ExploiterHeistFissure"]
2687
});
2688
if (count >= 35) {
2689
worldState.GlobalUpgrades.push({
2690
_id: { $oid: "5c81cefa4c4566791728eaa6" },
2691
Activation: { $date: { $numberLong: activation.toString() } },
2692
ExpiryDate: { $date: { $numberLong: expiry.toString() } },
2693
UpgradeType: "GAMEPLAY_MONEY_REWARD_AMOUNT",
2694
OperationType: "MULTIPLY",
2695
Value: 2,
2696
Nodes: ["SolNode129"]
2697
});
2698
}
2699
// Not sure about that
2700
if (count == 100) {
2701
worldState.GlobalUpgrades.push({
2702
_id: { $oid: "5c81cefa4c4566791728eaa7" },
2703
Activation: { $date: { $numberLong: activation.toString() } },
2704
ExpiryDate: { $date: { $numberLong: expiry.toString() } },
2705
UpgradeType: "GAMEPLAY_PICKUP_AMOUNT",
2706
OperationType: "MULTIPLY",
2707
Value: 2,
2708
Nodes: ["SolNode129"]
2709
});
2710
}
2711
}
2712
2632
2713
// Nightwave Challenges
2633
2714
const nightwaveSyndicateTag = getNightwaveSyndicateTag(buildLabel);
2634
2715
if (nightwaveSyndicateTag) {
@@ -2727,7 +2808,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
2727
2808
: Date.UTC(
2728
2809
date.getUTCFullYear(),
2729
2810
date.getUTCMonth(),
2730
date.getUTCDate() + (day - ghoulsCycleDay + 17)
2811
date.getUTCDate() + activeStartDay
2731
2812
).toString()
2732
2813
}
2733
2814
},
@@ -2738,7 +2819,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
2738
2819
: Date.UTC(
2739
2820
date.getUTCFullYear(),
2740
2821
date.getUTCMonth(),
2741
date.getUTCDate() + (day - ghoulsCycleDay + 21)
2822
date.getUTCDate() + activeEndDay
2742
2823
).toString()
2743
2824
}
2744
2825
},
@@ -43,7 +43,7 @@ export interface IGoal {
43
43
Count?: number;
44
44
HealthPct?: number;
45
45
46
Icon: string;
46
Icon?: string;
47
47
Desc: string;
48
48
ToolTip?: string;
49
49
Faction?: string;
@@ -94,6 +94,9 @@ export interface IGoal {
94
94
MissionKeyRotation?: string[];
95
95
MissionKeyRotationInterval?: number;
96
96
97
OptionalInMission?: boolean;
98
UpgradeIds?: IOid[];
99
97
100
NightLevel?: string;
98
101
}
99
102
@@ -128,8 +131,9 @@ export interface IGlobalUpgrade {
128
131
UpgradeType: string;
129
132
OperationType: string;
130
133
Value: number;
131
LocalizeTag: string;
132
LocalizeDescTag: string;
134
LocalizeTag?: string;
135
LocalizeDescTag?: string;
136
Nodes?: string[];
133
137
}
134
138
135
139
export interface IInvasion {
@@ -183,7 +187,7 @@ export interface INodeOverride {
183
187
Seed?: number;
184
188
LevelOverride?: string;
185
189
Faction?: string;
186
CustomNpcEncounters?: string;
190
CustomNpcEncounters?: string[];
187
191
}
188
192
189
193
export interface ISortie {
@@ -1103,6 +1103,25 @@
1103
1103
</form>
1104
1104
</div>
1105
1105
</div>
1106
<div class="form-group mt-2 d-flex gap-2">
1107
<div class="flex-fill">
1108
<label class="form-label" for="worldState.thermiaFracturesOverride" data-loc="worldState_thermiaFractures"></label>
1109
<select class="form-control" id="worldState.thermiaFracturesOverride" data-default="null">
1110
<option value="null" data-loc="normal"></option>
1111
<option value="true" data-loc="enabled"></option>
1112
<option value="false" data-loc="disabled"></option>
1113
</select>
1114
</div>
1115
<div class="flex-fill">
1116
<form class="form-group" onsubmit="doSaveConfigInt('worldState.thermiaFracturesProgressOverride'); return false;">
1117
<label class="form-label" for="worldState.thermiaFracturesProgressOverride" data-loc="worldState_thermiaFracturesProgressOverride"></label>
1118
<div class="input-group">
1119
<input id="worldState.thermiaFracturesProgressOverride" class="form-control" type="number" min="0" max="100" data-default="0" />
1120
<button class="btn btn-secondary" type="submit" data-loc="cheats_save"></button>
1121
</div>
1122
</form>
1123
</div>
1124
</div>
1106
1125
<div class="form-group mt-2">
1107
1126
<label class="form-label" for="worldState.eidolonOverride" data-loc="worldState_eidolonOverride"></label>
1108
1127
<select class="form-control" id="worldState.eidolonOverride" data-default="">
@@ -265,6 +265,8 @@ dict = {
265
265
worldState_bellyOfTheBeastProgressOverride: `[UNTRANSLATED] Belly of the Beast Progress`,
266
266
worldState_eightClaw: `Acht Klauen`,
267
267
worldState_eightClawProgressOverride: `[UNTRANSLATED] Eight Claw Progress`,
268
worldState_thermiaFractures: `Thermische Risse`,
269
worldState_thermiaFracturesProgressOverride: `[UNTRANSLATED] Thermia Fractures Progress`,
268
270
worldState_from_year: `[UNTRANSLATED] from |VAL|`,
269
271
worldState_pre_year: `[UNTRANSLATED] pre |VAL|`,
270
272
worldState_week: `[UNTRANSLATED] Week |VAL|`,
@@ -264,6 +264,8 @@ dict = {
264
264
worldState_bellyOfTheBeastProgressOverride: `Belly of the Beast Progress`,
265
265
worldState_eightClaw: `Eight Claw`,
266
266
worldState_eightClawProgressOverride: `Eight Claw Progress`,
267
worldState_thermiaFractures: `Thermia Fractures`,
268
worldState_thermiaFracturesProgressOverride: `Thermia Fractures Progress`,
267
269
worldState_from_year: `from |VAL|`,
268
270
worldState_pre_year: `pre |VAL|`,
269
271
worldState_week: `Week |VAL|`,
@@ -265,6 +265,8 @@ dict = {
265
265
worldState_bellyOfTheBeastProgressOverride: `Progreso del Vientre de la Bestia`,
266
266
worldState_eightClaw: `Octava Garra`,
267
267
worldState_eightClawProgressOverride: `Progreso de Octava Garra`,
268
worldState_thermiaFractures: `Fracturas Thermia`,
269
worldState_thermiaFracturesProgressOverride: `[UNTRANSLATED] Thermia Fractures Progress`,
268
270
worldState_from_year: `de |VAL|`,
269
271
worldState_pre_year: `antes de |VAL|`,
270
272
worldState_week: `Semana |VAL|`,
@@ -265,6 +265,8 @@ dict = {
265
265
worldState_bellyOfTheBeastProgressOverride: `[UNTRANSLATED] Belly of the Beast Progress`,
266
266
worldState_eightClaw: `Huitième Griffe`,
267
267
worldState_eightClawProgressOverride: `[UNTRANSLATED] Eight Claw Progress`,
268
worldState_thermiaFractures: `Crevasses Thermia`,
269
worldState_thermiaFracturesProgressOverride: `[UNTRANSLATED] Thermia Fractures Progress`,
268
270
worldState_from_year: `[UNTRANSLATED] from |VAL|`,
269
271
worldState_pre_year: `[UNTRANSLATED] pre |VAL|`,
270
272
worldState_week: `[UNTRANSLATED] Week |VAL|`,
@@ -265,6 +265,8 @@ dict = {
265
265
worldState_bellyOfTheBeastProgressOverride: `Прогресс Чрева зверя`,
266
266
worldState_eightClaw: `Восемь когтей`,
267
267
worldState_eightClawProgressOverride: `Прогресс Восьми когтей`,
268
worldState_thermiaFractures: `Разломы Термии`,
269
worldState_thermiaFracturesProgressOverride: `Прогресс Разломов Термии`,
268
270
worldState_from_year: `из |VAL|`,
269
271
worldState_pre_year: `до |VAL|`,
270
272
worldState_week: `Неделя |VAL|`,
@@ -265,6 +265,8 @@ dict = {
265
265
worldState_bellyOfTheBeastProgressOverride: `Прогрес У лігві звіра`,
266
266
worldState_eightClaw: `Вісім кігтів`,
267
267
worldState_eightClawProgressOverride: `Прогрес Восьми кігтів`,
268
worldState_thermiaFractures: `Розломи термії`,
269
worldState_thermiaFracturesProgressOverride: `[UNTRANSLATED] Thermia Fractures Progress`,
268
270
worldState_from_year: `з |VAL|`,
269
271
worldState_pre_year: `до |VAL|`,
270
272
worldState_week: `Тиждень |VAL|`,