diff --git a/Arrowgene.Ddon.GameServer/DdonGameServer.cs b/Arrowgene.Ddon.GameServer/DdonGameServer.cs index f2b454bae..392da7364 100644 --- a/Arrowgene.Ddon.GameServer/DdonGameServer.cs +++ b/Arrowgene.Ddon.GameServer/DdonGameServer.cs @@ -86,7 +86,7 @@ public DdonGameServer(GameServerSetting setting, IDatabase database, AssetReposi public List StageList { get; } public override GameClientLookup ClientLookup { get; } - + // TODO: Maybe place somewhere else public readonly Dictionary LastRevivalPowerRechargeTime = new Dictionary(); @@ -164,7 +164,7 @@ private void LoadPacketHandler() AddHandler(new BazaarGetItemInfoHandler(this)); AddHandler(new BazaarGetItemListHandler(this)); AddHandler(new BazaarProceedsHandler(this)); - + AddHandler(new BinarySaveSetCharacterBinSavedataHandler(this)); AddHandler(new BlackListGetBlackListHandler(this)); @@ -216,7 +216,7 @@ private void LoadPacketHandler() AddHandler(new CraftGetCraftSettingHandler(this)); AddHandler(new CraftRecipeGetCraftRecipeHandler(this)); AddHandler(new CraftStartCraftHandler(this)); - + AddHandler(new DailyMissionListGetHandler(this)); AddHandler(new EquipChangeCharacterEquipHandler(this)); @@ -239,8 +239,9 @@ private void LoadPacketHandler() AddHandler(new Gp_28_2_1_Handler(this)); AddHandler(new GpGetUpdateAppCourseBonusFlagHandler(this)); AddHandler(new GpGetValidChatComGroupHandler(this)); - AddHandler(new GpGpEditGetVoiceListHandler(this)); - AddHandler(new GpGetGpHandler(this)); + AddHandler(new GpGpEditGetVoiceListHandler(this)); + AddHandler(new GpGetGpHandler(this)); + AddHandler(new GpGpCourseGetAvailableListHandler(this)); AddHandler(new GroupChatGroupChatGetMemberListHandler(this)); @@ -333,10 +334,10 @@ private void LoadPacketHandler() AddHandler(new PawnJoinPartyMypawnHandler(this)); AddHandler(new PawnPawnLostHandler(this)); AddHandler(new PawnTrainingGetPreparetionInfoToAdviceHandler(this)); - + AddHandler(new ProfileGetCharacterProfileHandler(this)); AddHandler(new ProfileGetMyCharacterProfileHandler(this)); - + AddHandler(new QuestEndDistributionQuestCancelHandler(this)); AddHandler(new QuestGetAdventureGuideQuestListHandler(this)); AddHandler(new QuestGetAdventureGuideQuestNoticeHandler(this)); @@ -363,7 +364,7 @@ private void LoadPacketHandler() AddHandler(new QuestSendLeaderQuestOrderConditionInfoHandler(this)); AddHandler(new QuestSendLeaderWaitOrderQuestListHandler(this)); AddHandler(new QuestSetPriorityQuestHandler(this)); - + AddHandler(new EntryBoardEntryBoardList(this)); AddHandler(new EntryBoardEntryBoardItemCreate(this)); AddHandler(new EntryBoardEntryBoardItemForceStart(this)); diff --git a/Arrowgene.Ddon.GameServer/Handler/CharacterDecideCharacterIdHandler.cs b/Arrowgene.Ddon.GameServer/Handler/CharacterDecideCharacterIdHandler.cs index d1d8984c5..c33947a46 100644 --- a/Arrowgene.Ddon.GameServer/Handler/CharacterDecideCharacterIdHandler.cs +++ b/Arrowgene.Ddon.GameServer/Handler/CharacterDecideCharacterIdHandler.cs @@ -1,6 +1,7 @@ using Arrowgene.Ddon.GameServer.Dump; using Arrowgene.Ddon.Server; using Arrowgene.Ddon.Server.Network; +using Arrowgene.Ddon.Shared; using Arrowgene.Ddon.Shared.Entity; using Arrowgene.Ddon.Shared.Entity.PacketStructure; using Arrowgene.Ddon.Shared.Entity.Structure; @@ -13,9 +14,11 @@ public class CharacterDecideCharacterIdHandler : PacketHandler { private static readonly ServerLogger Logger = LogProvider.Logger(typeof(CharacterDecideCharacterIdHandler)); + private AssetRepository _AssetRepo; public CharacterDecideCharacterIdHandler(DdonGameServer server) : base(server) { + _AssetRepo = server.AssetRepository; } public override PacketId Id => PacketId.C2S_CHARACTER_DECIDE_CHARACTER_ID_REQ; @@ -27,12 +30,21 @@ public override void Handle(GameClient client, IPacket packet) res.CharacterId = client.Character.CharacterId; res.CharacterInfo = new CDataCharacterInfo(client.Character); res.Unk0 = pcap.Unk0; // Removing this makes tons of tutorials pop up - + client.Send(res); - + // Unlocks menu options such as inventory, warping, etc. S2CCharacterContentsReleaseElementNtc contentsReleaseElementNotice = EntitySerializer.Get().Read(GameFull.data_Dump_20); client.Send(contentsReleaseElementNotice); + + foreach (var ValidCourse in _AssetRepo.GPCourseInfoAsset.ValidCourses) + { + client.Send(new S2CGPCourseStartNtc() + { + CourseID = ValidCourse.Value.Id, + ExpiryTimestamp = ValidCourse.Value.EndTime + }); + } } } } diff --git a/Arrowgene.Ddon.GameServer/Handler/GpGpCourseGetAvailableListHandler.cs b/Arrowgene.Ddon.GameServer/Handler/GpGpCourseGetAvailableListHandler.cs new file mode 100644 index 000000000..a72164062 --- /dev/null +++ b/Arrowgene.Ddon.GameServer/Handler/GpGpCourseGetAvailableListHandler.cs @@ -0,0 +1,39 @@ +using Arrowgene.Buffers; +using Arrowgene.Ddon.GameServer.Dump; +using Arrowgene.Ddon.Server; +using Arrowgene.Ddon.Server.Network; +using Arrowgene.Ddon.Shared; +using Arrowgene.Ddon.Shared.Entity.PacketStructure; +using Arrowgene.Ddon.Shared.Network; +using Arrowgene.Logging; + +namespace Arrowgene.Ddon.GameServer.Handler +{ + public class GpGpCourseGetAvailableListHandler : PacketHandler + { + private static readonly ServerLogger Logger = LogProvider.Logger(typeof(GpGpCourseGetAvailableListHandler)); + + private AssetRepository _AssetRepo; + + public GpGpCourseGetAvailableListHandler(DdonGameServer server) : base(server) + { + _AssetRepo = server.AssetRepository; + } + + public override PacketId Id => PacketId.C2S_GP_GP_COURSE_GET_AVAILABLE_LIST_REQ; + + public override void Handle(GameClient client, IPacket packet) + { + S2CGpGpCourseGetAvailableListRes Response = new S2CGpGpCourseGetAvailableListRes(); + + // foreach (var Course in _AssetRepo.GPCourseInfoAsset.ValidCourses) + // { + // + // } + + // TODO: Send back real data based on JSON contents? + // TODO: PCAP doesn't have sample packet contents to see what is in it. + client.Send(Response); + } + } +} diff --git a/Arrowgene.Ddon.LoginServer/Handler/GetCharacterListHandler.cs b/Arrowgene.Ddon.LoginServer/Handler/GetCharacterListHandler.cs index 1ef683e2e..4de79a2b4 100644 --- a/Arrowgene.Ddon.LoginServer/Handler/GetCharacterListHandler.cs +++ b/Arrowgene.Ddon.LoginServer/Handler/GetCharacterListHandler.cs @@ -3,7 +3,9 @@ using Arrowgene.Buffers; using Arrowgene.Ddon.Server; using Arrowgene.Ddon.Server.Network; +using Arrowgene.Ddon.Shared; using Arrowgene.Ddon.Shared.Entity; +using Arrowgene.Ddon.Shared.Entity.PacketStructure; using Arrowgene.Ddon.Shared.Entity.Structure; using Arrowgene.Ddon.Shared.Model; using Arrowgene.Ddon.Shared.Network; @@ -14,10 +16,13 @@ namespace Arrowgene.Ddon.LoginServer.Handler public class GetCharacterListHandler : PacketHandler { private static readonly ServerLogger Logger = LogProvider.Logger(typeof(GetCharacterListHandler)); + private AssetRepository _AssetRepo; + public GetCharacterListHandler(DdonLoginServer server) : base(server) { + _AssetRepo = server.AssetRepository; } public override PacketId Id => PacketId.C2L_GET_CHARACTER_LIST_REQ; @@ -39,6 +44,27 @@ public override void Handle(LoginClient client, IPacket packet) cResponse.CharacterListElement.CommunityCharacterBaseInfo.CharacterName.LastName = c.LastName; cResponse.CharacterListElement.CurrentJobBaseInfo.Job = c.Job; cResponse.CharacterListElement.CurrentJobBaseInfo.Level = (byte) c.ActiveCharacterJobData.Lv; + + List ValidCourses = new List(); + + foreach (var ValidCourse in _AssetRepo.GPCourseInfoAsset.ValidCourses) + { + CDataGPCourseValid cDataGPCourseValid = new CDataGPCourseValid() + { + Id = c.CharacterId, + CourseId = ValidCourse.Value.Id, + NameA = _AssetRepo.GPCourseInfoAsset.Courses[ValidCourse.Value.Id].Name, // Course Name + NameB = _AssetRepo.GPCourseInfoAsset.Courses[ValidCourse.Value.Id].IconPath, // Link to a icon + StartTime = ValidCourse.Value.StartTime, + EndTime = ValidCourse.Value.EndTime, + }; + + ValidCourses.Add(cDataGPCourseValid); + } + + cResponse.GpCourseValidList = ValidCourses; + cResponse.NextFlowType = 1; + cResponse.IsClanMemberNotice = 1; // REMOVE // maybe? //cResponse.CharacterListElement.CurrentJobBaseInfo.Job = c.CharacterInfo.MatchingProfile.CurrentJob; //cResponse.CharacterListElement.CurrentJobBaseInfo.Level = (byte) c.CharacterInfo.MatchingProfile.CurrentJobLevel; @@ -48,11 +74,11 @@ public override void Handle(LoginClient client, IPacket packet) cResponse.MatchingProfile = c.MatchingProfile; cResponse.EquipItemInfo = c.Equipment.getEquipmentAsCDataEquipItemInfo(c.Job, EquipType.Performance) .Union(c.Equipment.getEquipmentAsCDataEquipItemInfo(c.Job, EquipType.Visual)) - .ToList(); + .ToList(); characterListResponse.Add(cResponse); } - + EntitySerializer.Get().WriteList(buffer, characterListResponse); Packet response = new Packet(PacketId.L2C_GET_CHARACTER_LIST_RES, buffer.GetAllBytes()); client.Send(response); diff --git a/Arrowgene.Ddon.LoginServer/Handler/GpCourseGetInfoHandler.cs b/Arrowgene.Ddon.LoginServer/Handler/GpCourseGetInfoHandler.cs index ea5eb5fbc..19e9a5144 100644 --- a/Arrowgene.Ddon.LoginServer/Handler/GpCourseGetInfoHandler.cs +++ b/Arrowgene.Ddon.LoginServer/Handler/GpCourseGetInfoHandler.cs @@ -1,8 +1,13 @@ -using Arrowgene.Ddon.LoginServer.Dump; +using Arrowgene.Ddon.LoginServer.Dump; using Arrowgene.Ddon.Server; using Arrowgene.Ddon.Server.Network; +using Arrowgene.Ddon.Shared; +using Arrowgene.Ddon.Shared.Entity.PacketStructure; +using Arrowgene.Ddon.Shared.Entity.Structure; using Arrowgene.Ddon.Shared.Network; using Arrowgene.Logging; +using System; +using System.Linq; namespace Arrowgene.Ddon.LoginServer.Handler { @@ -10,16 +15,50 @@ public class GpCourseGetInfoHandler : PacketHandler { private static readonly ServerLogger Logger = LogProvider.Logger(typeof(GpCourseGetInfoHandler)); + private AssetRepository _AssetRepo; public GpCourseGetInfoHandler(DdonLoginServer server) : base(server) { + _AssetRepo = server.AssetRepository; } public override PacketId Id => PacketId.C2L_GP_COURSE_GET_INFO_REQ; public override void Handle(LoginClient client, IPacket packet) { - client.Send(LoginDump.Dump_22); + L2CGpCourseGetInfoRes Response = new L2CGpCourseGetInfoRes(); + + foreach (var Course in _AssetRepo.GPCourseInfoAsset.Courses) + { + CDataGPCourseInfo cDataGPCourseInfo = new CDataGPCourseInfo() + { + CourseId = Course.Value.Id, + CourseName = Course.Value.Name, + DoubleCourseTarget = Course.Value.Target, + PrioGroup = (byte)Course.Value.PriorityGroup, + PrioSameTime = (byte)Course.Value.PrioritySameTime, + AnnounceType = (byte)Course.Value.AnnounceType, + EffectUIDs = Course.Value.Effects + }; + + Response.CourseInfo.Add(cDataGPCourseInfo); + } + + foreach (var Effect in _AssetRepo.GPCourseInfoAsset.Effects) + { + CDataGPCourseEffectParam cDataGPCourseEffectParam = new CDataGPCourseEffectParam() + { + EffectUID = Effect.Value.Uid, + EffectID = Effect.Value.Id, + Param0 = Effect.Value.Param0, + Param1 = Effect.Value.Param1 + }; + + Response.Effects.Add(cDataGPCourseEffectParam); + } + + // client.Send(LoginDump.Dump_22); + client.Send(Response); } } } diff --git a/Arrowgene.Ddon.Shared/Asset/GPCourseInfoAsset.cs b/Arrowgene.Ddon.Shared/Asset/GPCourseInfoAsset.cs new file mode 100644 index 000000000..566170152 --- /dev/null +++ b/Arrowgene.Ddon.Shared/Asset/GPCourseInfoAsset.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using Arrowgene.Ddon.Shared.Model; + +namespace Arrowgene.Ddon.Shared.Asset +{ + public class GPCourseInfoAsset + { + public GPCourseInfoAsset() + { + Courses = new Dictionary(); + Effects = new Dictionary(); + ValidCourses = new Dictionary(); + } + public Dictionary Courses { get; set; } + public Dictionary Effects { get; set; } + public Dictionary ValidCourses { get; set; } + } +} diff --git a/Arrowgene.Ddon.Shared/AssetReader/GPCourseInfoDeserializer.cs b/Arrowgene.Ddon.Shared/AssetReader/GPCourseInfoDeserializer.cs new file mode 100644 index 000000000..2750fdf13 --- /dev/null +++ b/Arrowgene.Ddon.Shared/AssetReader/GPCourseInfoDeserializer.cs @@ -0,0 +1,76 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.Json; +using Arrowgene.Ddon.Shared.Model; +using Arrowgene.Logging; +using Arrowgene.Ddon.Shared.Asset; + +namespace Arrowgene.Ddon.Shared.Csv +{ + public class GPCourseInfoDeserializer : IAssetDeserializer + { + private static readonly ILogger Logger = LogProvider.Logger(typeof(GPCourseInfoDeserializer)); + + public GPCourseInfoAsset ReadPath(string path) + { + Logger.Info($"Reading {path}"); + + GPCourseInfoAsset asset = new GPCourseInfoAsset(); + + string json = File.ReadAllText(path); + JsonDocument document = JsonDocument.Parse(json); + + var ValidCourses = document.RootElement.GetProperty("valid_courses").EnumerateArray().ToList(); + foreach (var ValidCourse in ValidCourses) + { + GPValidCourse obj = new GPValidCourse(); + obj.Id = ValidCourse.GetProperty("course_id").GetUInt32(); + obj.StartTime = ValidCourse.GetProperty("start_time").GetUInt64(); + obj.EndTime = ValidCourse.GetProperty("end_time").GetUInt64(); + obj.Comment = ValidCourse.GetProperty("comment").GetString(); + + asset.ValidCourses.Add(obj.Id, obj); + } + + var Courses = document.RootElement.GetProperty("courses").EnumerateArray().ToList(); + foreach (var Course in Courses) + { + GPCourse obj = new GPCourse(); + obj.Id = Course.GetProperty("id").GetUInt32(); + obj.Name = Course.GetProperty("name").GetString(); + obj.Target = Course.GetProperty("target").GetUInt32() == 1; + obj.PriorityGroup = Course.GetProperty("priority_grp").GetUInt32(); + obj.PrioritySameTime = Course.GetProperty("priority_same_time").GetUInt32(); + obj.AnnounceType = Course.GetProperty("announce_type").GetUInt32(); + obj.Comment = Course.GetProperty("comment").GetString(); + obj.Url = Course.GetProperty("url").GetString(); + obj.IconPath = Course.GetProperty("icon_path").GetString(); + obj.Description = Course.GetProperty("description").GetString(); + + var EffectUIDs = Course.GetProperty("effects").EnumerateArray().ToList(); + foreach (var EffectUID in EffectUIDs) + { + obj.Effects.Add(EffectUID.GetUInt32()); + } + + asset.Courses.Add(obj.Id, obj); + } + + var Effects = document.RootElement.GetProperty("effects").EnumerateArray().ToList(); + foreach (var Effect in Effects) + { + GpCourseEffect obj = new GpCourseEffect(); + obj.Uid = Effect.GetProperty("uid").GetUInt32(); + obj.Id = Effect.GetProperty("id").GetUInt32(); + obj.Param0 = Effect.GetProperty("param0").GetUInt32(); + obj.Param1 = Effect.GetProperty("param1").GetUInt32(); + obj.Comment = Effect.GetProperty("comment").GetString(); + + asset.Effects.Add(obj.Uid, obj); + } + + return asset; + } + } +} diff --git a/Arrowgene.Ddon.Shared/AssetRepository.cs b/Arrowgene.Ddon.Shared/AssetRepository.cs index fd300fa99..7d5951f7c 100644 --- a/Arrowgene.Ddon.Shared/AssetRepository.cs +++ b/Arrowgene.Ddon.Shared/AssetRepository.cs @@ -31,6 +31,7 @@ public class AssetRepository public const string WarpPointsKey = "WarpPoints.csv"; public const string CraftingRecipesKey = "CraftingRecipes.json"; public const string LearnedNormalSkillsKey = "LearnedNormalSkills.json"; + public const string GPCourseInfoKey = "GpCourseInfo.json"; private static readonly ILogger Logger = LogProvider.Logger(typeof(AssetRepository)); @@ -64,6 +65,7 @@ public AssetRepository(string folder) WarpPoints = new List(); CraftingRecipesAsset = new List(); LearnedNormalSkillsAsset = new LearnedNormalSkillsAsset(); + GPCourseInfoAsset = new GPCourseInfoAsset(); } public List ClientErrorCodes { get; private set; } @@ -80,6 +82,7 @@ public AssetRepository(string folder) public List WarpPoints { get; private set; } public List CraftingRecipesAsset { get; private set; } public LearnedNormalSkillsAsset LearnedNormalSkillsAsset { get; set; } + public GPCourseInfoAsset GPCourseInfoAsset { get; private set; } public void Initialize() { @@ -97,6 +100,7 @@ public void Initialize() RegisterAsset(value => WarpPoints = value, WarpPointsKey, new WarpPointCsv()); RegisterAsset(value => CraftingRecipesAsset = value, CraftingRecipesKey, new JsonReaderWriter>()); RegisterAsset(value => LearnedNormalSkillsAsset = value, LearnedNormalSkillsKey, new LearnedNormalSkillsDeserializer()); + RegisterAsset(value => GPCourseInfoAsset = value, GPCourseInfoKey, new GPCourseInfoDeserializer()); } private void RegisterAsset(Action onLoadAction, string key, IAssetDeserializer readerWriter) diff --git a/Arrowgene.Ddon.Shared/Entity/EntitySerializer.cs b/Arrowgene.Ddon.Shared/Entity/EntitySerializer.cs index 42e094725..e9557fb99 100644 --- a/Arrowgene.Ddon.Shared/Entity/EntitySerializer.cs +++ b/Arrowgene.Ddon.Shared/Entity/EntitySerializer.cs @@ -105,6 +105,9 @@ static EntitySerializer() Create(new CDataGoodsParamUnk7.Serializer()); Create(new CDataGatheringItemElement.Serializer()); Create(new CDataGPCourseValidSerializer()); + Create(new CDataGPCourseInfoSerializer()); + Create(new CDataGPCourseEffectParamSerializer()); + Create(new CDataGPCourseAvailableSerializer()); Create(new CDataHistoryElement.Serializer()); Create(new CDataItemEquipElement.Serializer()); Create(new CDataItemEquipElementParam.Serializer()); @@ -426,6 +429,7 @@ static EntitySerializer() Create(new L2CLoginRes.Serializer()); Create(new L2CLoginWaitNumNtc.Serializer()); Create(new L2CNextConnectionServerNtc.Serializer()); + Create(new L2CGpCourseGetInfoRes.Serializer()); Create(new S2CActionSetPlayerActionHistoryRes.Serializer()); @@ -510,6 +514,8 @@ static EntitySerializer() Create(new S2CEquipUpdateHidePawnHeadArmorRes.Serializer()); Create(new S2CEquipUpdateHidePawnLanternRes.Serializer()); Create(new S2CGpGetValidChatComGroupRes.Serializer()); + Create(new S2CGpGpCourseGetAvailableListRes.Serializer()); + Create(new S2CGPCourseStartNtc.Serializer()); Create(new S2CInnGetPenaltyHealStayPriceRes.Serializer()); Create(new S2CInnGetStayPriceRes.Serializer()); Create(new S2CInnStayInnRes.Serializer()); diff --git a/Arrowgene.Ddon.Shared/Entity/PacketStructure/L2CGpCourseGetInfoRes.cs b/Arrowgene.Ddon.Shared/Entity/PacketStructure/L2CGpCourseGetInfoRes.cs new file mode 100644 index 000000000..fa1318475 --- /dev/null +++ b/Arrowgene.Ddon.Shared/Entity/PacketStructure/L2CGpCourseGetInfoRes.cs @@ -0,0 +1,50 @@ +using Arrowgene.Buffers; +using Arrowgene.Ddon.Shared.Entity.Structure; +using Arrowgene.Ddon.Shared.Network; +using System.Collections.Generic; + +namespace Arrowgene.Ddon.Shared.Entity.PacketStructure +{ + public class L2CGpCourseGetInfoRes : ServerResponse + { + public L2CGpCourseGetInfoRes() + { + CourseInfo = new List(); + Effects = new List(); + Unk0 = new byte[] + { + 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x30, 0xB0, 0x00, 0x49, 0xE3, 0x83, 0x9F + }; + } + + public List CourseInfo { get; set; } + public List Effects { get; set; } + public byte[] Unk0 { get; set; } + + public override PacketId Id => PacketId.L2C_GP_COURSE_GET_INFO_RES; + + public class Serializer : PacketEntitySerializer + { + + public override void Write(IBuffer buffer, L2CGpCourseGetInfoRes obj) + { + WriteServerResponse(buffer, obj); + WriteEntityList(buffer, obj.CourseInfo); + WriteEntityList(buffer, obj.Effects); + WriteByteArray(buffer, obj.Unk0); + } + + public override L2CGpCourseGetInfoRes Read(IBuffer buffer) + { + L2CGpCourseGetInfoRes obj = new L2CGpCourseGetInfoRes(); + + ReadServerResponse(buffer, obj); + obj.CourseInfo = ReadEntityList(buffer); + obj.Effects = ReadEntityList(buffer); + obj.Unk0 = ReadByteArray(buffer, obj.Unk0.Length); + + return obj; + } + } + } +} diff --git a/Arrowgene.Ddon.Shared/Entity/PacketStructure/S2CGPCourseStartNtc.cs b/Arrowgene.Ddon.Shared/Entity/PacketStructure/S2CGPCourseStartNtc.cs new file mode 100644 index 000000000..a28351d94 --- /dev/null +++ b/Arrowgene.Ddon.Shared/Entity/PacketStructure/S2CGPCourseStartNtc.cs @@ -0,0 +1,31 @@ +using Arrowgene.Buffers; +using Arrowgene.Ddon.Shared.Network; +using System; + +namespace Arrowgene.Ddon.Shared.Entity.PacketStructure +{ + public class S2CGPCourseStartNtc : IPacketStructure + { + public PacketId Id => PacketId.S2C_GP_COURSE_START_NTC; + + public UInt32 CourseID { get; set; } + public UInt64 ExpiryTimestamp { get; set; } + + public class Serializer : PacketEntitySerializer + { + public override void Write(IBuffer buffer, S2CGPCourseStartNtc obj) + { + WriteUInt32(buffer, obj.CourseID); + WriteUInt64(buffer, obj.ExpiryTimestamp); + } + + public override S2CGPCourseStartNtc Read(IBuffer buffer) + { + S2CGPCourseStartNtc obj = new S2CGPCourseStartNtc(); + obj.CourseID = ReadUInt32(buffer); + obj.ExpiryTimestamp = ReadUInt64(buffer); + return obj; + } + } + } +} diff --git a/Arrowgene.Ddon.Shared/Entity/PacketStructure/S2CGpGpCourseGetAvailableListRes.cs b/Arrowgene.Ddon.Shared/Entity/PacketStructure/S2CGpGpCourseGetAvailableListRes.cs new file mode 100644 index 000000000..00e89237f --- /dev/null +++ b/Arrowgene.Ddon.Shared/Entity/PacketStructure/S2CGpGpCourseGetAvailableListRes.cs @@ -0,0 +1,36 @@ +using Arrowgene.Buffers; +using Arrowgene.Ddon.Shared.Entity.Structure; +using Arrowgene.Ddon.Shared.Network; +using System.Collections.Generic; + +namespace Arrowgene.Ddon.Shared.Entity.PacketStructure +{ + public class S2CGpGpCourseGetAvailableListRes : ServerResponse + { + public override PacketId Id => PacketId.S2C_GP_GP_COURSE_GET_AVAILABLE_LIST_RES; + + public S2CGpGpCourseGetAvailableListRes() + { + AvailableCourses = new List(); + } + + public List AvailableCourses { get; set; } + + public class Serializer : PacketEntitySerializer + { + public override void Write(IBuffer buffer, S2CGpGpCourseGetAvailableListRes obj) + { + WriteServerResponse(buffer, obj); + WriteEntityList(buffer, obj.AvailableCourses); + } + + public override S2CGpGpCourseGetAvailableListRes Read(IBuffer buffer) + { + S2CGpGpCourseGetAvailableListRes obj = new S2CGpGpCourseGetAvailableListRes(); + ReadServerResponse(buffer, obj); + obj.AvailableCourses = ReadEntityList(buffer); + return obj; + } + } + } +} diff --git a/Arrowgene.Ddon.Shared/Entity/Structure/CDataCharacterListInfo.cs b/Arrowgene.Ddon.Shared/Entity/Structure/CDataCharacterListInfo.cs index e91f65a89..5242bfea6 100644 --- a/Arrowgene.Ddon.Shared/Entity/Structure/CDataCharacterListInfo.cs +++ b/Arrowgene.Ddon.Shared/Entity/Structure/CDataCharacterListInfo.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using Arrowgene.Buffers; namespace Arrowgene.Ddon.Shared.Entity.Structure @@ -18,15 +18,15 @@ public CDataCharacterListInfo() IsClanMemberNotice = 0; } - public CDataCharacterListElement CharacterListElement; - public CDataEditInfo EditInfo; - public CDataMatchingProfile MatchingProfile; - public List EquipItemInfo; - public List GpCourseValidList; - public byte NextFlowType; - public string ClanName; - public string ClanNameShort; - public byte IsClanMemberNotice; + public CDataCharacterListElement CharacterListElement { get; set; } + public CDataEditInfo EditInfo { get; set; } + public CDataMatchingProfile MatchingProfile { get; set; } + public List EquipItemInfo { get; set; } + public List GpCourseValidList { get; set; } + public byte NextFlowType { get; set; } + public string ClanName { get; set; } + public string ClanNameShort { get; set; } + public byte IsClanMemberNotice { get; set; } } public class CDataCharacterListInfoSerializer : EntitySerializer diff --git a/Arrowgene.Ddon.Shared/Entity/Structure/CDataGPCourseAvailable.cs b/Arrowgene.Ddon.Shared/Entity/Structure/CDataGPCourseAvailable.cs new file mode 100644 index 000000000..de5a734d6 --- /dev/null +++ b/Arrowgene.Ddon.Shared/Entity/Structure/CDataGPCourseAvailable.cs @@ -0,0 +1,50 @@ +using Arrowgene.Buffers; +using System; + +namespace Arrowgene.Ddon.Shared.Entity.Structure +{ + public class CDataGPCourseAvailable + { + public CDataGPCourseAvailable() + { + CourseID = 0; + CourseName = ""; + } + + // Character ID? + public UInt32 ID { get; set; } + public string CourseName { get; set; } + public UInt64 UseLimitTime { get; set; } + public UInt32 CourseID { get; set; } + public UInt32 LineupID { get; set; } + public UInt32 BackIconID { get; set; } + public UInt32 FrameIconID { get; set; } + } + + public class CDataGPCourseAvailableSerializer : EntitySerializer + { + public override void Write(IBuffer buffer, CDataGPCourseAvailable obj) + { + WriteUInt32(buffer, obj.ID); + WriteMtString(buffer, obj.CourseName); + WriteUInt64(buffer, obj.UseLimitTime); + WriteUInt32(buffer, obj.CourseID); + WriteUInt32(buffer, obj.LineupID); + WriteUInt32(buffer, obj.BackIconID); + WriteUInt32(buffer, obj.FrameIconID); + } + + public override CDataGPCourseAvailable Read(IBuffer buffer) + { + CDataGPCourseAvailable obj = new CDataGPCourseAvailable(); + obj.ID = ReadUInt32(buffer); + obj.CourseName = ReadMtString(buffer); + obj.UseLimitTime = ReadUInt64(buffer); + obj.CourseID = ReadUInt32(buffer); + obj.LineupID = ReadUInt32(buffer); + obj.BackIconID = ReadUInt32(buffer); + obj.FrameIconID = ReadUInt32(buffer); + return obj; + } + } +} diff --git a/Arrowgene.Ddon.Shared/Entity/Structure/CDataGPCourseEffectParam.cs b/Arrowgene.Ddon.Shared/Entity/Structure/CDataGPCourseEffectParam.cs new file mode 100644 index 000000000..8a8ed4796 --- /dev/null +++ b/Arrowgene.Ddon.Shared/Entity/Structure/CDataGPCourseEffectParam.cs @@ -0,0 +1,42 @@ +using Arrowgene.Buffers; +using System; + +namespace Arrowgene.Ddon.Shared.Entity.Structure +{ + public class CDataGPCourseEffectParam + { + public CDataGPCourseEffectParam() + { + EffectUID = 0; + EffectID = 0; + Param0 = 0; + Param1 = 0; + } + + public UInt32 EffectUID { get; set; } + public UInt32 EffectID { get; set; } + public UInt32 Param0 { get; set; } + public UInt32 Param1 { get; set; } + } + + public class CDataGPCourseEffectParamSerializer : EntitySerializer + { + public override void Write(IBuffer buffer, CDataGPCourseEffectParam obj) + { + WriteUInt32(buffer, obj.EffectUID); + WriteUInt32(buffer, obj.EffectID); + WriteUInt32(buffer, obj.Param0); + WriteUInt32(buffer, obj.Param1); + } + + public override CDataGPCourseEffectParam Read(IBuffer buffer) + { + CDataGPCourseEffectParam obj = new CDataGPCourseEffectParam(); + obj.EffectUID = ReadUInt32(buffer); + obj.EffectID = ReadUInt32(buffer); + obj.Param0 = ReadUInt32(buffer); + obj.Param1 = ReadUInt32(buffer); + return obj; + } + } +} diff --git a/Arrowgene.Ddon.Shared/Entity/Structure/CDataGPCourseInfo.cs b/Arrowgene.Ddon.Shared/Entity/Structure/CDataGPCourseInfo.cs new file mode 100644 index 000000000..5573e8dc8 --- /dev/null +++ b/Arrowgene.Ddon.Shared/Entity/Structure/CDataGPCourseInfo.cs @@ -0,0 +1,65 @@ +using Arrowgene.Buffers; +using System; +using System.Collections.Generic; + +namespace Arrowgene.Ddon.Shared.Entity.Structure +{ + public class CDataGPCourseInfo + { + public CDataGPCourseInfo() + { + CourseId = 0; + CourseName = "unknown"; + DoubleCourseTarget = false; + PrioGroup = 0; + PrioSameTime = 0; + AnnounceType = 0; + EffectUIDs = new List(); + } + + public UInt32 CourseId { get; set; } + public string CourseName { get; set; } + public bool DoubleCourseTarget; + public byte PrioGroup; + public byte PrioSameTime; + public byte AnnounceType; + public List EffectUIDs; + } + + public class CDataGPCourseInfoSerializer : EntitySerializer + { + public override void Write(IBuffer buffer, CDataGPCourseInfo obj) + { + WriteUInt32(buffer, obj.CourseId); + WriteMtString(buffer,obj.CourseName); + WriteByte(buffer, Convert.ToByte(obj.DoubleCourseTarget)); + WriteByte(buffer, obj.PrioGroup); + WriteByte(buffer, obj.PrioSameTime); + WriteByte(buffer, obj.AnnounceType); + WriteMtArray(buffer, obj.EffectUIDs, WriteEffectUID); + } + + public override CDataGPCourseInfo Read(IBuffer buffer) + { + CDataGPCourseInfo obj = new CDataGPCourseInfo(); + obj.CourseId = ReadUInt32(buffer); + obj.CourseName = ReadMtString(buffer); + obj.DoubleCourseTarget = Convert.ToBoolean(ReadByte(buffer)); + obj.PrioGroup = ReadByte(buffer); + obj.PrioSameTime = ReadByte(buffer); + obj.AnnounceType = ReadByte(buffer); + obj.EffectUIDs = ReadMtArray(buffer, ReadEffectUID); + + return obj; + } + private UInt32 ReadEffectUID(IBuffer buffer) + { + return ReadUInt32(buffer); + } + + private void WriteEffectUID(IBuffer buffer, UInt32 Value) + { + WriteUInt32(buffer, Value); + } + } +} diff --git a/Arrowgene.Ddon.Shared/Files/Assets/GpCourseInfo.json b/Arrowgene.Ddon.Shared/Files/Assets/GpCourseInfo.json new file mode 100644 index 000000000..360810e77 --- /dev/null +++ b/Arrowgene.Ddon.Shared/Files/Assets/GpCourseInfo.json @@ -0,0 +1,852 @@ +{ + "comment": [ + "You can find official course effects described at https://web.archive.org/web/20170711054053/https://members.dd-on.jp/shop/payment/stone/top", + "", + "It is possible to modify this file to change the course which is available to be used.", + "The 'valid_courses' key, contains a list of all valid courses for every character on the server.", + "The 'course_id' field corresponds to the 'id' field of the objects in the 'courses' key.", + "The 'start_time' and 'end_time' values are in unix timestamp format." + ], + "valid_courses": [ + { + "course_id": 17, + "start_time": 1440993600, + "end_time": 4103413199, + "comment": "Course 17 valid until the year 2100" + } + ], + "courses": [ + { + "id": 1, + "name": "冒険パスポート", + "comment": "Adventure Passport", + "icon_path": "", + "description": "Resurrection power is restored as many times as you like! A set of basic services that make playing DDON useful, such as expanding storage boxes.", + "url": "https://web.archive.org/web/20170711035052/https://members.dd-on.jp/shop/payment/course/1", + "target": 0, + "priority_grp": 100, + "priority_same_time": 70, + "announce_type": 2, + "effects": [ 1, 2, 3, 5, 6, 7, 9, 10, 11, 40, 41, 44, 50, 52, 128, 213, 215, 218, 253 ] + }, + { + "id": 2, + "name": "報酬サポートコース", + "comment": "Reward Support Course", + "icon_path": "", + "description": "Rarely small items are available! Acquisition amount of rims and blood orbs, acquisition number of collection/mining/treasure boxes, etc.", + "url": "https://web.archive.org/web/20170711035052/https://members.dd-on.jp/shop/payment/course/2", + "target": 1, + "priority_grp": 100, + "priority_same_time": 40, + "announce_type": 3, + "effects": [ 12, 13, 14, 15, 16, 17, 51, 59, 149 ] + }, + { + "id": 3, + "name": "成長サポートコース", + "comment": "Growth Support Course", + "icon_path": "", + "description": "Experience of learners and pawns, a course to help grow learners and pawns that also raise area points!", + "url": "https://web.archive.org/web/20170711035052/https://members.dd-on.jp/shop/payment/course/3", + "target": 1, + "priority_grp": 100, + "priority_same_time": 30, + "announce_type": 3, + "effects": [ 18, 19, 20, 22, 23, 25, 26, 27, 70, 119, 150, 151, 208, 209, 210, 211, 212, 246, 254 ] + }, + { + "id": 4, + "name": "安心アシストコース", + "comment": "Reliable Assist Course", + "icon_path": "", + "description": "Reduces damage to learners and pawns, as well as accumulation of abnormal conditions! It reduces the danger of adventure and provides a reassuring life.", + "url": "https://web.archive.org/web/20170711035052/https://members.dd-on.jp/shop/payment/course/4", + "target": 1, + "priority_grp": 100, + "priority_same_time": 50, + "announce_type": 3, + "effects": [ 71, 72, 73, 74, 75 ] + }, + { + "id": 5, + "name": "ダブル発動特典", + "comment": "Double Activation Benefit", + "icon_path": "", + "description": "", + "url": "", + "target": 0, + "priority_grp": 90, + "priority_same_time": 20, + "announce_type": 1, + "effects": [ 189, 190, 191, 192, 193, 194, 195, 196, 248, 255, 266 ] + }, + { + "id": 6, + "name": "トリプル発動特典", + "comment": "Triple Activation Benefit", + "icon_path": "", + "description": "", + "url": "", + "target": 0, + "priority_grp": 80, + "priority_same_time": 10, + "announce_type": 1, + "effects": [ 197, 198, 199, 200, 201, 202, 203, 204, 247, 256, 264, 265, 267 ] + }, + { + "id": 7, + "name": "グランドミッションコース", + "comment": "Grand Mission Course", + "icon_path": "", + "description": "Grand Mission Earnings Score and Job Points Up!Cumulative score rewards make it easier to aim for high rank rewards!", + "url": "https://web.archive.org/web/20170711035052/https://members.dd-on.jp/shop/payment/course/7", + "target": 0, + "priority_grp": 200, + "priority_same_time": 100, + "announce_type": 1, + "effects": [] + }, + { + "id": 8, + "name": "ネットカフェ特典コース", + "comment": "Internet Cafe Special Course", + "icon_path": "", + "description": "", + "url": "", + "target": 0, + "priority_grp": 50, + "priority_same_time": 0, + "announce_type": 1, + "effects": [ 49, 1, 2, 3, 5, 6, 7, 9, 10, 11, 40, 41, 44, 50, 52, 128, 213, 215, 218, 253, 12, 13, 14, 15, 16, 17, 51, 59, 149, 18, 19, 20, 22, 23, 25, 26, 27, 70, 119, 150, 151, 208, 209, 210, 211, 212, 246, 254, 189, 190, 191, 192, 193, 194, 195, 196, 248, 255, 266, 69, 216, 217 ] + }, + { + "id": 9, + "name": "格納チェストパスポート1", + "comment": "Storage Chest Passport 1", + "icon_path": "", + "description": "Store 400 additional items!A passport that makes playing DDON even more convenient!", + "url": "https://web.archive.org/web/20170711035052/https://members.dd-on.jp/shop/payment/course/9", + "target": 0, + "priority_grp": 100, + "priority_same_time": 80, + "announce_type": 2, + "effects": [ 69 ] + }, + { + "id": 10, + "name": "討伐経験値5倍コース", + "comment": "Subjugation Experience Value 5x Course", + "icon_path": "", + "description": "", + "url": "", + "target": 0, + "priority_grp": 100, + "priority_same_time": 25, + "announce_type": 3, + "effects": [ 76, 77, 78 ] + }, + { + "id": 11, + "name": "格納チェストパスポート2", + "comment": "Storage Chest Passport 2", + "icon_path": "", + "description": "", + "url": "", + "target": 0, + "priority_grp": 100, + "priority_same_time": 85, + "announce_type": 2, + "effects": [ 216 ] + }, + { + "id": 12, + "name": "格納チェストパスポート3", + "comment": "Storage Chest Passport 3", + "icon_path": "", + "description": "", + "url": "", + "target": 0, + "priority_grp": 100, + "priority_same_time": 90, + "announce_type": 2, + "effects": [ 217 ] + }, + { + "id": 13, + "name": "PP獲得量3倍コース", + "comment": "3x PP Acquisition Course", + "icon_path": "", + "description": "", + "url": "", + "target": 0, + "priority_grp": 100, + "priority_same_time": 24, + "announce_type": 3, + "effects": [ 219 ] + }, + { + "id": 14, + "name": "PP獲得量5倍コース", + "comment": "5x PP Acquisition Course", + "icon_path": "", + "description": "", + "url": "", + "target": 0, + "priority_grp": 100, + "priority_same_time": 23, + "announce_type": 3, + "effects": [ 229 ] + }, + { + "id": 15, + "name": "全コース無料開放", + "comment": "All courses free of charge", + "icon_path": "", + "description": "", + "url": "", + "target": 0, + "priority_grp": 20, + "priority_same_time": 0, + "announce_type": 3, + "effects": [ 1, 2, 3, 5, 6, 7, 9, 10, 11, 40, 41, 44, 50, 52, 128, 213, 215, 218, 253, 12, 13, 14, 15, 16, 17, 51, 59, 149, 18, 19, 20, 22, 23, 25, 26, 27, 70, 119, 150, 151, 208, 209, 210, 211, 212, 246, 254, 71, 72, 73, 74, 75, 69, 216, 217 ] + }, + { + "id": 16, + "name": "PP獲得量5倍コースⅡ", + "comment": "5x PP Acquisition Course II", + "icon_path": "", + "description": "", + "url": "", + "target": 0, + "priority_grp": 100, + "priority_same_time": 22, + "announce_type": 3, + "effects": [ 261, 262 ] + }, + { + "id": 17, + "name": "Arrowgene QOL Course", + "comment": "Example of custom made course effect.", + "icon_path": "", + "description": "Allows item boxes to be used outside the main city, enable expanded storage tabs and allows craft items to be consumed from the storage box.", + "url": "", + "target": 0, + "priority_grp": 100, + "priority_same_time": 70, + "announce_type": 2, + "effects": [ 2, 3, 69, 216, 217, 128 ] + } + ], + "effects": [ + { + "uid": 1, + "id": 1, + "param0": 0, + "param1": 0, + "comment": "GP_COURSE_EFFECT_INFINITE_REVIVE" + }, + { + "uid": 2, + "id": 2, + "param0": 0, + "param1": 0, + "comment": "GP_COURSE_EFFECT_STRAGE_EXTEND" + }, + { + "uid": 3, + "id": 3, + "param0": 0, + "param1": 0, + "comment": "GP_COURSE_EFFECT_EXTRA_STRAGE_BOX" + }, + { + "uid": 5, + "id": 5, + "param0": 100, + "param1": 0, + "comment": "GP_COURSE_EFFECT_FREE_MY_WARP_POINT" + }, + { + "uid": 6, + "id": 6, + "param0": 50, + "param1": 0, + "comment": "GP_COURSE_EFFECT_WARP_DISCOUNT" + }, + { + "uid": 7, + "id": 7, + "param0": 10, + "param1": 0, + "comment": "GP_COURSE_EFFECT_QUEST_ORDER_LIST_EXTEND" + }, + { + "uid": 9, + "id": 9, + "param0": 5, + "param1": 0, + "comment": "GP_COURSE_EFFECT_BAZAAR_EXHIBIT_EXTEND" + }, + { + "uid": 10, + "id": 10, + "param0": 86400, + "param1": 0, + "comment": "GP_COURSE_EFFECT_BAZAAR_RE_EXHIBIT_SHORTEN" + }, + { + "uid": 11, + "id": 11, + "param0": 200, + "param1": 0, + "comment": "GP_COURSE_EFFECT_AREA_MASTER_SUPPLY" + }, + { + "uid": 12, + "id": 12, + "param0": 200, + "param1": 0, + "comment": "GP_COURSE_EFFECT_WORLD_QUEST_REWARD_REALITY_UP" + }, + { + "uid": 13, + "id": 13, + "param0": 0, + "param1": 0, + "comment": "GP_COURSE_EFFECT_WORLD_QUEST_SPECIAL_REWARD" + }, + { + "uid": 14, + "id": 14, + "param0": 200, + "param1": 0, + "comment": "GP_COURSE_EFFECT_RIM_BQ_REWARD_UP" + }, + { + "uid": 15, + "id": 15, + "param0": 200, + "param1": 0, + "comment": "GP_COURSE_EFFECT_RIM_WQ_REWARD_UP" + }, + { + "uid": 16, + "id": 16, + "param0": 200, + "param1": 0, + "comment": "GP_COURSE_EFFECT_ENEMY_DROP_UP" + }, + { + "uid": 17, + "id": 17, + "param0": 200, + "param1": 0, + "comment": "GP_COURSE_EFFECT_GATHERING_ITEM_NUM_UP" + }, + { + "uid": 18, + "id": 18, + "param0": 200, + "param1": 0, + "comment": "GP_COURSE_EFFECT_ENEMY_EXP_UP" + }, + { + "uid": 19, + "id": 19, + "param0": 200, + "param1": 0, + "comment": "GP_COURSE_EFFECT_BQ_REWARD_EXP_UP" + }, + { + "uid": 20, + "id": 20, + "param0": 200, + "param1": 0, + "comment": "GP_COURSE_EFFECT_WQ_REWARD_EXP_UP" + }, + { + "uid": 22, + "id": 22, + "param0": 150, + "param1": 0, + "comment": "GP_COURSE_EFFECT_AREA_POINT_BQ_REWARD_UP" + }, + { + "uid": 23, + "id": 23, + "param0": 150, + "param1": 0, + "comment": "GP_COURSE_EFFECT_AREA_POINT_WQ_REWARD_UP" + }, + { + "uid": 25, + "id": 25, + "param0": 200, + "param1": 0, + "comment": "GP_COURSE_EFFECT_PAWN_ENEMY_EXP_UP" + }, + { + "uid": 26, + "id": 26, + "param0": 200, + "param1": 0, + "comment": "GP_COURSE_EFFECT_PAWN_BQ_REWARD_EXP_UP" + }, + { + "uid": 27, + "id": 27, + "param0": 200, + "param1": 0, + "comment": "GP_COURSE_EFFECT_PAWN_WQ_REWARD_EXP_UP" + }, + { + "uid": 40, + "id": 28, + "param0": 150, + "param1": 0, + "comment": "GP_COURSE_EFFECT_PAWN_CRAFT_EXP_UP" + }, + { + "uid": 41, + "id": 4, + "param0": 0, + "param1": 0, + "comment": "GP_COURSE_EFFECT_ALL_RELEASE_WARP_POINT" + }, + { + "uid": 44, + "id": 38, + "param0": 0, + "param1": 0, + "comment": "GP_COURSE_EFFECT_PAWN_REVIVE_BY_RIM" + }, + { + "uid": 49, + "id": 40, + "param0": 1500, + "param1": 0, + "comment": "GP_COURSE_EFFECT_REGULARLY_SEND_MAIL" + }, + { + "uid": 50, + "id": 34, + "param0": 50, + "param1": 0, + "comment": "GP_COURSE_EFFECT_PAWN_RESCUE_MOTION_SHORTEN" + }, + { + "uid": 51, + "id": 37, + "param0": 150, + "param1": 0, + "comment": "GP_COURSE_EFFECT_BLOOD_ORB_UP" + }, + { + "uid": 52, + "id": 35, + "param0": 100, + "param1": 0, + "comment": "GP_COURSE_EFFECT_STAY_DISCOUNT" + }, + { + "uid": 59, + "id": 41, + "param0": 200, + "param1": 0, + "comment": "GP_COURSE_EFFECT_EXM_REWARD_UP" + }, + { + "uid": 69, + "id": 42, + "param0": 0, + "param1": 0, + "comment": "GP_COURSE_EFFECT_BAGGAGE_RENTAL01" + }, + { + "uid": 70, + "id": 43, + "param0": 0, + "param1": 0, + "comment": "GP_COURSE_EFFECT_DISABLE_PARTY_ADJUST_ENEMY_EXP" + }, + { + "uid": 71, + "id": 44, + "param0": 50, + "param1": 0, + "comment": "GP_COURSE_EFFECT_INCOMING_DAMAGE_CUT_OFF" + }, + { + "uid": 72, + "id": 45, + "param0": 125, + "param1": 0, + "comment": "GP_COURSE_EFFECT_ENDURANCE_UP" + }, + { + "uid": 73, + "id": 46, + "param0": 50, + "param1": 0, + "comment": "GP_COURSE_EFFECT_DEBUFF_DAMAGE_CUT_OFF" + }, + { + "uid": 74, + "id": 47, + "param0": 66, + "param1": 200, + "comment": "GP_COURSE_EFFECT_ENABLE_LEVER_GACHA_ASSIST" + }, + { + "uid": 75, + "id": 48, + "param0": 350, + "param1": 0, + "comment": "GP_COURSE_EFFECT_PAWN_AUTO_RESCUE" + }, + { + "uid": 76, + "id": 18, + "param0": 500, + "param1": 0, + "comment": "GP_COURSE_EFFECT_ENEMY_EXP_UP" + }, + { + "uid": 77, + "id": 25, + "param0": 500, + "param1": 0, + "comment": "GP_COURSE_EFFECT_PAWN_ENEMY_EXP_UP" + }, + { + "uid": 78, + "id": 43, + "param0": 0, + "param1": 0, + "comment": "GP_COURSE_EFFECT_DISABLE_PARTY_ADJUST_ENEMY_EXP" + }, + { + "uid": 119, + "id": 49, + "param0": 200, + "param1": 0, + "comment": "GP_COURSE_EFFECT_ENEMY_PP_UP" + }, + { + "uid": 128, + "id": 50, + "param0": 0, + "param1": 0, + "comment": "GP_COURSE_EFFECT_CRAFT_BAGGAGE_EXTEND" + }, + { + "uid": 149, + "id": 51, + "param0": 200, + "param1": 0, + "comment": "" + }, + { + "uid": 150, + "id": 52, + "param0": 200, + "param1": 0, + "comment": "" + }, + { + "uid": 151, + "id": 53, + "param0": 200, + "param1": 0, + "comment": "" + }, + { + "uid": 189, + "id": 18, + "param0": 250, + "param1": 0, + "comment": "GP_COURSE_EFFECT_ENEMY_EXP_UP" + }, + { + "uid": 190, + "id": 19, + "param0": 250, + "param1": 0, + "comment": "GP_COURSE_EFFECT_PAWN_ENEMY_EXP_UP" + }, + { + "uid": 191, + "id": 20, + "param0": 250, + "param1": 0, + "comment": "GP_COURSE_EFFECT_WQ_REWARD_EXP_UP" + }, + { + "uid": 192, + "id": 52, + "param0": 250, + "param1": 0, + "comment": "" + }, + { + "uid": 193, + "id": 25, + "param0": 250, + "param1": 0, + "comment": "GP_COURSE_EFFECT_PAWN_ENEMY_EXP_UP" + }, + { + "uid": 194, + "id": 26, + "param0": 250, + "param1": 0, + "comment": "GP_COURSE_EFFECT_PAWN_BQ_REWARD_EXP_UP" + }, + { + "uid": 195, + "id": 27, + "param0": 250, + "param1": 0, + "comment": "GP_COURSE_EFFECT_PAWN_WQ_REWARD_EXP_UP" + }, + { + "uid": 196, + "id": 53, + "param0": 250, + "param1": 0, + "comment": "" + }, + { + "uid": 197, + "id": 18, + "param0": 300, + "param1": 0, + "comment": "GP_COURSE_EFFECT_ENEMY_EXP_UP" + }, + { + "uid": 198, + "id": 19, + "param0": 300, + "param1": 0, + "comment": "GP_COURSE_EFFECT_BQ_REWARD_EXP_UP" + }, + { + "uid": 199, + "id": 20, + "param0": 300, + "param1": 0, + "comment": "GP_COURSE_EFFECT_WQ_REWARD_EXP_UP" + }, + { + "uid": 200, + "id": 52, + "param0": 300, + "param1": 0, + "comment": "" + }, + { + "uid": 201, + "id": 25, + "param0": 300, + "param1": 0, + "comment": "GP_COURSE_EFFECT_PAWN_ENEMY_EXP_UP" + }, + { + "uid": 202, + "id": 26, + "param0": 300, + "param1": 0, + "comment": "GP_COURSE_EFFECT_PAWN_BQ_REWARD_EXP_UP" + }, + { + "uid": 203, + "id": 27, + "param0": 300, + "param1": 0, + "comment": "GP_COURSE_EFFECT_PAWN_BQ_REWARD_EXP_UP" + }, + { + "uid": 204, + "id": 53, + "param0": 300, + "param1": 0, + "comment": "" + }, + { + "uid": 208, + "id": 60, + "param0": 200, + "param1": 0, + "comment": "" + }, + { + "uid": 209, + "id": 61, + "param0": 200, + "param1": 0, + "comment": "" + }, + { + "uid": 210, + "id": 64, + "param0": 200, + "param1": 0, + "comment": "" + }, + { + "uid": 211, + "id": 65, + "param0": 200, + "param1": 0, + "comment": "" + }, + { + "uid": 212, + "id": 59, + "param0": 200, + "param1": 0, + "comment": "" + }, + { + "uid": 213, + "id": 63, + "param0": 0, + "param1": 0, + "comment": "" + }, + { + "uid": 215, + "id": 57, + "param0": 0, + "param1": 0, + "comment": "" + }, + { + "uid": 216, + "id": 54, + "param0": 0, + "param1": 0, + "comment": "" + }, + { + "uid": 217, + "id": 55, + "param0": 0, + "param1": 0, + "comment": "" + }, + { + "uid": 218, + "id": 62, + "param0": 0, + "param1": 0, + "comment": "" + }, + { + "uid": 219, + "id": 49, + "param0": 300, + "param1": 0, + "comment": "GP_COURSE_EFFECT_ENEMY_PP_UP" + }, + { + "uid": 229, + "id": 49, + "param0": 500, + "param1": 0, + "comment": "GP_COURSE_EFFECT_ENEMY_PP_UP" + }, + { + "uid": 246, + "id": 72, + "param0": 200, + "param1": 0, + "comment": "" + }, + { + "uid": 247, + "id": 49, + "param0": 300, + "param1": 0, + "comment": "GP_COURSE_EFFECT_ENEMY_PP_UP" + }, + { + "uid": 248, + "id": 49, + "param0": 250, + "param1": 0, + "comment": "GP_COURSE_EFFECT_ENEMY_PP_UP" + }, + { + "uid": 253, + "id": 58, + "param0": 0, + "param1": 0, + "comment": "" + }, + { + "uid": 254, + "id": 73, + "param0": 200, + "param1": 0, + "comment": "" + }, + { + "uid": 255, + "id": 73, + "param0": 250, + "param1": 0, + "comment": "" + }, + { + "uid": 256, + "id": 73, + "param0": 300, + "param1": 0, + "comment": "" + }, + { + "uid": 261, + "id": 49, + "param0": 500, + "param1": 0, + "comment": "GP_COURSE_EFFECT_ENEMY_PP_UP" + }, + { + "uid": 262, + "id": 73, + "param0": 500, + "param1": 0, + "comment": "" + }, + { + "uid": 264, + "id": 16, + "param0": 300, + "param1": 0, + "comment": "GP_COURSE_EFFECT_ENEMY_DROP_UP" + }, + { + "uid": 265, + "id": 17, + "param0": 300, + "param1": 0, + "comment": "GP_COURSE_EFFECT_GATHERING_ITEM_NUM_UP" + }, + { + "uid": 266, + "id": 37, + "param0": 250, + "param1": 0, + "comment": "GP_COURSE_EFFECT_BLOOD_ORB_UP" + }, + { + "uid": 267, + "id": 37, + "param0": 300, + "param1": 0, + "comment": "GP_COURSE_EFFECT_BLOOD_ORB_UP" + } + ] +} \ No newline at end of file diff --git a/Arrowgene.Ddon.Shared/Model/GPCourse.cs b/Arrowgene.Ddon.Shared/Model/GPCourse.cs new file mode 100644 index 000000000..8c93a8bb1 --- /dev/null +++ b/Arrowgene.Ddon.Shared/Model/GPCourse.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; + +namespace Arrowgene.Ddon.Shared.Model +{ + public class GPCourse + { + public GPCourse() + { + Effects = new List(); + } + + public uint Id { get; set; } + public string Name { get; set; } + public string Comment { get; set; } + public string Description { get; set; } + public string Url { get; set; } + public string IconPath { get; set; } + public bool Target { get; set; } + public uint PriorityGroup { get; set; } + public uint PrioritySameTime { get; set; } + public uint AnnounceType { get; set; } + public List Effects { get; set; } + } +} diff --git a/Arrowgene.Ddon.Shared/Model/GPCourseEffect.cs b/Arrowgene.Ddon.Shared/Model/GPCourseEffect.cs new file mode 100644 index 000000000..c7037ff2c --- /dev/null +++ b/Arrowgene.Ddon.Shared/Model/GPCourseEffect.cs @@ -0,0 +1,15 @@ +namespace Arrowgene.Ddon.Shared.Model +{ + public class GpCourseEffect + { + public GpCourseEffect() + { + } + + public uint Uid { get; set; } + public uint Id { get; set; } + public uint Param0 { get; set; } + public uint Param1 { get; set; } + public string Comment { get; set; } + } +} diff --git a/Arrowgene.Ddon.Shared/Model/GPValidCourse.cs b/Arrowgene.Ddon.Shared/Model/GPValidCourse.cs new file mode 100644 index 000000000..208f34c46 --- /dev/null +++ b/Arrowgene.Ddon.Shared/Model/GPValidCourse.cs @@ -0,0 +1,14 @@ +namespace Arrowgene.Ddon.Shared.Model +{ + public class GPValidCourse + { + public GPValidCourse() + { + } + + public uint Id { get; set; } + public ulong StartTime { get; set; } + public ulong EndTime { get; set; } + public string Comment { get; set; } + } +} diff --git a/Arrowgene.Ddon.Shared/Network/PacketId.cs b/Arrowgene.Ddon.Shared/Network/PacketId.cs index bb58e35bb..3f9f09866 100644 --- a/Arrowgene.Ddon.Shared/Network/PacketId.cs +++ b/Arrowgene.Ddon.Shared/Network/PacketId.cs @@ -50,7 +50,7 @@ public static PacketId GetPacketId(string name) return PacketId.UNKNOWN; } - + public static PacketId GetLoginPacketId(byte groupId, ushort handlerId, byte handlerSubId) { int hashCode = GetHashCode(groupId, handlerId, handlerSubId); @@ -72,7 +72,7 @@ public static PacketId GetGamePacketId(byte groupId, ushort handlerId, byte hand return new PacketId(groupId, handlerId, handlerSubId, "Unknown", ServerType.Game, PacketSource.Unknown); } - + public readonly byte GroupId; public readonly ushort HandlerId; public readonly byte HandlerSubId; @@ -130,13 +130,13 @@ public override int GetHashCode() { return GetHashCode(GroupId, HandlerId, HandlerSubId); } - - public static bool operator ==(PacketId a, PacketId b) + + public static bool operator ==(PacketId a, PacketId b) { return a.Equals(b); } - public static bool operator !=(PacketId a, PacketId b) + public static bool operator !=(PacketId a, PacketId b) { return !a.Equals(b); } @@ -1262,7 +1262,7 @@ private static Dictionary InitializeLoginPacketIds() public static readonly PacketId C2S_GP_GP_SHOP_CAN_BUY_REQ = new PacketId(28, 23, 1, "C2S_GP_GP_SHOP_CAN_BUY_REQ", ServerType.Game, PacketSource.Client); public static readonly PacketId S2C_GP_GP_SHOP_CAN_BUY_RES = new PacketId(28, 23, 2, "S2C_GP_GP_SHOP_CAN_BUY_RES", ServerType.Game, PacketSource.Server); // 課金商品購入可能状態の取得に public static readonly PacketId S2C_GP_28_24_16_NTC = new PacketId(28, 24, 16, "S2C_GP_28_24_16_NTC", ServerType.Game, PacketSource.Server); - public static readonly PacketId S2C_GP_28_25_16_NTC = new PacketId(28, 25, 16, "S2C_GP_28_25_16_NTC", ServerType.Game, PacketSource.Server); + public static readonly PacketId S2C_GP_COURSE_START_NTC = new PacketId(28, 25, 16, "S2C_GP_COURSE_START_NTC", ServerType.Game, PacketSource.Server); // S2C_GP_28_25_16_NTC public static readonly PacketId S2C_GP_28_26_16_NTC = new PacketId(28, 26, 16, "S2C_GP_28_26_16_NTC", ServerType.Game, PacketSource.Server); public static readonly PacketId S2C_GP_28_27_16_NTC = new PacketId(28, 27, 16, "S2C_GP_28_27_16_NTC", ServerType.Game, PacketSource.Server); public static readonly PacketId S2C_GP_28_28_16_NTC = new PacketId(28, 28, 16, "S2C_GP_28_28_16_NTC", ServerType.Game, PacketSource.Server); @@ -3168,7 +3168,7 @@ private static Dictionary InitializeGamePacketIds() AddPacketIdEntry(packetIds, C2S_GP_GP_SHOP_CAN_BUY_REQ); AddPacketIdEntry(packetIds, S2C_GP_GP_SHOP_CAN_BUY_RES); AddPacketIdEntry(packetIds, S2C_GP_28_24_16_NTC); - AddPacketIdEntry(packetIds, S2C_GP_28_25_16_NTC); + AddPacketIdEntry(packetIds, S2C_GP_COURSE_START_NTC); AddPacketIdEntry(packetIds, S2C_GP_28_26_16_NTC); AddPacketIdEntry(packetIds, S2C_GP_28_27_16_NTC); AddPacketIdEntry(packetIds, S2C_GP_28_28_16_NTC); @@ -4042,7 +4042,7 @@ private static Dictionary InitializeGamePacketIds() } #endregion - + // initialize at the very end private static readonly Dictionary LoginPacketIds = InitializeLoginPacketIds(); private static readonly Dictionary GamePacketIds = InitializeGamePacketIds();