Пример #1
0
        public void Player_Tick(double currentUnixTime)
        {
            actionQueue.RunActions();

            if (nextAgeUpdateTime <= currentUnixTime)
            {
                nextAgeUpdateTime = currentUnixTime + ageUpdateInterval;

                if (initialAgeTime == DateTime.MinValue)
                {
                    initialAge     = Age ?? 1;
                    initialAgeTime = DateTime.UtcNow;
                }

                Age = initialAge + (int)(DateTime.UtcNow - initialAgeTime).TotalSeconds;

                // In retail, this is sent every 7 seconds. If you adjust ageUpdateInterval from 7, you'll need to re-add logic to send this every 7s (if you want to match retail)
                Session.Network.EnqueueSend(new GameMessagePrivateUpdatePropertyInt(this, PropertyInt.Age, Age ?? 1));
            }

            if (FellowVitalUpdate && Fellowship != null)
            {
                Fellowship.OnVitalUpdate(this);
                FellowVitalUpdate = false;
            }
        }
Пример #2
0
        /// <summary>
        /// Applies damages to a player from a physical damage source
        /// </summary>
        public void TakeDamage(WorldObject source, DamageType damageType, float _amount, BodyPart bodyPart, bool crit = false)
        {
            if (Invincible ?? false)
            {
                return;
            }

            // check lifestone protection
            if (UnderLifestoneProtection)
            {
                HandleLifestoneProtection();
                return;
            }

            var amount  = (uint)Math.Round(_amount);
            var percent = (float)amount / Health.MaxValue;

            // update health
            var damageTaken = (uint)-UpdateVitalDelta(Health, (int)-amount);

            DamageHistory.Add(source, damageType, damageTaken);

            // update stamina
            UpdateVitalDelta(Stamina, -1);

            if (Fellowship != null)
            {
                Fellowship.OnVitalUpdate(this);
            }

            if (Health.Current == 0)
            {
                OnDeath(source, damageType, crit);
                Die();
                return;
            }

            var damageLocation = (DamageLocation)BodyParts.Indices[bodyPart];

            // send network messages
            var creature = source as Creature;
            var hotspot  = source as Hotspot;

            if (creature != null)
            {
                var text = new GameEventDefenderNotification(Session, creature.Name, damageType, percent, amount, damageLocation, crit, AttackConditions.None);
                Session.Network.EnqueueSend(text);

                var hitSound = new GameMessageSound(Guid, GetHitSound(source, bodyPart), 1.0f);
                var splatter = new GameMessageScript(Guid, (PlayScript)Enum.Parse(typeof(PlayScript), "Splatter" + creature.GetSplatterHeight() + creature.GetSplatterDir(this)));
                EnqueueBroadcast(hitSound, splatter);
            }

            if (percent >= 0.1f)
            {
                EnqueueBroadcast(new GameMessageSound(Guid, Sound.Wound1, 1.0f));
            }
        }
Пример #3
0
        /// <summary>
        /// Simplified player take damage function, only called for DoTs currently
        /// </summary>
        public override void TakeDamageOverTime(float _amount, DamageType damageType)
        {
            if (Invincible ?? false || IsDead)
            {
                return;
            }

            // check lifestone protection
            if (UnderLifestoneProtection)
            {
                HandleLifestoneProtection();
                return;
            }

            var amount  = (uint)Math.Round(_amount);
            var percent = (float)amount / Health.MaxValue;

            // update health
            var damageTaken = (uint)-UpdateVitalDelta(Health, (int)-amount);

            // update stamina
            UpdateVitalDelta(Stamina, -1);

            if (Fellowship != null)
            {
                Fellowship.OnVitalUpdate(this);
            }

            // send damage text message
            if (PropertyManager.GetBool("show_dot_messages").Item)
            {
                var nether = damageType == DamageType.Nether ? "nether " : "";
                var text   = new GameMessageSystemChat($"You receive {amount} points of periodic {nether}damage.", ChatMessageType.Combat);
                Session.Network.EnqueueSend(text);
            }

            // splatter effects
            //var splatter = new GameMessageScript(Guid, (PlayScript)Enum.Parse(typeof(PlayScript), "Splatter" + creature.GetSplatterHeight() + creature.GetSplatterDir(this)));  // not sent in retail, but great visual indicator?
            var splatter = new GameMessageScript(Guid, damageType == DamageType.Nether ? ACE.Entity.Enum.PlayScript.HealthDownVoid : ACE.Entity.Enum.PlayScript.DirtyFightingDamageOverTime);

            EnqueueBroadcast(splatter);

            if (Health.Current <= 0)
            {
                // since damage over time is possibly combined from multiple sources,
                // sending a message to the last damager here could be tricky..
                OnDeath(null, damageType, false);
                Die();

                return;
            }

            if (percent >= 0.1f)
            {
                EnqueueBroadcast(new GameMessageSound(Guid, Sound.Wound1, 1.0f));
            }
        }
