public void SpendAllAvailableAttributeXp(CreatureAttribute ability, bool sendNetworkPropertyUpdate = true) { var xpList = DatManager.PortalDat.XpTable.AbilityXpList; while (true) { uint currentRankXp = xpList[Convert.ToInt32(ability.Ranks)]; uint rank10; if (ability.Ranks + 10 >= (xpList.Count)) { var rank10Offset = 10 - (Convert.ToInt32(ability.Ranks + 10) - (xpList.Count - 1)); rank10 = xpList[Convert.ToInt32(ability.Ranks) + rank10Offset] - currentRankXp; } else { rank10 = xpList[Convert.ToInt32(ability.Ranks) + 10] - currentRankXp; } if (SpendAttributeXp(ability, rank10, sendNetworkPropertyUpdate) == 0) { break; } } }
private bool SpendAttributeXp(CreatureAttribute creatureAttribute, uint amount, bool sendNetworkUpdate = true) { // ensure attribute is not already max rank if (creatureAttribute.IsMaxRank) { log.Error($"{Name}.SpendAttributeXp({creatureAttribute.Attribute}, {amount}) - player tried to raise attribute beyond max rank"); return(false); } // the client should already handle this naturally, // but ensure player can't spend xp beyond the max rank var amountToEnd = creatureAttribute.ExperienceLeft; if (amount > amountToEnd) { log.Error($"{Name}.SpendAttributeXp({creatureAttribute.Attribute}, {amount}) - player tried to raise attribute beyond {amountToEnd} experience"); return(false); // returning error here, instead of setting amount to amountToEnd } // everything looks good at this point, // spend xp on attribute if (!SpendXP(amount, sendNetworkUpdate)) { log.Error($"{Name}.SpendAttributeXp({creatureAttribute.Attribute}, {amount}) - SpendXP failed"); return(false); } creatureAttribute.ExperienceSpent += amount; // calculate new rank creatureAttribute.Ranks = (ushort)CalcAttributeRank(creatureAttribute.ExperienceSpent); return(true); }
public GameMessagePrivateUpdateAttribute(WorldObject worldObject, CreatureAttribute creatureAttribute) : base(GameMessageOpcode.PrivateUpdateAttribute, GameMessageGroup.UIQueue) { Writer.Write(worldObject.Sequences.GetNextSequence(Sequence.SequenceType.UpdateAttribute, creatureAttribute.Attribute)); Writer.Write((uint)creatureAttribute.Attribute); Writer.Write(creatureAttribute.Ranks); Writer.Write(creatureAttribute.StartingValue); Writer.Write(creatureAttribute.ExperienceSpent); }
/// <summary> /// spends the xp on this ability. /// </summary> /// <returns>0 if it failed, total investment of the next rank if successful</returns> private uint SpendAttributeXp(CreatureAttribute ability, uint amount, bool sendNetworkPropertyUpdate = true) { uint result = 0; var xpList = DatManager.PortalDat.XpTable.AbilityXpList; // do not advance if we cannot spend xp to rank up our skill by 1 point if (ability.Ranks >= (xpList.Count - 1)) { return(result); } uint rankUps = 0u; uint currentRankXp = xpList[Convert.ToInt32(ability.Ranks)]; uint rank1 = xpList[Convert.ToInt32(ability.Ranks) + 1] - currentRankXp; uint rank10; int rank10Offset = 0; if (ability.Ranks + 10 >= (xpList.Count)) { rank10Offset = 10 - (Convert.ToInt32(ability.Ranks + 10) - (xpList.Count - 1)); rank10 = xpList[Convert.ToInt32(ability.Ranks) + rank10Offset] - currentRankXp; } else { rank10 = xpList[Convert.ToInt32(ability.Ranks) + 10] - currentRankXp; } if (amount == rank1) { rankUps = 1u; } else if (amount == rank10) { if (rank10Offset > 0u) { rankUps = Convert.ToUInt32(rank10Offset); } else { rankUps = 10u; } } if (rankUps > 0) { if (SpendXP(amount, sendNetworkPropertyUpdate)) { ability.Ranks += rankUps; ability.ExperienceSpent += amount; result = ability.ExperienceSpent; } } return(result); }
/// <summary> /// spends the xp on this ability. /// </summary> /// <returns>0 if it failed, total investment of the next rank if successful</returns> private uint SpendAttributeXp(CreatureAttribute ability, uint amount) { uint result = 0; var xpList = DatManager.PortalDat.XpTable.AbilityXpList; // do not advance if we cannot spend xp to rank up our skill by 1 point if (ability.Ranks >= (xpList.Count - 1)) { return(result); } uint rankUps = 0u; uint currentRankXp = xpList[Convert.ToInt32(ability.Ranks)]; uint rank1 = xpList[Convert.ToInt32(ability.Ranks) + 1] - currentRankXp; uint rank10; int rank10Offset = 0; if (ability.Ranks + 10 >= (xpList.Count)) { rank10Offset = 10 - (Convert.ToInt32(ability.Ranks + 10) - (xpList.Count - 1)); rank10 = xpList[Convert.ToInt32(ability.Ranks) + rank10Offset] - currentRankXp; } else { rank10 = xpList[Convert.ToInt32(ability.Ranks) + 10] - currentRankXp; } if (amount == rank1) { rankUps = 1u; } else if (amount == rank10) { if (rank10Offset > 0u) { rankUps = Convert.ToUInt32(rank10Offset); } else { rankUps = 10u; } } if (rankUps > 0) { // FIXME(ddevec): // Really AddRank() should probably be a method of CreatureAbility/CreatureVital ability.Ranks += rankUps; ability.ExperienceSpent += amount; SpendXp(amount); result = ability.ExperienceSpent; } return(result); }
public void RaiseAttributeGameAction(PropertyAttribute attribute, uint amount) { var creatureAttribute = new CreatureAttribute(this, attribute); uint result = SpendAttributeXp(creatureAttribute, amount); if (result > 0u) { GameMessage abilityUpdate = new GameMessagePrivateUpdateAttribute(this, attribute, creatureAttribute.Ranks, creatureAttribute.StartingValue, result); // checks if max rank is achieved and plays fireworks w/ special text string messageText; if (IsAttributeMaxRank(creatureAttribute.Ranks)) { // fireworks PlayParticleEffect(ACE.Entity.Enum.PlayScript.WeddingBliss, Guid); messageText = $"Your base {attribute} is now {creatureAttribute.Base} and has reached its upper limit!"; } else { messageText = $"Your base {attribute} is now {creatureAttribute.Base}!"; } var soundEvent = new GameMessageSound(Guid, Sound.RaiseTrait, 1f); var message = new GameMessageSystemChat(messageText, ChatMessageType.Advancement); // This seems to be needed to keep health up to date properly. // Needed when increasing health and endurance. if (attribute == PropertyAttribute.Endurance) { var healthUpdate = new GameMessagePrivateUpdateVital(this, PropertyAttribute2nd.MaxHealth, Health.Ranks, Health.StartingValue, Health.ExperienceSpent, Health.Current); Session.Network.EnqueueSend(abilityUpdate, soundEvent, message, healthUpdate); } else if (attribute == PropertyAttribute.Self) { var manaUpdate = new GameMessagePrivateUpdateVital(this, PropertyAttribute2nd.MaxMana, Mana.Ranks, Mana.StartingValue, Mana.ExperienceSpent, Mana.Current); Session.Network.EnqueueSend(abilityUpdate, soundEvent, message, manaUpdate); } else { Session.Network.EnqueueSend(abilityUpdate, soundEvent, message); } // retail was missing the 'raise attribute' runrate hook here if ((attribute == PropertyAttribute.Strength || attribute == PropertyAttribute.Quickness) && PropertyManager.GetBool("runrate_add_hooks").Item) { HandleRunRateUpdate(); } } else { ChatPacket.SendServerMessage(Session, $"Your attempt to raise {attribute} has failed.", ChatMessageType.Broadcast); } }
public void SpendAllAvailableAttributeXp(CreatureAttribute creatureAttribute, bool sendNetworkUpdate = true) { var amountRemaining = creatureAttribute.ExperienceLeft; if (amountRemaining > AvailableExperience) { amountRemaining = (uint)AvailableExperience; } SpendAttributeXp(creatureAttribute, amountRemaining, sendNetworkUpdate); }
public void SpendAllAvailableAttributeXp(CreatureAttribute creatureAttribute, bool sendNetworkUpdate = true) { var amountRemaining = creatureAttribute.ExperienceLeft; if (amountRemaining > AvailableExperience) { amountRemaining = (uint)AvailableExperience; } SpendAttributeXp(creatureAttribute, amountRemaining, sendNetworkUpdate); if (sendNetworkUpdate) { Session.Network.EnqueueSend(new GameMessagePrivateUpdateAttribute(this, creatureAttribute)); } }
internal EnumCreatureAttribute(CreatureAttribute type) { this.Enum = type; }