Compare commits

..

3 Commits

Author SHA1 Message Date
Kei-Luna
f7814b0537 Adds a dailybuff to Paradox. 2026-05-02 09:46:47 +09:00
Kei-Luna
2fdda3157f Unlock all of Paradox's talents 2026-05-02 09:13:04 +09:00
Kei-Luna
f07c5f77fd Unlock all difficulty levels of Paradox 2026-05-02 08:42:57 +09:00
8 changed files with 254 additions and 3 deletions

View File

@@ -0,0 +1,18 @@
using Newtonsoft.Json;
namespace MikuSB.Data.Excel;
[ResourceEntity("dailybuff.json")]
public class Rogue3DDailyBuffExcel : ExcelResource
{
[JsonProperty("ID")] public uint Id { get; set; }
[JsonProperty("GroupID")] public uint GroupId { get; set; }
[JsonProperty("ScoreBuffID")] public uint ScoreBuffId { get; set; }
public override uint GetId() => Id;
public override void Loaded()
{
GameData.Rogue3DDailyBuffData[Id] = this;
}
}

View File

@@ -0,0 +1,19 @@
using Newtonsoft.Json;
namespace MikuSB.Data.Excel;
[ResourceEntity("server_10_season.json")]
public class Rogue3DSeasonExcel : ExcelResource
{
[JsonProperty("SeasonID")] public uint SeasonId { get; set; }
[JsonProperty("Type")] public int Type { get; set; }
[JsonProperty("OpenTime")] public string OpenTime { get; set; } = "";
[JsonProperty("CloseTime")] public string CloseTime { get; set; } = "";
public override uint GetId() => SeasonId;
public override void Loaded()
{
GameData.Rogue3DSeasonData[SeasonId] = this;
}
}

View File

@@ -0,0 +1,31 @@
using Newtonsoft.Json;
namespace MikuSB.Data.Excel;
[ResourceEntity("server_03_talent.json")]
public class Rogue3DTalentExcel : ExcelResource
{
[JsonProperty("TalentID")] public uint TalentId { get; set; }
[JsonProperty("UnlockCondition")] private object? UnlockConditionRaw { get; set; }
[JsonIgnore] public uint UnlockCondition { get; private set; }
public override uint GetId() => TalentId;
public override void Loaded()
{
UnlockCondition = ParseUnlockCondition(UnlockConditionRaw);
GameData.Rogue3DTalentData[TalentId] = this;
}
private static uint ParseUnlockCondition(object? raw)
{
return raw switch
{
null => 0,
long value when value > 0 => (uint)value,
int value when value > 0 => (uint)value,
string text when uint.TryParse(text, out var value) => value,
_ => 0
};
}
}

View File

@@ -16,6 +16,9 @@ public static class GameData
public static Dictionary<uint, ArItemExcel> ArItemData { get; private set; } = [];
public static Dictionary<uint, ManifestationExcel> ManifestationData { get; private set; } = [];
public static Dictionary<uint, Rogue3DDifficultExcel> Rogue3DDifficultData { get; private set; } = [];
public static Dictionary<uint, Rogue3DSeasonExcel> Rogue3DSeasonData { get; private set; } = [];
public static Dictionary<uint, Rogue3DTalentExcel> Rogue3DTalentData { get; private set; } = [];
public static Dictionary<uint, Rogue3DDailyBuffExcel> Rogue3DDailyBuffData { get; private set; } = [];
public static Dictionary<int, BreakExcel> BreakData { get; private set; } = [];
public static Dictionary<uint, SpineExcel> SpineData { get; private set; } = [];
public static Dictionary<uint, NodeConditionExcel> NodeConditionData { get; private set; } = [];

View File

