Chests, ore and artifact drops
Gadgets are streamed alongside monsters now, so chests and ore nodes show up in the world and can be interacted with. The two flows differ: for a chest the client sends the finish request itself and the loot is granted on that one, for ore it sends nothing more so the server has to close everything on the first request. Artifacts used to be silently dropped on the floor because the item ids that actually roll were not in the reliquary table at all. Added the missing rows and gave them real main stat and substat rolls instead of the fixed four. Dropped items survive a relogin. The inventory is still rebuilt from the tables on every login, so the trick is to remember where the default set ends and only persist what was found in the world. Gacha and shop weapons were disappearing the same way and are fixed by the same change.
This commit is contained in:
parent
fc2ac1050f
commit
62205c8062
16 changed files with 1323 additions and 211 deletions
|
|
@ -8,6 +8,7 @@ public sealed class ReliquaryAffixExcel : ExcelItem
|
||||||
{
|
{
|
||||||
[JsonPropertyName("id")] public uint Id { get; set; }
|
[JsonPropertyName("id")] public uint Id { get; set; }
|
||||||
[JsonPropertyName("depotId")] public uint DepotId { get; set; }
|
[JsonPropertyName("depotId")] public uint DepotId { get; set; }
|
||||||
|
[JsonPropertyName("groupId")] public uint GroupId { get; set; }
|
||||||
[JsonPropertyName("propType")] public string PropType { get; set; } = string.Empty;
|
[JsonPropertyName("propType")] public string PropType { get; set; } = string.Empty;
|
||||||
[JsonPropertyName("propValue")] public float PropValue { get; set; }
|
[JsonPropertyName("propValue")] public float PropValue { get; set; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ public sealed class ReliquaryExcel : ExcelItem
|
||||||
[JsonPropertyName("mainPropDepotId")] public uint MainPropDepotId { get; set; }
|
[JsonPropertyName("mainPropDepotId")] public uint MainPropDepotId { get; set; }
|
||||||
[JsonPropertyName("appendPropDepotId")] public uint AppendPropDepotId { get; set; }
|
[JsonPropertyName("appendPropDepotId")] public uint AppendPropDepotId { get; set; }
|
||||||
[JsonPropertyName("setId")] public uint SetId { get; set; }
|
[JsonPropertyName("setId")] public uint SetId { get; set; }
|
||||||
|
[JsonPropertyName("appendPropNum")] public uint AppendPropNum { get; set; }
|
||||||
|
|
||||||
public override uint ExcelId => Id;
|
public override uint ExcelId => Id;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
186
Yuanshen.Gameserver/Controllers/GadgetController.cs
Normal file
186
Yuanshen.Gameserver/Controllers/GadgetController.cs
Normal file
|
|
@ -0,0 +1,186 @@
|
||||||
|
using Yuanshen.Common.Data.Excel;
|
||||||
|
using Yuanshen.Gameserver.Controllers.Attributes;
|
||||||
|
using Yuanshen.Gameserver.Controllers.Result;
|
||||||
|
using Yuanshen.Gameserver.Database;
|
||||||
|
using Yuanshen.Gameserver.Game;
|
||||||
|
using Yuanshen.Gameserver.Network.Session;
|
||||||
|
using Yuanshen.Protocol;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Yuanshen.Gameserver.Controllers;
|
||||||
|
|
||||||
|
[NetController]
|
||||||
|
internal sealed class GadgetController : ControllerBase
|
||||||
|
{
|
||||||
|
private const uint ChestOpenedState = 102;
|
||||||
|
private const uint ActionReasonOpenChest = 39;
|
||||||
|
private const uint ActionReasonGather = 11;
|
||||||
|
private const uint MoraItemId = 202;
|
||||||
|
private const uint PrimogemItemId = 201;
|
||||||
|
|
||||||
|
private static readonly Random Random = new();
|
||||||
|
|
||||||
|
[NetCommand(CmdType.GadgetInteractReq)]
|
||||||
|
public async ValueTask<IResult> OnGadgetInteractReq(NetSession session, Player player, SceneManager scene,
|
||||||
|
DropTable drops, ExcelTableCollection excel, PlayerPersistence persistence, ILogger<GadgetController> logger)
|
||||||
|
{
|
||||||
|
GadgetInteractReq req = Packet!.DecodeBody<GadgetInteractReq>();
|
||||||
|
|
||||||
|
GameGadget? gadget = player.Gadgets.FirstOrDefault(candidate => candidate.EntityId == req.GadgetEntityId);
|
||||||
|
if (gadget is null)
|
||||||
|
return Reply(req, Retcode.RET_GADGET_NOT_EXIST);
|
||||||
|
|
||||||
|
if (gadget.IsChest)
|
||||||
|
return await OpenChestAsync(session, player, scene, drops, excel, persistence, logger, gadget, req);
|
||||||
|
|
||||||
|
return await GatherAsync(session, player, scene, drops, excel, persistence, logger, gadget, req);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async ValueTask<IResult> OpenChestAsync(NetSession session, Player player, SceneManager scene,
|
||||||
|
DropTable drops, ExcelTableCollection excel, PlayerPersistence persistence, ILogger logger,
|
||||||
|
GameGadget gadget, GadgetInteractReq req)
|
||||||
|
{
|
||||||
|
if (req.OpType == InterOpType.InterOpStart)
|
||||||
|
{
|
||||||
|
if (player.OpenedGadgetIds.Contains(gadget.NodeId))
|
||||||
|
return Reply(req, Retcode.RET_CHEST_IS_LOCKED);
|
||||||
|
|
||||||
|
return Reply(req, Retcode.RET_SUCC, InteractType.InteractOpenChest);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!player.OpenedGadgetIds.Add(gadget.NodeId))
|
||||||
|
return Reply(req, Retcode.RET_CHEST_IS_LOCKED);
|
||||||
|
|
||||||
|
await session.NotifyAsync(CmdType.GadgetInteractRsp, Build(req, Retcode.RET_SUCC, InteractType.InteractOpenChest));
|
||||||
|
await scene.SetGadgetStateAsync(gadget, ChestOpenedState, false);
|
||||||
|
|
||||||
|
Dictionary<uint, uint> rolled = drops.Roll(gadget.Node.DropId, Random);
|
||||||
|
await GrantAsync(session, player, drops, excel, gadget, rolled, ActionReasonOpenChest);
|
||||||
|
|
||||||
|
await persistence.SaveAsync();
|
||||||
|
|
||||||
|
logger.LogInformation("Chest {gadgetId} node {node} opened, drop {dropId} gave {count} stacks",
|
||||||
|
gadget.GadgetId, gadget.NodeId, gadget.Node.DropId, rolled.Count);
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async ValueTask<IResult> GatherAsync(NetSession session, Player player, SceneManager scene,
|
||||||
|
DropTable drops, ExcelTableCollection excel, PlayerPersistence persistence, ILogger logger,
|
||||||
|
GameGadget gadget, GadgetInteractReq req)
|
||||||
|
{
|
||||||
|
if (req.OpType != InterOpType.InterOpStart)
|
||||||
|
return Reply(req, Retcode.RET_SUCC, InteractType.InteractGather);
|
||||||
|
|
||||||
|
if (!player.OpenedGadgetIds.Add(gadget.NodeId))
|
||||||
|
return Reply(req, Retcode.RET_GADGET_NOT_EXIST);
|
||||||
|
|
||||||
|
await session.NotifyAsync(CmdType.GadgetInteractRsp, Build(req, Retcode.RET_SUCC, InteractType.InteractGather));
|
||||||
|
|
||||||
|
Dictionary<uint, uint> rolled = new();
|
||||||
|
|
||||||
|
if (gadget.Node.SubfieldId != 0)
|
||||||
|
{
|
||||||
|
uint dropId = drops.SubfieldDropId(gadget.Node.SubfieldId, gadget.Node.Level);
|
||||||
|
if (dropId != 0)
|
||||||
|
rolled = drops.Roll(dropId, Random);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rolled.Count == 0 && gadget.Node.GatherItemId != 0)
|
||||||
|
rolled[gadget.Node.GatherItemId] = 1;
|
||||||
|
|
||||||
|
await GrantAsync(session, player, drops, excel, gadget, rolled, ActionReasonGather);
|
||||||
|
await scene.DespawnGadgetAsync(gadget, VisionType.VisionGatherEscape);
|
||||||
|
await persistence.SaveAsync();
|
||||||
|
|
||||||
|
logger.LogInformation("Gathered {gadgetId} node {node}, gave {count} stacks",
|
||||||
|
gadget.GadgetId, gadget.NodeId, rolled.Count);
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async ValueTask GrantAsync(NetSession session, Player player, DropTable drops,
|
||||||
|
ExcelTableCollection excel, GameGadget gadget, Dictionary<uint, uint> rolled, uint reason)
|
||||||
|
{
|
||||||
|
if (rolled.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
StoreItemChangeNotify store = new() { StoreType = StoreType.StorePack };
|
||||||
|
ItemAddHintNotify hint = new()
|
||||||
|
{
|
||||||
|
Reason = reason,
|
||||||
|
Position = gadget.Node.Pos,
|
||||||
|
IsPositionValid = true
|
||||||
|
};
|
||||||
|
|
||||||
|
bool currencyChanged = false;
|
||||||
|
|
||||||
|
foreach ((uint itemId, uint count) in rolled)
|
||||||
|
{
|
||||||
|
switch (drops.TypeOf(itemId))
|
||||||
|
{
|
||||||
|
case "weapon":
|
||||||
|
for (uint made = 0; made < Math.Min(count, 10u); made++)
|
||||||
|
store.ItemList.Add(player.CreateWeapon(itemId).AsItem());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "virtual" when itemId == MoraItemId:
|
||||||
|
player.Scoin += count;
|
||||||
|
currencyChanged = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "virtual" when itemId == PrimogemItemId:
|
||||||
|
player.Hcoin += count;
|
||||||
|
currencyChanged = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "virtual":
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case "reliquary":
|
||||||
|
for (uint made = 0; made < Math.Min(count, 5u); made++)
|
||||||
|
{
|
||||||
|
GameReliquary? reliquary = player.CreateReliquary(itemId, Random);
|
||||||
|
if (reliquary is not null)
|
||||||
|
store.ItemList.Add(reliquary.AsItem());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
player.GiveMaterial(itemId, count);
|
||||||
|
store.ItemList.Add(new Item
|
||||||
|
{
|
||||||
|
ItemId = itemId,
|
||||||
|
Guid = player.MaterialGuid(itemId),
|
||||||
|
Material = new Material { Count = player.Materials.GetValueOrDefault(itemId) }
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
hint.ItemList.Add(new ItemHint { ItemId = itemId, Count = count, IsNew = false });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hint.ItemList.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (store.ItemList.Count != 0)
|
||||||
|
await session.NotifyAsync(CmdType.StoreItemChangeNotify, store);
|
||||||
|
|
||||||
|
if (currencyChanged)
|
||||||
|
await session.NotifyAsync(CmdType.PlayerPropNotify, player.BuildCurrencyProps());
|
||||||
|
|
||||||
|
await session.NotifyAsync(CmdType.ItemAddHintNotify, hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IResult Reply(GadgetInteractReq req, int retcode, InteractType interactType = InteractType.InteractNone)
|
||||||
|
=> Response(CmdType.GadgetInteractRsp, Build(req, retcode, interactType));
|
||||||
|
|
||||||
|
private static GadgetInteractRsp Build(GadgetInteractReq req, int retcode, InteractType interactType) => new()
|
||||||
|
{
|
||||||
|
Retcode = retcode,
|
||||||
|
GadgetEntityId = req.GadgetEntityId,
|
||||||
|
GadgetId = req.GadgetId,
|
||||||
|
InteractType = interactType,
|
||||||
|
OpType = req.OpType
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -14,6 +14,9 @@ internal sealed class PlayerRecord
|
||||||
public Dictionary<uint, AvatarProgress> AvatarProgress { get; set; } = new();
|
public Dictionary<uint, AvatarProgress> AvatarProgress { get; set; } = new();
|
||||||
public Dictionary<uint, uint> Materials { get; set; } = new();
|
public Dictionary<uint, uint> Materials { get; set; } = new();
|
||||||
public List<uint> KilledNodes { get; set; } = new();
|
public List<uint> KilledNodes { get; set; } = new();
|
||||||
|
public List<uint> OpenedGadgets { get; set; } = new();
|
||||||
|
public List<DroppedWeapon> DroppedWeapons { get; set; } = new();
|
||||||
|
public List<DroppedReliquary> DroppedReliquaries { get; set; } = new();
|
||||||
public uint SpawnDataVersion { get; set; }
|
public uint SpawnDataVersion { get; set; }
|
||||||
public Dictionary<uint, uint> GachaPity { get; set; } = new();
|
public Dictionary<uint, uint> GachaPity { get; set; } = new();
|
||||||
public Dictionary<uint, uint> GachaGuarantee { get; set; } = new();
|
public Dictionary<uint, uint> GachaGuarantee { get; set; } = new();
|
||||||
|
|
@ -46,3 +49,21 @@ internal sealed class GachaLogEntry
|
||||||
public string Kind { get; set; } = string.Empty;
|
public string Kind { get; set; } = string.Empty;
|
||||||
public long Time { get; set; }
|
public long Time { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal sealed class DroppedWeapon
|
||||||
|
{
|
||||||
|
public uint ItemId { get; set; }
|
||||||
|
public uint Level { get; set; } = 1;
|
||||||
|
public uint PromoteLevel { get; set; }
|
||||||
|
public uint Refinement { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class DroppedReliquary
|
||||||
|
{
|
||||||
|
public uint ItemId { get; set; }
|
||||||
|
public uint EquipType { get; set; }
|
||||||
|
public uint MainPropId { get; set; }
|
||||||
|
public uint Level { get; set; } = 1;
|
||||||
|
public uint PromoteLevel { get; set; }
|
||||||
|
public List<uint> AppendPropIds { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,13 @@ internal sealed class CombatManager
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case "reliquary":
|
case "reliquary":
|
||||||
continue;
|
for (uint made = 0; made < Math.Min(count, 5u); made++)
|
||||||
|
{
|
||||||
|
GameReliquary? reliquary = _player.CreateReliquary(itemId, Random);
|
||||||
|
if (reliquary is not null)
|
||||||
|
store.ItemList.Add(reliquary.AsItem());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
_player.GiveMaterial(itemId, count);
|
_player.GiveMaterial(itemId, count);
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,26 @@ internal sealed class DropTable
|
||||||
private readonly Dictionary<uint, List<DropEntry>> _drops = new();
|
private readonly Dictionary<uint, List<DropEntry>> _drops = new();
|
||||||
private readonly Dictionary<uint, string> _itemTypes = new();
|
private readonly Dictionary<uint, string> _itemTypes = new();
|
||||||
|
|
||||||
|
private readonly Dictionary<uint, List<(uint MaxLevel, uint DropId)>> _subfields = new();
|
||||||
|
|
||||||
public DropTable()
|
public DropTable()
|
||||||
{
|
{
|
||||||
Load("monster_drops.json");
|
Load("monster_drops.json");
|
||||||
|
Load("gadget_drops.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint SubfieldDropId(uint subfieldId, uint level)
|
||||||
|
{
|
||||||
|
if (!_subfields.TryGetValue(subfieldId, out List<(uint MaxLevel, uint DropId)>? bands) || bands.Count == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
foreach ((uint maxLevel, uint dropId) in bands.OrderBy(band => band.MaxLevel))
|
||||||
|
{
|
||||||
|
if (level <= maxLevel)
|
||||||
|
return dropId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bands[^1].DropId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsEmpty => _drops.Count == 0;
|
public bool IsEmpty => _drops.Count == 0;
|
||||||
|
|
@ -103,7 +120,25 @@ internal sealed class DropTable
|
||||||
using JsonDocument document = JsonDocument.Parse(File.ReadAllText(path));
|
using JsonDocument document = JsonDocument.Parse(File.ReadAllText(path));
|
||||||
JsonElement root = document.RootElement;
|
JsonElement root = document.RootElement;
|
||||||
|
|
||||||
foreach (JsonProperty monster in root.GetProperty("monsters").EnumerateObject())
|
if (root.TryGetProperty("subfield", out JsonElement subfields))
|
||||||
|
{
|
||||||
|
foreach (JsonProperty subfield in subfields.EnumerateObject())
|
||||||
|
{
|
||||||
|
if (!uint.TryParse(subfield.Name, out uint subfieldId))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
List<(uint, uint)> bands = new();
|
||||||
|
foreach (JsonElement band in subfield.Value.EnumerateArray())
|
||||||
|
bands.Add((band.GetProperty("maxLevel").GetUInt32(), band.GetProperty("dropId").GetUInt32()));
|
||||||
|
|
||||||
|
if (bands.Count != 0)
|
||||||
|
_subfields[subfieldId] = bands;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (JsonProperty monster in root.TryGetProperty("monsters", out JsonElement monsterRoot)
|
||||||
|
? monsterRoot.EnumerateObject()
|
||||||
|
: default)
|
||||||
{
|
{
|
||||||
if (!uint.TryParse(monster.Name, out uint monsterId))
|
if (!uint.TryParse(monster.Name, out uint monsterId))
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -120,7 +155,7 @@ internal sealed class DropTable
|
||||||
_monsters[monsterId] = byLevel;
|
_monsters[monsterId] = byLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (JsonProperty drop in root.GetProperty("drops").EnumerateObject())
|
foreach (JsonProperty drop in root.TryGetProperty("drops", out JsonElement dropRoot) ? dropRoot.EnumerateObject() : default)
|
||||||
{
|
{
|
||||||
if (!uint.TryParse(drop.Name, out uint dropId))
|
if (!uint.TryParse(drop.Name, out uint dropId))
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -141,7 +176,7 @@ internal sealed class DropTable
|
||||||
_drops[dropId] = entries;
|
_drops[dropId] = entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (JsonProperty item in root.GetProperty("items").EnumerateObject())
|
foreach (JsonProperty item in root.TryGetProperty("items", out JsonElement itemRoot) ? itemRoot.EnumerateObject() : default)
|
||||||
{
|
{
|
||||||
if (uint.TryParse(item.Name, out uint itemId))
|
if (uint.TryParse(item.Name, out uint itemId))
|
||||||
_itemTypes[itemId] = item.Value.GetProperty("type").GetString() ?? "material";
|
_itemTypes[itemId] = item.Value.GetProperty("type").GetString() ?? "material";
|
||||||
|
|
|
||||||
85
Yuanshen.Gameserver/Game/GadgetSpawnTable.cs
Normal file
85
Yuanshen.Gameserver/Game/GadgetSpawnTable.cs
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
using System.Text.Json;
|
||||||
|
using Yuanshen.Protocol;
|
||||||
|
|
||||||
|
namespace Yuanshen.Gameserver.Game;
|
||||||
|
|
||||||
|
internal readonly record struct GadgetNode(
|
||||||
|
uint NodeId,
|
||||||
|
uint ConfigId,
|
||||||
|
uint GroupId,
|
||||||
|
uint GadgetId,
|
||||||
|
uint Level,
|
||||||
|
Vector Pos,
|
||||||
|
Vector Rot,
|
||||||
|
string Kind,
|
||||||
|
uint State,
|
||||||
|
uint GadgetType,
|
||||||
|
uint DropId,
|
||||||
|
uint GatherItemId,
|
||||||
|
uint SubfieldId,
|
||||||
|
uint MarkFlag)
|
||||||
|
{
|
||||||
|
public bool IsChest => Kind == "chest";
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class GadgetSpawnTable
|
||||||
|
{
|
||||||
|
public IReadOnlyList<GadgetNode> Nodes { get; }
|
||||||
|
|
||||||
|
public GadgetSpawnTable()
|
||||||
|
{
|
||||||
|
Nodes = Load("scene3_gadgets.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<GadgetNode> Load(string fileName)
|
||||||
|
{
|
||||||
|
List<GadgetNode> nodes = new();
|
||||||
|
string path = Path.Combine(AppContext.BaseDirectory, "assets", "scene", fileName);
|
||||||
|
if (!File.Exists(path))
|
||||||
|
return nodes;
|
||||||
|
|
||||||
|
using JsonDocument document = JsonDocument.Parse(File.ReadAllText(path));
|
||||||
|
|
||||||
|
foreach (JsonElement row in document.RootElement.EnumerateArray())
|
||||||
|
{
|
||||||
|
string kind = row.TryGetProperty("k", out JsonElement k) ? k.GetString() ?? string.Empty : string.Empty;
|
||||||
|
if (kind.Length == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
nodes.Add(new GadgetNode(
|
||||||
|
Number(row, "n"),
|
||||||
|
Number(row, "c"),
|
||||||
|
Number(row, "g"),
|
||||||
|
Number(row, "gi"),
|
||||||
|
Math.Max(Number(row, "l"), 1u),
|
||||||
|
new Vector { X = Real(row, "x"), Y = Real(row, "y"), Z = Real(row, "z") },
|
||||||
|
new Vector { X = Real(row, "rx"), Y = Real(row, "ry"), Z = Real(row, "rz") },
|
||||||
|
kind,
|
||||||
|
Number(row, "st"),
|
||||||
|
Number(row, "ty"),
|
||||||
|
Number(row, "rd"),
|
||||||
|
Number(row, "ii"),
|
||||||
|
Subfield(row),
|
||||||
|
Number(row, "mf")));
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static uint Subfield(JsonElement row)
|
||||||
|
{
|
||||||
|
if (!row.TryGetProperty("sf", out JsonElement subfields))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
foreach (JsonProperty entry in subfields.EnumerateObject())
|
||||||
|
return entry.Value.GetUInt32();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static uint Number(JsonElement row, string name)
|
||||||
|
=> row.TryGetProperty(name, out JsonElement value) && value.TryGetUInt32(out uint parsed) ? parsed : 0;
|
||||||
|
|
||||||
|
private static float Real(JsonElement row, string name)
|
||||||
|
=> row.TryGetProperty(name, out JsonElement value) ? (float)value.GetDouble() : 0f;
|
||||||
|
}
|
||||||
67
Yuanshen.Gameserver/Game/GameGadget.cs
Normal file
67
Yuanshen.Gameserver/Game/GameGadget.cs
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
using Yuanshen.Protocol;
|
||||||
|
|
||||||
|
namespace Yuanshen.Gameserver.Game;
|
||||||
|
|
||||||
|
internal sealed class GameGadget
|
||||||
|
{
|
||||||
|
public uint EntityId { get; }
|
||||||
|
public GadgetNode Node { get; }
|
||||||
|
|
||||||
|
public uint GadgetId => Node.GadgetId;
|
||||||
|
public uint NodeId => Node.NodeId;
|
||||||
|
public bool IsChest => Node.IsChest;
|
||||||
|
|
||||||
|
public GameGadget(GadgetNode node, uint entityId)
|
||||||
|
{
|
||||||
|
Node = node;
|
||||||
|
EntityId = entityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SceneEntityInfo AsSceneEntity()
|
||||||
|
{
|
||||||
|
SceneEntityInfo entity = new()
|
||||||
|
{
|
||||||
|
EntityType = ProtEntityType.ProtEntityGadget,
|
||||||
|
EntityId = EntityId,
|
||||||
|
LifeState = 1,
|
||||||
|
MotionInfo = new MotionInfo
|
||||||
|
{
|
||||||
|
Pos = Node.Pos,
|
||||||
|
Rot = Node.Rot,
|
||||||
|
Speed = new Vector(),
|
||||||
|
State = MotionState.MotionStandby
|
||||||
|
},
|
||||||
|
EntityClientData = new EntityClientData(),
|
||||||
|
EntityAuthorityInfo = new EntityAuthorityInfo
|
||||||
|
{
|
||||||
|
AbilityInfo = new AbilitySyncStateInfo { IsInited = true },
|
||||||
|
RendererChangedInfo = new EntityRendererChangedInfo(),
|
||||||
|
AiInfo = new SceneEntityAiInfo { IsAiOpen = false, BornPos = Node.Pos },
|
||||||
|
BornPos = Node.Pos
|
||||||
|
},
|
||||||
|
Gadget = new SceneGadgetInfo
|
||||||
|
{
|
||||||
|
GadgetId = Node.GadgetId,
|
||||||
|
GroupId = Node.GroupId,
|
||||||
|
ConfigId = Node.ConfigId,
|
||||||
|
OwnerEntityId = 0,
|
||||||
|
BornType = GadgetBornType.GadgetBornNone,
|
||||||
|
GadgetState = Node.State,
|
||||||
|
GadgetType = Node.GadgetType,
|
||||||
|
IsShowCutscene = false,
|
||||||
|
AuthorityPeerId = Player.PeerId,
|
||||||
|
IsEnableInteract = true,
|
||||||
|
InteractId = 0,
|
||||||
|
MarkFlag = Node.MarkFlag
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
entity.PropList.Add(new PropPair
|
||||||
|
{
|
||||||
|
Type = 4001,
|
||||||
|
PropValue = new PropValue { Type = 4001, Ival = Node.Level, Val = Node.Level }
|
||||||
|
});
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,7 @@ internal sealed class Player
|
||||||
public uint Uid { get; private set; } = 1;
|
public uint Uid { get; private set; } = 1;
|
||||||
public const uint PeerId = 1;
|
public const uint PeerId = 1;
|
||||||
public const uint TeamEntityId = 0x09000001;
|
public const uint TeamEntityId = 0x09000001;
|
||||||
|
private const uint StarterReliquaryRank = 5;
|
||||||
public const uint MpLevelEntityId = 0x0B000001;
|
public const uint MpLevelEntityId = 0x0B000001;
|
||||||
|
|
||||||
public static readonly uint[] Flycloaks = { 140001, 140002, 140003, 140004, 140005 };
|
public static readonly uint[] Flycloaks = { 140001, 140002, 140003, 140004, 140005 };
|
||||||
|
|
@ -18,7 +19,9 @@ internal sealed class Player
|
||||||
public List<GameWeapon> Weapons { get; } = new();
|
public List<GameWeapon> Weapons { get; } = new();
|
||||||
public List<GameReliquary> Reliquaries { get; } = new();
|
public List<GameReliquary> Reliquaries { get; } = new();
|
||||||
public List<GameMonster> Monsters { get; } = new();
|
public List<GameMonster> Monsters { get; } = new();
|
||||||
|
public List<GameGadget> Gadgets { get; } = new();
|
||||||
public HashSet<uint> KilledNodeIds { get; } = new();
|
public HashSet<uint> KilledNodeIds { get; } = new();
|
||||||
|
public HashSet<uint> OpenedGadgetIds { get; } = new();
|
||||||
public Dictionary<uint, uint> Materials { get; } = new();
|
public Dictionary<uint, uint> Materials { get; } = new();
|
||||||
|
|
||||||
public bool IsInitialized { get; private set; }
|
public bool IsInitialized { get; private set; }
|
||||||
|
|
@ -29,9 +32,11 @@ internal sealed class Player
|
||||||
|
|
||||||
private readonly ExcelTableCollection _excel;
|
private readonly ExcelTableCollection _excel;
|
||||||
private uint _guidSeq;
|
private uint _guidSeq;
|
||||||
|
private uint _defaultGuidCeiling;
|
||||||
private uint _avatarEntitySeq;
|
private uint _avatarEntitySeq;
|
||||||
private uint _weaponEntitySeq;
|
private uint _weaponEntitySeq;
|
||||||
private uint _monsterEntitySeq;
|
private uint _monsterEntitySeq;
|
||||||
|
private uint _gadgetEntitySeq;
|
||||||
|
|
||||||
public Player(ExcelTableCollection excel) => _excel = excel;
|
public Player(ExcelTableCollection excel) => _excel = excel;
|
||||||
|
|
||||||
|
|
@ -86,6 +91,7 @@ internal sealed class Player
|
||||||
|
|
||||||
CurrentAvatarGuid = Avatars[0].Guid;
|
CurrentAvatarGuid = Avatars[0].Guid;
|
||||||
TeamAvatarGuids.Add(Avatars[0].Guid);
|
TeamAvatarGuids.Add(Avatars[0].Guid);
|
||||||
|
_defaultGuidCeiling = _guidSeq;
|
||||||
IsInitialized = true;
|
IsInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -169,6 +175,13 @@ internal sealed class Player
|
||||||
return monster;
|
return monster;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GameGadget SpawnGadget(GadgetNode node)
|
||||||
|
{
|
||||||
|
GameGadget gadget = new(node, 0x04000000 + ++_gadgetEntitySeq);
|
||||||
|
Gadgets.Add(gadget);
|
||||||
|
return gadget;
|
||||||
|
}
|
||||||
|
|
||||||
public PlayerRecord ToRecord(Yuanshen.Protocol.Vector pos) => new()
|
public PlayerRecord ToRecord(Yuanshen.Protocol.Vector pos) => new()
|
||||||
{
|
{
|
||||||
Uid = Uid,
|
Uid = Uid,
|
||||||
|
|
@ -191,6 +204,23 @@ internal sealed class Player
|
||||||
.ToDictionary(group => group.Key, group => BuildProgress(group.First())),
|
.ToDictionary(group => group.Key, group => BuildProgress(group.First())),
|
||||||
Materials = new Dictionary<uint, uint>(Materials),
|
Materials = new Dictionary<uint, uint>(Materials),
|
||||||
KilledNodes = KilledNodeIds.ToList(),
|
KilledNodes = KilledNodeIds.ToList(),
|
||||||
|
OpenedGadgets = OpenedGadgetIds.ToList(),
|
||||||
|
DroppedWeapons = Weapons.Where(IsDropped).Select(weapon => new DroppedWeapon
|
||||||
|
{
|
||||||
|
ItemId = weapon.ItemId,
|
||||||
|
Level = weapon.Level,
|
||||||
|
PromoteLevel = weapon.PromoteLevel,
|
||||||
|
Refinement = weapon.Refinement
|
||||||
|
}).ToList(),
|
||||||
|
DroppedReliquaries = Reliquaries.Where(IsDropped).Select(reliquary => new DroppedReliquary
|
||||||
|
{
|
||||||
|
ItemId = reliquary.ItemId,
|
||||||
|
EquipType = reliquary.EquipType,
|
||||||
|
MainPropId = reliquary.MainPropId,
|
||||||
|
Level = reliquary.Level,
|
||||||
|
PromoteLevel = reliquary.PromoteLevel,
|
||||||
|
AppendPropIds = reliquary.AppendPropIds.ToList()
|
||||||
|
}).ToList(),
|
||||||
SpawnDataVersion = CurrentSpawnDataVersion,
|
SpawnDataVersion = CurrentSpawnDataVersion,
|
||||||
GachaPity = GachaPity.ToDictionary(pair => pair.Key, pair => pair.Value),
|
GachaPity = GachaPity.ToDictionary(pair => pair.Key, pair => pair.Value),
|
||||||
GachaGuarantee = GachaGuarantee.ToDictionary(pair => pair.Key, pair => pair.Value),
|
GachaGuarantee = GachaGuarantee.ToDictionary(pair => pair.Key, pair => pair.Value),
|
||||||
|
|
@ -207,6 +237,8 @@ internal sealed class Player
|
||||||
{
|
{
|
||||||
CurrentTeamId = record.CurrentTeamId;
|
CurrentTeamId = record.CurrentTeamId;
|
||||||
|
|
||||||
|
RestoreDropped(record);
|
||||||
|
|
||||||
Hcoin = record.Hcoin != 0 || record.Scoin != 0 ? record.Hcoin : StartingHcoin;
|
Hcoin = record.Hcoin != 0 || record.Scoin != 0 ? record.Hcoin : StartingHcoin;
|
||||||
Scoin = record.Hcoin != 0 || record.Scoin != 0 ? record.Scoin : StartingScoin;
|
Scoin = record.Hcoin != 0 || record.Scoin != 0 ? record.Scoin : StartingScoin;
|
||||||
|
|
||||||
|
|
@ -229,6 +261,10 @@ internal sealed class Player
|
||||||
foreach (uint nodeId in record.SpawnDataVersion == CurrentSpawnDataVersion ? record.KilledNodes : new List<uint>())
|
foreach (uint nodeId in record.SpawnDataVersion == CurrentSpawnDataVersion ? record.KilledNodes : new List<uint>())
|
||||||
KilledNodeIds.Add(nodeId);
|
KilledNodeIds.Add(nodeId);
|
||||||
|
|
||||||
|
OpenedGadgetIds.Clear();
|
||||||
|
foreach (uint gadgetNodeId in record.OpenedGadgets)
|
||||||
|
OpenedGadgetIds.Add(gadgetNodeId);
|
||||||
|
|
||||||
HashSet<ulong> takenWeapons = new();
|
HashSet<ulong> takenWeapons = new();
|
||||||
foreach ((uint avatarId, ulong itemId) in record.EquippedWeapons)
|
foreach ((uint avatarId, ulong itemId) in record.EquippedWeapons)
|
||||||
{
|
{
|
||||||
|
|
@ -314,6 +350,35 @@ internal sealed class Player
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsDropped(GameWeapon weapon) => (uint)(weapon.Guid & 0xFFFFFFFF) > _defaultGuidCeiling;
|
||||||
|
|
||||||
|
private bool IsDropped(GameReliquary reliquary) => (uint)(reliquary.Guid & 0xFFFFFFFF) > _defaultGuidCeiling;
|
||||||
|
|
||||||
|
private void RestoreDropped(PlayerRecord record)
|
||||||
|
{
|
||||||
|
foreach (DroppedWeapon saved in record.DroppedWeapons)
|
||||||
|
{
|
||||||
|
GameWeapon weapon = CreateWeapon(saved.ItemId);
|
||||||
|
weapon.Level = saved.Level;
|
||||||
|
weapon.PromoteLevel = saved.PromoteLevel;
|
||||||
|
weapon.Refinement = saved.Refinement;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (DroppedReliquary saved in record.DroppedReliquaries)
|
||||||
|
{
|
||||||
|
GameReliquary reliquary = new(saved.ItemId, NextGuid(), saved.EquipType, saved.MainPropId)
|
||||||
|
{
|
||||||
|
Level = saved.Level,
|
||||||
|
PromoteLevel = saved.PromoteLevel
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (uint appendPropId in saved.AppendPropIds)
|
||||||
|
reliquary.AppendPropIds.Add(appendPropId);
|
||||||
|
|
||||||
|
Reliquaries.Add(reliquary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public GameWeapon CreateWeapon(uint itemId)
|
public GameWeapon CreateWeapon(uint itemId)
|
||||||
{
|
{
|
||||||
GameWeapon weapon = new(itemId, NextGuid());
|
GameWeapon weapon = new(itemId, NextGuid());
|
||||||
|
|
@ -321,6 +386,50 @@ internal sealed class Player
|
||||||
return weapon;
|
return weapon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GameReliquary? CreateReliquary(uint itemId, Random random)
|
||||||
|
{
|
||||||
|
ReliquaryExcel? excel = _excel.GetTable(ExcelType.Reliquary).Items.OfType<ReliquaryExcel>()
|
||||||
|
.FirstOrDefault(candidate => candidate.Id == itemId);
|
||||||
|
|
||||||
|
if (excel is null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
List<ReliquaryMainPropExcel> pool = _excel.GetTable(ExcelType.ReliquaryMainProp)
|
||||||
|
.Items.OfType<ReliquaryMainPropExcel>()
|
||||||
|
.Where(candidate => candidate.PropDepotId == excel.MainPropDepotId)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (pool.Count == 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
ReliquaryMainPropExcel main = pool[random.Next(pool.Count)];
|
||||||
|
GameReliquary reliquary = new(excel.Id, NextGuid(), EquipTypeId(excel.EquipType), main.Id)
|
||||||
|
{
|
||||||
|
Level = 1,
|
||||||
|
PromoteLevel = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
List<IGrouping<uint, ReliquaryAffixExcel>> groups = _excel.GetTable(ExcelType.ReliquaryAffix)
|
||||||
|
.Items.OfType<ReliquaryAffixExcel>()
|
||||||
|
.Where(candidate => candidate.DepotId == excel.AppendPropDepotId && candidate.PropType != main.PropType)
|
||||||
|
.GroupBy(candidate => candidate.GroupId)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
int wanted = (int)Math.Clamp(excel.AppendPropNum, 1u, (uint)groups.Count);
|
||||||
|
|
||||||
|
for (int taken = 0; taken < wanted && groups.Count != 0; taken++)
|
||||||
|
{
|
||||||
|
int index = random.Next(groups.Count);
|
||||||
|
List<ReliquaryAffixExcel> tiers = groups[index].ToList();
|
||||||
|
groups.RemoveAt(index);
|
||||||
|
|
||||||
|
reliquary.AppendPropIds.Add(tiers[random.Next(tiers.Count)].Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Reliquaries.Add(reliquary);
|
||||||
|
return reliquary;
|
||||||
|
}
|
||||||
|
|
||||||
private void CreateReliquaries()
|
private void CreateReliquaries()
|
||||||
{
|
{
|
||||||
List<ReliquaryMainPropExcel> mainProps = _excel.GetTable(ExcelType.ReliquaryMainProp)
|
List<ReliquaryMainPropExcel> mainProps = _excel.GetTable(ExcelType.ReliquaryMainProp)
|
||||||
|
|
@ -328,7 +437,8 @@ internal sealed class Player
|
||||||
List<ReliquaryAffixExcel> affixes = _excel.GetTable(ExcelType.ReliquaryAffix)
|
List<ReliquaryAffixExcel> affixes = _excel.GetTable(ExcelType.ReliquaryAffix)
|
||||||
.Items.OfType<ReliquaryAffixExcel>().ToList();
|
.Items.OfType<ReliquaryAffixExcel>().ToList();
|
||||||
|
|
||||||
foreach (ReliquaryExcel excel in _excel.GetTable(ExcelType.Reliquary).Items.OfType<ReliquaryExcel>())
|
foreach (ReliquaryExcel excel in _excel.GetTable(ExcelType.Reliquary).Items.OfType<ReliquaryExcel>()
|
||||||
|
.Where(candidate => candidate.RankLevel == StarterReliquaryRank))
|
||||||
{
|
{
|
||||||
ReliquaryMainPropExcel? main = mainProps.FirstOrDefault(p => p.PropDepotId == excel.MainPropDepotId);
|
ReliquaryMainPropExcel? main = mainProps.FirstOrDefault(p => p.PropDepotId == excel.MainPropDepotId);
|
||||||
if (main is null)
|
if (main is null)
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,32 @@ internal sealed class SceneManager
|
||||||
await _session.NotifyAsync(CmdType.SceneEntityAppearNotify, notify);
|
await _session.NotifyAsync(CmdType.SceneEntityAppearNotify, notify);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async ValueTask AppearGadgetAsync(GameGadget gadget)
|
||||||
|
{
|
||||||
|
SceneEntityAppearNotify notify = new() { AppearType = VisionType.VisionBorn };
|
||||||
|
notify.EntityList.Add(gadget.AsSceneEntity());
|
||||||
|
await _session.NotifyAsync(CmdType.SceneEntityAppearNotify, notify);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask DespawnGadgetAsync(GameGadget gadget, VisionType visionType)
|
||||||
|
{
|
||||||
|
_player.Gadgets.Remove(gadget);
|
||||||
|
|
||||||
|
SceneEntityDisappearNotify notify = new() { DisappearType = visionType };
|
||||||
|
notify.EntityList.Add(gadget.EntityId);
|
||||||
|
await _session.NotifyAsync(CmdType.SceneEntityDisappearNotify, notify);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask SetGadgetStateAsync(GameGadget gadget, uint state, bool enableInteract)
|
||||||
|
{
|
||||||
|
await _session.NotifyAsync(CmdType.GadgetStateNotify, new GadgetStateNotify
|
||||||
|
{
|
||||||
|
GadgetEntityId = gadget.EntityId,
|
||||||
|
GadgetState = state,
|
||||||
|
IsEnableInteract = enableInteract
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public async ValueTask SyncMonsterLevelAsync(GameMonster monster)
|
public async ValueTask SyncMonsterLevelAsync(GameMonster monster)
|
||||||
{
|
{
|
||||||
await _session.NotifyAsync(CmdType.EntityPropNotify, new EntityPropNotify
|
await _session.NotifyAsync(CmdType.EntityPropNotify, new EntityPropNotify
|
||||||
|
|
|
||||||
|
|
@ -9,23 +9,27 @@ internal sealed class WorldSpawner
|
||||||
private const float StreamStepSq = 20f * 20f;
|
private const float StreamStepSq = 20f * 20f;
|
||||||
private const int ConcurrentCap = 25;
|
private const int ConcurrentCap = 25;
|
||||||
private const int WildlifeCap = 6;
|
private const int WildlifeCap = 6;
|
||||||
|
private const int GadgetCap = 40;
|
||||||
|
|
||||||
private readonly Player _player;
|
private readonly Player _player;
|
||||||
private readonly SceneManager _scene;
|
private readonly SceneManager _scene;
|
||||||
private readonly MonsterSpawnTable _table;
|
private readonly MonsterSpawnTable _table;
|
||||||
|
private readonly GadgetSpawnTable _gadgets;
|
||||||
|
|
||||||
private Vector? _lastStream;
|
private Vector? _lastStream;
|
||||||
|
|
||||||
public WorldSpawner(Player player, SceneManager scene, MonsterSpawnTable table)
|
public WorldSpawner(Player player, SceneManager scene, MonsterSpawnTable table, GadgetSpawnTable gadgets)
|
||||||
{
|
{
|
||||||
_player = player;
|
_player = player;
|
||||||
_scene = scene;
|
_scene = scene;
|
||||||
_table = table;
|
_table = table;
|
||||||
|
_gadgets = gadgets;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask EnterSceneAsync(Vector pos)
|
public async ValueTask EnterSceneAsync(Vector pos)
|
||||||
{
|
{
|
||||||
_player.Monsters.Clear();
|
_player.Monsters.Clear();
|
||||||
|
_player.Gadgets.Clear();
|
||||||
_lastStream = null;
|
_lastStream = null;
|
||||||
await StreamAsync(pos, force: true);
|
await StreamAsync(pos, force: true);
|
||||||
}
|
}
|
||||||
|
|
@ -82,6 +86,39 @@ internal sealed class WorldSpawner
|
||||||
active.Add(node.NodeId);
|
active.Add(node.NodeId);
|
||||||
await _scene.AppearMonsterAsync(monster);
|
await _scene.AppearMonsterAsync(monster);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await StreamGadgetsAsync(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async ValueTask StreamGadgetsAsync(Vector pos)
|
||||||
|
{
|
||||||
|
HashSet<uint> live = new();
|
||||||
|
foreach (GameGadget gadget in _player.Gadgets)
|
||||||
|
live.Add(gadget.NodeId);
|
||||||
|
|
||||||
|
foreach (GameGadget gadget in _player.Gadgets
|
||||||
|
.Where(gadget => HorizontalSq(pos, gadget.Node.Pos) > DespawnRadiusSq)
|
||||||
|
.ToList())
|
||||||
|
{
|
||||||
|
live.Remove(gadget.NodeId);
|
||||||
|
await _scene.DespawnGadgetAsync(gadget, VisionType.VisionRemove);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (GadgetNode node in _gadgets.Nodes)
|
||||||
|
{
|
||||||
|
if (live.Count >= GadgetCap)
|
||||||
|
break;
|
||||||
|
if (live.Contains(node.NodeId))
|
||||||
|
continue;
|
||||||
|
if (node.IsChest && _player.OpenedGadgetIds.Contains(node.NodeId))
|
||||||
|
continue;
|
||||||
|
if (HorizontalSq(pos, node.Pos) > SpawnRadiusSq)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
GameGadget gadget = _player.SpawnGadget(node);
|
||||||
|
live.Add(node.NodeId);
|
||||||
|
await _scene.AppearGadgetAsync(gadget);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float HorizontalSq(Vector a, Vector b)
|
private static float HorizontalSq(Vector a, Vector b)
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ builder.Services.AddScoped<CombatManager>();
|
||||||
builder.Services.AddScoped<GmCommandService>();
|
builder.Services.AddScoped<GmCommandService>();
|
||||||
builder.Services.AddSingleton<MonsterSpawnTable>();
|
builder.Services.AddSingleton<MonsterSpawnTable>();
|
||||||
builder.Services.AddSingleton<DropTable>();
|
builder.Services.AddSingleton<DropTable>();
|
||||||
|
builder.Services.AddSingleton<GadgetSpawnTable>();
|
||||||
builder.Services.AddScoped<WorldSpawner>();
|
builder.Services.AddScoped<WorldSpawner>();
|
||||||
builder.Services.AddScoped<Yuanshen.Gameserver.Database.PlayerPersistence>();
|
builder.Services.AddScoped<Yuanshen.Gameserver.Database.PlayerPersistence>();
|
||||||
builder.Services.AddSingleton<Yuanshen.Gameserver.Database.PlayerSessionRegistry>();
|
builder.Services.AddSingleton<Yuanshen.Gameserver.Database.PlayerSessionRegistry>();
|
||||||
|
|
|
||||||
1
Yuanshen.Gameserver/assets/drops/gadget_drops.json
Normal file
1
Yuanshen.Gameserver/assets/drops/gadget_drops.json
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -1,211 +1,12 @@
|
||||||
[
|
[
|
||||||
{
|
|
||||||
"id": 23481,
|
|
||||||
"equipType": "EQUIP_RING",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 5099,
|
|
||||||
"appendPropDepotId": 964,
|
|
||||||
"setId": 10003
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23482,
|
|
||||||
"equipType": "EQUIP_NECKLACE",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 2000,
|
|
||||||
"appendPropDepotId": 961,
|
|
||||||
"setId": 10003
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23483,
|
|
||||||
"equipType": "EQUIP_DRESS",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 3095,
|
|
||||||
"appendPropDepotId": 965,
|
|
||||||
"setId": 10003
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23484,
|
|
||||||
"equipType": "EQUIP_BRACER",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 4000,
|
|
||||||
"appendPropDepotId": 962,
|
|
||||||
"setId": 10003
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23485,
|
|
||||||
"equipType": "EQUIP_SHOES",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 1099,
|
|
||||||
"appendPropDepotId": 963,
|
|
||||||
"setId": 10003
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23521,
|
|
||||||
"equipType": "EQUIP_RING",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 5099,
|
|
||||||
"appendPropDepotId": 964,
|
|
||||||
"setId": 10005
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23522,
|
|
||||||
"equipType": "EQUIP_NECKLACE",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 2000,
|
|
||||||
"appendPropDepotId": 961,
|
|
||||||
"setId": 10005
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23523,
|
|
||||||
"equipType": "EQUIP_DRESS",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 3095,
|
|
||||||
"appendPropDepotId": 965,
|
|
||||||
"setId": 10005
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23524,
|
|
||||||
"equipType": "EQUIP_BRACER",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 4000,
|
|
||||||
"appendPropDepotId": 962,
|
|
||||||
"setId": 10005
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23525,
|
|
||||||
"equipType": "EQUIP_SHOES",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 1099,
|
|
||||||
"appendPropDepotId": 963,
|
|
||||||
"setId": 10005
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23511,
|
|
||||||
"equipType": "EQUIP_RING",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 5088,
|
|
||||||
"appendPropDepotId": 964,
|
|
||||||
"setId": 10007
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23512,
|
|
||||||
"equipType": "EQUIP_NECKLACE",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 2000,
|
|
||||||
"appendPropDepotId": 961,
|
|
||||||
"setId": 10007
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23513,
|
|
||||||
"equipType": "EQUIP_DRESS",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 3093,
|
|
||||||
"appendPropDepotId": 965,
|
|
||||||
"setId": 10007
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23514,
|
|
||||||
"equipType": "EQUIP_BRACER",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 4000,
|
|
||||||
"appendPropDepotId": 962,
|
|
||||||
"setId": 10007
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23515,
|
|
||||||
"equipType": "EQUIP_SHOES",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 1095,
|
|
||||||
"appendPropDepotId": 963,
|
|
||||||
"setId": 10007
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23451,
|
|
||||||
"equipType": "EQUIP_RING",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 5094,
|
|
||||||
"appendPropDepotId": 964,
|
|
||||||
"setId": 14001
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23452,
|
|
||||||
"equipType": "EQUIP_NECKLACE",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 2000,
|
|
||||||
"appendPropDepotId": 961,
|
|
||||||
"setId": 14001
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23458,
|
|
||||||
"equipType": "EQUIP_DRESS",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 3096,
|
|
||||||
"appendPropDepotId": 965,
|
|
||||||
"setId": 14001
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23454,
|
|
||||||
"equipType": "EQUIP_BRACER",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 4000,
|
|
||||||
"appendPropDepotId": 962,
|
|
||||||
"setId": 14001
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23455,
|
|
||||||
"equipType": "EQUIP_SHOES",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 1099,
|
|
||||||
"appendPropDepotId": 963,
|
|
||||||
"setId": 14001
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23441,
|
|
||||||
"equipType": "EQUIP_RING",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 5095,
|
|
||||||
"appendPropDepotId": 964,
|
|
||||||
"setId": 14002
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23442,
|
|
||||||
"equipType": "EQUIP_NECKLACE",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 2000,
|
|
||||||
"appendPropDepotId": 961,
|
|
||||||
"setId": 14002
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23443,
|
|
||||||
"equipType": "EQUIP_DRESS",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 3096,
|
|
||||||
"appendPropDepotId": 965,
|
|
||||||
"setId": 14002
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23444,
|
|
||||||
"equipType": "EQUIP_BRACER",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 4000,
|
|
||||||
"appendPropDepotId": 962,
|
|
||||||
"setId": 14002
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23445,
|
|
||||||
"equipType": "EQUIP_SHOES",
|
|
||||||
"rankLevel": 5,
|
|
||||||
"mainPropDepotId": 1099,
|
|
||||||
"appendPropDepotId": 963,
|
|
||||||
"setId": 14002
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": 23431,
|
"id": 23431,
|
||||||
"equipType": "EQUIP_RING",
|
"equipType": "EQUIP_RING",
|
||||||
"rankLevel": 5,
|
"rankLevel": 5,
|
||||||
"mainPropDepotId": 5096,
|
"mainPropDepotId": 5096,
|
||||||
"appendPropDepotId": 964,
|
"appendPropDepotId": 964,
|
||||||
"setId": 14003
|
"setId": 14003,
|
||||||
|
"appendPropNum": 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 23432,
|
"id": 23432,
|
||||||
|
|
@ -213,7 +14,8 @@
|
||||||
"rankLevel": 5,
|
"rankLevel": 5,
|
||||||
"mainPropDepotId": 2000,
|
"mainPropDepotId": 2000,
|
||||||
"appendPropDepotId": 961,
|
"appendPropDepotId": 961,
|
||||||
"setId": 14003
|
"setId": 14003,
|
||||||
|
"appendPropNum": 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 23433,
|
"id": 23433,
|
||||||
|
|
@ -221,7 +23,8 @@
|
||||||
"rankLevel": 5,
|
"rankLevel": 5,
|
||||||
"mainPropDepotId": 3096,
|
"mainPropDepotId": 3096,
|
||||||
"appendPropDepotId": 965,
|
"appendPropDepotId": 965,
|
||||||
"setId": 14003
|
"setId": 14003,
|
||||||
|
"appendPropNum": 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 23434,
|
"id": 23434,
|
||||||
|
|
@ -229,7 +32,8 @@
|
||||||
"rankLevel": 5,
|
"rankLevel": 5,
|
||||||
"mainPropDepotId": 4000,
|
"mainPropDepotId": 4000,
|
||||||
"appendPropDepotId": 962,
|
"appendPropDepotId": 962,
|
||||||
"setId": 14003
|
"setId": 14003,
|
||||||
|
"appendPropNum": 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 23435,
|
"id": 23435,
|
||||||
|
|
@ -237,6 +41,727 @@
|
||||||
"rankLevel": 5,
|
"rankLevel": 5,
|
||||||
"mainPropDepotId": 1099,
|
"mainPropDepotId": 1099,
|
||||||
"appendPropDepotId": 963,
|
"appendPropDepotId": 963,
|
||||||
"setId": 14003
|
"setId": 14003,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23441,
|
||||||
|
"equipType": "EQUIP_RING",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 5095,
|
||||||
|
"appendPropDepotId": 964,
|
||||||
|
"setId": 14002,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23442,
|
||||||
|
"equipType": "EQUIP_NECKLACE",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 2000,
|
||||||
|
"appendPropDepotId": 961,
|
||||||
|
"setId": 14002,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23443,
|
||||||
|
"equipType": "EQUIP_DRESS",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 3096,
|
||||||
|
"appendPropDepotId": 965,
|
||||||
|
"setId": 14002,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23444,
|
||||||
|
"equipType": "EQUIP_BRACER",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 4000,
|
||||||
|
"appendPropDepotId": 962,
|
||||||
|
"setId": 14002,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23445,
|
||||||
|
"equipType": "EQUIP_SHOES",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 1099,
|
||||||
|
"appendPropDepotId": 963,
|
||||||
|
"setId": 14002,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23451,
|
||||||
|
"equipType": "EQUIP_RING",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 5094,
|
||||||
|
"appendPropDepotId": 964,
|
||||||
|
"setId": 14001,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23452,
|
||||||
|
"equipType": "EQUIP_NECKLACE",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 2000,
|
||||||
|
"appendPropDepotId": 961,
|
||||||
|
"setId": 14001,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23454,
|
||||||
|
"equipType": "EQUIP_BRACER",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 4000,
|
||||||
|
"appendPropDepotId": 962,
|
||||||
|
"setId": 14001,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23455,
|
||||||
|
"equipType": "EQUIP_SHOES",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 1099,
|
||||||
|
"appendPropDepotId": 963,
|
||||||
|
"setId": 14001,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23458,
|
||||||
|
"equipType": "EQUIP_DRESS",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 3096,
|
||||||
|
"appendPropDepotId": 965,
|
||||||
|
"setId": 14001,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23481,
|
||||||
|
"equipType": "EQUIP_RING",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 5099,
|
||||||
|
"appendPropDepotId": 964,
|
||||||
|
"setId": 10003,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23482,
|
||||||
|
"equipType": "EQUIP_NECKLACE",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 2000,
|
||||||
|
"appendPropDepotId": 961,
|
||||||
|
"setId": 10003,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23483,
|
||||||
|
"equipType": "EQUIP_DRESS",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 3095,
|
||||||
|
"appendPropDepotId": 965,
|
||||||
|
"setId": 10003,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23484,
|
||||||
|
"equipType": "EQUIP_BRACER",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 4000,
|
||||||
|
"appendPropDepotId": 962,
|
||||||
|
"setId": 10003,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23485,
|
||||||
|
"equipType": "EQUIP_SHOES",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 1099,
|
||||||
|
"appendPropDepotId": 963,
|
||||||
|
"setId": 10003,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23511,
|
||||||
|
"equipType": "EQUIP_RING",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 5088,
|
||||||
|
"appendPropDepotId": 964,
|
||||||
|
"setId": 10007,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23512,
|
||||||
|
"equipType": "EQUIP_NECKLACE",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 2000,
|
||||||
|
"appendPropDepotId": 961,
|
||||||
|
"setId": 10007,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23513,
|
||||||
|
"equipType": "EQUIP_DRESS",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 3093,
|
||||||
|
"appendPropDepotId": 965,
|
||||||
|
"setId": 10007,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23514,
|
||||||
|
"equipType": "EQUIP_BRACER",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 4000,
|
||||||
|
"appendPropDepotId": 962,
|
||||||
|
"setId": 10007,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23515,
|
||||||
|
"equipType": "EQUIP_SHOES",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 1095,
|
||||||
|
"appendPropDepotId": 963,
|
||||||
|
"setId": 10007,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23521,
|
||||||
|
"equipType": "EQUIP_RING",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 5099,
|
||||||
|
"appendPropDepotId": 964,
|
||||||
|
"setId": 10005,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23522,
|
||||||
|
"equipType": "EQUIP_NECKLACE",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 2000,
|
||||||
|
"appendPropDepotId": 961,
|
||||||
|
"setId": 10005,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23523,
|
||||||
|
"equipType": "EQUIP_DRESS",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 3095,
|
||||||
|
"appendPropDepotId": 965,
|
||||||
|
"setId": 10005,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23524,
|
||||||
|
"equipType": "EQUIP_BRACER",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 4000,
|
||||||
|
"appendPropDepotId": 962,
|
||||||
|
"setId": 10005,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23525,
|
||||||
|
"equipType": "EQUIP_SHOES",
|
||||||
|
"rankLevel": 5,
|
||||||
|
"mainPropDepotId": 1099,
|
||||||
|
"appendPropDepotId": 963,
|
||||||
|
"setId": 10005,
|
||||||
|
"appendPropNum": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 55311,
|
||||||
|
"equipType": "EQUIP_RING",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 5000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10005
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 55312,
|
||||||
|
"equipType": "EQUIP_RING",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 5000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 2,
|
||||||
|
"setId": 10005
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 55321,
|
||||||
|
"equipType": "EQUIP_NECKLACE",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 2000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10005
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 55322,
|
||||||
|
"equipType": "EQUIP_NECKLACE",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 2000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 2,
|
||||||
|
"setId": 10005
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 55331,
|
||||||
|
"equipType": "EQUIP_DRESS",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 3000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10005
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 55332,
|
||||||
|
"equipType": "EQUIP_DRESS",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 3000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 2,
|
||||||
|
"setId": 10005
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 55341,
|
||||||
|
"equipType": "EQUIP_BRACER",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 4000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10005
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 55342,
|
||||||
|
"equipType": "EQUIP_BRACER",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 4000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 2,
|
||||||
|
"setId": 10005
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 55351,
|
||||||
|
"equipType": "EQUIP_SHOES",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 1000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10005
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 55352,
|
||||||
|
"equipType": "EQUIP_SHOES",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 1000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 2,
|
||||||
|
"setId": 10005
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 57311,
|
||||||
|
"equipType": "EQUIP_RING",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 5000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10007
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 57312,
|
||||||
|
"equipType": "EQUIP_RING",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 5000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 2,
|
||||||
|
"setId": 10007
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 57321,
|
||||||
|
"equipType": "EQUIP_NECKLACE",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 2000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10007
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 57322,
|
||||||
|
"equipType": "EQUIP_NECKLACE",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 2000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 2,
|
||||||
|
"setId": 10007
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 57331,
|
||||||
|
"equipType": "EQUIP_DRESS",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 3000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10007
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 57332,
|
||||||
|
"equipType": "EQUIP_DRESS",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 3000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 2,
|
||||||
|
"setId": 10007
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 57341,
|
||||||
|
"equipType": "EQUIP_BRACER",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 4000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10007
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 57342,
|
||||||
|
"equipType": "EQUIP_BRACER",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 4000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 2,
|
||||||
|
"setId": 10007
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 57351,
|
||||||
|
"equipType": "EQUIP_SHOES",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 1000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10007
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 57352,
|
||||||
|
"equipType": "EQUIP_SHOES",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 1000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 2,
|
||||||
|
"setId": 10007
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 59311,
|
||||||
|
"equipType": "EQUIP_RING",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 5000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10009
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 59312,
|
||||||
|
"equipType": "EQUIP_RING",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 5000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 2,
|
||||||
|
"setId": 10009
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 59321,
|
||||||
|
"equipType": "EQUIP_NECKLACE",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 2000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10009
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 59322,
|
||||||
|
"equipType": "EQUIP_NECKLACE",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 2000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 2,
|
||||||
|
"setId": 10009
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 59331,
|
||||||
|
"equipType": "EQUIP_DRESS",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 3000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10009
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 59332,
|
||||||
|
"equipType": "EQUIP_DRESS",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 3000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 2,
|
||||||
|
"setId": 10009
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 59341,
|
||||||
|
"equipType": "EQUIP_BRACER",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 4000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10009
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 59342,
|
||||||
|
"equipType": "EQUIP_BRACER",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 4000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 2,
|
||||||
|
"setId": 10009
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 59351,
|
||||||
|
"equipType": "EQUIP_SHOES",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 1000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10009
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 59352,
|
||||||
|
"equipType": "EQUIP_SHOES",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 1000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 2,
|
||||||
|
"setId": 10009
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63110,
|
||||||
|
"equipType": "EQUIP_RING",
|
||||||
|
"rankLevel": 1,
|
||||||
|
"mainPropDepotId": 5000,
|
||||||
|
"appendPropDepotId": 101,
|
||||||
|
"appendPropNum": 0,
|
||||||
|
"setId": 10013
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63120,
|
||||||
|
"equipType": "EQUIP_NECKLACE",
|
||||||
|
"rankLevel": 1,
|
||||||
|
"mainPropDepotId": 2000,
|
||||||
|
"appendPropDepotId": 101,
|
||||||
|
"appendPropNum": 0,
|
||||||
|
"setId": 10013
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63130,
|
||||||
|
"equipType": "EQUIP_DRESS",
|
||||||
|
"rankLevel": 1,
|
||||||
|
"mainPropDepotId": 3000,
|
||||||
|
"appendPropDepotId": 101,
|
||||||
|
"appendPropNum": 0,
|
||||||
|
"setId": 10013
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63140,
|
||||||
|
"equipType": "EQUIP_BRACER",
|
||||||
|
"rankLevel": 1,
|
||||||
|
"mainPropDepotId": 4000,
|
||||||
|
"appendPropDepotId": 101,
|
||||||
|
"appendPropNum": 0,
|
||||||
|
"setId": 10013
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63150,
|
||||||
|
"equipType": "EQUIP_SHOES",
|
||||||
|
"rankLevel": 1,
|
||||||
|
"mainPropDepotId": 1000,
|
||||||
|
"appendPropDepotId": 101,
|
||||||
|
"appendPropNum": 0,
|
||||||
|
"setId": 10013
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63210,
|
||||||
|
"equipType": "EQUIP_RING",
|
||||||
|
"rankLevel": 2,
|
||||||
|
"mainPropDepotId": 5000,
|
||||||
|
"appendPropDepotId": 201,
|
||||||
|
"appendPropNum": 0,
|
||||||
|
"setId": 10013
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63211,
|
||||||
|
"equipType": "EQUIP_RING",
|
||||||
|
"rankLevel": 2,
|
||||||
|
"mainPropDepotId": 5000,
|
||||||
|
"appendPropDepotId": 201,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10013
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63220,
|
||||||
|
"equipType": "EQUIP_NECKLACE",
|
||||||
|
"rankLevel": 2,
|
||||||
|
"mainPropDepotId": 2000,
|
||||||
|
"appendPropDepotId": 201,
|
||||||
|
"appendPropNum": 0,
|
||||||
|
"setId": 10013
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63221,
|
||||||
|
"equipType": "EQUIP_NECKLACE",
|
||||||
|
"rankLevel": 2,
|
||||||
|
"mainPropDepotId": 2000,
|
||||||
|
"appendPropDepotId": 201,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10013
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63230,
|
||||||
|
"equipType": "EQUIP_DRESS",
|
||||||
|
"rankLevel": 2,
|
||||||
|
"mainPropDepotId": 3000,
|
||||||
|
"appendPropDepotId": 201,
|
||||||
|
"appendPropNum": 0,
|
||||||
|
"setId": 10013
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63231,
|
||||||
|
"equipType": "EQUIP_DRESS",
|
||||||
|
"rankLevel": 2,
|
||||||
|
"mainPropDepotId": 3000,
|
||||||
|
"appendPropDepotId": 201,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10013
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63240,
|
||||||
|
"equipType": "EQUIP_BRACER",
|
||||||
|
"rankLevel": 2,
|
||||||
|
"mainPropDepotId": 4000,
|
||||||
|
"appendPropDepotId": 201,
|
||||||
|
"appendPropNum": 0,
|
||||||
|
"setId": 10013
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63241,
|
||||||
|
"equipType": "EQUIP_BRACER",
|
||||||
|
"rankLevel": 2,
|
||||||
|
"mainPropDepotId": 4000,
|
||||||
|
"appendPropDepotId": 201,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10013
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63250,
|
||||||
|
"equipType": "EQUIP_SHOES",
|
||||||
|
"rankLevel": 2,
|
||||||
|
"mainPropDepotId": 1000,
|
||||||
|
"appendPropDepotId": 201,
|
||||||
|
"appendPropNum": 0,
|
||||||
|
"setId": 10013
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63251,
|
||||||
|
"equipType": "EQUIP_SHOES",
|
||||||
|
"rankLevel": 2,
|
||||||
|
"mainPropDepotId": 1000,
|
||||||
|
"appendPropDepotId": 201,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10013
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63311,
|
||||||
|
"equipType": "EQUIP_RING",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 5000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10013
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63312,
|
||||||
|
"equipType": "EQUIP_RING",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 5000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 2,
|
||||||
|
"setId": 10013
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63321,
|
||||||
|
"equipType": "EQUIP_NECKLACE",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 2000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10013
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63322,
|
||||||
|
"equipType": "EQUIP_NECKLACE",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 2000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 2,
|
||||||
|
"setId": 10013
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63331,
|
||||||
|
"equipType": "EQUIP_DRESS",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 3000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10013
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63332,
|
||||||
|
"equipType": "EQUIP_DRESS",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 3000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 2,
|
||||||
|
"setId": 10013
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63341,
|
||||||
|
"equipType": "EQUIP_BRACER",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 4000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10013
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63342,
|
||||||
|
"equipType": "EQUIP_BRACER",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 4000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 2,
|
||||||
|
"setId": 10013
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63351,
|
||||||
|
"equipType": "EQUIP_SHOES",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 1000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 1,
|
||||||
|
"setId": 10013
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63352,
|
||||||
|
"equipType": "EQUIP_SHOES",
|
||||||
|
"rankLevel": 3,
|
||||||
|
"mainPropDepotId": 1000,
|
||||||
|
"appendPropDepotId": 301,
|
||||||
|
"appendPropNum": 2,
|
||||||
|
"setId": 10013
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
1
Yuanshen.Gameserver/assets/scene/scene3_gadgets.json
Normal file
1
Yuanshen.Gameserver/assets/scene/scene3_gadgets.json
Normal file
File diff suppressed because one or more lines are too long
9
Yuanshen.Proto/GadgetStateNotify.proto
Normal file
9
Yuanshen.Proto/GadgetStateNotify.proto
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
option csharp_namespace = "Yuanshen.Protocol";
|
||||||
|
|
||||||
|
message GadgetStateNotify {
|
||||||
|
uint32 gadgetEntityId = 1;
|
||||||
|
uint32 gadgetState = 2;
|
||||||
|
bool isEnableInteract = 3;
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue