mirror of
https://github.com/EpinelPS/EpinelPS.git
synced 2025-12-14 16:04:36 +01:00
Experimental archive support
Note archive event returns to stage 1 if hard mode is played and left unfinished quick battle doesnt work as well Prolouge always plays
This commit is contained in:
@@ -62,6 +62,8 @@ namespace EpinelPS.Database
|
|||||||
public class EventData
|
public class EventData
|
||||||
{
|
{
|
||||||
public List<string> CompletedScenarios = new();
|
public List<string> CompletedScenarios = new();
|
||||||
|
public int Diff = 0; // Default value for Diff
|
||||||
|
public int LastStage = 0; // Default value for LastStage
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SynchroSlot
|
public class SynchroSlot
|
||||||
|
|||||||
@@ -48,6 +48,10 @@ namespace EpinelPS.StaticInfo
|
|||||||
public Dictionary<int, LiveWallpaperRecord> lwptablemgrs = new Dictionary<int, LiveWallpaperRecord>(); // Fixed initialization
|
public Dictionary<int, LiveWallpaperRecord> lwptablemgrs = new Dictionary<int, LiveWallpaperRecord>(); // Fixed initialization
|
||||||
private Dictionary<int, AlbumResourceRecord> albumResourceRecords = new Dictionary<int, AlbumResourceRecord>();
|
private Dictionary<int, AlbumResourceRecord> albumResourceRecords = new Dictionary<int, AlbumResourceRecord>();
|
||||||
public Dictionary<int, UserFrameTableRecord> userFrameTable = new Dictionary<int, UserFrameTableRecord>();
|
public Dictionary<int, UserFrameTableRecord> userFrameTable = new Dictionary<int, UserFrameTableRecord>();
|
||||||
|
public Dictionary<int, ArchiveRecordManagerRecord> archiveRecordManagerTable = new Dictionary<int, ArchiveRecordManagerRecord>();
|
||||||
|
public Dictionary<int, ArchiveEventStoryRecord> archiveEventStoryRecords = new Dictionary<int, ArchiveEventStoryRecord>();
|
||||||
|
public Dictionary<int, ArchiveEventQuestRecord> archiveEventQuestRecords = new Dictionary<int, ArchiveEventQuestRecord>();
|
||||||
|
public Dictionary<int, ArchiveEventDungeonStageRecord> archiveEventDungeonStageRecords = new Dictionary<int, ArchiveEventDungeonStageRecord>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -377,6 +381,12 @@ namespace EpinelPS.StaticInfo
|
|||||||
{
|
{
|
||||||
OutpostBattle.Add(obj.id, obj);
|
OutpostBattle.Add(obj.id, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var archiveRecordManagerTableData = await LoadZip<ArchiveRecordManagerTable>("ArchiveRecordManagerTable.json", progress);
|
||||||
|
foreach (var obj in archiveRecordManagerTableData.records)
|
||||||
|
{
|
||||||
|
archiveRecordManagerTable.Add(obj.id, obj);
|
||||||
|
}
|
||||||
|
|
||||||
var gachaTypeTable = await LoadZip<GachaTypeTable>("GachaTypeTable.json", progress);
|
var gachaTypeTable = await LoadZip<GachaTypeTable>("GachaTypeTable.json", progress);
|
||||||
|
|
||||||
@@ -407,6 +417,26 @@ namespace EpinelPS.StaticInfo
|
|||||||
{
|
{
|
||||||
userFrameTable[record.id] = record;
|
userFrameTable[record.id] = record;
|
||||||
}
|
}
|
||||||
|
// Load and parse ArchiveEventDungeonStageTable.json
|
||||||
|
var archiveEventDungeonStageData = await LoadZip<ArchiveEventDungeonStageTable>("ArchiveEventDungeonStageTable.json", progress);
|
||||||
|
foreach (var obj in archiveEventDungeonStageData.records)
|
||||||
|
{
|
||||||
|
archiveEventDungeonStageRecords.Add(obj.id, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load and parse ArchiveEventStoryTable.json
|
||||||
|
var archiveEventStoryTable = await LoadZip<ArchiveEventStoryTable>("ArchiveEventStoryTable.json", progress);
|
||||||
|
foreach (var obj in archiveEventStoryTable.records)
|
||||||
|
{
|
||||||
|
archiveEventStoryRecords.Add(obj.id, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load and parse ArchiveEventQuestTable.json
|
||||||
|
var archiveEventQuestTable = await LoadZip<ArchiveEventQuestTable>("ArchiveEventQuestTable.json", progress);
|
||||||
|
foreach (var obj in archiveEventQuestTable.records)
|
||||||
|
{
|
||||||
|
archiveEventQuestRecords.Add(obj.id, obj);
|
||||||
|
}
|
||||||
|
|
||||||
var albumResourceTable = await LoadZip<AlbumResourceTable>("AlbumResourceTable.json", progress);
|
var albumResourceTable = await LoadZip<AlbumResourceTable>("AlbumResourceTable.json", progress);
|
||||||
foreach (var obj in albumResourceTable.records)
|
foreach (var obj in albumResourceTable.records)
|
||||||
|
|||||||
@@ -317,5 +317,77 @@
|
|||||||
{
|
{
|
||||||
public List<UserFrameTableRecord> records;
|
public List<UserFrameTableRecord> records;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ArchiveRecordManagerRecord
|
||||||
|
{
|
||||||
|
public int id;
|
||||||
|
public string record_type;
|
||||||
|
public string record_title_locale;
|
||||||
|
public int record_main_archive_event_id;
|
||||||
|
public int record_list_order;
|
||||||
|
public int unlock_ticket_id;
|
||||||
|
public int unlock_ticket_count;
|
||||||
|
public int reward_info_list_id;
|
||||||
|
public int event_quest_clear_reward_id;
|
||||||
|
public int recommended_story_list_id;
|
||||||
|
public int included_contents_group_id;
|
||||||
|
public string record_slot_bg_addressable;
|
||||||
|
public string record_unlock_bg_addressable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ArchiveRecordManagerTable
|
||||||
|
{
|
||||||
|
public List<ArchiveRecordManagerRecord> records;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ArchiveEventStoryRecord
|
||||||
|
{
|
||||||
|
public int id;
|
||||||
|
public int event_id;
|
||||||
|
public string prologue_scenario = "";
|
||||||
|
public int dungeon_id;
|
||||||
|
public int album_category_group;
|
||||||
|
public string ui_prefab = "";
|
||||||
|
public int archive_ticket_item_id;
|
||||||
|
public int archive_currency_item_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ArchiveEventStoryTable
|
||||||
|
{
|
||||||
|
public List<ArchiveEventStoryRecord> records;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ArchiveEventQuestRecord
|
||||||
|
{
|
||||||
|
public int id;
|
||||||
|
public int event_quest_manager_id;
|
||||||
|
public string condition_type = "";
|
||||||
|
public int condition_value;
|
||||||
|
public string name_localkey = "";
|
||||||
|
public string description_localkey = "";
|
||||||
|
public int next_quest_id;
|
||||||
|
public string end_scenario_id = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ArchiveEventQuestTable
|
||||||
|
{
|
||||||
|
public List<ArchiveEventQuestRecord> records;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ArchiveEventDungeonStageRecord
|
||||||
|
{
|
||||||
|
public int id;
|
||||||
|
public int group;
|
||||||
|
public int step;
|
||||||
|
public string stage_name = "";
|
||||||
|
public string stage_contents_type = "";
|
||||||
|
public int stage_id;
|
||||||
|
public bool is_repeat_clear;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ArchiveEventDungeonStageTable
|
||||||
|
{
|
||||||
|
public List<ArchiveEventDungeonStageRecord> records;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
43
EpinelPS/LobbyServer/Msgs/Archive/ArchiveClearStage.cs
Normal file
43
EpinelPS/LobbyServer/Msgs/Archive/ArchiveClearStage.cs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
using EpinelPS.Utils;
|
||||||
|
using EpinelPS.Database;
|
||||||
|
namespace EpinelPS.LobbyServer.Msgs.Archive
|
||||||
|
{
|
||||||
|
[PacketPath("/archive/storydungeon/clearstage")]
|
||||||
|
public class ClearArchiveStage : LobbyMsgHandler
|
||||||
|
{
|
||||||
|
protected override async Task HandleAsync()
|
||||||
|
{
|
||||||
|
var req = await ReadData<ReqClearArchiveStage>(); // has fields EventId, StageId, BattleResult
|
||||||
|
var evid = req.EventId;
|
||||||
|
var stgid = req.StageId;
|
||||||
|
var result = req.BattleResult; // if 2 add to event info as last stage
|
||||||
|
var user = GetUser();
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
throw new Exception("User not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the EventInfo exists for the given EventId
|
||||||
|
if (!user.EventInfo.ContainsKey(evid))
|
||||||
|
{
|
||||||
|
throw new Exception($"Event with ID {evid} not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the EventData if BattleResult is 2
|
||||||
|
if (result == 1)
|
||||||
|
{
|
||||||
|
var eventData = user.EventInfo[evid];
|
||||||
|
|
||||||
|
// Update the LastStage in EventData
|
||||||
|
eventData.LastStage = stgid;
|
||||||
|
|
||||||
|
}
|
||||||
|
JsonDb.Save();
|
||||||
|
var response = new ResClearArchiveStage();
|
||||||
|
|
||||||
|
// Send the response back to the client
|
||||||
|
await WriteDataAsync(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
EpinelPS/LobbyServer/Msgs/Archive/ArchiveEnterStage.cs
Normal file
18
EpinelPS/LobbyServer/Msgs/Archive/ArchiveEnterStage.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using EpinelPS.Utils;
|
||||||
|
|
||||||
|
namespace EpinelPS.LobbyServer.Msgs.Archive
|
||||||
|
{
|
||||||
|
[PacketPath("/archive/storydungeon/enterstage")]
|
||||||
|
public class EnterArchiveStage : LobbyMsgHandler
|
||||||
|
{
|
||||||
|
protected override async Task HandleAsync()
|
||||||
|
{
|
||||||
|
var req = await ReadData<ReqEnterArchiveStage>();// has fields EventId StageId TeamNumber
|
||||||
|
var evid = req.EventId;
|
||||||
|
|
||||||
|
var response = new ResEnterArchiveStage();
|
||||||
|
|
||||||
|
await WriteDataAsync(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
38
EpinelPS/LobbyServer/Msgs/Archive/CompleteArchiveScenario.cs
Normal file
38
EpinelPS/LobbyServer/Msgs/Archive/CompleteArchiveScenario.cs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
using EpinelPS.Utils;
|
||||||
|
using EpinelPS.Database;
|
||||||
|
using EpinelPS.StaticInfo; // Ensure this namespace is included
|
||||||
|
|
||||||
|
namespace EpinelPS.LobbyServer.Msgs.Archive
|
||||||
|
{
|
||||||
|
[PacketPath("/archive/scenario/complete")]
|
||||||
|
public class CompleteScenario : LobbyMsgHandler
|
||||||
|
{
|
||||||
|
protected override async Task HandleAsync()
|
||||||
|
{
|
||||||
|
var req = await ReadData<ReqCompleteArchiveScenario>(); // req has EventId, ScenarioId, DialogType fields
|
||||||
|
var evid = req.EventId;
|
||||||
|
var scenid = req.ScenarioId;
|
||||||
|
var dialtyp = req.DialogType;
|
||||||
|
|
||||||
|
var user = GetUser();
|
||||||
|
|
||||||
|
// Ensure we are working with the user's EventInfo and not CompletedScenarios
|
||||||
|
if (!user.EventInfo.TryGetValue(evid, out var evt))
|
||||||
|
{
|
||||||
|
// Create a new EventData if the event doesn't exist
|
||||||
|
evt = new EventData();
|
||||||
|
user.EventInfo[evid] = evt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the CompletedScenarios list is initialized and add the ScenarioId
|
||||||
|
if (!evt.CompletedScenarios.Contains(scenid))
|
||||||
|
{
|
||||||
|
evt.CompletedScenarios.Add(scenid);
|
||||||
|
}
|
||||||
|
JsonDb.Save();
|
||||||
|
// Prepare and send the response
|
||||||
|
var response = new ResCompleteArchiveScenario();
|
||||||
|
await WriteDataAsync(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
38
EpinelPS/LobbyServer/Msgs/Archive/FastClearArchiveStage.cs
Normal file
38
EpinelPS/LobbyServer/Msgs/Archive/FastClearArchiveStage.cs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
using EpinelPS.Utils;
|
||||||
|
using EpinelPS.Database;
|
||||||
|
namespace EpinelPS.LobbyServer.Msgs.Archive
|
||||||
|
{
|
||||||
|
[PacketPath("/archive/storydungeon/fastclearstage")]
|
||||||
|
public class FastClearArchiveStage : LobbyMsgHandler
|
||||||
|
{
|
||||||
|
protected override async Task HandleAsync()
|
||||||
|
{
|
||||||
|
var req = await ReadData<ReqFastClearArchiveStage>();
|
||||||
|
var evid = req.EventId;
|
||||||
|
var stgid = req.StageId;
|
||||||
|
|
||||||
|
var user = GetUser();
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
throw new Exception("User not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the EventInfo exists for the given EventId
|
||||||
|
if (!user.EventInfo.ContainsKey(evid))
|
||||||
|
{
|
||||||
|
throw new Exception($"Event with ID {evid} not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var eventData = user.EventInfo[evid];
|
||||||
|
// Update the LastStage in EventData
|
||||||
|
eventData.LastStage = stgid;
|
||||||
|
|
||||||
|
JsonDb.Save();
|
||||||
|
var response = new ResFastClearArchiveStage();
|
||||||
|
|
||||||
|
// Send the response back to the client
|
||||||
|
await WriteDataAsync(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
50
EpinelPS/LobbyServer/Msgs/Archive/GetArchiveStoryDungeon.cs
Normal file
50
EpinelPS/LobbyServer/Msgs/Archive/GetArchiveStoryDungeon.cs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
using EpinelPS.Utils;
|
||||||
|
using EpinelPS.Database;
|
||||||
|
|
||||||
|
namespace EpinelPS.LobbyServer.Msgs.Archive
|
||||||
|
{
|
||||||
|
[PacketPath("/archive/storydungeon/get")]
|
||||||
|
public class GetArchiveStoryDungeon : LobbyMsgHandler
|
||||||
|
{
|
||||||
|
protected override async Task HandleAsync()
|
||||||
|
{
|
||||||
|
var req = await ReadData<ReqGetArchiveStoryDungeon>(); // has EventId field
|
||||||
|
var evid = req.EventId;
|
||||||
|
|
||||||
|
// Retrieve the user based on session (assuming GetCurrentUser is defined elsewhere)
|
||||||
|
var user = GetUser();
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
throw new Exception("User not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Access EventData directly
|
||||||
|
if (!user.EventInfo.ContainsKey(evid))
|
||||||
|
{
|
||||||
|
throw new Exception($"Event with ID {evid} not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var eventData = user.EventInfo[evid];
|
||||||
|
|
||||||
|
// Prepare the response
|
||||||
|
var response = new ResGetArchiveStoryDungeon();
|
||||||
|
|
||||||
|
// Populate team data
|
||||||
|
response.TeamData = new NetUserTeamData()
|
||||||
|
{
|
||||||
|
LastContentsTeamNumber = 1,
|
||||||
|
Type = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
// Populate the last cleared stage
|
||||||
|
response.LastClearedArchiveStageList.Add(new NetLastClearedArchiveStage()
|
||||||
|
{
|
||||||
|
DifficultyId = eventData.Diff,
|
||||||
|
StageId = eventData.LastStage
|
||||||
|
});
|
||||||
|
|
||||||
|
// Send the response
|
||||||
|
await WriteDataAsync(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using EpinelPS.Utils;
|
using EpinelPS.Utils;
|
||||||
|
using EpinelPS.StaticInfo;
|
||||||
|
|
||||||
namespace EpinelPS.LobbyServer.Msgs.Archive
|
namespace EpinelPS.LobbyServer.Msgs.Archive
|
||||||
{
|
{
|
||||||
@@ -10,8 +11,20 @@ namespace EpinelPS.LobbyServer.Msgs.Archive
|
|||||||
var req = await ReadData<ReqGetArchiveRecord>();
|
var req = await ReadData<ReqGetArchiveRecord>();
|
||||||
|
|
||||||
var response = new ResGetArchiveRecord();
|
var response = new ResGetArchiveRecord();
|
||||||
response.ArchiveRecordManagerList.AddRange([100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800]);
|
|
||||||
response.UnlockedArchiveRecordList.AddRange([100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800]);
|
// Explicitly select IDs from the records
|
||||||
|
var allIds = GameData.Instance.archiveRecordManagerTable.Values.Select(record => record.id).ToList();
|
||||||
|
|
||||||
|
// Add the IDs to the response lists
|
||||||
|
response.ArchiveRecordManagerList.AddRange(allIds);
|
||||||
|
response.UnlockedArchiveRecordList.AddRange(allIds);
|
||||||
|
|
||||||
|
// Get entries with record_type "EventQuest"
|
||||||
|
var eventQuestRecords = GameData.Instance.archiveRecordManagerTable.Values.Where(record => record.record_type == "EventQuest").ToList();
|
||||||
|
|
||||||
|
response.UnlockedArchiveEventQuestList.AddRange(eventQuestRecords.Select(record => record.id));
|
||||||
|
|
||||||
|
|
||||||
// TODO: allow unlocking
|
// TODO: allow unlocking
|
||||||
await WriteDataAsync(response);
|
await WriteDataAsync(response);
|
||||||
}
|
}
|
||||||
|
|||||||
53
EpinelPS/LobbyServer/Msgs/Archive/GetNonResettable.cs
Normal file
53
EpinelPS/LobbyServer/Msgs/Archive/GetNonResettable.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
using EpinelPS.Utils;
|
||||||
|
using EpinelPS.StaticInfo; // Ensure this namespace is included
|
||||||
|
|
||||||
|
|
||||||
|
namespace EpinelPS.LobbyServer.Msgs.Archive
|
||||||
|
{
|
||||||
|
[PacketPath("/archive/scenario/getnonresettable")]
|
||||||
|
public class GetNonResettable : LobbyMsgHandler
|
||||||
|
{
|
||||||
|
protected override async Task HandleAsync()
|
||||||
|
{
|
||||||
|
var req = await ReadData<ReqGetNonResettableArchiveScenario>(); // req has EventId field
|
||||||
|
var evid = req.EventId;
|
||||||
|
var response = new ResGetNonResettableArchiveScenario();
|
||||||
|
|
||||||
|
// Access the GameData instance
|
||||||
|
var gameData = GameData.Instance;
|
||||||
|
|
||||||
|
if (evid == 130002)
|
||||||
|
{
|
||||||
|
// Directly use the archiveEventQuestRecords dictionary
|
||||||
|
foreach (var record in gameData.archiveEventQuestRecords.Values)
|
||||||
|
{
|
||||||
|
if (record.event_quest_manager_id == evid)
|
||||||
|
{
|
||||||
|
// Add the end_scenario_id to the ScenarioIdList
|
||||||
|
if (!string.IsNullOrEmpty(record.end_scenario_id))
|
||||||
|
{
|
||||||
|
response.ScenarioIdList.Add(record.end_scenario_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Directly use the archiveEventStoryRecords dictionary
|
||||||
|
foreach (var record in gameData.archiveEventStoryRecords.Values)
|
||||||
|
{
|
||||||
|
if (record.event_id == evid)
|
||||||
|
{
|
||||||
|
// Add the prologue_scenario to the ScenarioIdList
|
||||||
|
if (!string.IsNullOrEmpty(record.prologue_scenario))
|
||||||
|
{
|
||||||
|
response.ScenarioIdList.Add(record.prologue_scenario);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await WriteDataAsync(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
EpinelPS/LobbyServer/Msgs/Archive/GetResettable.cs
Normal file
22
EpinelPS/LobbyServer/Msgs/Archive/GetResettable.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using EpinelPS.Utils;
|
||||||
|
using EpinelPS.StaticInfo;
|
||||||
|
namespace EpinelPS.LobbyServer.Msgs.Archive
|
||||||
|
{
|
||||||
|
[PacketPath("/archive/scenario/getresettable")]
|
||||||
|
public class GetResettable : LobbyMsgHandler
|
||||||
|
{
|
||||||
|
protected override async Task HandleAsync()
|
||||||
|
{
|
||||||
|
var req = await ReadData<ReqGetResettableArchiveScenario>();
|
||||||
|
var response = new ResGetResettableArchiveScenario(); // has ScenarioIdList field that takes in strings
|
||||||
|
|
||||||
|
// Retrieve stage IDs from GameData
|
||||||
|
var stageIds = GameData.Instance.archiveEventDungeonStageRecords.Values.Select(record => record.stage_id.ToString()).ToList();
|
||||||
|
|
||||||
|
// Add them to the response
|
||||||
|
response.ScenarioIdList.Add(stageIds);
|
||||||
|
|
||||||
|
await WriteDataAsync(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user