259 lines
10 KiB
C#
259 lines
10 KiB
C#
using MetaAssets;
|
|
using Microsoft.IdentityModel.Tokens;
|
|
using ServerCommon;
|
|
using ServerCore; using ServerBase;
|
|
|
|
namespace GameServer
|
|
{
|
|
public class AbilityAction : EntityActionBase
|
|
{
|
|
private Dictionary<AttributeType, int> m_abilities { get; set; } = new();
|
|
|
|
public AbilityAction(EntityBase owner)
|
|
: base(owner)
|
|
{
|
|
}
|
|
|
|
public override async Task<Result> onInit()
|
|
{
|
|
await Task.CompletedTask;
|
|
|
|
var result = new Result();
|
|
|
|
clearAbility();
|
|
|
|
return result;
|
|
}
|
|
|
|
public override void onClear()
|
|
{
|
|
return;
|
|
}
|
|
|
|
public void clearAbility()
|
|
{
|
|
foreach (var ability in EnumHelper.getValuesWithoutScope<AttributeType>())
|
|
{
|
|
m_abilities[ability] = 0;
|
|
}
|
|
}
|
|
|
|
public int? getAbility(AttributeType abilityId) => m_abilities.TryGetValue(abilityId, out var ability) ? ability : null;
|
|
|
|
public Dictionary<AttributeType, int> getAbilities() => m_abilities;
|
|
|
|
public async Task<Result> forceResetAll()
|
|
{
|
|
clearAbility();
|
|
|
|
var owner = getOwner();
|
|
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!! - {toBasicString()}");
|
|
|
|
|
|
var inventory_action_base = owner.getEntityAction<InventoryActionBase>();
|
|
NullReferenceCheckHelper.throwIfNull(inventory_action_base, () => $"inventory_action_base is null !!! - {owner.toBasicString()}");
|
|
|
|
var result = await inventory_action_base.tryResetAttributeByTattoo();
|
|
if(result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
var buff_action = owner.getEntityAction<BuffAction>();
|
|
NullReferenceCheckHelper.throwIfNull(buff_action, () => $"buff_action is null !!! - {owner.toBasicString()}");
|
|
result = await buff_action.tryResetAttributeByBuff();
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public void forceSetAbilityAll(int toSetAbility)
|
|
{
|
|
var owner = getOwner();
|
|
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!! - {toBasicString()}");
|
|
|
|
var attribute_types = EnumHelper.getValuesWithoutScopeAll<AttributeType>();
|
|
foreach (var attribute_type in attribute_types)
|
|
{
|
|
m_abilities[attribute_type] = toSetAbility;
|
|
}
|
|
}
|
|
|
|
public void setAbility(AttributeType abilityId, int ability, bool decrease)
|
|
{
|
|
var change_value = decrease ? ability * -1 : ability;
|
|
m_abilities[abilityId] += change_value;
|
|
}
|
|
|
|
public async Task<Result> setAbilities(ItemBase item, Int16 level, bool decrease)
|
|
{
|
|
ArgumentNullReferenceCheckHelper.throwIfNull(item, () => $"item is null !!! - {toBasicString()}");
|
|
|
|
await Task.CompletedTask;
|
|
|
|
var result = new Result();
|
|
string err_msg;
|
|
|
|
var item_attribute = item.getEntityAttribute<ItemAttributeBase>();
|
|
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {toBasicString()}");
|
|
|
|
var item_meta = item.getItemMeta();
|
|
NullReferenceCheckHelper.throwIfNull(item_meta, () => $"item_meta is null !!! - {toBasicString()}");
|
|
var enchant = getEnchantData(level, item_meta);
|
|
if (null == enchant)
|
|
{
|
|
err_msg = $"Fail to get enchant data : {nameof(getEnchantData)}";
|
|
result.setFail(ServerErrorCode.ItemEnchantNotFoundInMeta, err_msg);
|
|
Log.getLogger().error(err_msg);
|
|
return result;
|
|
}
|
|
|
|
// 배열의 위치를 AttributeType으로 활용하다보니 불필요한 예외 처리 코드를 작성해야 한다. !!!
|
|
// Key-Value 구조로 바꾸고 싶지만... 간단한 수정 범위는 아니다.
|
|
// MetaHelper를 통해 메타 데이터를 가공하는 방법도 있다.... - kangms
|
|
for(var i = 0; i < enchant.Count; i++)
|
|
{
|
|
if (false == EnumHelper.isDefined<AttributeType>(item_attribute.Attributes[i]))
|
|
{
|
|
Log.getLogger().warn($"Invalid Ability Enum Type : {item_attribute.Attributes[i]}");
|
|
continue;
|
|
}
|
|
|
|
if (item_attribute.Attributes.Count <= i)
|
|
{
|
|
Log.getLogger().warn($"Ability Type outof range !!! : enchantIndex:{i} > itemAttributeIndex:{i}");
|
|
item_attribute.Attributes.Add(0);
|
|
}
|
|
|
|
setAbility((AttributeType)item_attribute.Attributes[i], enchant[i], decrease);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<Result> changeAbilities(ItemBase item, Dictionary<int, int> slotWithAttributeIds, bool decrease)
|
|
{
|
|
await Task.CompletedTask;
|
|
|
|
var owner = getOwner();
|
|
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
|
|
|
ArgumentNullReferenceCheckHelper.throwIfNull(item, () => $"item is null !!! - {owner.toBasicString()}");
|
|
ArgumentNullReferenceCheckHelper.throwIfNull(slotWithAttributeIds, () => $"slotWithAttributeIds is null !!! - {owner.toBasicString()}");
|
|
|
|
var result = new Result();
|
|
string err_msg;
|
|
|
|
var item_attribute = item.getEntityAttribute<ItemAttributeBase>();
|
|
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {owner.toBasicString()}");
|
|
|
|
var item_meta = item.getItemMeta();
|
|
NullReferenceCheckHelper.throwIfNull(item_meta, () => $"item_meta is null !!! - {owner.toBasicString()}");
|
|
var enchant = getEnchantData(item_attribute.Level, item_meta);
|
|
if (null == enchant)
|
|
{
|
|
err_msg = $"Fail to get enchant data : {nameof(getEnchantData)}";
|
|
result.setFail(ServerErrorCode.ItemEnchantNotFoundInMeta, err_msg);
|
|
Log.getLogger().error(err_msg);
|
|
return result;
|
|
}
|
|
|
|
foreach (var each in slotWithAttributeIds)
|
|
{
|
|
if (false == EnumHelper.isDefined<AttributeType>(each.Value))
|
|
{
|
|
Log.getLogger().warn($"Invalid Ability Enum Type : {each.Value}");
|
|
continue;
|
|
}
|
|
|
|
// 배열의 위치를 AttributeType으로 활용하다보니 불필요한 예외 처리 코드를 작성해야 한다. !!!
|
|
// Key-Value 구조로 바꾸고 싶지만... MetaHelper를 통해 메타 데이터를 가공하는 방법도 있다.... - kangms
|
|
if (each.Key >= enchant.Count)
|
|
{
|
|
Log.getLogger().warn($"Ability Type outof range !!! : enchantCount:{enchant.Count} > slotWithAttributeIndex:{each.Key}");
|
|
continue;
|
|
}
|
|
|
|
setAbility((AttributeType)each.Value, enchant[each.Key], decrease);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public Result hasAbilities(Dictionary<string, Int32> toCheckAbilities)
|
|
{
|
|
var owner = getOwner();
|
|
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!! - {toBasicString()}");
|
|
ArgumentNullReferenceCheckHelper.throwIfNull(toCheckAbilities, () => $"toCheckAbilities is null !!! - {owner.toBasicString()}");
|
|
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var ability_action = owner.getEntityAction<AbilityAction>();
|
|
NullReferenceCheckHelper.throwIfNull(ability_action, () => $"ability_action is null !!! - {toBasicString()}");
|
|
|
|
foreach (var each in toCheckAbilities)
|
|
{
|
|
var ability_name = each.Key;
|
|
var ability_value = each.Value;
|
|
|
|
if (false == EnumHelper.tryParse<AttributeType>(ability_name, out var attribute_type))
|
|
{
|
|
err_msg = $"Invalid Ability Enum Type : {attribute_type} - {owner.toBasicString()}";
|
|
result.setFail(ServerErrorCode.ServerTypeInvalid, err_msg);
|
|
Log.getLogger().error(err_msg);
|
|
return result;
|
|
}
|
|
|
|
var curr_value = ability_action.getAbility(attribute_type);
|
|
if (curr_value == null)
|
|
{
|
|
err_msg = $"Invalid Ability Enum Type : {attribute_type} - {owner.toBasicString()}";
|
|
result.setFail(ServerErrorCode.ServerTypeInvalid, err_msg);
|
|
Log.getLogger().error(err_msg);
|
|
return result;
|
|
}
|
|
|
|
if (curr_value < ability_value)
|
|
{
|
|
err_msg = $"Not enough Ability !!! : AbilityName:{attribute_type}, currValue:{curr_value} >= reqValue:{ability_value} - {getOwner().toBasicString()}";
|
|
result.setFail(ServerErrorCode.AbilityNotEnough, err_msg);
|
|
Log.getLogger().info(err_msg);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private IReadOnlyList<int>? getEnchantData(int level, MetaAssets.ItemMetaData item)
|
|
{
|
|
ArgumentNullReferenceCheckHelper.throwIfNull(item, () => $"item is null !!! - {toBasicString()}");
|
|
|
|
if (false == MetaData.Instance._ItemLevelEnchantMetaTable.TryGetValue(level, out var enchant_by_level))
|
|
{
|
|
return null;
|
|
}
|
|
var enchant = enchant_by_level.GetConsumeItem(item.Rarity);
|
|
return enchant?.AttributeValues;
|
|
}
|
|
|
|
public AbilityInfo toAbilityInfo()
|
|
{
|
|
var owner = getOwner();
|
|
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
|
|
|
var ability_info = new AbilityInfo();
|
|
foreach(var each in m_abilities)
|
|
{
|
|
ability_info.Values.Add((Int16)each.Key, each.Value);
|
|
}
|
|
|
|
return ability_info;
|
|
}
|
|
}
|
|
}
|