mirror of
https://github.com/MikuLeaks/MikuSB.git
synced 2026-06-04 02:43:57 +00:00
VirCaptureTower_EnterLevel
This commit is contained in:
44
Common/Data/Excel/VirCaptureTowerExcel.cs
Normal file
44
Common/Data/Excel/VirCaptureTowerExcel.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace MikuSB.Data.Excel;
|
||||
|
||||
[ResourceEntity("dlc/vircapture/tower.json")]
|
||||
public class VirCaptureTowerExcel : ExcelResource
|
||||
{
|
||||
[JsonProperty("ID")] public uint Id { get; set; }
|
||||
[JsonProperty("Condition")] public JToken? ConditionRaw { get; set; }
|
||||
[JsonProperty("MapID")] public uint MapId { get; set; }
|
||||
[JsonProperty("TrialCard")] public List<uint> TrialCard { get; set; } = [];
|
||||
[JsonProperty("TaskPath")] public string TaskPath { get; set; } = "";
|
||||
|
||||
[JsonIgnore]
|
||||
public Dictionary<int, uint> Condition { get; } = [];
|
||||
|
||||
public override uint GetId() => Id;
|
||||
|
||||
public override void Loaded()
|
||||
{
|
||||
Condition.Clear();
|
||||
if (ConditionRaw is JObject obj)
|
||||
{
|
||||
foreach (var property in obj.Properties())
|
||||
{
|
||||
if (!int.TryParse(property.Name, out var key))
|
||||
continue;
|
||||
|
||||
uint value = 0;
|
||||
if (property.Value.Type == JTokenType.Integer)
|
||||
value = property.Value.Value<uint>();
|
||||
else if (property.Value.Type == JTokenType.String &&
|
||||
uint.TryParse(property.Value.Value<string>(), out var parsed))
|
||||
value = parsed;
|
||||
|
||||
if (value > 0)
|
||||
Condition[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
GameData.VirCaptureTowerData[Id] = this;
|
||||
}
|
||||
}
|
||||
@@ -57,6 +57,7 @@ public static class GameData
|
||||
public static Dictionary<uint, VirCaptureLevelListExcel> VirCaptureLevelListData { get; private set; } = [];
|
||||
public static Dictionary<ulong, MonsterCardExcel> MonsterCardData { get; private set; } = [];
|
||||
public static Dictionary<uint, FishingFoodExcel> FishingFoodData { get; private set; } = [];
|
||||
public static Dictionary<uint, VirCaptureTowerExcel> VirCaptureTowerData { get; private set; } = [];
|
||||
}
|
||||
|
||||
public static class GameResourceTemplateId
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Text.Json.Serialization;
|
||||
using MikuSB.GameServer.Game.BossPvp;
|
||||
using MikuSB.Proto;
|
||||
using MikuSB.GameServer.Server.CallGS.Handlers.Tower;
|
||||
using MikuSB.GameServer.Server.CallGS.Handlers.VirCapture;
|
||||
|
||||
namespace MikuSB.GameServer.Server.CallGS.Handlers.Chapter;
|
||||
|
||||
@@ -72,6 +73,13 @@ public class Chapter_DealLevelSettlement : ICallGSHandler
|
||||
return response;
|
||||
}
|
||||
|
||||
if (string.Equals(sCmd, "VirCaptureTower_LevelSettlement", StringComparison.Ordinal))
|
||||
{
|
||||
var (response, sync) = VirCaptureTower_LevelSettlement.HandleSettlement(connection.Player!, tbParam);
|
||||
extraSync = sync;
|
||||
return response;
|
||||
}
|
||||
|
||||
return tbParam?.DeepClone() ?? new JsonObject();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
using MikuSB.Data;
|
||||
using MikuSB.Database.Player;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace MikuSB.GameServer.Server.CallGS.Handlers.VirCapture;
|
||||
|
||||
[CallGSApi("VirCaptureTower_EnterLevel")]
|
||||
public class VirCaptureTower_EnterLevel : ICallGSHandler
|
||||
{
|
||||
private const uint LaunchPassGroupId = 22;
|
||||
private const uint VirCaptureGroupId = 128;
|
||||
private const uint VirCaptureLevelSid = 3;
|
||||
private static readonly Random Random = new();
|
||||
|
||||
public async Task Handle(Connection connection, string param, ushort seqNo)
|
||||
{
|
||||
var req = JsonSerializer.Deserialize<VirCaptureTowerEnterLevelParam>(param);
|
||||
if (req == null || req.LevelId <= 0 || req.TeamId <= 0)
|
||||
{
|
||||
await CallGSRouter.SendScript(connection, "VirCaptureTower_EnterLevel", "{\"sErr\":\"error.BadParam\"}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GameData.VirCaptureTowerData.TryGetValue((uint)req.LevelId, out var levelCfg))
|
||||
{
|
||||
await CallGSRouter.SendScript(connection, "VirCaptureTower_EnterLevel", "{\"sErr\":\"error.BadParam\"}");
|
||||
return;
|
||||
}
|
||||
|
||||
var player = connection.Player!;
|
||||
if (!CheckConditions(player.Data, levelCfg.Condition))
|
||||
{
|
||||
await CallGSRouter.SendScript(connection, "VirCaptureTower_EnterLevel", "{\"sErr\":\"tip.LevelLocked\"}");
|
||||
return;
|
||||
}
|
||||
|
||||
await CallGSRouter.SendScript(connection, "VirCaptureTower_EnterLevel", $"{{\"nSeed\":{Random.Next(1, 1_000_000_000)}}}");
|
||||
}
|
||||
|
||||
private static bool CheckConditions(PlayerGameData data, IReadOnlyDictionary<int, uint> conditions)
|
||||
{
|
||||
foreach (var (key, value) in conditions)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case 1:
|
||||
if (data.Level < value)
|
||||
return false;
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
var pass = data.Attrs.FirstOrDefault(x => x.Gid == LaunchPassGroupId && x.Sid == value)?.Val ?? 0;
|
||||
if (pass == 0)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case 20:
|
||||
{
|
||||
var virLevel = data.Attrs.FirstOrDefault(x => x.Gid == VirCaptureGroupId && x.Sid == VirCaptureLevelSid)?.Val ?? 0;
|
||||
if (virLevel < value)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class VirCaptureTowerEnterLevelParam
|
||||
{
|
||||
[JsonPropertyName("nID")]
|
||||
public int LevelId { get; set; }
|
||||
|
||||
[JsonPropertyName("nTeamID")]
|
||||
public int TeamId { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
using MikuSB.Database;
|
||||
using MikuSB.Database.Player;
|
||||
using MikuSB.GameServer.Game.Player;
|
||||
using MikuSB.Proto;
|
||||
using MikuSB.Util;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace MikuSB.GameServer.Server.CallGS.Handlers.VirCapture;
|
||||
|
||||
[CallGSApi("VirCaptureTower_LevelSettlement")]
|
||||
public class VirCaptureTower_LevelSettlement : ICallGSHandler
|
||||
{
|
||||
private const uint LaunchLevelStateGroupId = 21;
|
||||
private const uint LaunchPassGroupId = 22;
|
||||
private const uint PassedFlagBit = 1u << 8;
|
||||
private static readonly Logger Logger = new("VirCaptureTower");
|
||||
|
||||
public async Task Handle(Connection connection, string param, ushort seqNo)
|
||||
{
|
||||
var (response, sync) = HandleSettlement(connection.Player!, JsonNode.Parse(param));
|
||||
await CallGSRouter.SendScript(connection, "VirCaptureTower_LevelSettlement", response.ToJsonString(), sync);
|
||||
}
|
||||
|
||||
public static (JsonNode Response, NtfSyncPlayer Sync) HandleSettlement(PlayerInstance player, JsonNode? tbParam)
|
||||
{
|
||||
var req = tbParam?.Deserialize<VirCaptureTowerSettlementParam>();
|
||||
if (req == null || req.LevelId == 0)
|
||||
{
|
||||
Logger.Error($"Invalid vircapture tower settlement payload: {tbParam?.ToJsonString() ?? "null"}");
|
||||
return (new JsonObject { ["sErr"] = "error.BadParam" }, new NtfSyncPlayer());
|
||||
}
|
||||
|
||||
var sync = new NtfSyncPlayer();
|
||||
|
||||
var levelStateAttr = GetOrCreateAttr(player.Data, LaunchLevelStateGroupId, (uint)req.LevelId);
|
||||
levelStateAttr.Val |= MergeStarMask(req.StarMask) | PassedFlagBit;
|
||||
SyncAttr(sync, player, levelStateAttr);
|
||||
|
||||
var passAttr = GetOrCreateAttr(player.Data, LaunchPassGroupId, (uint)req.LevelId);
|
||||
passAttr.Val = Math.Max(1u, passAttr.Val + 1);
|
||||
SyncAttr(sync, player, passAttr);
|
||||
|
||||
Logger.Info(
|
||||
$"VirCaptureTower settlement saved. uid={player.Uid} levelId={req.LevelId} starMask={req.StarMask} " +
|
||||
$"levelStateVal={levelStateAttr.Val} passVal={passAttr.Val}");
|
||||
|
||||
DatabaseHelper.SaveDatabaseType(player.Data);
|
||||
return (new JsonObject(), sync);
|
||||
}
|
||||
|
||||
private static uint MergeStarMask(int starMask)
|
||||
{
|
||||
uint result = 0;
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
if (((starMask >> i) & 1) != 0)
|
||||
result |= 1u << i;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static PlayerAttr GetOrCreateAttr(PlayerGameData data, uint gid, uint sid)
|
||||
{
|
||||
var attr = data.Attrs.FirstOrDefault(x => x.Gid == gid && x.Sid == sid);
|
||||
if (attr != null)
|
||||
return attr;
|
||||
|
||||
attr = new PlayerAttr
|
||||
{
|
||||
Gid = gid,
|
||||
Sid = sid
|
||||
};
|
||||
data.Attrs.Add(attr);
|
||||
return attr;
|
||||
}
|
||||
|
||||
private static void SyncAttr(NtfSyncPlayer sync, PlayerInstance player, PlayerAttr attr)
|
||||
{
|
||||
sync.Custom[player.ToPackedAttrKey(attr.Gid, attr.Sid)] = attr.Val;
|
||||
sync.Custom[player.ToShiftedAttrKey(attr.Gid, attr.Sid)] = attr.Val;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class VirCaptureTowerSettlementParam
|
||||
{
|
||||
[JsonPropertyName("nID")]
|
||||
public int LevelId { get; set; }
|
||||
|
||||
[JsonPropertyName("nStar")]
|
||||
public int StarMask { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user