From e006ae1419149e9d9bc91dcfcb1ae64612c6cc00 Mon Sep 17 00:00:00 2001 From: alborrajo Date: Sun, 16 Jun 2024 01:31:32 +0200 Subject: [PATCH 01/10] Set EquipCharacterID and EquipPawnID fields in CDataItemList --- .../Handler/ItemGetStorageItemListHandler.cs | 3 +- .../Model/CharacterCommon.cs | 2 +- Arrowgene.Ddon.Shared/Model/Equipment.cs | 3 +- Arrowgene.Ddon.Shared/Model/Storages.cs | 35 ++++++++++++++++--- 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/Arrowgene.Ddon.GameServer/Handler/ItemGetStorageItemListHandler.cs b/Arrowgene.Ddon.GameServer/Handler/ItemGetStorageItemListHandler.cs index 8678e712..7d92cfd4 100644 --- a/Arrowgene.Ddon.GameServer/Handler/ItemGetStorageItemListHandler.cs +++ b/Arrowgene.Ddon.GameServer/Handler/ItemGetStorageItemListHandler.cs @@ -1,6 +1,7 @@ using System.Linq; using Arrowgene.Ddon.Server; using Arrowgene.Ddon.Shared.Entity.PacketStructure; +using Arrowgene.Ddon.Shared.Entity.Structure; using Arrowgene.Ddon.Shared.Model; using Arrowgene.Ddon.Shared.Network; using Arrowgene.Logging; @@ -21,7 +22,7 @@ public override void Handle(GameClient client, StructurePacket client.Character.Storage.getStorageAsCDataItemList((StorageType) cDataCommonU8.Value)) + .SelectMany(cDataCommonU8 => client.Character.Storage.getStorageAsCDataItemList(client.Character, (StorageType) cDataCommonU8.Value)) .ToList() }; client.Send(res); diff --git a/Arrowgene.Ddon.Shared/Model/CharacterCommon.cs b/Arrowgene.Ddon.Shared/Model/CharacterCommon.cs index 921baa73..10e75f00 100644 --- a/Arrowgene.Ddon.Shared/Model/CharacterCommon.cs +++ b/Arrowgene.Ddon.Shared/Model/CharacterCommon.cs @@ -1,7 +1,6 @@ #nullable enable using System.Collections.Generic; using System.Linq; -using Arrowgene.Ddon.Shared.Entity.PacketStructure; using Arrowgene.Ddon.Shared.Entity.Structure; namespace Arrowgene.Ddon.Shared.Model @@ -27,6 +26,7 @@ public CharacterCommon() .Select(jobId => (jobId, Enumerable.Repeat(null, 10).ToList())) .ToDictionary(pair => pair.jobId, pair => pair.Item2); OnlineStatus = OnlineStatus.Offline; + ExtendedParams = new CDataOrbGainExtendParam(); } public CDataCharacterJobData? ActiveCharacterJobData diff --git a/Arrowgene.Ddon.Shared/Model/Equipment.cs b/Arrowgene.Ddon.Shared/Model/Equipment.cs index 5e3f7f64..ef4c145b 100644 --- a/Arrowgene.Ddon.Shared/Model/Equipment.cs +++ b/Arrowgene.Ddon.Shared/Model/Equipment.cs @@ -8,7 +8,7 @@ namespace Arrowgene.Ddon.Shared.Model #nullable enable public class Equipment { - private static readonly byte EQUIP_SLOT_NUMBER = 15; + public static readonly byte EQUIP_SLOT_NUMBER = 15; private static readonly byte JOB_ITEM_SLOT_NUMBER = 2; // TODO: Verify private readonly Dictionary>> equipment; @@ -130,7 +130,6 @@ public List getEquipmentAsCDataCharacterEquipInfo(JobId .ToList(); } - public List getJobItemsAsCDataEquipJobItem(JobId job) { return GetJobItems(job) diff --git a/Arrowgene.Ddon.Shared/Model/Storages.cs b/Arrowgene.Ddon.Shared/Model/Storages.cs index 5a0e6a4e..6740b5bb 100644 --- a/Arrowgene.Ddon.Shared/Model/Storages.cs +++ b/Arrowgene.Ddon.Shared/Model/Storages.cs @@ -46,7 +46,7 @@ public void addStorage(StorageType storageType, Storage storage) storages[storageType] = storage; } - public List getStorageAsCDataItemList(StorageType storageType) + public List getStorageAsCDataItemList(Character character, StorageType storageType) { return getStorage(storageType).Items .Select((item, index) => new {item = item, slot = (ushort) (index+1)}) @@ -63,8 +63,8 @@ public List getStorageAsCDataItemList(StorageType storageType) PlusValue = tuple.item.Item1.PlusValue, Bind = true, EquipPoint = 0, - EquipCharacterID = 0, - EquipPawnID = 0, + EquipCharacterID = determineCharacterId(character, storageType, tuple.slot), + EquipPawnID = determinePawnId(character, storageType, tuple.slot), WeaponCrestDataList = tuple.item.Item1.WeaponCrestDataList, ArmorCrestDataList = tuple.item.Item1.ArmorCrestDataList, EquipElementParamList = tuple.item.Item1.EquipElementParamList @@ -99,6 +99,31 @@ public List getStorageAsCDataItemList(StorageType storageType) : new Tuple(newItem, itemCount); return oldItem; } + + private uint determineCharacterId(Character character, StorageType storageType, ushort slot) + { + if(storageType == StorageType.CharacterEquipment) + { + return character.CharacterId; + } + else + { + return 0; + } + } + + private uint determinePawnId(Character character, StorageType storageType, ushort slot) + { + if(storageType == StorageType.PawnEquipment) + { + int pawnIndex = slot / (Equipment.EQUIP_SLOT_NUMBER * 2); + return character.Pawns[pawnIndex].PawnId; + } + else + { + return 0; + } + } } public class Storage @@ -148,8 +173,8 @@ public enum StorageType : byte Unk11 = 0xB, Unk12 = 0xC, Unk13 = 0xD, - Unk14 = 0xE, - Unk15 = 0xF, + CharacterEquipment = 0xE, + PawnEquipment = 0xF, Unk16 = 0x10, Unk17 = 0x11, } From ff6238f4921760a23e3eccf61648981ee7bc1efe Mon Sep 17 00:00:00 2001 From: alborrajo Date: Sun, 16 Jun 2024 01:32:42 +0200 Subject: [PATCH 02/10] Add current job equipped items to CharacterEquipment and PawnEquipment storage types on creation --- .../Handler/CreateCharacterHandler.cs | 58 ++++++++++++++----- .../Files/Assets/Storage.csv | 4 +- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/Arrowgene.Ddon.LoginServer/Handler/CreateCharacterHandler.cs b/Arrowgene.Ddon.LoginServer/Handler/CreateCharacterHandler.cs index c857371a..92caf852 100644 --- a/Arrowgene.Ddon.LoginServer/Handler/CreateCharacterHandler.cs +++ b/Arrowgene.Ddon.LoginServer/Handler/CreateCharacterHandler.cs @@ -1131,6 +1131,51 @@ public override void Handle(LoginClient client, StructurePacket performanceEquipItems = character.Equipment.GetEquipment(character.Job, EquipType.Performance); + for (int i = 0; i < performanceEquipItems.Count; i++) + { + Item? item = performanceEquipItems[i]; + ushort slot = (ushort)(i+1); + character.Storage.setStorageItem(item, 1, StorageType.CharacterEquipment, slot); + } + + List visualEquipItems = character.Equipment.GetEquipment(character.Job, EquipType.Visual); + for (int i = 0; i < visualEquipItems.Count; i++) + { + Item? item = visualEquipItems[i]; + ushort slot = (ushort)(i+Equipment.EQUIP_SLOT_NUMBER+1); + character.Storage.setStorageItem(item, 1, StorageType.CharacterEquipment, slot); + } + + // Pawns + for (int i = 0; i < Server.AssetRepository.MyPawnAsset.Count; i++) + { + MyPawnCsv myPawnCsvData = Server.AssetRepository.MyPawnAsset[i]; + Pawn pawn = LoadDefaultPawn(character, myPawnCsvData); + Database.CreatePawn(pawn); + Database.InsertGainExtendParam(pawn.CommonId, new CDataOrbGainExtendParam()); + + // Add pawn's current job equipment to storage + int pawnSlotOffset = i * Equipment.EQUIP_SLOT_NUMBER * 2; + + List pawnPerformanceEquipItems = character.Equipment.GetEquipment(character.Job, EquipType.Performance); + for (int j = 0; j < pawnPerformanceEquipItems.Count; j++) + { + Item? item = pawnPerformanceEquipItems[j]; + ushort slot = (ushort)(pawnSlotOffset+j+1); + character.Storage.setStorageItem(item, 1, StorageType.PawnEquipment, slot); + } + + List pawnVisualEquipItems = character.Equipment.GetEquipment(character.Job, EquipType.Visual); + for (int j = 0; j < pawnVisualEquipItems.Count; j++) + { + Item? item = pawnVisualEquipItems[j]; + ushort slot = (ushort)(pawnSlotOffset+j+Equipment.EQUIP_SLOT_NUMBER+1); + character.Storage.setStorageItem(item, 1, StorageType.PawnEquipment, slot); + } + } + L2CCreateCharacterDataRes res = new L2CCreateCharacterDataRes(); if (!Database.CreateCharacter(character)) { @@ -1154,14 +1199,6 @@ public override void Handle(LoginClient client, StructurePacket LoadDefaultPawn(character, myPawnCsvData)).ToList(); - } - private Pawn LoadDefaultPawn(Character character, MyPawnCsv myPawnCsvData) { S2CContextGetPartyMypawnContextNtc pcapPawn = EntitySerializer.Get().Read(data_Dump_Pawn35_3_16); // TODO: Replace pcap data diff --git a/Arrowgene.Ddon.Shared/Files/Assets/Storage.csv b/Arrowgene.Ddon.Shared/Files/Assets/Storage.csv index 8c6d782d..eebcf3c9 100644 --- a/Arrowgene.Ddon.Shared/Files/Assets/Storage.csv +++ b/Arrowgene.Ddon.Shared/Files/Assets/Storage.csv @@ -17,7 +17,7 @@ 11, 0 12, 800 13, 400 -14, 0 -15, 0 +14, 30 +15, 90 16, 0 17, 0 \ No newline at end of file From 91cb836ad2c656d76185d85da02b756093bda67b Mon Sep 17 00:00:00 2001 From: alborrajo Date: Sun, 16 Jun 2024 01:34:13 +0200 Subject: [PATCH 03/10] Sync CharacterEquipment and PawnEquipment storage types with the equipped items --- Arrowgene.Ddon.Database/IDatabase.cs | 2 +- .../Sql/Core/DdonSqlDbEquipItem.cs | 16 +- .../Characters/EquipManager.cs | 224 +++--------------- 3 files changed, 39 insertions(+), 203 deletions(-) diff --git a/Arrowgene.Ddon.Database/IDatabase.cs b/Arrowgene.Ddon.Database/IDatabase.cs index 16d9929c..690abc77 100644 --- a/Arrowgene.Ddon.Database/IDatabase.cs +++ b/Arrowgene.Ddon.Database/IDatabase.cs @@ -92,7 +92,7 @@ public interface IDatabase bool InsertEquipItem(uint commonId, JobId job, EquipType equipType, byte equipSlot, string itemUId); bool ReplaceEquipItem(uint commonId, JobId job, EquipType equipType, byte equipSlot, string itemUId); bool UpdateEquipItem(uint commonId, JobId job, EquipType equipType, byte equipSlot, string itemUId); - bool DeleteEquipItem(uint commonId, JobId job, EquipType equipType, byte equipSlot, string itemUId); + bool DeleteEquipItem(uint commonId, JobId job, EquipType equipType, byte equipSlot); // Job Items bool InsertEquipJobItem(string itemUId, uint commonId, JobId job, ushort slotNo); diff --git a/Arrowgene.Ddon.Database/Sql/Core/DdonSqlDbEquipItem.cs b/Arrowgene.Ddon.Database/Sql/Core/DdonSqlDbEquipItem.cs index e6442357..f318a508 100644 --- a/Arrowgene.Ddon.Database/Sql/Core/DdonSqlDbEquipItem.cs +++ b/Arrowgene.Ddon.Database/Sql/Core/DdonSqlDbEquipItem.cs @@ -1,5 +1,4 @@ using System.Data.Common; -using Arrowgene.Ddon.Shared.Entity.Structure; using Arrowgene.Ddon.Shared.Model; namespace Arrowgene.Ddon.Database.Sql.Core @@ -18,7 +17,7 @@ public abstract partial class DdonSqlDb : SqlDb { - AddParameter(command, commonId, job, equipType, equipSlot, itemUId); + AddParameter(command, commonId, job, equipType, equipSlot); }) == 1; } - private void AddParameter(TCom command, uint commonId, JobId job, EquipType equipType, byte equipSlot, string itemUId) + private void AddParameter(TCom command, uint commonId, JobId job, EquipType equipType, byte equipSlot) { - AddParameter(command, "item_uid", itemUId); AddParameter(command, "character_common_id", commonId); AddParameter(command, "job", (byte) job); AddParameter(command, "equip_type", (byte) equipType); AddParameter(command, "equip_slot", equipSlot); } + + private void AddParameter(TCom command, uint commonId, JobId job, EquipType equipType, byte equipSlot, string itemUId) + { + AddParameter(command, "item_uid", itemUId); + AddParameter(command, commonId, job, equipType, equipSlot); + } } } diff --git a/Arrowgene.Ddon.GameServer/Characters/EquipManager.cs b/Arrowgene.Ddon.GameServer/Characters/EquipManager.cs index 525c9e29..b74da436 100644 --- a/Arrowgene.Ddon.GameServer/Characters/EquipManager.cs +++ b/Arrowgene.Ddon.GameServer/Characters/EquipManager.cs @@ -79,17 +79,27 @@ public void HandleChangeEquipList(DdonGameServer server, GameClient client, Char string itemUId = changeCharacterEquipInfo.EquipItemUId; EquipType equipType = (EquipType) changeCharacterEquipInfo.EquipType; byte equipSlot = changeCharacterEquipInfo.EquipCategory; + ushort storageSlot = equipSlot; + + if(equipType == EquipType.Visual) + { + storageSlot += Equipment.EQUIP_SLOT_NUMBER; + } uint characterId, pawnId; + StorageType equipmentStorageType; if(characterToEquipTo is Character character1) { characterId = character1.CharacterId; pawnId = 0; + equipmentStorageType = StorageType.CharacterEquipment; } else if(characterToEquipTo is Pawn pawn) { characterId = pawn.CharacterId; pawnId = pawn.PawnId; + equipmentStorageType = StorageType.PawnEquipment; + storageSlot = (ushort)(storageSlot + client.Character.Pawns.IndexOf(pawn)*Equipment.EQUIP_SLOT_NUMBER*2); } else { @@ -98,11 +108,26 @@ public void HandleChangeEquipList(DdonGameServer server, GameClient client, Char if(itemUId.Length == 0) { - this.UnequipItem(server, client, characterToEquipTo, updateCharacterItemNtc, equipType, equipSlot, storageTypes, characterId, pawnId); + // Unequip + // TODO: Move to the other storage types if the first one is full + StorageType destinationStorageType = storageTypes[0]; + Item? equippedItem = characterToEquipTo.Equipment.SetEquipItem(null, characterToEquipTo.Job, equipType, equipSlot); + if(equippedItem == null) + { + throw new ResponseErrorException(ErrorCode.ERROR_CODE_ITEM_NOT_FOUND); + } + server.Database.DeleteEquipItem(characterToEquipTo.CommonId, characterToEquipTo.Job, equipType, equipSlot); + // Update storage + updateCharacterItemNtc.UpdateItemList.AddRange(server.ItemManager.MoveItem(server, client.Character, equipmentStorageType, equippedItem.UId, 1, destinationStorageType, 0)); } else { - this.EquipItem(server, client, characterToEquipTo, updateCharacterItemNtc, equipType, equipSlot, storageTypes, itemUId, characterId, pawnId); + // Equip + StorageType sourceStorageType = storageTypes[0]; + characterToEquipTo.Equipment.SetEquipItem(server.Database.SelectItem(itemUId), characterToEquipTo.Job, equipType, equipSlot); + server.Database.ReplaceEquipItem(characterToEquipTo.CommonId, characterToEquipTo.Job, equipType, equipSlot, itemUId); + // Update storage + updateCharacterItemNtc.UpdateItemList.AddRange(server.ItemManager.MoveItem(server, client.Character, sourceStorageType, itemUId, 1, equipmentStorageType, storageSlot)); } } @@ -142,199 +167,6 @@ public void HandleChangeEquipList(DdonGameServer server, GameClient client, Char } client.Send(updateCharacterItemNtc); - } - - private void UnequipItem(DdonGameServer server, GameClient client, CharacterCommon characterToEquipTo, S2CItemUpdateCharacterItemNtc updateCharacterItemNtc, EquipType equipType, byte equipSlot, List storageTypes, uint characterId, uint pawnId) - { - // TODO: Move to the other storage types if the first one is full - StorageType storageType = storageTypes[0]; - - // Find in equipment the item to unequip - Item item = characterToEquipTo.Equipment.GetEquipItem(characterToEquipTo.Job, equipType, equipSlot) ?? throw new Exception("No item found in this slot"); - - characterToEquipTo.Equipment.SetEquipItem(null, characterToEquipTo.Job, equipType, equipSlot); - server.Database.DeleteEquipItem(characterToEquipTo.CommonId, characterToEquipTo.Job, equipType, equipSlot, item.UId); - - ushort dstSlotNo = client.Character.Storage.addStorageItem(item, 1, storageType); - server.Database.InsertStorageItem(client.Character.CharacterId, storageType, dstSlotNo, item.UId, 1); - - updateCharacterItemNtc.UpdateItemList.Add(new CDataItemUpdateResult() { - UpdateItemNum = 0, - ItemList = new CDataItemList() { - ItemUId = item.UId, - ItemId = item.ItemId, - ItemNum = 0, - Unk3 = item.Unk3, - StorageType = StorageType.Unk14, - SlotNo = 1, - Color = item.Color, - PlusValue = item.PlusValue, - Bind = true, - EquipPoint = 0, - EquipCharacterID = characterId, - EquipPawnID = pawnId, - WeaponCrestDataList = item.WeaponCrestDataList, - ArmorCrestDataList = item.ArmorCrestDataList, - EquipElementParamList = item.EquipElementParamList - } - }); - updateCharacterItemNtc.UpdateItemList.Add(new CDataItemUpdateResult() { - UpdateItemNum = 1, - ItemList = new CDataItemList() { - ItemUId = item.UId, - ItemId = item.ItemId, - ItemNum = 1, - Unk3 = item.Unk3, - StorageType = storageType, - SlotNo = dstSlotNo, - Color = item.Color, - PlusValue = item.PlusValue, - Bind = true, - EquipPoint = 0, - EquipCharacterID = 0, - EquipPawnID = 0, - WeaponCrestDataList = item.WeaponCrestDataList, - ArmorCrestDataList = item.ArmorCrestDataList, - EquipElementParamList = item.EquipElementParamList - } - }); - } - - private void EquipItem(DdonGameServer server, GameClient client, CharacterCommon characterToEquipTo, S2CItemUpdateCharacterItemNtc updateCharacterItemNtc, EquipType equipType, byte equipSlot, List storageTypes, string itemUId, uint characterId, uint pawnId) - { - Item? previouslyEquippedItem = characterToEquipTo.Equipment.GetEquipItem(characterToEquipTo.Job, equipType, equipSlot); - if (previouslyEquippedItem?.UId == itemUId) - { - // Don't do anything - return; - } - - // Find in the storages the item to equip - Item? itemToEquip = null; - uint itemToEquipNum = 0; - ushort storageSlotNo = 0; - StorageType storageType = 0; - foreach (StorageType storageTypeToCheck in storageTypes) - { - try - { - var tuple = client.Character.Storage.getStorage(storageTypeToCheck).Items - .Select((item, index) => new { item, slot = (ushort) (index+1)}) - .Where(tuple => tuple.item?.Item1.UId == itemUId) - .First(); - itemToEquip = tuple.item!.Item1; - itemToEquipNum = tuple.item.Item2; - storageSlotNo = tuple.slot; - storageType = storageTypeToCheck; - break; - } - catch(InvalidOperationException) - { - // Do nothing, continue and try other storage - } - } - - if (itemToEquip == null) - { - throw new ResponseErrorException(ErrorCode.ERROR_CODE_ITEM_NOT_FOUND, "Couldn't find the item to equip"); - } - - characterToEquipTo.Equipment.SetEquipItem(itemToEquip, characterToEquipTo.Job, equipType, equipSlot); - - server.Database.ReplaceEquipItem(characterToEquipTo.CommonId, characterToEquipTo.Job, equipType, equipSlot, itemToEquip.UId); - - if(previouslyEquippedItem != null) - { - // When equipping over an already equipped slot, move item in that slot to storage - client.Character.Storage.setStorageItem(previouslyEquippedItem, 1, storageType, storageSlotNo); - server.Database.ReplaceStorageItem(client.Character.CharacterId, storageType, storageSlotNo, previouslyEquippedItem.UId, 1); - updateCharacterItemNtc.UpdateItemList.Add(new CDataItemUpdateResult() { - UpdateItemNum = 0, - ItemList = new CDataItemList() { - ItemUId = previouslyEquippedItem.UId, - ItemId = previouslyEquippedItem.ItemId, - ItemNum = 0, - Unk3 = previouslyEquippedItem.Unk3, - StorageType = StorageType.Unk14, - SlotNo = 1, - Color = previouslyEquippedItem.Color, - PlusValue = previouslyEquippedItem.PlusValue, - Bind = true, - EquipPoint = 0, - EquipCharacterID = characterId, - EquipPawnID = pawnId, - WeaponCrestDataList = previouslyEquippedItem.WeaponCrestDataList, - ArmorCrestDataList = previouslyEquippedItem.ArmorCrestDataList, - EquipElementParamList = previouslyEquippedItem.EquipElementParamList - } - }); - updateCharacterItemNtc.UpdateItemList.Add(new CDataItemUpdateResult() { - UpdateItemNum = 1, - ItemList = new CDataItemList() { - ItemUId = previouslyEquippedItem.UId, - ItemId = previouslyEquippedItem.ItemId, - ItemNum = 1, - Unk3 = previouslyEquippedItem.Unk3, - StorageType = storageType, - SlotNo = storageSlotNo, - Color = previouslyEquippedItem.Color, - PlusValue = previouslyEquippedItem.PlusValue, - Bind = true, - EquipPoint = 0, - EquipCharacterID = 0, - EquipPawnID = 0, - WeaponCrestDataList = previouslyEquippedItem.WeaponCrestDataList, - ArmorCrestDataList = previouslyEquippedItem.ArmorCrestDataList, - EquipElementParamList = previouslyEquippedItem.EquipElementParamList - } - }); - } - else - { - client.Character.Storage.setStorageItem(null, 0, storageType, storageSlotNo); - server.Database.DeleteStorageItem(client.Character.CharacterId, storageType, storageSlotNo); - } - - updateCharacterItemNtc.UpdateItemList.Add(new CDataItemUpdateResult() { - UpdateItemNum = 0, // TODO: ? - ItemList = new CDataItemList() { - ItemUId = itemToEquip.UId, - ItemId = itemToEquip.ItemId, - ItemNum = 0, - Unk3 = itemToEquip.Unk3, - StorageType = storageType, - SlotNo = storageSlotNo, - Color = itemToEquip.Color, - PlusValue = itemToEquip.PlusValue, - Bind = true, - EquipPoint = 0, - EquipCharacterID = characterId, - EquipPawnID = pawnId, - WeaponCrestDataList = itemToEquip.WeaponCrestDataList, - ArmorCrestDataList = itemToEquip.ArmorCrestDataList, - EquipElementParamList = itemToEquip.EquipElementParamList - } - }); - updateCharacterItemNtc.UpdateItemList.Add(new CDataItemUpdateResult() { - UpdateItemNum = 1, - ItemList = new CDataItemList() { - ItemUId = itemToEquip.UId, - ItemId = itemToEquip.ItemId, - ItemNum = 1, - Unk3 = itemToEquip.Unk3, - StorageType = StorageType.Unk14, - SlotNo = 1, - Color = itemToEquip.Color, - PlusValue = itemToEquip.PlusValue, - Bind = true, - EquipPoint = 0, - EquipCharacterID = characterId, - EquipPawnID = pawnId, - WeaponCrestDataList = itemToEquip.WeaponCrestDataList, - ArmorCrestDataList = itemToEquip.ArmorCrestDataList, - EquipElementParamList = itemToEquip.EquipElementParamList - } - }); - } + } } } From 56a092043e0101660f4a978a0ce8b3af06ac3f38 Mon Sep 17 00:00:00 2001 From: alborrajo Date: Sun, 16 Jun 2024 01:36:20 +0200 Subject: [PATCH 04/10] Swap CharacterEquipment/PawnEquipment items with storage items when switching jobs Makes it so it behaves like in the original server. Equipped items go into the storage when switching jobs. Items previously equipped to the job being switched to will be taken from the storage too --- .../Characters/JobManager.cs | 123 +++++++++++++++--- .../Chat/Command/Commands/JobCommand.cs | 2 +- Arrowgene.Ddon.GameServer/DdonGameServer.cs | 2 +- .../Handler/JobChangeJobHandler.cs | 3 +- .../Handler/JobChangePawnJobHandler.cs | 2 +- 5 files changed, 106 insertions(+), 26 deletions(-) diff --git a/Arrowgene.Ddon.GameServer/Characters/JobManager.cs b/Arrowgene.Ddon.GameServer/Characters/JobManager.cs index 239c6461..5a69f543 100644 --- a/Arrowgene.Ddon.GameServer/Characters/JobManager.cs +++ b/Arrowgene.Ddon.GameServer/Characters/JobManager.cs @@ -1,16 +1,13 @@ using System; using System.Collections.Generic; -using System.ComponentModel.Design; using System.Linq; using Arrowgene.Ddon.Database; -using Arrowgene.Ddon.Database.Model; using Arrowgene.Ddon.GameServer.Handler; using Arrowgene.Ddon.Server; using Arrowgene.Ddon.Shared; using Arrowgene.Ddon.Shared.Entity.PacketStructure; using Arrowgene.Ddon.Shared.Entity.Structure; using Arrowgene.Ddon.Shared.Model; -using Arrowgene.Ddon.Shared.Model.Quest; using Arrowgene.Logging; namespace Arrowgene.Ddon.GameServer.Characters @@ -18,18 +15,44 @@ namespace Arrowgene.Ddon.GameServer.Characters public class JobManager { private static readonly ServerLogger Logger = LogProvider.Logger(typeof(JobManager)); - private readonly IDatabase _Database; + private readonly DdonGameServer _Server; - public JobManager(IDatabase database) + public JobManager(DdonGameServer server) { - _Database = database; + _Server = server; } - public void SetJob(DdonServer server, GameClient client, CharacterCommon common, JobId jobId) + public void SetJob(GameClient client, CharacterCommon common, JobId jobId) { + // TODO: Reject job change if there's no primary and secondary weapon for the new job in storage + + JobId oldJobId = common.Job; common.Job = jobId; - server.Database.UpdateCharacterCommonBaseInfo(common); + // Swap equipment + int pawnIdx; + StorageType equipmentStorageType; + S2CItemUpdateCharacterItemNtc updateCharacterItemNtc = new S2CItemUpdateCharacterItemNtc(); + if (common is Character) + { + pawnIdx = 0; + equipmentStorageType = StorageType.CharacterEquipment; + updateCharacterItemNtc.UpdateType = 0x28; + } + else if (common is Pawn) + { + Pawn pawn = (Pawn)common; + pawnIdx = client.Character.Pawns.IndexOf(pawn); + equipmentStorageType = StorageType.PawnEquipment; + updateCharacterItemNtc.UpdateType = 0x29; + } + else + { + throw new Exception("Unknown character type"); + } + updateCharacterItemNtc.UpdateItemList.AddRange(SwapEquipmentAndStorage(client, common, pawnIdx, equipmentStorageType, oldJobId, jobId, EquipType.Performance)); + updateCharacterItemNtc.UpdateItemList.AddRange(SwapEquipmentAndStorage(client, common, pawnIdx, equipmentStorageType, oldJobId, jobId, EquipType.Visual)); + client.Send(updateCharacterItemNtc); CDataCharacterJobData? activeCharacterJobData = common.ActiveCharacterJobData; @@ -42,7 +65,7 @@ public void SetJob(DdonServer server, GameClient client, CharacterCo activeCharacterJobData.Lv = 1; // TODO: All the other stats common.CharacterJobDataList.Add(activeCharacterJobData); - server.Database.ReplaceCharacterJobData(common.CommonId, activeCharacterJobData); + _Server.Database.ReplaceCharacterJobData(common.CommonId, activeCharacterJobData); } // TODO: Figure out if it should send all equips or just the ones for the current job @@ -67,9 +90,6 @@ public void SetJob(DdonServer server, GameClient client, CharacterCo .ToList(); List jobItems = common.Equipment.getJobItemsAsCDataEquipJobItem(common.Job); - S2CItemUpdateCharacterItemNtc updateCharacterItemNtc = new S2CItemUpdateCharacterItemNtc(); - // TODO: Move previous job equipment to storage box, and move new job equipment from storage box - if (common is Character) { Character character = (Character)common; @@ -84,14 +104,11 @@ public void SetJob(DdonServer server, GameClient client, CharacterCo changeJobNotice.EquipJobItemList = jobItems; // TODO: Unk0 - foreach (GameClient otherClient in server.ClientLookup.GetAll()) + foreach (GameClient otherClient in _Server.ClientLookup.GetAll()) { otherClient.Send(changeJobNotice); } - updateCharacterItemNtc.UpdateType = 0x28; - client.Send(updateCharacterItemNtc); - S2CJobChangeJobRes changeJobResponse = new S2CJobChangeJobRes(); changeJobResponse.CharacterJobData = activeCharacterJobData; changeJobResponse.CharacterEquipList = characterEquipList; @@ -122,14 +139,11 @@ public void SetJob(DdonServer server, GameClient client, CharacterCo changeJobNotice.LearnNormalSkillParamList = normalSkills; changeJobNotice.EquipJobItemList = jobItems; // TODO: Unk0 - foreach (GameClient otherClient in server.ClientLookup.GetAll()) + foreach (GameClient otherClient in _Server.ClientLookup.GetAll()) { otherClient.Send(changeJobNotice); } - updateCharacterItemNtc.UpdateType = 0x29; - client.Send(updateCharacterItemNtc); - S2CJobChangePawnJobRes changeJobResponse = new S2CJobChangePawnJobRes(); changeJobResponse.PawnId = pawn.PawnId; changeJobResponse.CharacterJobData = activeCharacterJobData; @@ -150,6 +164,73 @@ public void SetJob(DdonServer server, GameClient client, CharacterCo } } + private List SwapEquipmentAndStorage(GameClient client, CharacterCommon common, int pawnIdx, StorageType equipmentStorageType, JobId oldJobId, JobId newJobId, EquipType equipType) + { + int equipmentStorageSlotOffset = pawnIdx * Equipment.EQUIP_SLOT_NUMBER * 2; + if(equipType == EquipType.Visual) + { + equipmentStorageSlotOffset += Equipment.EQUIP_SLOT_NUMBER; + } + + List itemUpdateResultList = new List(); + List oldPerformanceEquipment = common.Equipment.GetEquipment(oldJobId, EquipType.Performance); + List performanceEquipment = common.Equipment.GetEquipment(newJobId, EquipType.Performance); + for (int i = 0; i < performanceEquipment.Count; i++) + { + ushort equipSlot = (ushort)(i+1); + ushort equipmentStorageSlot = (ushort)(equipSlot + equipmentStorageSlotOffset); + Item? oldEquippedItem = oldPerformanceEquipment[i]; + Item? equippedItem = performanceEquipment[i]; + if(oldEquippedItem != null && equippedItem == null) + { + // Unequip item from an empty slot + try + { + List moveResult = _Server.ItemManager.MoveItem(_Server, client.Character, equipmentStorageType, oldEquippedItem.UId, 1, StorageType.StorageBoxNormal, 0); + itemUpdateResultList.AddRange(moveResult); + } + catch (InvalidOperationException) + { + // Handle the item not being in equipment storage + // This should probably return an error response instead? Logging and handling gracefully prevents messy situations, but may be undesirable + Logger.Error($"Failed to unequip item {oldEquippedItem.UId} from {equipType} slot {equipSlot} of {oldJobId}. The item wasn't in the equipment storage"); + common.Equipment.SetEquipItem(null, oldJobId, equipType, (byte) equipSlot); + _Server.Database.DeleteEquipItem(common.CommonId, oldJobId, equipType, (byte) equipSlot); + } + } + else if (equippedItem != null && equippedItem.UId != oldEquippedItem?.UId) + { + // Equip item to a slot, if it's not already equipped. Search item in multiple storages + List? moveResult = null; + foreach (StorageType searchStorageType in ItemManager.BothStorageTypes) + { + try + { + moveResult = _Server.ItemManager.MoveItem(_Server, client.Character, StorageType.ItemBagEquipment, equippedItem.UId, 1, equipmentStorageType, equipmentStorageSlot); + itemUpdateResultList.AddRange(moveResult); + break; + } + catch (InvalidOperationException) + { + // Do nothing, item to equip not in this storage type. + } + } + + if (moveResult == null) + { + // Handle the item not being in storage anymore + common.Equipment.SetEquipItem(null, newJobId, equipType, (byte) equipSlot); + _Server.Database.DeleteEquipItem(common.CommonId, oldJobId, equipType, (byte) equipSlot); + } + } + } + + // Persist job change in DB + _Server.Database.UpdateCharacterCommonBaseInfo(common); + + return itemUpdateResultList; + } + public void UnlockSkill(IDatabase database, GameClient client, CharacterCommon character, JobId job, uint skillId, byte skillLv) { // Check if there is a learned skill of the same ID (This unlock is a level upgrade) @@ -557,7 +638,7 @@ public void RemoveAbility(IDatabase database, CharacterCommon character, byte sl public bool UnlockSecretAbility(CharacterCommon Character, SecretAbility secretAbilityType) { - return _Database.InsertSecretAbilityUnlock(Character.CommonId, secretAbilityType); + return _Server.Database.InsertSecretAbilityUnlock(Character.CommonId, secretAbilityType); } } } diff --git a/Arrowgene.Ddon.GameServer/Chat/Command/Commands/JobCommand.cs b/Arrowgene.Ddon.GameServer/Chat/Command/Commands/JobCommand.cs index 43308fe0..c8fbe7c8 100644 --- a/Arrowgene.Ddon.GameServer/Chat/Command/Commands/JobCommand.cs +++ b/Arrowgene.Ddon.GameServer/Chat/Command/Commands/JobCommand.cs @@ -72,7 +72,7 @@ public override void Execute(string[] command, GameClient client, ChatMessage me } else { - _server.JobManager.SetJob(_server, client, client.Character, (JobId) job); + _server.JobManager.SetJob(client, client.Character, (JobId) job); } } } diff --git a/Arrowgene.Ddon.GameServer/DdonGameServer.cs b/Arrowgene.Ddon.GameServer/DdonGameServer.cs index e4ba9960..1b93b04b 100644 --- a/Arrowgene.Ddon.GameServer/DdonGameServer.cs +++ b/Arrowgene.Ddon.GameServer/DdonGameServer.cs @@ -63,7 +63,7 @@ public DdonGameServer(GameServerSetting setting, IDatabase database, AssetReposi ItemManager = new ItemManager(); PartyManager = new PartyManager(assetRepository); ExpManager = new ExpManager(database, ClientLookup); - JobManager = new JobManager(database); + JobManager = new JobManager(this); EquipManager = new EquipManager(); ShopManager = new ShopManager(assetRepository, database); WalletManager = new WalletManager(database); diff --git a/Arrowgene.Ddon.GameServer/Handler/JobChangeJobHandler.cs b/Arrowgene.Ddon.GameServer/Handler/JobChangeJobHandler.cs index f154dc65..2b87aa50 100644 --- a/Arrowgene.Ddon.GameServer/Handler/JobChangeJobHandler.cs +++ b/Arrowgene.Ddon.GameServer/Handler/JobChangeJobHandler.cs @@ -4,7 +4,6 @@ using Arrowgene.Logging; using Arrowgene.Ddon.Shared.Network; using Arrowgene.Ddon.GameServer.Characters; -using Arrowgene.Ddon.Shared.Entity; namespace Arrowgene.Ddon.GameServer.Handler { @@ -21,7 +20,7 @@ public JobChangeJobHandler(DdonGameServer server) : base(server) public override void Handle(GameClient client, StructurePacket packet) { - jobManager.SetJob(Server, client, client.Character, packet.Structure.JobId); + jobManager.SetJob(client, client.Character, packet.Structure.JobId); } } } \ No newline at end of file diff --git a/Arrowgene.Ddon.GameServer/Handler/JobChangePawnJobHandler.cs b/Arrowgene.Ddon.GameServer/Handler/JobChangePawnJobHandler.cs index 934d5447..3353abdc 100644 --- a/Arrowgene.Ddon.GameServer/Handler/JobChangePawnJobHandler.cs +++ b/Arrowgene.Ddon.GameServer/Handler/JobChangePawnJobHandler.cs @@ -22,7 +22,7 @@ public JobChangePawnJobHandler(DdonGameServer server) : base(server) public override void Handle(GameClient client, StructurePacket packet) { Pawn pawn = client.Character.Pawns.Where(pawn => pawn.PawnId == packet.Structure.PawnId).Single(); - jobManager.SetJob(Server, client, pawn, packet.Structure.JobId); + jobManager.SetJob(client, pawn, packet.Structure.JobId); } } } \ No newline at end of file From 1972d7b1451438028b36d01bef1df2ae474d2351 Mon Sep 17 00:00:00 2001 From: alborrajo Date: Sun, 16 Jun 2024 01:56:59 +0200 Subject: [PATCH 05/10] Fix character creation --- .../Handler/CreateCharacterHandler.cs | 42 +++++++++++-------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/Arrowgene.Ddon.LoginServer/Handler/CreateCharacterHandler.cs b/Arrowgene.Ddon.LoginServer/Handler/CreateCharacterHandler.cs index 92caf852..0da16964 100644 --- a/Arrowgene.Ddon.LoginServer/Handler/CreateCharacterHandler.cs +++ b/Arrowgene.Ddon.LoginServer/Handler/CreateCharacterHandler.cs @@ -1148,6 +1148,23 @@ public override void Handle(LoginClient client, StructurePacket pawnVisualEquipItems = character.Equipment.GetEquipment(character.Job, EquipType.Visual); @@ -1173,26 +1194,13 @@ public override void Handle(LoginClient client, StructurePacket Date: Sun, 16 Jun 2024 13:25:53 +0200 Subject: [PATCH 06/10] Renamed Equipment constants for better clarity --- Arrowgene.Ddon.GameServer/Characters/EquipManager.cs | 4 ++-- Arrowgene.Ddon.GameServer/Characters/JobManager.cs | 7 +++++-- .../Handler/CreateCharacterHandler.cs | 6 +++--- Arrowgene.Ddon.Shared/Model/Equipment.cs | 8 ++++---- Arrowgene.Ddon.Shared/Model/Storages.cs | 2 +- 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/Arrowgene.Ddon.GameServer/Characters/EquipManager.cs b/Arrowgene.Ddon.GameServer/Characters/EquipManager.cs index b74da436..49e0dc80 100644 --- a/Arrowgene.Ddon.GameServer/Characters/EquipManager.cs +++ b/Arrowgene.Ddon.GameServer/Characters/EquipManager.cs @@ -83,7 +83,7 @@ public void HandleChangeEquipList(DdonGameServer server, GameClient client, Char if(equipType == EquipType.Visual) { - storageSlot += Equipment.EQUIP_SLOT_NUMBER; + storageSlot += Equipment.TOTAL_EQUIP_SLOTS; } uint characterId, pawnId; @@ -99,7 +99,7 @@ public void HandleChangeEquipList(DdonGameServer server, GameClient client, Char characterId = pawn.CharacterId; pawnId = pawn.PawnId; equipmentStorageType = StorageType.PawnEquipment; - storageSlot = (ushort)(storageSlot + client.Character.Pawns.IndexOf(pawn)*Equipment.EQUIP_SLOT_NUMBER*2); + storageSlot = (ushort)(storageSlot + client.Character.Pawns.IndexOf(pawn)*Equipment.TOTAL_EQUIP_SLOTS*2); } else { diff --git a/Arrowgene.Ddon.GameServer/Characters/JobManager.cs b/Arrowgene.Ddon.GameServer/Characters/JobManager.cs index 5a69f543..2b5705c3 100644 --- a/Arrowgene.Ddon.GameServer/Characters/JobManager.cs +++ b/Arrowgene.Ddon.GameServer/Characters/JobManager.cs @@ -166,10 +166,12 @@ public void SetJob(GameClient client, CharacterCommon common, JobId jobId) private List SwapEquipmentAndStorage(GameClient client, CharacterCommon common, int pawnIdx, StorageType equipmentStorageType, JobId oldJobId, JobId newJobId, EquipType equipType) { - int equipmentStorageSlotOffset = pawnIdx * Equipment.EQUIP_SLOT_NUMBER * 2; + // TODO: Run in a transaction + + int equipmentStorageSlotOffset = pawnIdx * Equipment.TOTAL_EQUIP_SLOTS * 2; if(equipType == EquipType.Visual) { - equipmentStorageSlotOffset += Equipment.EQUIP_SLOT_NUMBER; + equipmentStorageSlotOffset += Equipment.TOTAL_EQUIP_SLOTS; } List itemUpdateResultList = new List(); @@ -184,6 +186,7 @@ private List SwapEquipmentAndStorage(GameClient client, C if(oldEquippedItem != null && equippedItem == null) { // Unequip item from an empty slot + // TODO: Attempt moving into other storages if the storage box is full try { List moveResult = _Server.ItemManager.MoveItem(_Server, client.Character, equipmentStorageType, oldEquippedItem.UId, 1, StorageType.StorageBoxNormal, 0); diff --git a/Arrowgene.Ddon.LoginServer/Handler/CreateCharacterHandler.cs b/Arrowgene.Ddon.LoginServer/Handler/CreateCharacterHandler.cs index 0da16964..bbf900cf 100644 --- a/Arrowgene.Ddon.LoginServer/Handler/CreateCharacterHandler.cs +++ b/Arrowgene.Ddon.LoginServer/Handler/CreateCharacterHandler.cs @@ -1144,7 +1144,7 @@ public override void Handle(LoginClient client, StructurePacket pawnPerformanceEquipItems = character.Equipment.GetEquipment(character.Job, EquipType.Performance); for (int j = 0; j < pawnPerformanceEquipItems.Count; j++) @@ -1192,7 +1192,7 @@ public override void Handle(LoginClient client, StructurePacket>> equipment; private readonly Dictionary> jobItems; @@ -28,14 +28,14 @@ public Equipment() equipment[job] = new Dictionary>(); foreach (EquipType equipType in Enum.GetValues(typeof(EquipType))) { - equipment[job][equipType] = Enumerable.Repeat(null, EQUIP_SLOT_NUMBER).ToList(); + equipment[job][equipType] = Enumerable.Repeat(null, TOTAL_EQUIP_SLOTS).ToList(); } } jobItems = new Dictionary>(); foreach (JobId job in Enum.GetValues(typeof(JobId))) { - jobItems[job] = Enumerable.Repeat(null, JOB_ITEM_SLOT_NUMBER).ToList(); + jobItems[job] = Enumerable.Repeat(null, TOTAL_JOB_ITEM_SLOT).ToList(); } } diff --git a/Arrowgene.Ddon.Shared/Model/Storages.cs b/Arrowgene.Ddon.Shared/Model/Storages.cs index 6740b5bb..a6106c67 100644 --- a/Arrowgene.Ddon.Shared/Model/Storages.cs +++ b/Arrowgene.Ddon.Shared/Model/Storages.cs @@ -116,7 +116,7 @@ private uint determinePawnId(Character character, StorageType storageType, ushor { if(storageType == StorageType.PawnEquipment) { - int pawnIndex = slot / (Equipment.EQUIP_SLOT_NUMBER * 2); + int pawnIndex = slot / (Equipment.TOTAL_EQUIP_SLOTS * 2); return character.Pawns[pawnIndex].PawnId; } else From f149208d1ecd47900d06ffd38ced6b9aae921a7b Mon Sep 17 00:00:00 2001 From: alborrajo Date: Sun, 16 Jun 2024 13:26:20 +0200 Subject: [PATCH 07/10] Fix character creation issues --- Arrowgene.Ddon.LoginServer/Handler/CreateCharacterHandler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Arrowgene.Ddon.LoginServer/Handler/CreateCharacterHandler.cs b/Arrowgene.Ddon.LoginServer/Handler/CreateCharacterHandler.cs index bbf900cf..0c8163c3 100644 --- a/Arrowgene.Ddon.LoginServer/Handler/CreateCharacterHandler.cs +++ b/Arrowgene.Ddon.LoginServer/Handler/CreateCharacterHandler.cs @@ -1176,7 +1176,7 @@ public override void Handle(LoginClient client, StructurePacket pawnPerformanceEquipItems = character.Equipment.GetEquipment(character.Job, EquipType.Performance); + List pawnPerformanceEquipItems = pawn.Equipment.GetEquipment(pawn.Job, EquipType.Performance); for (int j = 0; j < pawnPerformanceEquipItems.Count; j++) { Item? item = pawnPerformanceEquipItems[j]; @@ -1188,7 +1188,7 @@ public override void Handle(LoginClient client, StructurePacket pawnVisualEquipItems = character.Equipment.GetEquipment(character.Job, EquipType.Visual); + List pawnVisualEquipItems = pawn.Equipment.GetEquipment(pawn.Job, EquipType.Visual); for (int j = 0; j < pawnVisualEquipItems.Count; j++) { Item? item = pawnVisualEquipItems[j]; From 77c3319d0ebd59b66facd9bbacb0a3f50b7d6a9e Mon Sep 17 00:00:00 2001 From: alborrajo Date: Sun, 16 Jun 2024 13:26:39 +0200 Subject: [PATCH 08/10] Fix job change equipment swapping issues --- .../Characters/JobManager.cs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/Arrowgene.Ddon.GameServer/Characters/JobManager.cs b/Arrowgene.Ddon.GameServer/Characters/JobManager.cs index 2b5705c3..9365a539 100644 --- a/Arrowgene.Ddon.GameServer/Characters/JobManager.cs +++ b/Arrowgene.Ddon.GameServer/Characters/JobManager.cs @@ -41,8 +41,7 @@ public void SetJob(GameClient client, CharacterCommon common, JobId jobId) } else if (common is Pawn) { - Pawn pawn = (Pawn)common; - pawnIdx = client.Character.Pawns.IndexOf(pawn); + pawnIdx = client.Character.Pawns.IndexOf((Pawn)common); equipmentStorageType = StorageType.PawnEquipment; updateCharacterItemNtc.UpdateType = 0x29; } @@ -175,14 +174,14 @@ private List SwapEquipmentAndStorage(GameClient client, C } List itemUpdateResultList = new List(); - List oldPerformanceEquipment = common.Equipment.GetEquipment(oldJobId, EquipType.Performance); - List performanceEquipment = common.Equipment.GetEquipment(newJobId, EquipType.Performance); - for (int i = 0; i < performanceEquipment.Count; i++) + List oldEquipment = common.Equipment.GetEquipment(oldJobId, equipType); + List equipment = common.Equipment.GetEquipment(newJobId, equipType); + for (int i = 0; i < equipment.Count; i++) { ushort equipSlot = (ushort)(i+1); ushort equipmentStorageSlot = (ushort)(equipSlot + equipmentStorageSlotOffset); - Item? oldEquippedItem = oldPerformanceEquipment[i]; - Item? equippedItem = performanceEquipment[i]; + Item? oldEquippedItem = oldEquipment[i]; + Item? equippedItem = equipment[i]; if(oldEquippedItem != null && equippedItem == null) { // Unequip item from an empty slot @@ -196,20 +195,20 @@ private List SwapEquipmentAndStorage(GameClient client, C { // Handle the item not being in equipment storage // This should probably return an error response instead? Logging and handling gracefully prevents messy situations, but may be undesirable - Logger.Error($"Failed to unequip item {oldEquippedItem.UId} from {equipType} slot {equipSlot} of {oldJobId}. The item wasn't in the equipment storage"); + Logger.Error($"Failed to unequip item {oldEquippedItem.UId} from {equipType} slot {equipSlot} of {oldJobId}. The item wasn't in the {equipmentStorageType} slot {equipmentStorageSlot}"); common.Equipment.SetEquipItem(null, oldJobId, equipType, (byte) equipSlot); _Server.Database.DeleteEquipItem(common.CommonId, oldJobId, equipType, (byte) equipSlot); } } else if (equippedItem != null && equippedItem.UId != oldEquippedItem?.UId) { - // Equip item to a slot, if it's not already equipped. Search item in multiple storages + // Equip item to a slot, if said item is not already equipped. Search item in multiple storages List? moveResult = null; foreach (StorageType searchStorageType in ItemManager.BothStorageTypes) { try { - moveResult = _Server.ItemManager.MoveItem(_Server, client.Character, StorageType.ItemBagEquipment, equippedItem.UId, 1, equipmentStorageType, equipmentStorageSlot); + moveResult = _Server.ItemManager.MoveItem(_Server, client.Character, searchStorageType, equippedItem.UId, 1, equipmentStorageType, equipmentStorageSlot); itemUpdateResultList.AddRange(moveResult); break; } From cfa561abb9b12a16880285bb9687074b118b6d22 Mon Sep 17 00:00:00 2001 From: alborrajo Date: Sun, 16 Jun 2024 13:29:04 +0200 Subject: [PATCH 09/10] Use ItemNoticeType enum values in JobManager.SetJob --- Arrowgene.Ddon.GameServer/Characters/JobManager.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Arrowgene.Ddon.GameServer/Characters/JobManager.cs b/Arrowgene.Ddon.GameServer/Characters/JobManager.cs index 9365a539..5d36e88b 100644 --- a/Arrowgene.Ddon.GameServer/Characters/JobManager.cs +++ b/Arrowgene.Ddon.GameServer/Characters/JobManager.cs @@ -37,13 +37,13 @@ public void SetJob(GameClient client, CharacterCommon common, JobId jobId) { pawnIdx = 0; equipmentStorageType = StorageType.CharacterEquipment; - updateCharacterItemNtc.UpdateType = 0x28; + updateCharacterItemNtc.UpdateType = (ushort) ItemNoticeType.ChangeJob; } else if (common is Pawn) { pawnIdx = client.Character.Pawns.IndexOf((Pawn)common); equipmentStorageType = StorageType.PawnEquipment; - updateCharacterItemNtc.UpdateType = 0x29; + updateCharacterItemNtc.UpdateType = (ushort) ItemNoticeType.ChangePawnJob; } else { From aeb8d6f33eb07fb7fbef37a6f538b2c7b9cf8d3f Mon Sep 17 00:00:00 2001 From: alborrajo Date: Sun, 16 Jun 2024 13:29:15 +0200 Subject: [PATCH 10/10] Address requested changes during review --- Arrowgene.Ddon.Shared/Model/Storages.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Arrowgene.Ddon.Shared/Model/Storages.cs b/Arrowgene.Ddon.Shared/Model/Storages.cs index a6106c67..5c02e933 100644 --- a/Arrowgene.Ddon.Shared/Model/Storages.cs +++ b/Arrowgene.Ddon.Shared/Model/Storages.cs @@ -63,8 +63,8 @@ public List getStorageAsCDataItemList(Character character, Storag PlusValue = tuple.item.Item1.PlusValue, Bind = true, EquipPoint = 0, - EquipCharacterID = determineCharacterId(character, storageType, tuple.slot), - EquipPawnID = determinePawnId(character, storageType, tuple.slot), + EquipCharacterID = DetermineCharacterId(character, storageType, tuple.slot), + EquipPawnID = DeterminePawnId(character, storageType, tuple.slot), WeaponCrestDataList = tuple.item.Item1.WeaponCrestDataList, ArmorCrestDataList = tuple.item.Item1.ArmorCrestDataList, EquipElementParamList = tuple.item.Item1.EquipElementParamList @@ -100,7 +100,7 @@ public List getStorageAsCDataItemList(Character character, Storag return oldItem; } - private uint determineCharacterId(Character character, StorageType storageType, ushort slot) + private uint DetermineCharacterId(Character character, StorageType storageType, ushort slot) { if(storageType == StorageType.CharacterEquipment) { @@ -112,7 +112,7 @@ private uint determineCharacterId(Character character, StorageType storageType, } } - private uint determinePawnId(Character character, StorageType storageType, ushort slot) + private uint DeterminePawnId(Character character, StorageType storageType, ushort slot) { if(storageType == StorageType.PawnEquipment) {