Пример #4
0
        public void Player_Tick(double currentUnixTime)
        {
            actionQueue.RunActions();

            if (nextAgeUpdateTime <= currentUnixTime)
            {
                nextAgeUpdateTime = currentUnixTime + ageUpdateInterval;

                if (initialAgeTime == DateTime.MinValue)
                {
                    initialAge     = Age ?? 1;
                    initialAgeTime = DateTime.UtcNow;
                }

                Age = initialAge + (int)(DateTime.UtcNow - initialAgeTime).TotalSeconds;

                // In retail, this is sent every 7 seconds. If you adjust ageUpdateInterval from 7, you'll need to re-add logic to send this every 7s (if you want to match retail)
                Session.Network.EnqueueSend(new GameMessagePrivateUpdatePropertyInt(this, PropertyInt.Age, Age ?? 1));
            }

            if (FellowVitalUpdate && Fellowship != null)
            {
                Fellowship.OnVitalUpdate(this);
                FellowVitalUpdate = false;
            }

            if (House != null && PropertyManager.GetBool("house_rent_enabled").Item)
            {
                if (houseRentWarnTimestamp > 0 && currentUnixTime > houseRentWarnTimestamp)
                {
                    HouseManager.GetHouse(House.Guid.Full, (house) =>
                    {
                        if (house != null && house.HouseStatus == HouseStatus.Active && !house.SlumLord.IsRentPaid())
                        {
                            Session.Network.EnqueueSend(new GameMessageSystemChat($"Warning!  You have not paid your maintenance costs for the last {(house.IsApartment ? "90" : "30")} day maintenance period.  Please pay these costs by this deadline or you will lose your house, and all your items within it.", ChatMessageType.Broadcast));
                        }
                    });

                    houseRentWarnTimestamp = Time.GetFutureUnixTime(houseRentWarnInterval);
                }
                else if (houseRentWarnTimestamp == 0)
                {
                    houseRentWarnTimestamp = Time.GetFutureUnixTime(houseRentWarnInterval);
                }
            }
        }
Пример #5
0
        /// <summary>
        /// Method used to perform the animation, sound, and vital update on consumption of food or potions
        /// </summary>
        /// <param name="consumableName">Name of the consumable</param>
        /// <param name="sound">Either Sound.Eat1 or Sound.Drink1</param>
        /// <param name="buffType">ConsumableBuffType.Spell,ConsumableBuffType.Health,ConsumableBuffType.Stamina,ConsumableBuffType.Mana</param>
        /// <param name="boostAmount">Amount the Vital is boosted by; can be null, if buffType = ConsumableBuffType.Spell</param>
        /// <param name="spellDID">Id of the spell cast by the consumable; can be null, if buffType != ConsumableBuffType.Spell</param>
        public void ApplyConsumable(string consumableName, Sound sound, ConsumableBuffType buffType, uint?boostAmount, uint?spellDID)
        {
            MotionCommand motionCommand;

            if (sound == Sound.Eat1)
            {
                motionCommand = MotionCommand.Eat;
            }
            else
            {
                motionCommand = MotionCommand.Drink;
            }

            // start the eat/drink motion
            var motion = new Motion(MotionStance.NonCombat, motionCommand);

            EnqueueBroadcastMotion(motion);

            var motionTable = DatManager.PortalDat.ReadFromDat <MotionTable>(MotionTableId);
            var animTime    = motionTable.GetAnimationLength(CurrentMotionState.Stance, motionCommand, MotionCommand.Ready);

            var actionChain = new ActionChain();

            actionChain.AddDelaySeconds(animTime);

            actionChain.AddAction(this, () =>
            {
                GameMessageSystemChat buffMessage;

                if (buffType == ConsumableBuffType.Spell)
                {
                    bool result = false;

                    uint spellId = spellDID ?? 0;

                    if (spellId != 0)
                    {
                        result = CreateSingleSpell(spellId);
                    }

                    if (result)
                    {
                        var spell   = new Server.Entity.Spell(spellId);
                        buffMessage = new GameMessageSystemChat($"{consumableName} casts {spell.Name} on you.", ChatMessageType.Magic);
                    }
                    else
                    {
                        buffMessage = new GameMessageSystemChat($"Consuming {consumableName} attempted to apply a spell not yet fully implemented.", ChatMessageType.System);
                    }
                }
                else
                {
                    CreatureVital creatureVital;
                    string vitalName;

                    // Null check for safety
                    if (boostAmount == null)
                    {
                        boostAmount = 0;
                    }

                    switch (buffType)
                    {
                    case ConsumableBuffType.Health:
                        creatureVital = Health;
                        vitalName     = "Health";
                        break;

                    case ConsumableBuffType.Mana:
                        creatureVital = Mana;
                        vitalName     = "Mana";
                        break;

                    default:
                        creatureVital = Stamina;
                        vitalName     = "Stamina";
                        break;
                    }

                    var vitalChange = UpdateVitalDelta(creatureVital, (uint)boostAmount);
                    if (vitalName == "Health")
                    {
                        DamageHistory.OnHeal((uint)vitalChange);
                        if (Fellowship != null)
                        {
                            Fellowship.OnVitalUpdate(this);
                        }
                    }

                    buffMessage = new GameMessageSystemChat($"You regain {vitalChange} {vitalName}.", ChatMessageType.Craft);
                }

                var soundEvent = new GameMessageSound(Guid, sound, 1.0f);
                EnqueueBroadcast(soundEvent);

                Session.Network.EnqueueSend(buffMessage);

                // return to original stance
                var returnStance = new Motion(CurrentMotionState.Stance);
                EnqueueBroadcastMotion(returnStance);
            });

            actionChain.EnqueueChain();
        }