Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Equipment as a storage type #350

Draft
wants to merge 10 commits into
base: develop
Choose a base branch
from
2 changes: 1 addition & 1 deletion Arrowgene.Ddon.Database/IDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
16 changes: 10 additions & 6 deletions Arrowgene.Ddon.Database/Sql/Core/DdonSqlDbEquipItem.cs
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -18,7 +17,7 @@ public abstract partial class DdonSqlDb<TCon, TCom, TReader> : SqlDb<TCon, TCom,
private readonly string SqlInsertIfNotExistsEquipItem = $"INSERT INTO \"ddon_equip_item\" ({BuildQueryField(CDataEquipItemFields)}) SELECT {BuildQueryInsert(CDataEquipItemFields)} WHERE NOT EXISTS (SELECT 1 FROM \"ddon_equip_item\" WHERE \"character_common_id\"=@character_common_id AND \"job\"=@job AND \"equip_type\"=@equip_type AND \"equip_slot\"=@equip_slot);";
private static readonly string SqlUpdateEquipItem = $"UPDATE \"ddon_equip_item\" SET {BuildQueryUpdate(CDataEquipItemFields)} WHERE \"character_common_id\"=@character_common_id AND \"job\"=@job AND \"equip_type\"=@equip_type AND \"equip_slot\"=@equip_slot;";
private static readonly string SqlSelectEquipItemByCharacter = $"SELECT {BuildQueryField(CDataEquipItemFields)} FROM \"ddon_equip_item\" WHERE \"character_common_id\"=@character_common_id;";
private static readonly string SqlDeleteEquipItem = "DELETE FROM \"ddon_equip_item\" WHERE \"item_uid\"=@item_uid AND \"character_common_id\"=@character_common_id AND \"job\"=@job AND \"equip_type\"=@equip_type AND \"equip_slot\"=@equip_slot;";
private static readonly string SqlDeleteEquipItem = "DELETE FROM \"ddon_equip_item\" WHERE \"character_common_id\"=@character_common_id AND \"job\"=@job AND \"equip_type\"=@equip_type AND \"equip_slot\"=@equip_slot;";

public bool InsertIfNotExistsEquipItem(uint commonId, JobId job, EquipType equipType, byte equipSlot, string itemUId)
{
Expand Down Expand Up @@ -79,21 +78,26 @@ public bool UpdateEquipItem(TCon connection, uint commonId, JobId job, EquipType
}) == 1;
}

public bool DeleteEquipItem(uint commonId, JobId job, EquipType equipType, byte equipSlot, string itemUId)
public bool DeleteEquipItem(uint commonId, JobId job, EquipType equipType, byte equipSlot)
{
return ExecuteNonQuery(SqlDeleteEquipItem, command =>
{
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);
}
}
}
224 changes: 28 additions & 196 deletions Arrowgene.Ddon.GameServer/Characters/EquipManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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.TOTAL_EQUIP_SLOTS;
}

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.TOTAL_EQUIP_SLOTS*2);
}
else
{
Expand All @@ -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));
}
}

Expand Down Expand Up @@ -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<StorageType> 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<StorageType> 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
}
});
}
}
}
}