csharp/ACEmulator/ACE/Source/ACE.Server/WorldObjects/ManaStone.cs

WorldObjects
ManaStone.cs
using System;
using System.Collections.Generic;
using System.Linq;

using log4net;

using ACE.Common;
using ACE.Ensaty;
using ACE.Ensaty.Enum;
using ACE.Ensaty.Enum.Properties;
using ACE.Ensaty.Models;
using ACE.Server.Network.GameEvent.Events;
using ACE.Server.Network.GameMessages.Messages;

namespace ACE.Server.WorldObjects
{
    public clast ManaStone : WorldObject
    {
        private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        /// 
        /// A new biota be created taking all of its values from weenie.
        /// 
        public ManaStone(Weenie weenie, ObjectGuid guid) : base(weenie, guid)
        {
            SetEphemeralValues();
        }

        /// 
        /// Restore a WorldObject from the database.
        /// 
        public ManaStone(Biota biota) : base(biota)
        {
            SetEphemeralValues();
        }

        private void SetEphemeralValues()
        {
        }

        private double? Efficiency
        {
            get => GetProperty(PropertyFloat.ItemEfficiency);
            set { if (!value.HasValue) RemoveProperty(PropertyFloat.ItemEfficiency); else SetProperty(PropertyFloat.ItemEfficiency, value.Value); }
        }

        private double? DestroyChance
        {
            get => GetProperty(PropertyFloat.ManaStoneDestroyChance);
            set { if (!value.HasValue) RemoveProperty(PropertyFloat.ManaStoneDestroyChance); else SetProperty(PropertyFloat.ManaStoneDestroyChance, value.Value); }
        }

        public void SetUiEffect(Player player, UiEffects effect)
        {
            UiEffects = effect;
            player.EnqueueBroadcast(new GameMessagePublicUpdatePropertyInt(this, PropertyInt.UiEffects, (int)effect));
        }

        public override void HandleActionUseOnTarget(Player player, WorldObject target)
        {
            WorldObject invTarget;

            var useResult = WeenieError.None;

            if (player.IsOlthoiPlayer)
            {
                player.SendUseDoneEvent(WeenieError.OlthoiCannotInteractWithThat);
                return;
            }

            if (player != target)
            {
                invTarget = player.FindObject(target.Guid.Full, Player.SearchLocations.MyInventory | Player.SearchLocations.MyEquippedItems);
                if (invTarget == null)
                {
                    // Haven't looked to see if an error was sent for this case; however, this one fits
                    player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, WeenieError.YouDoNotOwnThasatem));
                    return;
                }

                target = invTarget;
            }

            if (!ItemCurMana.HasValue)
            {
                if (target == player)
                    useResult = WeenieError.ActionCancelled;
                else if (target.ItemCurMana.HasValue && target.ItemCurMana.Value > 0 && target.ItemMaxMana.HasValue && target.ItemMaxMana.Value > 0)
                {
                    // absorb mana from the item
                    if (target.Retained)
                        useResult = WeenieError.ActionCancelled;
                    else
                    {
                        if (!player.TryConsumeFromInventoryWithNetworking(target, 1) && !player.TryDequipObjectWithNetworking(target.Guid, out _, Player.DequipObjectAction.ConsumeItem))
                        {
                            log.Error($"Failed to remove {target.Name} from player inventory.");
                            player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, WeenieError.ActionCancelled));
                            return;
                        }

                        //The Mana Stone drains 5,253 points of mana from the Wand.
                        //The Wand is destroyed.

                        //The Mana Stone drains 4,482 points of mana from the Pantaloons.
                        //The Pantaloons is destroyed.

                        var manaDrained = (int)Math.Round(Efficiency.Value * target.ItemCurMana.Value);
                        ItemCurMana = manaDrained;
                        player.Session.Network.EnqueueSend(new GameMessageSystemChat($"The Mana Stone drains {ItemCurMana:N0} points of mana from the {target.Name}.\nThe {target.Name} is destroyed.", ChatMessageType.Broadcast));
                        SetUiEffect(player, ACE.Ensaty.Enum.UiEffects.Magical);
                    }
                }
                else
                {
                    useResult = WeenieError.ItemDoesntHaveEnoughMana;
                }
            }
            else if (ItemCurMana.Value > 0)
            {
                if (target == player)
                {
                    // dump mana into equipped items
                    var origItemsNeedingMana = player.EquippedObjects.Values.Where(k => k.ItemCurMana.HasValue && k.ItemMaxMana.HasValue && k.ItemCurMana < k.ItemMaxMana).ToList();
                    var itemsGivenMana = new Dictionary();

                    while (ItemCurMana > 0)
                    {
                        var itemsNeedingMana = origItemsNeedingMana.Where(k => k.ItemCurMana < k.ItemMaxMana).ToList();
                        if (itemsNeedingMana.Count < 1)
                            break;

                        var ration = Math.Max(ItemCurMana.Value / itemsNeedingMana.Count, 1);

                        foreach (var item in itemsNeedingMana)
                        {
                            var manaNeededForTopoff = (int)(item.ItemMaxMana - item.ItemCurMana);
                            var adjustedRation = Math.Min(ration, manaNeededForTopoff);

                            ItemCurMana -= adjustedRation;

                            if (player.LumAugItemManaGain != 0)
                            {
                                adjustedRation = (int)Math.Round(adjustedRation * Creature.GetPositiveRatingMod(player.LumAugItemManaGain * 5));
                                if (adjustedRation > manaNeededForTopoff)
                                {
                                    var diff = adjustedRation - manaNeededForTopoff;
                                    adjustedRation = manaNeededForTopoff;
                                    ItemCurMana += diff;
                                }
                            }

                            item.ItemCurMana += adjustedRation;
                            if (!itemsGivenMana.ContainsKey(item))
                                itemsGivenMana[item] = adjustedRation;
                            else
                                itemsGivenMana[item] += adjustedRation;

                            if (ItemCurMana