@@ -0,0 +1,178 @@
using MikuSB.Data;
using MikuSB.Database.Player;
using MikuSB.GameServer.Game.Player;
using MikuSB.Proto;
namespace MikuSB.GameServer.Server.CallGS.Handlers.Rogue3D;
internal static class Rogue3DStateHelper
{
private const uint GroupId = 124;
private const uint LevelPassStart = 20;
private const uint DailyBuffStart = 51;
private const uint DailyBuffEnd = 65;
private const int DailyBuffBitCount = 10;
private const int DailyBuffBitsPerValue = DailyBuffBitCount + 1;
private const uint DailyBuffMask = (1u << DailyBuffBitCount) - 1;
private const uint UnlockDiff1Sid = LevelPassStart + 1;
private const uint UnlockDiff2Sid = LevelPassStart + 2;
private const uint UnlockDiff3Sid = LevelPassStart + 3;
private const uint UnlockDiff4Sid = LevelPassStart + 4;
private static uint[]? ShuffledDailyBuffIds;
public static NtfSyncPlayer EnsureUnlockState(PlayerInstance player)
{
var sync = new NtfSyncPlayer();
EnsureMinAttr(player, UnlockDiff1Sid, 1, sync);
EnsureMinAttr(player, UnlockDiff2Sid, 1, sync);
EnsureMinAttr(player, UnlockDiff3Sid, 1, sync);
EnsureMinAttr(player, UnlockDiff4Sid, 1, sync);
foreach (var scienceSid in GetUnlockTalentScienceSids())
{
EnsureMinAttr(player, scienceSid, 1, sync);
}
EnsureDailyBuffAttrs(player, sync);
return sync;
}
private static IEnumerable<uint> GetUnlockTalentScienceSids()
{
return GameData.Rogue3DTalentData.Values
.Select(x => x.UnlockCondition)
.Where(x => x > 0)
.Distinct()
.OrderBy(x => x);
}
private static void EnsureDailyBuffAttrs(PlayerInstance player, NtfSyncPlayer sync)
{
var buffIds = GetOrCreateDailyBuffIds()
.Take((int)(DailyBuffEnd - DailyBuffStart + 1) * 3)
.ToArray();
var index = 0;
for (var sid = DailyBuffStart; sid <= DailyBuffEnd; sid++)
{
uint packed = 0;
for (var slot = 0; slot < 3 && index < buffIds.Length; slot++, index++)
{
packed |= (buffIds[index] & DailyBuffMask) << (slot * DailyBuffBitsPerValue);
}
SetAttr(player, sid, packed, sync);
}
}
private static uint[] GetOrCreateDailyBuffIds()
{
if (ShuffledDailyBuffIds != null)
{
return ShuffledDailyBuffIds;
}
var groupedBuffIds = GameData.Rogue3DDailyBuffData.Values
.Where(x => x.ScoreBuffId > 0 && x.ScoreBuffId <= DailyBuffMask)
.GroupBy(x => x.GroupId)
.OrderBy(x => x.Key)
.Select(x => x
.OrderBy(y => y.Id)
.Select(y => y.ScoreBuffId)
.Distinct()
.ToList())
.ToList();
var random = new Random();
foreach (var group in groupedBuffIds)
{
Shuffle(group, random);
}
Shuffle(groupedBuffIds, random);
var buffIds = new List<uint>();
var indexByGroup = new int[groupedBuffIds.Count];
var hasRemaining = true;
while (hasRemaining)
{
hasRemaining = false;
for (var i = 0; i < groupedBuffIds.Count; i++)
{
var group = groupedBuffIds[i];
var index = indexByGroup[i];
if (index >= group.Count)
{
continue;
}
buffIds.Add(group[index]);
indexByGroup[i] = index + 1;
hasRemaining = true;
}
}
ShuffledDailyBuffIds = buffIds.ToArray();
return ShuffledDailyBuffIds;
}
private static IEnumerable<uint> GetDailyBuffIds()
{
return GetOrCreateDailyBuffIds();
}
private static void Shuffle<T>(IList<T> list, Random random)
{
for (var i = list.Count - 1; i > 0; i--)
{
var swapIndex = random.Next(i + 1);
(list[i], list[swapIndex]) = (list[swapIndex], list[i]);
}
}
private static void EnsureMinAttr(PlayerInstance player, uint sid, uint value, NtfSyncPlayer sync, bool overwrite = false)
{
var attr = player.Data.Attrs.FirstOrDefault(x => x.Gid == GroupId && x.Sid == sid);
if (attr == null)
{
attr = new PlayerAttr { Gid = GroupId, Sid = sid, Val = value };
player.Data.Attrs.Add(attr);
AddSync(player, sync, sid, value);
return;
}
if ((!overwrite && attr.Val >= value) || (overwrite && attr.Val == value))
{
return;
}
attr.Val = value;
AddSync(player, sync, sid, value);
}
private static void SetAttr(PlayerInstance player, uint sid, uint value, NtfSyncPlayer sync)
{
var attr = player.Data.Attrs.FirstOrDefault(x => x.Gid == GroupId && x.Sid == sid);
if (attr == null)
{
attr = new PlayerAttr { Gid = GroupId, Sid = sid };
player.Data.Attrs.Add(attr);
}
if (attr.Val == value)
{
return;
}
attr.Val = value;
AddSync(player, sync, sid, value);
}
private static void AddSync(PlayerInstance player, NtfSyncPlayer sync, uint sid, uint value)
{
sync.Custom[player.ToPackedAttrKey(GroupId, sid)] = value;
sync.Custom[player.ToShiftedAttrKey(GroupId, sid)] = value;
}
}

View File

@@ -8,6 +8,7 @@ public class Rogue3D_CheckOpenAct : ICallGSHandler
{
public async Task Handle(Connection connection, string param, ushort seqNo)
{
await CallGSRouter.SendScript(connection, "Rogue3D_CheckOpenAct", "{\"bOpen\":true}");
var sync = Rogue3DStateHelper.EnsureUnlockState(connection.Player!);
await CallGSRouter.SendScript(connection, "Rogue3D_CheckOpenAct", "{\"bOpen\":true}", sync);
}
}

View File

@@ -8,6 +8,7 @@ public class Rogue3D_SelectMode : ICallGSHandler
{
public async Task Handle(Connection connection, string param, ushort seqNo)
{
await CallGSRouter.SendScript(connection, "Rogue3D_SelectMode", "{}");
var sync = Rogue3DStateHelper.EnsureUnlockState(connection.Player!);
await CallGSRouter.SendScript(connection, "Rogue3D_SelectMode", "{}", sync);
}
}

View File

@@ -1 +1 @@
v=1.6
v=1.7