using System;
using ACE.Common.Extensions;
using ACE.DatLoader;
using ACE.Entity.Enum;
using ACE.Entity.Enum.Properties;
using ACE.Entity.Models;
namespace ACE.Server.WorldObjects.Entity
{
public class CreatureAttribute
{
private readonly Creature creature;
public readonly PropertyAttribute Attribute;
// the underlying database record
private readonly PropertiesAttribute propertiesAttribute;
///
/// If the creature's biota does not contain this attribute, a new record will be created.
///
public CreatureAttribute(Creature creature, PropertyAttribute attribute)
{
this.creature = creature;
Attribute = attribute;
if (!creature.Biota.PropertiesAttribute.TryGetValue(attribute, out propertiesAttribute))
{
propertiesAttribute = new PropertiesAttribute();
creature.Biota.PropertiesAttribute[attribute] = propertiesAttribute;
}
}
///
/// Returns the Base Value for a Creature's attribute, for Players this is set during Character Creation
///
public uint StartingValue
{
get => propertiesAttribute.InitLevel;
set => propertiesAttribute.InitLevel = value;
}
///
/// Total Experience Spent on an attribute
///
public uint ExperienceSpent
{
get => propertiesAttribute.CPSpent;
set => propertiesAttribute.CPSpent = value;
}
///
/// Returns the amount of attribute experience remaining
/// until max rank is reached
///
public uint ExperienceLeft
{
get
{
var attributeXPTable = DatManager.PortalDat.XpTable.AttributeXpList;
return attributeXPTable[attributeXPTable.Count - 1] - ExperienceSpent;
}
}
///
/// The number of levels an attribute has been raised,
/// derived from ExperienceSpent
///
public uint Ranks
{
get => propertiesAttribute.LevelFromCP;
set => propertiesAttribute.LevelFromCP = value;
}
///
/// Returns TRUE if this attribute has been raised the maximum # of times
///
public bool IsMaxRank
{
get
{
var attributeXPTable = DatManager.PortalDat.XpTable.AttributeXpList;
return Ranks >= (attributeXPTable.Count - 1);
}
}
///
/// Returns the Base Value Plus the Ranked Value
///
public uint Base
{
get
{
uint total = Ranks + StartingValue;
// TODO: cap at 10x of these augs across the board elsewhere
// verify this with client formula
// NOTE: this has been moved to InitLevel
/*if (creature is Player player)
{
switch (Attribute)
{
case PropertyAttribute.Strength:
if (player.AugmentationInnateStrength > 0)
total += (uint)(player.AugmentationInnateStrength * 5);
break;
case PropertyAttribute.Endurance:
if (player.AugmentationInnateEndurance > 0)
total += (uint)(player.AugmentationInnateEndurance * 5);
break;
case PropertyAttribute.Coordination:
if (player.AugmentationInnateCoordination > 0)
total += (uint)(player.AugmentationInnateCoordination * 5);
break;
case PropertyAttribute.Quickness:
if (player.AugmentationInnateQuickness > 0)
total += (uint)(player.AugmentationInnateQuickness * 5);
break;
case PropertyAttribute.Focus:
if (player.AugmentationInnateFocus > 0)
total += (uint)(player.AugmentationInnateFocus * 5);
break;
case PropertyAttribute.Self:
if (player.AugmentationInnateSelf > 0)
total += (uint)(player.AugmentationInnateSelf * 5);
break;
}
}*/
return total;
}
}
public uint Current => GetCurrent(true);
public uint GetCurrent(bool enchanted)
{
var multipliers = enchanted ? creature.EnchantmentManager.GetAttributeMod_Multiplier(Attribute) : 1.0f;
var additives = enchanted ? creature.EnchantmentManager.GetAttributeMod_Additive(Attribute) : 0;
var total = (int)Base * multipliers + additives;
total = total.Round();
// attributes cannot be debuffed below 10 normally,
// or 1 for creatures with very low starting attributes
var minimumAttribute = Base >= 10 ? 10 : 1;
return (uint)Math.Max(minimumAttribute, total);
}
public ModifierType ModifierType
{
get
{
var diff = (int)GetCurrent(true) - (int)GetCurrent(false);
if (diff > 0)
return ModifierType.Buffed;
else if (diff < 0)
return ModifierType.Debuffed;
else
return ModifierType.None;
}
}
}
}