From a337f60f3dcab11f08b95381c8eae0cb75cca1ac Mon Sep 17 00:00:00 2001 From: Ryan Yappert Date: Fri, 30 Aug 2024 00:42:50 -0700 Subject: [PATCH 1/2] Implement traning (sic) room. --- Arrowgene.Ddon.GameServer/DdonGameServer.cs | 2 + .../Handler/InstanceEnemyKillHandler.cs | 13 ++ .../InstanceTraningRoomGetEnemyListHandler.cs | 58 ++++++++ .../InstanceTraningRoomSetEnemyHandler.cs | 126 ++++++++++++++++++ .../Entity/EntitySerializer.cs | 8 +- .../C2SInstanceTraningRoomGetEnemyListReq.cs | 23 ++++ .../C2SInstanceTraningRoomSetEnemyReq.cs | 40 ++++++ .../C2STrainingRoomSetEnemyReq.cs | 37 ----- .../C2STraningRoomGetEnemyListReq.cs | 23 ---- .../PacketStructure/S2CInstanceEnemyDieNtc.cs | 3 +- ... S2CInstanceTraningRoomGetEnemyListRes.cs} | 12 +- ...s => S2CInstanceTraningRoomSetEnemyRes.cs} | 10 +- .../Structure/CDataTraningRoomEnemyHeader.cs | 8 +- .../Files/Assets/EnemySpawn.json | 28 ---- Arrowgene.Ddon.Shared/Network/PacketId.cs | 6 +- 15 files changed, 285 insertions(+), 112 deletions(-) create mode 100644 Arrowgene.Ddon.GameServer/Handler/InstanceTraningRoomGetEnemyListHandler.cs create mode 100644 Arrowgene.Ddon.GameServer/Handler/InstanceTraningRoomSetEnemyHandler.cs create mode 100644 Arrowgene.Ddon.Shared/Entity/PacketStructure/C2SInstanceTraningRoomGetEnemyListReq.cs create mode 100644 Arrowgene.Ddon.Shared/Entity/PacketStructure/C2SInstanceTraningRoomSetEnemyReq.cs delete mode 100644 Arrowgene.Ddon.Shared/Entity/PacketStructure/C2STrainingRoomSetEnemyReq.cs delete mode 100644 Arrowgene.Ddon.Shared/Entity/PacketStructure/C2STraningRoomGetEnemyListReq.cs rename Arrowgene.Ddon.Shared/Entity/PacketStructure/{S2CTraningRoomGetEnemyListRes.cs => S2CInstanceTraningRoomGetEnemyListRes.cs} (66%) rename Arrowgene.Ddon.Shared/Entity/PacketStructure/{S2CTraningRoomSetEnemyRes.cs => S2CInstanceTraningRoomSetEnemyRes.cs} (50%) diff --git a/Arrowgene.Ddon.GameServer/DdonGameServer.cs b/Arrowgene.Ddon.GameServer/DdonGameServer.cs index 6e0150e04..445425800 100644 --- a/Arrowgene.Ddon.GameServer/DdonGameServer.cs +++ b/Arrowgene.Ddon.GameServer/DdonGameServer.cs @@ -358,6 +358,8 @@ private void LoadPacketHandler() AddHandler(new InstanceCharacterStartBadStatusHandler(this)); AddHandler(new InstancePlTouchOmHandler(this)); AddHandler(new InstanceGetOmInstantKeyValueAllHandler(this)); + AddHandler(new InstanceTraningRoomGetEnemyListHandler(this)); + AddHandler(new InstanceTraningRoomSetEnemyHandler(this)); AddHandler(new ItemConsumeStorageItemHandler(this)); AddHandler(new ItemGetStorageItemListHandler(this)); diff --git a/Arrowgene.Ddon.GameServer/Handler/InstanceEnemyKillHandler.cs b/Arrowgene.Ddon.GameServer/Handler/InstanceEnemyKillHandler.cs index 7ac4fca55..5e3f19636 100644 --- a/Arrowgene.Ddon.GameServer/Handler/InstanceEnemyKillHandler.cs +++ b/Arrowgene.Ddon.GameServer/Handler/InstanceEnemyKillHandler.cs @@ -21,6 +21,11 @@ public class InstanceEnemyKillHandler : StructurePacketHandler _ignoreKillsInStageIds = new HashSet() + { + 349, //White Dragon Temple, Training Room + }; + public InstanceEnemyKillHandler(DdonGameServer server) : base(server) { _gameServer = server; @@ -32,6 +37,14 @@ public override void Handle(GameClient client, StructurePacket + { + private static readonly ServerLogger Logger = LogProvider.Logger(typeof(QuestGetQuestCompletedListHandler)); + + public static readonly CDataStageLayoutId TrainingRoomLayout = new CDataStageLayoutId(349, 0, 1); + + public InstanceTraningRoomGetEnemyListHandler(DdonGameServer server) : base(server) + { + } + + public override S2CInstanceTraningRoomGetEnemyListRes Handle(GameClient client, C2SInstanceTraningRoomGetEnemyListReq request) + { + // TODO: Figure out a better way to do this. + // If the reset notice is too soon before the repop notice (in InstanceTraningRoomSetEnemyHandler), + // the repop sometimes fails to happen. + client.Party.SendToAll(new S2CInstanceEnemyGroupResetNtc() + { + LayoutId = TrainingRoomLayout + }); + + return new S2CInstanceTraningRoomGetEnemyListRes() + { + MaxLv = 100, + InfoList = new List() + { + new CDataTraningRoomEnemyHeader() + { + OptionId = 1, + Name = "Orc Soldiers" + }, + new CDataTraningRoomEnemyHeader() + { + OptionId = 2, + Name = "Cyclops" + }, + new CDataTraningRoomEnemyHeader() + { + OptionId = 3, + Name = "Ogre" + }, + new CDataTraningRoomEnemyHeader() + { + OptionId = 4, + Name = "Training Dummy Zuhl" + }, + } + }; + } + } +} diff --git a/Arrowgene.Ddon.GameServer/Handler/InstanceTraningRoomSetEnemyHandler.cs b/Arrowgene.Ddon.GameServer/Handler/InstanceTraningRoomSetEnemyHandler.cs new file mode 100644 index 000000000..0af5a30f2 --- /dev/null +++ b/Arrowgene.Ddon.GameServer/Handler/InstanceTraningRoomSetEnemyHandler.cs @@ -0,0 +1,126 @@ +using Arrowgene.Ddon.Shared.Entity.PacketStructure; +using Arrowgene.Ddon.Shared.Entity.Structure; + +namespace Arrowgene.Ddon.GameServer.Handler +{ + public class InstanceTraningRoomSetEnemyHandler : GameRequestPacketHandler + { + public InstanceTraningRoomSetEnemyHandler(DdonGameServer server) : base(server) + { + } + + public override S2CInstanceTraningRoomSetEnemyRes Handle(GameClient client, C2SInstanceTraningRoomSetEnemyReq request) + { + + // TODO: Enemies that share the same positionIndex sometimes spawn with the wrong HP. + // To avoid this in the meantime, each enemy must have its own unique positionIndex. + // But the training room layout only has 6 (0-5) indices, so you can only have six different spawns. + + var layoutId = InstanceTraningRoomGetEnemyListHandler.TrainingRoomLayout; + + switch (request.OptionId) + { + case 1: // Two orc soldiers + client.Party.SendToAll(new S2CInstanceEnemyRepopNtc() + { + LayoutId = layoutId, + EnemyData = new CDataLayoutEnemyData() + { + PositionIndex = 0, + EnemyInfo = new CDataStageLayoutEnemyPresetEnemyInfoClient() + { + EnemyId = 0x15800, + NamedEnemyParamsId = 47, // Training + Lv = (ushort)request.Lv, + RepopCount = 10, + Scale = 100, + IsBossGauge = true, + } + }, + WaitSecond = 1, + }); + client.Party.SendToAll(new S2CInstanceEnemyRepopNtc() + { + LayoutId = layoutId, + EnemyData = new CDataLayoutEnemyData() + { + PositionIndex = 1, + EnemyInfo = new CDataStageLayoutEnemyPresetEnemyInfoClient() + { + EnemyId = 0x15800, + NamedEnemyParamsId = 47, // Training + Lv = (ushort)request.Lv, + RepopCount = 10, + Scale = 100, + IsBossGauge = true, + } + }, + WaitSecond = 1, + }); + break; + case 2: // Cyclops + client.Party.SendToAll(new S2CInstanceEnemyRepopNtc() + { + LayoutId = layoutId, + EnemyData = new CDataLayoutEnemyData() + { + PositionIndex = 2, + EnemyInfo = new CDataStageLayoutEnemyPresetEnemyInfoClient() + { + EnemyId = 0x15000, + NamedEnemyParamsId = 47, // Training + Lv = (ushort)request.Lv, + RepopCount = 10, + Scale = 100, + IsBossGauge = true, + } + }, + WaitSecond = 1, + }); + break; + case 3: //Ogre + client.Party.SendToAll(new S2CInstanceEnemyRepopNtc() + { + LayoutId = layoutId, + EnemyData = new CDataLayoutEnemyData() + { + PositionIndex = 3, + EnemyInfo = new CDataStageLayoutEnemyPresetEnemyInfoClient() + { + EnemyId = 0x15500, + NamedEnemyParamsId = 47, // Training + Lv = (ushort)request.Lv, + RepopCount = 10, + Scale = 100, + IsBossGauge = true, + } + }, + WaitSecond = 1, + }); + break; + case 4: //Passive Zuhl + client.Party.SendToAll(new S2CInstanceEnemyRepopNtc() + { + LayoutId = layoutId, + EnemyData = new CDataLayoutEnemyData() + { + PositionIndex = 4, + EnemyInfo = new CDataStageLayoutEnemyPresetEnemyInfoClient() + { + EnemyId = 0x100101, + NamedEnemyParamsId = 722, // Practice , has extra HP. + Lv = (ushort)request.Lv, + RepopCount = 10, + Scale = 75, + IsBossGauge = true, + } + }, + WaitSecond = 1, + }); + break; + } + + return new S2CInstanceTraningRoomSetEnemyRes(); + } + } +} diff --git a/Arrowgene.Ddon.Shared/Entity/EntitySerializer.cs b/Arrowgene.Ddon.Shared/Entity/EntitySerializer.cs index a49fdbe59..4a728fe04 100644 --- a/Arrowgene.Ddon.Shared/Entity/EntitySerializer.cs +++ b/Arrowgene.Ddon.Shared/Entity/EntitySerializer.cs @@ -649,8 +649,8 @@ static EntitySerializer() Create(new C2SSetCommunicationShortcutReq.Serializer()); Create(new C2SStageAreaChangeReq.Serializer()); Create(new C2SStageGetStageListReq.Serializer()); - Create(new C2STraningRoomGetEnemyListReq.Serializer()); - Create(new C2STrainingRoomSetEnemyReq.Serializer()); + Create(new C2SInstanceTraningRoomGetEnemyListReq.Serializer()); + Create(new C2SInstanceTraningRoomSetEnemyReq.Serializer()); Create(new C2SWarpAreaWarpReq.Serializer()); Create(new C2SWarpGetFavoriteWarpPointListReq.Serializer()); Create(new C2SWarpGetReleaseWarpPointListReq.Serializer()); @@ -1113,8 +1113,8 @@ static EntitySerializer() Create(new S2CShopGetShopGoodsListRes.Serializer()); Create(new S2CStageAreaChangeRes.Serializer()); Create(new S2CStageGetStageListRes.Serializer()); - Create(new S2CTraningRoomGetEnemyListRes.Serializer()); - Create(new S2CTraningRoomSetEnemyRes.Serializer()); + Create(new S2CInstanceTraningRoomGetEnemyListRes.Serializer()); + Create(new S2CInstanceTraningRoomSetEnemyRes.Serializer()); Create(new S2CUserListJoinNtc.Serializer()); Create(new S2CUserListLeaveNtc.Serializer()); Create(new S2CWarpAreaWarpRes.Serializer()); diff --git a/Arrowgene.Ddon.Shared/Entity/PacketStructure/C2SInstanceTraningRoomGetEnemyListReq.cs b/Arrowgene.Ddon.Shared/Entity/PacketStructure/C2SInstanceTraningRoomGetEnemyListReq.cs new file mode 100644 index 000000000..8b0bd20cc --- /dev/null +++ b/Arrowgene.Ddon.Shared/Entity/PacketStructure/C2SInstanceTraningRoomGetEnemyListReq.cs @@ -0,0 +1,23 @@ +using Arrowgene.Buffers; +using Arrowgene.Ddon.Shared.Network; + +namespace Arrowgene.Ddon.Shared.Entity.PacketStructure +{ + public class C2SInstanceTraningRoomGetEnemyListReq : IPacketStructure + { + public PacketId Id => PacketId.C2S_INSTANCE_TRANING_ROOM_GET_ENEMY_LIST_REQ; + public class Serializer : PacketEntitySerializer + { + + public override void Write(IBuffer buffer, C2SInstanceTraningRoomGetEnemyListReq obj) + { + } + + public override C2SInstanceTraningRoomGetEnemyListReq Read(IBuffer buffer) + { + return new C2SInstanceTraningRoomGetEnemyListReq(); + } + } + } + +} diff --git a/Arrowgene.Ddon.Shared/Entity/PacketStructure/C2SInstanceTraningRoomSetEnemyReq.cs b/Arrowgene.Ddon.Shared/Entity/PacketStructure/C2SInstanceTraningRoomSetEnemyReq.cs new file mode 100644 index 000000000..ae282b633 --- /dev/null +++ b/Arrowgene.Ddon.Shared/Entity/PacketStructure/C2SInstanceTraningRoomSetEnemyReq.cs @@ -0,0 +1,40 @@ +using Arrowgene.Buffers; +using Arrowgene.Ddon.Shared.Network; + +namespace Arrowgene.Ddon.Shared.Entity.PacketStructure +{ + public class C2SInstanceTraningRoomSetEnemyReq : IPacketStructure + { + public PacketId Id => PacketId.C2S_INSTANCE_TRANING_ROOM_SET_ENEMY_REQ; + + /// + /// Value returned from the TraningRoomGetEnemyList dialog. + /// + public uint OptionId { get; set; } + public uint Lv { get; set; } + + public C2SInstanceTraningRoomSetEnemyReq() + { + OptionId = 0; + Lv = 0; + } + + public class Serializer : PacketEntitySerializer + { + + public override void Write(IBuffer buffer, C2SInstanceTraningRoomSetEnemyReq obj) + { + WriteUInt32(buffer, obj.OptionId); + WriteUInt32(buffer, obj.Lv); + } + + public override C2SInstanceTraningRoomSetEnemyReq Read(IBuffer buffer) + { + C2SInstanceTraningRoomSetEnemyReq obj = new C2SInstanceTraningRoomSetEnemyReq(); + obj.OptionId = ReadUInt32(buffer); + obj.Lv = ReadUInt32(buffer); + return obj; + } + } + } +} diff --git a/Arrowgene.Ddon.Shared/Entity/PacketStructure/C2STrainingRoomSetEnemyReq.cs b/Arrowgene.Ddon.Shared/Entity/PacketStructure/C2STrainingRoomSetEnemyReq.cs deleted file mode 100644 index 976249f7f..000000000 --- a/Arrowgene.Ddon.Shared/Entity/PacketStructure/C2STrainingRoomSetEnemyReq.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Arrowgene.Buffers; -using Arrowgene.Ddon.Shared.Network; - -namespace Arrowgene.Ddon.Shared.Entity.PacketStructure -{ - public class C2STrainingRoomSetEnemyReq : IPacketStructure - { - public PacketId Id => PacketId.C2S_INSTANCE_TRANING_ROOM_SET_ENEMY_REQ; - - public uint ID { get; set; } // TODO is this enemyId ? - public uint Lv { get; set; } - - public C2STrainingRoomSetEnemyReq() - { - ID = 0; - Lv = 0; - } - - public class Serializer : PacketEntitySerializer - { - - public override void Write(IBuffer buffer, C2STrainingRoomSetEnemyReq obj) - { - WriteUInt32(buffer, obj.ID); - WriteUInt32(buffer, obj.Lv); - } - - public override C2STrainingRoomSetEnemyReq Read(IBuffer buffer) - { - C2STrainingRoomSetEnemyReq obj = new C2STrainingRoomSetEnemyReq(); - obj.ID = ReadUInt32(buffer); - obj.Lv = ReadUInt32(buffer); - return obj; - } - } - } -} diff --git a/Arrowgene.Ddon.Shared/Entity/PacketStructure/C2STraningRoomGetEnemyListReq.cs b/Arrowgene.Ddon.Shared/Entity/PacketStructure/C2STraningRoomGetEnemyListReq.cs deleted file mode 100644 index b0eda8371..000000000 --- a/Arrowgene.Ddon.Shared/Entity/PacketStructure/C2STraningRoomGetEnemyListReq.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Arrowgene.Buffers; -using Arrowgene.Ddon.Shared.Network; - -namespace Arrowgene.Ddon.Shared.Entity.PacketStructure -{ - public class C2STraningRoomGetEnemyListReq : IPacketStructure - { - public PacketId Id => PacketId.C2S_INSTANCE_TRANING_ROOM_GET_ENEMY_LIST_REQ; - public class Serializer : PacketEntitySerializer - { - - public override void Write(IBuffer buffer, C2STraningRoomGetEnemyListReq obj) - { - } - - public override C2STraningRoomGetEnemyListReq Read(IBuffer buffer) - { - return new C2STraningRoomGetEnemyListReq(); - } - } - } - -} diff --git a/Arrowgene.Ddon.Shared/Entity/PacketStructure/S2CInstanceEnemyDieNtc.cs b/Arrowgene.Ddon.Shared/Entity/PacketStructure/S2CInstanceEnemyDieNtc.cs index c86276f61..5a94d8c27 100644 --- a/Arrowgene.Ddon.Shared/Entity/PacketStructure/S2CInstanceEnemyDieNtc.cs +++ b/Arrowgene.Ddon.Shared/Entity/PacketStructure/S2CInstanceEnemyDieNtc.cs @@ -1,7 +1,6 @@ using Arrowgene.Buffers; using Arrowgene.Ddon.Shared.Entity.Structure; using Arrowgene.Ddon.Shared.Network; -using System; namespace Arrowgene.Ddon.Shared.Entity.PacketStructure { @@ -10,7 +9,7 @@ public class S2CInstanceEnemyDieNtc : IPacketStructure public PacketId Id => PacketId.S2C_INSTANCE_ENEMY_DIE_NTC; public CDataStageLayoutId LayoutId { get; set; } - public UInt32 SetId { get; set; } + public uint SetId { get; set; } public class Serializer : PacketEntitySerializer { diff --git a/Arrowgene.Ddon.Shared/Entity/PacketStructure/S2CTraningRoomGetEnemyListRes.cs b/Arrowgene.Ddon.Shared/Entity/PacketStructure/S2CInstanceTraningRoomGetEnemyListRes.cs similarity index 66% rename from Arrowgene.Ddon.Shared/Entity/PacketStructure/S2CTraningRoomGetEnemyListRes.cs rename to Arrowgene.Ddon.Shared/Entity/PacketStructure/S2CInstanceTraningRoomGetEnemyListRes.cs index 19d6787c8..302771d38 100644 --- a/Arrowgene.Ddon.Shared/Entity/PacketStructure/S2CTraningRoomGetEnemyListRes.cs +++ b/Arrowgene.Ddon.Shared/Entity/PacketStructure/S2CInstanceTraningRoomGetEnemyListRes.cs @@ -5,9 +5,9 @@ namespace Arrowgene.Ddon.Shared.Entity.PacketStructure { - public class S2CTraningRoomGetEnemyListRes : ServerResponse + public class S2CInstanceTraningRoomGetEnemyListRes : ServerResponse { - public S2CTraningRoomGetEnemyListRes() + public S2CInstanceTraningRoomGetEnemyListRes() { InfoList = new List(); MaxLv = 100; @@ -18,19 +18,19 @@ public S2CTraningRoomGetEnemyListRes() public List InfoList { get; set; } public uint MaxLv { get; set; } - public class Serializer : PacketEntitySerializer + public class Serializer : PacketEntitySerializer { - public override void Write(IBuffer buffer, S2CTraningRoomGetEnemyListRes obj) + public override void Write(IBuffer buffer, S2CInstanceTraningRoomGetEnemyListRes obj) { WriteServerResponse(buffer, obj); WriteEntityList(buffer, obj.InfoList); WriteUInt32(buffer, obj.MaxLv); } - public override S2CTraningRoomGetEnemyListRes Read(IBuffer buffer) + public override S2CInstanceTraningRoomGetEnemyListRes Read(IBuffer buffer) { - S2CTraningRoomGetEnemyListRes obj = new S2CTraningRoomGetEnemyListRes(); + S2CInstanceTraningRoomGetEnemyListRes obj = new S2CInstanceTraningRoomGetEnemyListRes(); ReadServerResponse(buffer, obj); obj.InfoList = ReadEntityList(buffer); obj.MaxLv = ReadUInt32(buffer); diff --git a/Arrowgene.Ddon.Shared/Entity/PacketStructure/S2CTraningRoomSetEnemyRes.cs b/Arrowgene.Ddon.Shared/Entity/PacketStructure/S2CInstanceTraningRoomSetEnemyRes.cs similarity index 50% rename from Arrowgene.Ddon.Shared/Entity/PacketStructure/S2CTraningRoomSetEnemyRes.cs rename to Arrowgene.Ddon.Shared/Entity/PacketStructure/S2CInstanceTraningRoomSetEnemyRes.cs index da5a1e553..fc6facb22 100644 --- a/Arrowgene.Ddon.Shared/Entity/PacketStructure/S2CTraningRoomSetEnemyRes.cs +++ b/Arrowgene.Ddon.Shared/Entity/PacketStructure/S2CInstanceTraningRoomSetEnemyRes.cs @@ -3,21 +3,21 @@ namespace Arrowgene.Ddon.Shared.Entity.PacketStructure { - public class S2CTraningRoomSetEnemyRes : ServerResponse + public class S2CInstanceTraningRoomSetEnemyRes : ServerResponse { public override PacketId Id => PacketId.S2C_INSTANCE_TRANING_ROOM_SET_ENEMY_RES; - public class Serializer : PacketEntitySerializer + public class Serializer : PacketEntitySerializer { - public override void Write(IBuffer buffer, S2CTraningRoomSetEnemyRes obj) + public override void Write(IBuffer buffer, S2CInstanceTraningRoomSetEnemyRes obj) { WriteServerResponse(buffer, obj); } - public override S2CTraningRoomSetEnemyRes Read(IBuffer buffer) + public override S2CInstanceTraningRoomSetEnemyRes Read(IBuffer buffer) { - S2CTraningRoomSetEnemyRes obj = new S2CTraningRoomSetEnemyRes(); + S2CInstanceTraningRoomSetEnemyRes obj = new S2CInstanceTraningRoomSetEnemyRes(); ReadServerResponse(buffer, obj); return obj; } diff --git a/Arrowgene.Ddon.Shared/Entity/Structure/CDataTraningRoomEnemyHeader.cs b/Arrowgene.Ddon.Shared/Entity/Structure/CDataTraningRoomEnemyHeader.cs index afe868395..71767ecb2 100644 --- a/Arrowgene.Ddon.Shared/Entity/Structure/CDataTraningRoomEnemyHeader.cs +++ b/Arrowgene.Ddon.Shared/Entity/Structure/CDataTraningRoomEnemyHeader.cs @@ -7,25 +7,25 @@ public class CDataTraningRoomEnemyHeader { public CDataTraningRoomEnemyHeader() { - Id = 0; + OptionId = 0; Name = string.Empty; } - public uint Id { get; set; } + public uint OptionId { get; set; } public string Name { get; set; } public class Serializer : EntitySerializer { public override void Write(IBuffer buffer, CDataTraningRoomEnemyHeader obj) { - WriteUInt32(buffer, obj.Id); + WriteUInt32(buffer, obj.OptionId); WriteMtString(buffer, obj.Name); } public override CDataTraningRoomEnemyHeader Read(IBuffer buffer) { CDataTraningRoomEnemyHeader obj = new CDataTraningRoomEnemyHeader(); - obj.Id = ReadUInt32(buffer); + obj.OptionId = ReadUInt32(buffer); obj.Name = ReadMtString(buffer); return obj; } diff --git a/Arrowgene.Ddon.Shared/Files/Assets/EnemySpawn.json b/Arrowgene.Ddon.Shared/Files/Assets/EnemySpawn.json index 60038c974..95565f0bf 100644 --- a/Arrowgene.Ddon.Shared/Files/Assets/EnemySpawn.json +++ b/Arrowgene.Ddon.Shared/Files/Assets/EnemySpawn.json @@ -228378,34 +228378,6 @@ 184, "00:00,23:59" ], - [ - 349, - 0, - 1, - 0, - "0x015500", - 2298, - 0, - 100, - 80, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - true, - false, - false, - false, - 0, - 0, - 840000, - -1, - "00:00,23:59" - ], [ 420, 0, diff --git a/Arrowgene.Ddon.Shared/Network/PacketId.cs b/Arrowgene.Ddon.Shared/Network/PacketId.cs index 7a18f262f..019f24453 100644 --- a/Arrowgene.Ddon.Shared/Network/PacketId.cs +++ b/Arrowgene.Ddon.Shared/Network/PacketId.cs @@ -890,10 +890,10 @@ private static Dictionary InitializeLoginPacketIds() public static readonly PacketId S2C_INSTANCE_ENEMY_GROUP_RESET_NTC = new PacketId(13, 32, 16, "S2C_INSTANCE_ENEMY_GROUP_RESET_NTC", ServerType.Game, PacketSource.Server, "S2C_INSTANCE_13_32_16_NTC"); public static readonly PacketId S2C_INSTANCE_ENEMY_SUB_GROUP_APPEAR_NTC = new PacketId(13, 33, 16, "S2C_INSTANCE_ENEMY_SUB_GROUP_APPEAR_NTC", ServerType.Game, PacketSource.Server, "S2C_INSTANCE_13_33_16_NTC"); public static readonly PacketId S2C_INSTANCE_GATHERING_ENEMY_APPEAR_NTC = new PacketId(13, 34, 16, "S2C_INSTANCE_GATHERING_ENEMY_APPEAR_NTC", ServerType.Game, PacketSource.Server, "S2C_INSTANCE_13_34_16_NTC"); - public static readonly PacketId S2C_INSTANCE_13_35_16_NTC = new PacketId(13, 35, 16, "S2C_INSTANCE_13_35_16_NTC", ServerType.Game, PacketSource.Server); + public static readonly PacketId S2C_INSTANCE_13_35_16_NTC = new PacketId(13, 35, 16, "S2C_INSTANCE_13_35_16_NTC", ServerType.Game, PacketSource.Server); // DUNGEON CLEAR large text popup. public static readonly PacketId S2C_INSTANCE_13_36_16_NTC = new PacketId(13, 36, 16, "S2C_INSTANCE_13_36_16_NTC", ServerType.Game, PacketSource.Server); - public static readonly PacketId S2C_INSTANCE_13_37_16_NTC = new PacketId(13, 37, 16, "S2C_INSTANCE_13_37_16_NTC", ServerType.Game, PacketSource.Server); - public static readonly PacketId S2C_INSTANCE_13_38_16_NTC = new PacketId(13, 38, 16, "S2C_INSTANCE_13_38_16_NTC", ServerType.Game, PacketSource.Server); + public static readonly PacketId S2C_INSTANCE_13_37_16_NTC = new PacketId(13, 37, 16, "S2C_INSTANCE_13_37_16_NTC", ServerType.Game, PacketSource.Server); // Ghidra says this does nothing. + public static readonly PacketId S2C_INSTANCE_13_38_16_NTC = new PacketId(13, 38, 16, "S2C_INSTANCE_13_38_16_NTC", ServerType.Game, PacketSource.Server); // Ghidra says this does nothing. public static readonly PacketId S2C_INSTANCE_POP_DROP_ITEM_NTC = new PacketId(13, 39, 16, "S2C_INSTANCE_POP_DROP_ITEM_NTC", ServerType.Game, PacketSource.Server, "S2C_INSTANCE_13_39_16_NTC"); public static readonly PacketId S2C_INSTANCE_ENEMY_REPOP_NTC = new PacketId(13, 40, 16, "S2C_INSTANCE_ENEMY_REPOP_NTC", ServerType.Game, PacketSource.Server, "S2C_INSTANCE_13_40_16_NTC"); public static readonly PacketId S2C_INSTANCE_ENCOUNTER_PAWN_NTC = new PacketId(13, 41, 16, "S2C_INSTANCE_ENCOUNTER_PAWN_NTC", ServerType.Game, PacketSource.Server, "S2C_INSTANCE_13_41_16_NTC"); From 1644f59e2a4510f70734df64cf71eeaa069a43f7 Mon Sep 17 00:00:00 2001 From: Ryan Yappert Date: Sun, 1 Sep 2024 22:15:26 -0700 Subject: [PATCH 2/2] Review comments; use a Task.Delay to properly space out the training reset. --- .../InstanceTraningRoomGetEnemyListHandler.cs | 12 +- .../InstanceTraningRoomSetEnemyHandler.cs | 202 ++++++++++-------- 2 files changed, 109 insertions(+), 105 deletions(-) diff --git a/Arrowgene.Ddon.GameServer/Handler/InstanceTraningRoomGetEnemyListHandler.cs b/Arrowgene.Ddon.GameServer/Handler/InstanceTraningRoomGetEnemyListHandler.cs index 0a92e5e95..f47ed85df 100644 --- a/Arrowgene.Ddon.GameServer/Handler/InstanceTraningRoomGetEnemyListHandler.cs +++ b/Arrowgene.Ddon.GameServer/Handler/InstanceTraningRoomGetEnemyListHandler.cs @@ -10,22 +10,14 @@ public class InstanceTraningRoomGetEnemyListHandler : GameRequestPacketHandler(typeof(QuestGetQuestCompletedListHandler)); - public static readonly CDataStageLayoutId TrainingRoomLayout = new CDataStageLayoutId(349, 0, 1); public InstanceTraningRoomGetEnemyListHandler(DdonGameServer server) : base(server) { } public override S2CInstanceTraningRoomGetEnemyListRes Handle(GameClient client, C2SInstanceTraningRoomGetEnemyListReq request) - { - // TODO: Figure out a better way to do this. - // If the reset notice is too soon before the repop notice (in InstanceTraningRoomSetEnemyHandler), - // the repop sometimes fails to happen. - client.Party.SendToAll(new S2CInstanceEnemyGroupResetNtc() - { - LayoutId = TrainingRoomLayout - }); - + { + // These OptionIds are intepreted in InstanceTraningRoomSetEnemyHandler. return new S2CInstanceTraningRoomGetEnemyListRes() { MaxLv = 100, diff --git a/Arrowgene.Ddon.GameServer/Handler/InstanceTraningRoomSetEnemyHandler.cs b/Arrowgene.Ddon.GameServer/Handler/InstanceTraningRoomSetEnemyHandler.cs index 0af5a30f2..d7c38a848 100644 --- a/Arrowgene.Ddon.GameServer/Handler/InstanceTraningRoomSetEnemyHandler.cs +++ b/Arrowgene.Ddon.GameServer/Handler/InstanceTraningRoomSetEnemyHandler.cs @@ -1,126 +1,138 @@ using Arrowgene.Ddon.Shared.Entity.PacketStructure; using Arrowgene.Ddon.Shared.Entity.Structure; +using Arrowgene.Ddon.Shared.Network; +using System.Threading.Tasks; namespace Arrowgene.Ddon.GameServer.Handler { - public class InstanceTraningRoomSetEnemyHandler : GameRequestPacketHandler + public class InstanceTraningRoomSetEnemyHandler : GameStructurePacketHandler { public InstanceTraningRoomSetEnemyHandler(DdonGameServer server) : base(server) { } - public override S2CInstanceTraningRoomSetEnemyRes Handle(GameClient client, C2SInstanceTraningRoomSetEnemyReq request) + private static readonly CDataStageLayoutId TrainingRoomLayout = new CDataStageLayoutId(349, 0, 1); + private static readonly int RepopDelay = 2000; // ms + + public override void Handle(GameClient client, StructurePacket packet) { // TODO: Enemies that share the same positionIndex sometimes spawn with the wrong HP. // To avoid this in the meantime, each enemy must have its own unique positionIndex. // But the training room layout only has 6 (0-5) indices, so you can only have six different spawns. - var layoutId = InstanceTraningRoomGetEnemyListHandler.TrainingRoomLayout; + client.Send(new S2CInstanceTraningRoomSetEnemyRes()); - switch (request.OptionId) + client.Party.SendToAll(new S2CInstanceEnemyGroupResetNtc() { - case 1: // Two orc soldiers - client.Party.SendToAll(new S2CInstanceEnemyRepopNtc() - { - LayoutId = layoutId, - EnemyData = new CDataLayoutEnemyData() + LayoutId = TrainingRoomLayout + }); + + ushort level = (ushort)packet.Structure.Lv; + + Task.Delay(RepopDelay).ContinueWith(_ => { + switch (packet.Structure.OptionId) + { + case 1: // Two orc soldiers + client.Party.SendToAll(new S2CInstanceEnemyRepopNtc() { - PositionIndex = 0, - EnemyInfo = new CDataStageLayoutEnemyPresetEnemyInfoClient() + LayoutId = TrainingRoomLayout, + EnemyData = new CDataLayoutEnemyData() { - EnemyId = 0x15800, - NamedEnemyParamsId = 47, // Training - Lv = (ushort)request.Lv, - RepopCount = 10, - Scale = 100, - IsBossGauge = true, - } - }, - WaitSecond = 1, - }); - client.Party.SendToAll(new S2CInstanceEnemyRepopNtc() - { - LayoutId = layoutId, - EnemyData = new CDataLayoutEnemyData() + PositionIndex = 0, + EnemyInfo = new CDataStageLayoutEnemyPresetEnemyInfoClient() + { + EnemyId = 0x15800, + NamedEnemyParamsId = 47, // Training + Lv = level, + RepopCount = 10, + Scale = 100, + IsBossGauge = true, + } + }, + WaitSecond = 0, + }); + client.Party.SendToAll(new S2CInstanceEnemyRepopNtc() { - PositionIndex = 1, - EnemyInfo = new CDataStageLayoutEnemyPresetEnemyInfoClient() + LayoutId = TrainingRoomLayout, + EnemyData = new CDataLayoutEnemyData() { - EnemyId = 0x15800, - NamedEnemyParamsId = 47, // Training - Lv = (ushort)request.Lv, - RepopCount = 10, - Scale = 100, - IsBossGauge = true, - } - }, - WaitSecond = 1, - }); - break; - case 2: // Cyclops - client.Party.SendToAll(new S2CInstanceEnemyRepopNtc() - { - LayoutId = layoutId, - EnemyData = new CDataLayoutEnemyData() + PositionIndex = 1, + EnemyInfo = new CDataStageLayoutEnemyPresetEnemyInfoClient() + { + EnemyId = 0x15800, + NamedEnemyParamsId = 47, // Training + Lv = level, + RepopCount = 10, + Scale = 100, + IsBossGauge = true, + } + }, + WaitSecond = 0, + }); + break; + case 2: // Cyclops + client.Party.SendToAll(new S2CInstanceEnemyRepopNtc() { - PositionIndex = 2, - EnemyInfo = new CDataStageLayoutEnemyPresetEnemyInfoClient() + LayoutId = TrainingRoomLayout, + EnemyData = new CDataLayoutEnemyData() { - EnemyId = 0x15000, - NamedEnemyParamsId = 47, // Training - Lv = (ushort)request.Lv, - RepopCount = 10, - Scale = 100, - IsBossGauge = true, - } - }, - WaitSecond = 1, - }); - break; - case 3: //Ogre - client.Party.SendToAll(new S2CInstanceEnemyRepopNtc() - { - LayoutId = layoutId, - EnemyData = new CDataLayoutEnemyData() + PositionIndex = 2, + EnemyInfo = new CDataStageLayoutEnemyPresetEnemyInfoClient() + { + EnemyId = 0x15000, + NamedEnemyParamsId = 47, // Training + Lv = level, + RepopCount = 10, + Scale = 100, + IsBossGauge = true, + } + }, + WaitSecond = 0, + }); + break; + case 3: //Ogre + client.Party.SendToAll(new S2CInstanceEnemyRepopNtc() { - PositionIndex = 3, - EnemyInfo = new CDataStageLayoutEnemyPresetEnemyInfoClient() + LayoutId = TrainingRoomLayout, + EnemyData = new CDataLayoutEnemyData() { - EnemyId = 0x15500, - NamedEnemyParamsId = 47, // Training - Lv = (ushort)request.Lv, - RepopCount = 10, - Scale = 100, - IsBossGauge = true, - } - }, - WaitSecond = 1, - }); - break; - case 4: //Passive Zuhl - client.Party.SendToAll(new S2CInstanceEnemyRepopNtc() - { - LayoutId = layoutId, - EnemyData = new CDataLayoutEnemyData() + PositionIndex = 3, + EnemyInfo = new CDataStageLayoutEnemyPresetEnemyInfoClient() + { + EnemyId = 0x15500, + NamedEnemyParamsId = 47, // Training + Lv = level, + RepopCount = 10, + Scale = 100, + IsBossGauge = true, + } + }, + WaitSecond = 0, + }); + break; + case 4: //Passive Zuhl + client.Party.SendToAll(new S2CInstanceEnemyRepopNtc() { - PositionIndex = 4, - EnemyInfo = new CDataStageLayoutEnemyPresetEnemyInfoClient() + LayoutId = TrainingRoomLayout, + EnemyData = new CDataLayoutEnemyData() { - EnemyId = 0x100101, - NamedEnemyParamsId = 722, // Practice , has extra HP. - Lv = (ushort)request.Lv, - RepopCount = 10, - Scale = 75, - IsBossGauge = true, - } - }, - WaitSecond = 1, - }); - break; - } - - return new S2CInstanceTraningRoomSetEnemyRes(); + PositionIndex = 4, + EnemyInfo = new CDataStageLayoutEnemyPresetEnemyInfoClient() + { + EnemyId = 0x100101, + NamedEnemyParamsId = 722, // Practice , has extra HP. + Lv = level, + RepopCount = 10, + Scale = 75, + IsBossGauge = true, + } + }, + WaitSecond = 0, + }); + break; + } + }); } } }