Example #1
0
        /// <summary>
        /// This signature services MoveToObject and TurnToObject
        /// Update Position prior to start, start them moving or turning, set statemachine to moving.
        /// Moved from player - we need to be able to move creatures as well.   Og II
        /// </summary>
        /// <param name="worldObjectPosition">Position in the world</param>
        /// <param name="sequence">Sequence for the object getting the message.</param>
        /// <param name="movementType">What type of movement are we about to execute</param>
        /// <param name="targetGuid">Who are we moving or turning toward</param>
        /// <returns>MovementStates</returns>
        public void OnAutonomousMove(Position worldObjectPosition, SequenceManager sequence, MovementTypes movementType, ObjectGuid targetGuid)
        {
            UniversalMotion newMotion = new UniversalMotion(MotionStance.Standing, worldObjectPosition, targetGuid);

            newMotion.DistanceFrom  = 0.60f;
            newMotion.MovementTypes = movementType;
            CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessageUpdatePosition(this));
            CurrentLandblock.EnqueueBroadcastMotion(this, newMotion);
        }
Example #2
0
        public void HandleActionGetAndWieldItem(uint itemId, int wieldLocation)
        {
            new ActionChain(this, () =>
            {
                var itemGuid = new ObjectGuid(itemId);

                if (TryRemoveFromInventory(itemGuid, out WorldObject item))
                {
                    if (!TryEquipObject(item, wieldLocation))
                    {
                        log.Error("Player_Inventory HandleActionGetAndWieldItem TryEquipObject failed");
                        return;
                    }

                    if ((EquipMask)wieldLocation == EquipMask.MissileAmmo)
                    {
                        Session.Network.EnqueueSend(
                            new GameEventWieldItem(Session, itemGuid.Full, wieldLocation),
                            new GameMessageSound(Guid, Sound.WieldObject, 1.0f));
                    }
                    else
                    {
                        if (((EquipMask)wieldLocation & EquipMask.Selectable) != 0)
                        {
                            SetChild(item, wieldLocation, out var placementId, out var childLocation);

                            // todo I think we need to recalc our SetupModel here. see CalculateObjDesc()

                            CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange,
                                                              new GameMessageParentEvent(Session.Player, item, childLocation, placementId),
                                                              new GameEventWieldItem(Session, itemGuid.Full, wieldLocation),
                                                              new GameMessageSound(Guid, Sound.WieldObject, 1.0f),
                                                              new GameMessageUpdateInstanceId(Session.Player.Sequences, item.Guid, PropertyInstanceId.Container, new ObjectGuid(0)),
                                                              new GameMessageUpdateInstanceId(Session.Player.Sequences, item.Guid, PropertyInstanceId.Wielder, Guid),
                                                              new GameMessagePublicUpdatePropertyInt(Session.Player.Sequences, item.Guid, PropertyInt.CurrentWieldedLocation, wieldLocation));

                            if (CombatMode == CombatMode.NonCombat || CombatMode == CombatMode.Undef)
                            {
                                return;
                            }

                            switch ((EquipMask)wieldLocation)
                            {
                            case EquipMask.MissileWeapon:
                                SetCombatMode(CombatMode.Missile);
                                break;

                            case EquipMask.Held:
                                SetCombatMode(CombatMode.Magic);
                                break;

                            default:
                                SetCombatMode(CombatMode.Melee);
                                break;
                            }
                        }
Example #3
0
        public void HandleSwitchToMissileCombatMode(ActionChain combatModeChain)
        {
            HeldItem mEquipedMissile = Children.Find(s => s.EquipMask == EquipMask.MissileWeapon);

            if (mEquipedMissile?.Guid != null)
            {
                WorldObject missileWeapon = GetInventoryItem(new ObjectGuid(mEquipedMissile.Guid));
                if (missileWeapon == null)
                {
                    log.InfoFormat("Changing combat mode for {0} - could not locate wielded weapon {1}", Guid, mEquipedMissile.Guid);
                    return;
                }

                var mEquipedAmmo = WieldedObjects.First(s => s.Value.CurrentWieldedLocation == EquipMask.MissileAmmo).Value;

                MotionStance ms;

                if (missileWeapon.DefaultCombatStyle != null)
                {
                    ms = (MotionStance)missileWeapon.DefaultCombatStyle;
                }
                else
                {
                    log.InfoFormat("Changing combat mode for {0} - wielded item {1} has not be assigned a default combat style", Guid, mEquipedMissile.Guid);
                    return;
                }

                UniversalMotion mm = new UniversalMotion(ms);
                mm.MovementData.CurrentStyle = (ushort)ms;
                if (mEquipedAmmo == null)
                {
                    CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessageUpdatePosition(this));
                    SetMotionState(this, mm);
                }
                else
                {
                    CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessageUpdatePosition(this));
                    SetMotionState(this, mm);
                    mm.MovementData.ForwardCommand = (uint)MotionCommand.Reload;
                    SetMotionState(this, mm);
                    CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessageUpdatePosition(this));
                    // FIXME: (Og II)<this is a hack for now to be removed. Need to pull delay from dat file
                    combatModeChain.AddDelaySeconds(0.25);
                    // System.Threading.Thread.Sleep(250); // used for debugging
                    mm.MovementData.ForwardCommand = (ushort)MotionCommand.Invalid;
                    SetMotionState(this, mm);
                    // FIXME: (Og II)<this is a hack for now to be removed. Need to pull delay from dat file
                    combatModeChain.AddDelaySeconds(0.40);
                    combatModeChain.AddAction(this, () => CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessageParentEvent(this, mEquipedAmmo, 1, 1)));
                    // CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessageParentEvent(this, ammo, 1, 1)); // used for debugging
                }
                CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessagePrivateUpdatePropertyInt(Sequences, PropertyInt.CombatMode, (uint)CombatMode.Missile));
            }
        }
Example #4
0
        /// <summary>
        /// This method is called in response to a put item in container message. It is used when the item going into a container was wielded.
        /// It sets the appropriate properties, sends out response messages  and handles switching stances - for example if you have a bow wielded and are in bow combat stance,
        /// when you unwield the bow, this also sends the messages needed to go into unarmed combat mode. Og II
        /// </summary>
        private void UnwieldItem(Container container, WorldObject item, int placement)
        {
            EquipMask?oldLocation = item.CurrentWieldedLocation;

            item.ContainerId = container.Guid.Full;
            item.SetPropertiesForContainer(placement);

            TryDequipObject(item.Guid);

            // todo I think we need to recalc our SetupModel here. see CalculateObjDesc()

            if ((oldLocation & EquipMask.Selectable) != 0)
            {
                // We are coming from a hand shield slot.
                Children.Remove(Children.Find(s => s.Guid == item.Guid.Full));
            }

            // Set the container stuff
            item.ContainerId       = container.Guid.Full;
            item.PlacementPosition = placement;

            ActionChain inContainerChain = new ActionChain();

            inContainerChain.AddAction(this, () =>
            {
                if (container.Guid != Guid)
                {
                    container.AddToInventory(item, placement);
                    //Burden += item.Burden;
                }
                else
                {
                    AddToInventory(item, placement);
                }
            });
            inContainerChain.EnqueueChain();

            CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange,
                                              new GameMessageUpdateInstanceId(Session.Player.Sequences, item.Guid, PropertyInstanceId.Wielder, new ObjectGuid(0)),
                                              new GameMessagePublicUpdatePropertyInt(Session.Player.Sequences, item.Guid, PropertyInt.CurrentWieldedLocation, 0),
                                              new GameMessageUpdateInstanceId(Session.Player.Sequences, item.Guid, PropertyInstanceId.Container, container.Guid),
                                              new GameMessagePickupEvent(item),
                                              new GameMessageSound(Guid, Sound.UnwieldObject, (float)1.0),
                                              new GameMessagePutObjectInContainer(Session, container.Guid, item, placement),
                                              new GameMessageObjDescEvent(this));

            if ((oldLocation != EquipMask.MissileWeapon && oldLocation != EquipMask.Held && oldLocation != EquipMask.MeleeWeapon) || ((CombatMode & CombatMode.CombatCombat) == 0))
            {
                return;
            }

            HandleSwitchToPeaceMode(CombatMode);
            HandleSwitchToMeleeCombatMode(CombatMode);
        }
Example #5
0
        /// <summary>
        /// Executes the weapon reload animation for the player
        /// </summary>
        public float ReloadMotion()
        {
            var reloadAnimation = new MotionItem(GetReloadAnimation(), 1.0f);
            var animLength      = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, reloadAnimation);

            var motion = new UniversalMotion(CurrentMotionState.Stance);

            motion.MovementData.CurrentStyle   = (uint)CurrentMotionState.Stance;
            motion.MovementData.ForwardCommand = (uint)MotionCommand.Reload;
            motion.MovementData.TurnSpeed      = 2.25f;
            //motion.HasTarget = true;
            //motion.TargetGuid = target.Guid;
            CurrentMotionState = motion;

            var actionChain = new ActionChain();

            actionChain.AddAction(this, () => DoMotion(motion));

            actionChain.AddDelaySeconds(animLength);
            actionChain.AddAction(this, () =>
            {
                motion.MovementData.ForwardCommand = (uint)MotionCommand.Invalid;
                DoMotion(motion);
                CurrentMotionState = motion;
            });

            var ammo = GetEquippedAmmo();

            if (ammo != null)
            {
                actionChain.AddAction(this, () => CurrentLandblock.EnqueueBroadcast(Location,
                                                                                    new GameMessageParentEvent(this, ammo, (int)ACE.Entity.Enum.ParentLocation.RightHand,
                                                                                                               (int)ACE.Entity.Enum.Placement.RightHandCombat)));
            }

            actionChain.AddDelaySeconds(animLength);

            var player = this as Player;

            if (player != null)
            {
                actionChain.AddAction(this, () => player.Session.Network.EnqueueSend(new GameEventAttackDone(player.Session)));
                actionChain.AddAction(this, () => player.Session.Network.EnqueueSend(new GameEventCombatCommmenceAttack(player.Session)));
                // TODO: This gets rid of the hourglass but doesn't seem to be sent in retail pcaps...
                actionChain.AddAction(this, () => player.Session.Network.EnqueueSend(new GameEventAttackDone(player.Session)));
            }
            actionChain.EnqueueChain();

            var weapon     = GetEquippedWeapon();
            var reloadTime = weapon.DefaultCombatStyle == CombatStyle.Crossbow ? 3.2f : 1.6f;

            return(animLength * reloadTime);
        }
Example #6
0
        public void HandleSwitchToPeaceMode(CombatMode oldCombatMode, bool isAutonomous = false)
        {
            HandleUnloadMissileAmmo(oldCombatMode);

            // FIXME: (Og II)<this is a hack for now to be removed.> Placement has an issue we have not figured out.   It has to do with animation frame. Og II
            PositionFlag &= ~UpdatePositionFlag.Placement;
            // End hack
            CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessageUpdatePosition(this));
            UniversalMotion mm = new UniversalMotion(MotionStance.Standing);

            mm.MovementData.CurrentStyle = (ushort)MotionStance.Standing;
            SetMotionState(this, mm);
            CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessagePrivateUpdatePropertyInt(Sequences, PropertyInt.CombatMode, (uint)CombatMode.NonCombat));
        }
Example #7
0
        /// <summary>
        /// This method is called in response to a put item in container message. It is used when the item going into a container was wielded.
        /// It sets the appropriate properties, sends out response messages  and handles switching stances - for example if you have a bow wielded and are in bow combat stance,
        /// when you unwield the bow, this also sends the messages needed to go into unarmed combat mode. Og II
        /// </summary>
        private void UnwieldItemWithNetworking(Container container, WorldObject item, int placement)
        {
            EquipMask?oldLocation = item.CurrentWieldedLocation;

            if (!TryDequipObject(item.Guid))
            {
                log.Error("Player_Inventory UnwieldItemWithNetworking TryDequipObject failed");
                return;
            }

            item.SetPropertiesForContainer();

            if (!container.TryAddToInventory(item, placement))
            {
                log.Error("Player_Inventory UnwieldItemWithNetworking TryAddToInventory failed");
                return;
            }

            // If we've unwielded the item to a side pack, we must increment our main EncumbranceValue and Value
            if (container != this)
            {
                EncumbranceVal += item.EncumbranceVal;
                Value          += item.Value;
            }

            if ((oldLocation & EquipMask.Selectable) != 0)
            {
                // We are coming from a hand shield slot.
                Children.Remove(Children.Find(s => s.Guid == item.Guid.Full));
            }

            // todo I think we need to recalc our SetupModel here. see CalculateObjDesc()

            CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange,
                                              new GameMessageUpdateInstanceId(Session.Player.Sequences, item.Guid, PropertyInstanceId.Wielder, new ObjectGuid(0)),
                                              new GameMessagePublicUpdatePropertyInt(Session.Player.Sequences, item.Guid, PropertyInt.CurrentWieldedLocation, 0),
                                              new GameMessageUpdateInstanceId(Session.Player.Sequences, item.Guid, PropertyInstanceId.Container, container.Guid),
                                              new GameMessagePickupEvent(item),
                                              new GameMessageSound(Guid, Sound.UnwieldObject, (float)1.0),
                                              new GameMessagePutObjectInContainer(Session, container.Guid, item, placement),
                                              new GameMessageObjDescEvent(this));

            if ((oldLocation != EquipMask.MissileWeapon && oldLocation != EquipMask.Held && oldLocation != EquipMask.MeleeWeapon) || ((CombatMode & CombatMode.CombatCombat) == 0))
            {
                return;
            }

            HandleSwitchToPeaceMode(CombatMode);
            HandleSwitchToMeleeCombatMode(CombatMode);
        }
Example #8
0
        public void HandleSwitchToMagicCombatMode()
        {
            EquippedItem mEquipedWand = Children.Find(s => s.EquipMask == EquipMask.Held);

            if (mEquipedWand != null)
            {
                UniversalMotion mm = new UniversalMotion(MotionStance.Spellcasting);
                mm.MovementData.CurrentStyle = (ushort)MotionStance.Spellcasting;
                SetMotionState(this, mm);
                CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessagePrivateUpdatePropertyInt(Sequences, PropertyInt.CombatMode, (uint)CombatMode.Magic));
            }
            else
            {
                log.InfoFormat("Changing combat mode for {0} - could not locate a wielded magic caster", Guid);
            }
        }
Example #9
0
        /// <summary>
        /// This method will remove a worldobject if we have consumed all of the amount in the merge.
        /// This checks inventory or wielded items (you could be pulling stackable ammo out of a wielded slot and into a stack in your pack
        /// It then creates and sends the remove object message. Lastly, if the wo has ever been saved to the db, we clean up after ourselves.
        /// </summary>
        /// <param name="session">Session is used for sequence and target</param>
        /// <param name="fromWo">World object of the item are we merging from that needs to be destroyed.</param>
        public void RemoveWorldObject(Session session, WorldObject fromWo)
        {
            if (HasInventoryItem(fromWo.Guid))
            {
                session.Player.TryRemoveFromInventory(fromWo.Guid);
            }

            GameMessageRemoveObject msgRemoveFrom = new GameMessageRemoveObject(fromWo);

            CurrentLandblock.EnqueueBroadcast(Location, MaxObjectTrackingRange, msgRemoveFrom);

            // todo fix for EF
            throw new NotImplementedException();
            //if (fromWo.SnapShotOfAceObject().HasEverBeenSavedToDatabase)
            //   DatabaseManager.Shard.DeleteObject(fromWo.SnapShotOfAceObject(), null);
        }
Example #10
0
        /// <summary>
        /// Updates the ammo count or destroys the ammo after launching the projectile.
        /// </summary>
        /// <param name="ammo">The missile ammo object</param>
        public void UpdateAmmoAfterLaunch(WorldObject ammo)
        {
            var player = this as Player;

            if (ammo.StackSize == 1)
            {
                TryDequipObject(ammo.Guid);
                player?.Session.Network.EnqueueSend(new GameMessageDeleteObject(ammo));
                CurrentLandblock.EnqueueActionBroadcast(Location, Landblock.MaxObjectRange, p => p.StopTrackingObject(ammo, true));
            }
            else
            {
                ammo.StackSize--;
                player?.Session.Network.EnqueueSend(new GameMessageSetStackSize(ammo));
                CurrentLandblock.EnqueueBroadcast(Location, new GameMessagePickupEvent(ammo));
            }
        }
Example #11
0
        private void Close(ObjectGuid closer = new ObjectGuid())
        {
            if (CurrentMotionState == motionStateClosed)
            {
                return;
            }

            CurrentLandblock.EnqueueBroadcastMotion(this, motionClosed);
            CurrentMotionState = motionStateClosed;
            Ethereal           = false;
            IsOpen             = false;
            CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessagePublicUpdatePropertyBool(Sequences, Guid, PropertyBool.Ethereal, Ethereal ?? false));
            CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessagePublicUpdatePropertyBool(Sequences, Guid, PropertyBool.Open, IsOpen ?? false));
            if (closer.Full > 0)
            {
                UseTimestamp++;
            }
        }
Example #12
0
        private void Open(ObjectGuid opener = new ObjectGuid())
        {
            if (CurrentMotionState == motionStateOpen)
            {
                return;
            }

            CurrentLandblock.EnqueueBroadcastMotion(this, motionOpen);
            CurrentMotionState = motionStateOpen;
            Ethereal           = true;
            IsOpen             = true;
            CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessagePublicUpdatePropertyBool(Sequences, Guid, PropertyBool.Ethereal, Ethereal ?? true));
            CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessagePublicUpdatePropertyBool(Sequences, Guid, PropertyBool.Open, IsOpen ?? true));
            if (opener.Full > 0)
            {
                UseTimestamp++;
            }
        }
Example #13
0
        /// <summary>
        /// Launches a missile attack from monster to target
        /// </summary>
        public void RangeAttack()
        {
            var dist = GetDistanceToTarget();

            //Console.WriteLine("RangeAttack: " + dist);

            NextAttackTime = Timer.CurrentTime + MissileDelay;

            var weapon = GetEquippedWeapon();
            var sound  = weapon.DefaultCombatStyle == CombatStyle.Crossbow ? Sound.CrossbowRelease : Sound.BowRelease;

            if (CurrentLandblock != null)
            {
                CurrentLandblock.EnqueueBroadcast(Location, new GameMessageSound(Guid, sound, 1.0f));
            }

            var player   = AttackTarget as Player;
            var bodyPart = GetBodyPart();

            float targetTime   = 0.0f;
            var   damageSource = LaunchProjectile(AttackTarget, out targetTime);
            var   animLength   = ReloadMotion();

            var actionChain = new ActionChain();

            actionChain.AddDelaySeconds(targetTime);
            actionChain.AddAction(this, () =>
            {
                var critical   = false;
                var damageType = DamageType.Undef;
                var damage     = CalculateDamage(ref damageType, bodyPart, ref critical);

                if (damage > 0.0f)
                {
                    player.TakeDamage(this, damageType, damage, bodyPart, critical);
                }
                else
                {
                    player.Session.Network.EnqueueSend(new GameMessageSystemChat($"You evaded {Name}!", ChatMessageType.CombatEnemy));
                }
            });

            actionChain.EnqueueChain();
        }
Example #14
0
        /// <summary>
        /// This method will remove a worldobject if we have consumed all of the amount in the merge.
        /// This checks inventory or wielded items (you could be pulling stackable ammo out of a wielded slot and into a stack in your pack
        /// It then creates and sends the remove object message.   Lastly, if the wo has ever been saved to the db, we clean up after ourselves.
        /// </summary>
        /// <param name="session">Session is used for sequence and target</param>
        /// <param name="fromWo">World object of the item are we merging from that needs to be destroyed.</param>
        public void RemoveWorldObject(Session session, WorldObject fromWo)
        {
            if (HasItem(fromWo.Guid))
            {
                session.Player.RemoveWorldObjectFromInventory(fromWo.Guid);
            }
            else
            {
                session.Player.RemoveFromWieldedObjects(fromWo.Guid);
            }
            GameMessageRemoveObject msgRemoveFrom = new GameMessageRemoveObject(fromWo);

            CurrentLandblock.EnqueueBroadcast(Location, MaxObjectTrackingRange, msgRemoveFrom);

            if (fromWo.SnapShotOfAceObject().HasEverBeenSavedToDatabase)
            {
                DatabaseManager.Shard.DeleteObject(fromWo.SnapShotOfAceObject(), null);
            }
        }
Example #15
0
        /// <summary>
        /// Launches a missile attack from player to target
        /// </summary>
        public void LaunchMissile(WorldObject target)
        {
            if (GetEquippedAmmo() == null || CombatMode == CombatMode.NonCombat)
            {
                return;
            }

            var creature = target as Creature;

            if (MissileTarget == null || creature.Health.Current <= 0)
            {
                MissileTarget = null;
                return;
            }

            var weapon = GetEquippedWeapon();
            var sound  = weapon.DefaultCombatStyle == CombatStyle.Crossbow ? Sound.CrossbowRelease : Sound.BowRelease;

            CurrentLandblock.EnqueueBroadcast(Location, new GameMessageSound(Guid, sound, 1.0f));

            float targetTime   = 0.0f;
            var   damageSource = LaunchProjectile(target, out targetTime);

            // todo: get correct animlengths for shoot + reload + aim
            var animLength = ReloadMotion() * 2.5f;

            var actionChain = new ActionChain();

            //actionChain.AddDelaySeconds(targetTime);
            //actionChain.AddAction(this, () => DamageTarget(target, damageSource));

            if (creature.Health.Current > 0 && GetCharacterOption(CharacterOption.AutoRepeatAttacks))
            {
                // reload animation, accuracy bar refill
                actionChain.AddDelaySeconds(animLength + AccuracyLevel);
                actionChain.AddAction(this, () => { LaunchMissile(target); });
                actionChain.EnqueueChain();
            }
            else
            {
                MissileTarget = null;
            }
        }
Example #16
0
        /// <summary>
        ///  Sends object description if the client requests it
        /// </summary>
        /// <param name="item"></param>
        public void HandleActionForceObjDescSend(ObjectGuid item)
        {
            ActionChain objDescChain = new ActionChain();

            objDescChain.AddAction(this, () =>
            {
                WorldObject wo = GetInventoryItem(item);
                if (wo != null)
                {
                    CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange,
                                                      new GameMessageObjDescEvent(wo));
                }
                else
                {
                    log.Debug($"Error - requested object description for an item I do not know about - {item.Full:X}");
                }
            });
            objDescChain.EnqueueChain();
        }
Example #17
0
        /// <summary>
        /// This method is called if we unwield missle ammo.   It will check to see if I have arrows wielded
        /// send the message to "hide" the arrow.
        /// </summary>
        /// <param name="oldCombatMode"></param>
        public void HandleUnloadMissileAmmo(CombatMode oldCombatMode)
        {
            // Before I can switch to any non missile mode, do I have missile ammo I need to remove?
            WorldObject ammo         = null;
            HeldItem    mEquipedAmmo = Children.Find(s => s.EquipMask == EquipMask.MissileAmmo);

            if (mEquipedAmmo != null)
            {
                ammo = GetInventoryItem(new ObjectGuid(mEquipedAmmo.Guid));
            }

            if (oldCombatMode == CombatMode.Missile)
            {
                if (ammo != null)
                {
                    ammo.Location = null;
                    CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessagePickupEvent(ammo));
                }
            }
        }
Example #18
0
        /// <summary>
        /// This method sets us into peace mode.   It checks our current state to see if we have missle ammo equipped
        /// it will make the call to hid the "ammo" as we switch to peace mode.   It will then send the message switch our stance. Og II
        /// </summary>
        /// <param name="oldCombatMode"></param>
        /// <param name="isAutonomous"></param>
        public void HandleSwitchToPeaceMode(CombatMode oldCombatMode, bool isAutonomous = false)
        {
            HandleUnloadMissileAmmo(oldCombatMode);

            // FIXME: (Og II)<this is a hack for now to be removed.> Placement has an issue we have not figured out.   It has to do with animation frame. Og II
            PositionFlag &= ~UpdatePositionFlag.Placement;
            // End hack
            CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessageUpdatePosition(this));
            UniversalMotion mm = new UniversalMotion(MotionStance.Standing);

            mm.MovementData.CurrentStyle = (uint)MotionStance.Standing;
            SetMotionState(this, mm);
            var mEquipedAmmo = WieldedObjects.FirstOrDefault(s => s.Value.CurrentWieldedLocation == EquipMask.MissileAmmo).Value;

            CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessagePrivateUpdatePropertyInt(Sequences, PropertyInt.CombatMode, (uint)CombatMode.NonCombat));
            if (mEquipedAmmo != null)
            {
                CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectGhostRange, new GameMessagePickupEvent(mEquipedAmmo));
            }
        }
Example #19
0
        /// <summary>
        /// Used for unlocking a door via lockpick, so contains a skill check
        /// player.Skills[Skill.Lockpick].ActiveValue should be sent for the skill check
        /// </summary>
        public UnlockDoorResults UnlockDoor(uint playerLockpickSkillLvl)
        {
            if (ResistLockpick == 0)
            {
                return(UnlockDoorResults.CannotBePicked);
            }

            if (playerLockpickSkillLvl >= ResistLockpick)
            {
                if (!IsLocked ?? false)
                {
                    return(UnlockDoorResults.AlreadyUnlocked);
                }

                IsLocked = false;
                CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessagePublicUpdatePropertyBool(Sequences, Guid, PropertyBool.Locked, IsLocked ?? false));
                CurrentLandblock.EnqueueBroadcastSound(this, Sound.LockSuccess);
                return(UnlockDoorResults.UnlockSuccess);
            }

            return(UnlockDoorResults.PickLockFailed);
        }
Example #20
0
        /// <summary>
        /// Used for unlocking a door via a key
        /// </summary>
        public UnlockDoorResults UnlockDoor(string keyCode)
        {
            if (IsOpen ?? false)
            {
                return(UnlockDoorResults.DoorOpen);
            }

            if (keyCode == LockCode)
            {
                if (!IsLocked ?? false)
                {
                    return(UnlockDoorResults.AlreadyUnlocked);
                }

                IsLocked = false;
                CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessagePublicUpdatePropertyBool(Sequences, Guid, PropertyBool.Locked, IsLocked ?? false));
                CurrentLandblock.EnqueueBroadcastSound(this, Sound.LockSuccess);
                return(UnlockDoorResults.UnlockSuccess);
            }

            return(UnlockDoorResults.IncorrectKey);
        }
Example #21
0
        /// <summary>
        /// Launches a projectile from player to target
        /// </summary>
        public float LaunchProjectile(WorldObject target)
        {
            var ammo  = GetEquippedAmmo();
            var arrow = WorldObjectFactory.CreateNewWorldObject(ammo.WeenieClassId);

            var origin = Location.ToGlobal();

            origin.Z += Height;

            var dest = target.Location.ToGlobal();

            dest.Z += target.Height / GetAimHeight(target);

            var speed = 35.0f;
            var dir   = Vector3.Normalize(dest - origin);

            origin += dir * 2.0f;

            arrow.Velocity = GetProjectileVelocity(target, origin, dir, dest, speed, out var time);

            var loc = Location;

            origin         = Position.FromGlobal(origin).Pos;
            arrow.Location = new Position(loc.LandblockId.Raw, origin.X, origin.Y, origin.Z, loc.Rotation.X, loc.Rotation.Y, loc.Rotation.Z, loc.RotationW);
            SetProjectilePhysicsState(arrow);

            LandblockManager.AddObject(arrow);
            CurrentLandblock.EnqueueBroadcast(arrow.Location, new GameMessageScript(arrow.Guid, ACE.Entity.Enum.PlayScript.Launch, 1.0f));

            var actionChain = new ActionChain();

            actionChain.AddDelaySeconds(time);
            actionChain.AddAction(arrow, () => Session.Network.EnqueueSend(new GameMessageSound(arrow.Guid, Sound.Collision, 1.0f)));
            actionChain.AddAction(arrow, () => CurrentLandblock.RemoveWorldObject(arrow.Guid, false));
            actionChain.EnqueueChain();

            return(time);
        }
Example #22
0
        private void Reset()
        {
            if ((Time.GetTimestamp() - UseTimestamp) < ResetInterval)
            {
                return;
            }

            if (!DefaultOpen)
            {
                Close(ObjectGuid.Invalid);
                if (DefaultLocked)
                {
                    IsLocked = true;
                    CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessagePublicUpdatePropertyBool(Sequences, Guid, PropertyBool.Locked, IsLocked ?? true));
                    // CurrentLandblock.EnqueueBroadcastSound(this, Sound.LockSuccess); // TODO: need to find the lock sound
                }
            }
            else
            {
                Open(ObjectGuid.Invalid);
            }

            ResetTimestamp++;
        }
Example #23
0
        public void HandleSwitchToMissileCombatMode(ActionChain combatModeChain)
        {
            // TODO and FIXME: GetInventoryItem doesn't work for this so this function is effectively broke
            HeldItem mEquipedMissile = Children.Find(s => s.EquipMask == EquipMask.MissileWeapon);

            if (mEquipedMissile?.Guid != null)
            {
                WorldObject missileWeapon = GetWieldedItem(new ObjectGuid(mEquipedMissile.Guid));
                if (missileWeapon == null)
                {
                    log.InfoFormat("Changing combat mode for {0} - could not locate wielded weapon {1}", Guid, mEquipedMissile.Guid);
                    return;
                }

                var mEquipedAmmo = GetEquippedAmmo();

                MotionStance ms;
                CombatStyle  cs;

                if (missileWeapon.DefaultCombatStyle != null)
                {
                    cs = missileWeapon.DefaultCombatStyle.Value;
                }
                else
                {
                    log.InfoFormat("Changing combat mode for {0} - wielded item {1} has not be assigned a default combat style", Guid, mEquipedMissile.Guid);
                    return;
                }

                switch (cs)
                {
                case CombatStyle.Bow:
                    ms = MotionStance.BowAttack;
                    break;

                case CombatStyle.Crossbow:
                    ms = MotionStance.CrossBowAttack;
                    break;

                default:
                    ms = MotionStance.Invalid;
                    break;
                }

                UniversalMotion mm = new UniversalMotion(ms);
                mm.MovementData.CurrentStyle = (ushort)ms;

                CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessageUpdatePosition(this));
                SetMotionState(this, mm);

                if (mEquipedAmmo != null)
                {
                    mm.MovementData.ForwardCommand = (uint)MotionCommand.Reload;
                    SetMotionState(this, mm);
                    CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessageUpdatePosition(this));
                    // FIXME: (Og II)<this is a hack for now to be removed. Need to pull delay from dat file
                    combatModeChain.AddDelaySeconds(0.25);
                    mm.MovementData.ForwardCommand = (ushort)MotionCommand.Invalid;
                    SetMotionState(this, mm);
                    // FIXME: (Og II)<this is a hack for now to be removed. Need to pull delay from dat file
                    combatModeChain.AddDelaySeconds(0.40);

                    // add to player tracking
                    var wielder = CurrentLandblock.GetObject(new ObjectGuid(mEquipedAmmo.WielderId.Value));
                    combatModeChain.AddAction(this, () => CurrentLandblock.EnqueueActionBroadcast(Location, Landblock.MaxObjectRange, (Player p) => p.TrackObject(wielder)));

                    combatModeChain.AddAction(this, () => CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessageParentEvent(this, mEquipedAmmo, 1, 1)));
                }

                var player = this as Player;
                if (player != null)
                {
                    player.Session.Network.EnqueueSend(new GameMessagePrivateUpdatePropertyInt(this, PropertyInt.CombatMode, (int)CombatMode.Missile));
                }
            }
        }
Example #24
0
        /// <summary>
        /// Method used for handling player targeted spell casts
        /// </summary>
        public void CreatePlayerSpell(ObjectGuid guidTarget, uint spellId)
        {
            Player         player         = CurrentLandblock.GetObject(Guid) as Player;
            WorldObject    target         = CurrentLandblock.GetObject(guidTarget);
            TargetCategory targetCategory = TargetCategory.WorldObject;

            if (target == null)
            {
                target         = GetWieldedItem(guidTarget);
                targetCategory = TargetCategory.Wielded;
            }
            if (target == null)
            {
                target         = GetInventoryItem(guidTarget);
                targetCategory = TargetCategory.Inventory;
            }
            if (target == null)
            {
                player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, errorType: WeenieError.TargetNotAcquired));
                targetCategory = TargetCategory.UnDef;
                return;
            }

            SpellTable spellTable = DatManager.PortalDat.SpellTable;

            if (!spellTable.Spells.ContainsKey(spellId))
            {
                player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, errorType: WeenieError.MagicInvalidSpellType));
                return;
            }

            SpellBase spell = spellTable.Spells[spellId];

            if (IsInvalidTarget(spell, target))
            {
                player.Session.Network.EnqueueSend(new GameEventCommunicationTransientString(player.Session, $"{spell.Name} cannot be cast on {target.Name}."));
                player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, errorType: WeenieError.None));
                return;
            }

            Database.Models.World.Spell spellStatMod = DatabaseManager.World.GetCachedSpell(spellId);
            if (spellStatMod == null)
            {
                player.Session.Network.EnqueueSend(new GameMessageSystemChat($"{spell.Name} spell not implemented, yet!", ChatMessageType.System));
                player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, errorType: WeenieError.MagicInvalidSpellType));
                return;
            }

            if (player.IsBusy == true)
            {
                player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, errorType: WeenieError.YoureTooBusy));
                return;
            }
            else
            {
                player.IsBusy = true;
            }

            uint targetEffect = spell.TargetEffect;

            // Grab player's skill level in the spell's Magic School
            var magicSkill = player.GetCreatureSkill(spell.School).Current;

            if (targetCategory == TargetCategory.WorldObject)
            {
                if (guidTarget != Guid)
                {
                    float distanceTo = Location.Distance2D(target.Location);

                    if (distanceTo > spell.BaseRangeConstant + magicSkill * spell.BaseRangeMod)
                    {
                        player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, errorType: WeenieError.MagicTargetOutOfRange),
                                                           new GameMessageSystemChat($"{target.Name} is out of range!", ChatMessageType.Magic));
                        player.IsBusy = false;
                        return;
                    }
                }
            }

            // Ensure that a harmful spell isn't being cast on a player target that doesn't have the same PK status
            if (target.WeenieClassId == 1 && player.PlayerKillerStatus != ACE.Entity.Enum.PlayerKillerStatus.NPK)
            {
                bool isSpellHarmful = IsSpellHarmful(spell);
                if (player.PlayerKillerStatus != target.PlayerKillerStatus && isSpellHarmful)
                {
                    player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, errorType: WeenieError.InvalidPkStatus));
                    player.IsBusy = false;
                    return;
                }
            }

            float scale   = SpellAttributes(player.Session.Account, spellId, out float castingDelay, out MotionCommand windUpMotion, out MotionCommand spellGesture);
            var   formula = SpellTable.GetSpellFormula(spellTable, spellId, player.Session.Account);

            bool spellCastSuccess = false || ((Physics.Common.Random.RollDice(0.0f, 1.0f) > (1.0f - SkillCheck.GetMagicSkillChance((int)magicSkill, (int)spell.Power))) &&
                                              (magicSkill >= (int)spell.Power - 50) && (magicSkill > 0));

            // Calculating mana usage
            #region
            CreatureSkill mc = player.GetCreatureSkill(Skill.ManaConversion);
            double        z  = mc.Current;
            double        baseManaPercent = 1;
            if (z > spell.Power)
            {
                baseManaPercent = spell.Power / z;
            }
            double preCost;
            uint   manaUsed;
            if ((int)Math.Floor(baseManaPercent) == 1)
            {
                preCost  = spell.BaseMana;
                manaUsed = (uint)preCost;
            }
            else
            {
                preCost = spell.BaseMana * baseManaPercent;
                if (preCost < 1)
                {
                    preCost = 1;
                }
                manaUsed = (uint)Physics.Common.Random.RollDice(1, (int)preCost);
            }
            if (spell.MetaSpellType == SpellType.Transfer)
            {
                uint vitalChange, casterVitalChange;
                vitalChange = (uint)(player.GetCurrentCreatureVital((PropertyAttribute2nd)spellStatMod.Source) * spellStatMod.Proportion);
                if (spellStatMod.TransferCap != 0)
                {
                    if (vitalChange > spellStatMod.TransferCap)
                    {
                        vitalChange = (uint)spellStatMod.TransferCap;
                    }
                }
                casterVitalChange = (uint)(vitalChange * (1.0f - spellStatMod.LossPercent));
                vitalChange       = (uint)(casterVitalChange / (1.0f - spellStatMod.LossPercent));

                if (spellStatMod.Source == (int)PropertyAttribute2nd.Mana && (vitalChange + 10 + manaUsed) > player.Mana.Current)
                {
                    ActionChain resourceCheckChain = new ActionChain();

                    resourceCheckChain.AddAction(this, () =>
                    {
                        CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(Guid, ACE.Entity.Enum.PlayScript.Fizzle, 0.5f));
                    });

                    resourceCheckChain.AddDelaySeconds(2.0f);
                    resourceCheckChain.AddAction(this, () =>
                    {
                        player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, errorType: WeenieError.YouDontHaveEnoughManaToCast));
                        player.IsBusy = false;
                    });

                    resourceCheckChain.EnqueueChain();

                    return;
                }
                else if ((vitalChange + 10) > player.GetCurrentCreatureVital((PropertyAttribute2nd)spellStatMod.Source))
                {
                    ActionChain resourceCheckChain = new ActionChain();

                    resourceCheckChain.AddAction(this, () =>
                    {
                        CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(Guid, ACE.Entity.Enum.PlayScript.Fizzle, 0.5f));
                    });

                    resourceCheckChain.AddDelaySeconds(2.0f);
                    resourceCheckChain.AddAction(this, () => player.IsBusy = false);
                    resourceCheckChain.EnqueueChain();

                    return;
                }
            }
            else if (manaUsed > player.Mana.Current)
            {
                ActionChain resourceCheckChain = new ActionChain();

                resourceCheckChain.AddAction(this, () =>
                {
                    CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(Guid, ACE.Entity.Enum.PlayScript.Fizzle, 0.5f));
                });

                resourceCheckChain.AddDelaySeconds(2.0f);
                resourceCheckChain.AddAction(this, () =>
                {
                    player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, errorType: WeenieError.YouDontHaveEnoughManaToCast));
                    player.IsBusy = false;
                });

                resourceCheckChain.EnqueueChain();

                return;
            }
            else
            {
                player.UpdateVital(player.Mana, player.Mana.Current - manaUsed);
            }
            #endregion

            ActionChain spellChain = new ActionChain();

            uint fastCast = (spell.Bitfield >> 14) & 0x1u;
            if (fastCast != 1)
            {
                spellChain.AddAction(this, () =>
                {
                    var motionWindUp = new UniversalMotion(MotionStance.Spellcasting);
                    motionWindUp.MovementData.CurrentStyle   = (ushort)((uint)MotionStance.Spellcasting & 0xFFFF);
                    motionWindUp.MovementData.ForwardCommand = (uint)windUpMotion;
                    motionWindUp.MovementData.ForwardSpeed   = 2;
                    DoMotion(motionWindUp);
                });
            }

            spellChain.AddAction(this, () =>
            {
                CurrentLandblock.EnqueueBroadcast(Location, new GameMessageCreatureMessage(SpellComponentsTable.GetSpellWords(DatManager.PortalDat.SpellComponentsTable,
                                                                                                                              formula), Name, Guid.Full, ChatMessageType.Magic));
            });

            spellChain.AddAction(this, () =>
            {
                var motionCastSpell = new UniversalMotion(MotionStance.Spellcasting);
                motionCastSpell.MovementData.CurrentStyle   = (ushort)((uint)MotionStance.Spellcasting & 0xFFFF);
                motionCastSpell.MovementData.ForwardCommand = (uint)spellGesture;
                motionCastSpell.MovementData.ForwardSpeed   = 2;
                DoMotion(motionCastSpell);
            });

            if (fastCast == 1)
            {
                spellChain.AddDelaySeconds(castingDelay * 0.26f);
            }
            else
            {
                spellChain.AddDelaySeconds(castingDelay);
            }

            if (spellCastSuccess == false)
            {
                spellChain.AddAction(this, () => CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(Guid, ACE.Entity.Enum.PlayScript.Fizzle, 0.5f)));
            }
            else
            {
                spellChain.AddAction(this, () =>
                {
                    bool targetDeath;
                    string message;

                    switch (spell.School)
                    {
                    case MagicSchool.WarMagic:
                        WarMagic(target, spell, spellStatMod);
                        break;

                    case MagicSchool.VoidMagic:
                        VoidMagic(target, spell, spellStatMod);
                        break;

                    case MagicSchool.CreatureEnchantment:
                        if (IsSpellHarmful(spell))
                        {
                            // Retrieve player's skill level in the Magic School
                            var playerMagicSkill = player.GetCreatureSkill(spell.School).Current;

                            // Retrieve target's Magic Defense Skill
                            Creature creature           = (Creature)target;
                            var targetMagicDefenseSkill = creature.GetCreatureSkill(Skill.MagicDefense).Current;

                            if (MagicDefenseCheck(playerMagicSkill, targetMagicDefenseSkill))
                            {
                                CurrentLandblock.EnqueueBroadcastSound(player, Sound.ResistSpell);
                                player.Session.Network.EnqueueSend(new GameMessageSystemChat($"{creature.Name} resists {spell.Name}", ChatMessageType.Magic));
                                break;
                            }
                        }
                        CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(target.Guid, (PlayScript)spell.TargetEffect, scale));
                        message = CreatureMagic(target, spell, spellStatMod);
                        if (message != "")
                        {
                            player.Session.Network.EnqueueSend(new GameMessageSystemChat(message, ChatMessageType.Magic));
                        }
                        break;

                    case MagicSchool.LifeMagic:
                        if (spell.MetaSpellType != SpellType.LifeProjectile)
                        {
                            if (IsSpellHarmful(spell))
                            {
                                // Retrieve player's skill level in the Magic School
                                var playerMagicSkill = player.GetCreatureSkill(spell.School).Current;

                                // Retrieve target's Magic Defense Skill
                                Creature creature           = (Creature)target;
                                var targetMagicDefenseSkill = creature.GetCreatureSkill(Skill.MagicDefense).Current;

                                if (MagicDefenseCheck(playerMagicSkill, targetMagicDefenseSkill))
                                {
                                    CurrentLandblock.EnqueueBroadcastSound(player, Sound.ResistSpell);
                                    player.Session.Network.EnqueueSend(new GameMessageSystemChat($"{creature.Name} resists {spell.Name}", ChatMessageType.Magic));
                                    break;
                                }
                            }
                        }
                        CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(target.Guid, (PlayScript)spell.TargetEffect, scale));
                        targetDeath = LifeMagic(target, spell, spellStatMod, out message);
                        if (message != null)
                        {
                            player.Session.Network.EnqueueSend(new GameMessageSystemChat(message, ChatMessageType.Magic));
                        }
                        if (targetDeath == true)
                        {
                            Creature creatureTarget = (Creature)target;
                            creatureTarget.Die();
                            Strings.DeathMessages.TryGetValue(DamageType.Base, out var messages);
                            player.Session.Network.EnqueueSend(new GameMessageSystemChat(string.Format(messages[0], target.Name), ChatMessageType.Broadcast));
                            player.EarnXP((long)target.XpOverride);
                        }
                        break;

                    case MagicSchool.ItemEnchantment:
                        if (guidTarget == Guid)
                        {
                            CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(Guid, (PlayScript)spell.CasterEffect, scale));
                        }
                        else
                        {
                            CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(target.Guid, (PlayScript)spell.TargetEffect, scale));
                        }
                        message = ItemMagic(target, spell, spellStatMod);
                        if (message != "")
                        {
                            player.Session.Network.EnqueueSend(new GameMessageSystemChat(message, ChatMessageType.Magic));
                        }
                        break;

                    default:
                        break;
                    }
                });
            }

            spellChain.AddAction(this, () =>
            {
                var motionReturnToCastStance = new UniversalMotion(MotionStance.Spellcasting);
                motionReturnToCastStance.MovementData.CurrentStyle   = (ushort)((uint)MotionStance.Spellcasting & 0xFFFF);
                motionReturnToCastStance.MovementData.ForwardCommand = (uint)MotionCommand.Invalid;
                DoMotion(motionReturnToCastStance);
            });

            spellChain.AddDelaySeconds(1.0f);

            spellChain.AddAction(this, () =>
            {
                player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, errorType: WeenieError.None));
                player.IsBusy = false;
            });

            spellChain.EnqueueChain();

            return;
        }
Example #25
0
        public void HandleSwitchToMeleeCombatMode(CombatMode olCombatMode)
        {
            bool shieldEquiped      = false;
            bool weaponInShieldSlot = false;

            // Check to see if we were in missile combat and have an arrow hanging around we might need to remove.
            HandleUnloadMissileAmmo(olCombatMode);

            EquippedItem mEquipedShieldSlot = Children.Find(s => s.EquipMask == EquipMask.Shield);

            if (mEquipedShieldSlot != null)
            {
                WorldObject itemInShieldSlot = GetInventoryItem(new ObjectGuid(mEquipedShieldSlot.Guid));
                if (itemInShieldSlot != null)
                {
                    if (itemInShieldSlot.ItemType == ItemType.Armor)
                    {
                        shieldEquiped = true;
                    }
                    else
                    {
                        weaponInShieldSlot = true;
                    }
                }
            }

            EquippedItem mEquipedMelee     = Children.Find(s => s.EquipMask == EquipMask.MeleeWeapon);
            EquippedItem mEquipedTwoHanded = Children.Find(s => s.EquipMask == EquipMask.TwoHanded);
            MotionStance ms = MotionStance.Invalid;

            // are we unarmed?   If so, do we have a shield?
            if (mEquipedMelee == null && mEquipedTwoHanded == null && !weaponInShieldSlot)
            {
                if (!shieldEquiped)
                {
                    ms = MotionStance.UaNoShieldAttack;
                }
                else
                {
                    ms = MotionStance.MeleeShieldAttack;
                }
            }
            else if (weaponInShieldSlot)
            {
                ms = MotionStance.DualWieldAttack;
            }

            if (mEquipedTwoHanded != null)
            {
                WorldObject twoHandedWeapon = GetInventoryItem(new ObjectGuid(mEquipedTwoHanded.Guid));
                if (twoHandedWeapon.DefaultCombatStyle != null)
                {
                    ms = twoHandedWeapon.DefaultCombatStyle.Value;
                }
            }

            // Let's see if we are melee single handed / two handed with our without shield as appropriate.
            if (mEquipedMelee?.Guid != null && ms != MotionStance.DualWieldAttack)
            {
                WorldObject meleeWeapon = GetInventoryItem(new ObjectGuid(mEquipedMelee.Guid));

                if (meleeWeapon == null)
                {
                    log.InfoFormat("Changing combat mode for {0} - could not locate wielded weapon {1}", Guid, mEquipedMelee.Guid);
                    return;
                }

                if (!shieldEquiped)
                {
                    if (meleeWeapon.DefaultCombatStyle != null)
                    {
                        ms = meleeWeapon.DefaultCombatStyle.Value;
                    }
                }
                else
                {
                    switch (meleeWeapon.DefaultCombatStyle)
                    {
                    case MotionStance.MeleeNoShieldAttack:
                        ms = MotionStance.MeleeShieldAttack;
                        break;

                    case MotionStance.ThrownWeaponAttack:
                        ms = MotionStance.ThrownShieldCombat;
                        break;

                    case MotionStance.UaNoShieldAttack:
                        ms = MotionStance.MeleeShieldAttack;
                        break;

                    default:
                        log.InfoFormat(
                            "Changing combat mode for {0} - unable to determine correct combat stance for weapon {1}", Guid, mEquipedMelee.Guid);
                        return;
                    }
                }
            }
            if (ms != MotionStance.Invalid)
            {
                UniversalMotion mm = new UniversalMotion(ms);
                mm.MovementData.CurrentStyle = (ushort)ms;
                SetMotionState(this, mm);
                CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessagePrivateUpdatePropertyInt(Sequences, PropertyInt.CombatMode, (uint)CombatMode.Melee));
            }
            else
            {
                log.InfoFormat("Changing combat mode for {0} - wielded item {1} has not be assigned a default combat style", Guid, mEquipedMelee?.Guid ?? mEquipedTwoHanded?.Guid);
            }
        }
Example #26
0
        /// <summary>
        /// Method used for handling player untargeted spell casts
        /// </summary>
        public void CreatePlayerSpell(uint spellId)
        {
            if (IsBusy == true)
            {
                Session.Network.EnqueueSend(new GameEventUseDone(Session, errorType: WeenieError.YoureTooBusy));
                return;
            }
            else
            {
                IsBusy = true;
            }

            SpellTable spellTable = DatManager.PortalDat.SpellTable;

            if (!spellTable.Spells.ContainsKey(spellId))
            {
                Session.Network.EnqueueSend(new GameEventUseDone(Session, errorType: WeenieError.MagicInvalidSpellType));
                IsBusy = false;
                return;
            }

            SpellBase spell = spellTable.Spells[spellId];

            Database.Models.World.Spell spellStatMod = DatabaseManager.World.GetCachedSpell(spellId);
            if (spellStatMod == null)
            {
                Session.Network.EnqueueSend(new GameMessageSystemChat($"{spell.Name} spell not implemented, yet!", ChatMessageType.System));
                Session.Network.EnqueueSend(new GameEventUseDone(Session, errorType: WeenieError.MagicInvalidSpellType));
                IsBusy = false;
                return;
            }

            // Grab player's skill level in the spell's Magic School
            var magicSkill = GetCreatureSkill(spell.School);

            float scale   = SpellAttributes(Session.Account, spellId, out float castingDelay, out MotionCommand windUpMotion, out MotionCommand spellGesture);
            var   formula = SpellTable.GetSpellFormula(spellTable, spellId, Session.Account);

            bool spellCastSuccess = false || ((Physics.Common.Random.RollDice(0.0f, 1.0f) > (1.0f - SkillCheck.GetMagicSkillChance((int)magicSkill.Current, (int)spell.Power))) &&
                                              (magicSkill.Current >= (int)spell.Power - 50) && (magicSkill.Current > 0));

            // Calculating mana usage
            #region
            if (spellCastSuccess == true)
            {
                CreatureSkill mc = GetCreatureSkill(Skill.ManaConversion);
                double        z  = mc.Current;
                double        baseManaPercent = 1;
                if (z > spell.Power)
                {
                    baseManaPercent = spell.Power / z;
                }
                double preCost;
                uint   manaUsed;
                if ((int)Math.Floor(baseManaPercent) == 1)
                {
                    preCost  = spell.BaseMana;
                    manaUsed = (uint)preCost;
                }
                else
                {
                    preCost = spell.BaseMana * baseManaPercent;
                    if (preCost < 1)
                    {
                        preCost = 1;
                    }
                    manaUsed = (uint)Physics.Common.Random.RollDice(1, (int)preCost);
                }
                if (spell.MetaSpellType == SpellType.Transfer)
                {
                    uint vitalChange, casterVitalChange;
                    vitalChange = (uint)(GetCurrentCreatureVital((PropertyAttribute2nd)spellStatMod.Source) * spellStatMod.Proportion);
                    if (spellStatMod.TransferCap != 0)
                    {
                        if (vitalChange > spellStatMod.TransferCap)
                        {
                            vitalChange = (uint)spellStatMod.TransferCap;
                        }
                    }
                    casterVitalChange = (uint)(vitalChange * (1.0f - spellStatMod.LossPercent));
                    vitalChange       = (uint)(casterVitalChange / (1.0f - spellStatMod.LossPercent));

                    if (spellStatMod.Source == (int)PropertyAttribute2nd.Mana && (vitalChange + 10 + manaUsed) > Mana.Current)
                    {
                        ActionChain resourceCheckChain = new ActionChain();

                        resourceCheckChain.AddAction(this, () =>
                        {
                            CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(Guid, ACE.Entity.Enum.PlayScript.Fizzle, 0.5f));
                        });

                        resourceCheckChain.AddDelaySeconds(2.0f);
                        resourceCheckChain.AddAction(this, () =>
                        {
                            Session.Network.EnqueueSend(new GameEventUseDone(Session, errorType: WeenieError.YouDontHaveEnoughManaToCast));
                            IsBusy = false;
                        });

                        resourceCheckChain.EnqueueChain();

                        return;
                    }

                    if ((vitalChange + 10) > GetCurrentCreatureVital((PropertyAttribute2nd)spellStatMod.Source))
                    {
                        ActionChain resourceCheckChain = new ActionChain();

                        resourceCheckChain.AddAction(this, () =>
                        {
                            CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(Guid, ACE.Entity.Enum.PlayScript.Fizzle, 0.5f));
                        });

                        resourceCheckChain.AddDelaySeconds(2.0f);
                        resourceCheckChain.AddAction(this, () => IsBusy = false);
                        resourceCheckChain.EnqueueChain();

                        return;
                    }
                }
                else if (manaUsed > Mana.Current)
                {
                    ActionChain resourceCheckChain = new ActionChain();

                    resourceCheckChain.AddAction(this, () =>
                    {
                        CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(Guid, ACE.Entity.Enum.PlayScript.Fizzle, 0.5f));
                    });

                    resourceCheckChain.AddDelaySeconds(2.0f);
                    resourceCheckChain.AddAction(this, () =>
                    {
                        Session.Network.EnqueueSend(new GameEventUseDone(Session, errorType: WeenieError.YouDontHaveEnoughManaToCast));
                        IsBusy = false;
                    });

                    resourceCheckChain.EnqueueChain();

                    return;
                }
                else
                {
                    UpdateVital(Mana, Mana.Current - manaUsed);
                }
            }
            #endregion

            ActionChain spellChain = new ActionChain();

            uint fastCast = (spell.Bitfield >> 14) & 0x1u;
            if (fastCast != 1)
            {
                spellChain.AddAction(this, () =>
                {
                    var motionWindUp = new UniversalMotion(MotionStance.Spellcasting);
                    motionWindUp.MovementData.CurrentStyle   = (ushort)((uint)MotionStance.Spellcasting & 0xFFFF);
                    motionWindUp.MovementData.ForwardCommand = (uint)windUpMotion;
                    motionWindUp.MovementData.ForwardSpeed   = 2;
                    DoMotion(motionWindUp);
                });
            }

            spellChain.AddAction(this, () =>
            {
                CurrentLandblock.EnqueueBroadcast(Location, new GameMessageCreatureMessage(SpellComponentsTable.GetSpellWords(DatManager.PortalDat.SpellComponentsTable,
                                                                                                                              formula), Name, Guid.Full, ChatMessageType.Magic));
            });

            spellChain.AddAction(this, () =>
            {
                var motionCastSpell = new UniversalMotion(MotionStance.Spellcasting);
                motionCastSpell.MovementData.CurrentStyle   = (ushort)((uint)MotionStance.Spellcasting & 0xFFFF);
                motionCastSpell.MovementData.ForwardCommand = (uint)spellGesture;
                motionCastSpell.MovementData.ForwardSpeed   = 2;
                DoMotion(motionCastSpell);
            });

            if (fastCast == 1)
            {
                spellChain.AddDelaySeconds(castingDelay * 0.26f);
            }
            else
            {
                spellChain.AddDelaySeconds(castingDelay);
            }

            if (spellCastSuccess == false)
            {
                spellChain.AddAction(this, () => CurrentLandblock.EnqueueBroadcast(Location, new GameMessageScript(Guid, ACE.Entity.Enum.PlayScript.Fizzle, 0.5f)));
            }
            else
            {
                // TODO - Successful spell casting code goes here for untargeted spells to replace line below
                Session.Network.EnqueueSend(new GameMessageSystemChat("Targeted SpellID " + spellId + " not yet implemented!", ChatMessageType.System));
            }

            spellChain.AddAction(this, () =>
            {
                var motionReturnToCastStance = new UniversalMotion(MotionStance.Spellcasting);
                motionReturnToCastStance.MovementData.CurrentStyle   = (ushort)((uint)MotionStance.Spellcasting & 0xFFFF);
                motionReturnToCastStance.MovementData.ForwardCommand = (uint)MotionCommand.Invalid;
                DoMotion(motionReturnToCastStance);
            });

            spellChain.AddDelaySeconds(1.0f);

            spellChain.AddAction(this, () =>
            {
                Session.Network.EnqueueSend(new GameEventUseDone(Session, errorType: WeenieError.None));
                IsBusy = false;
            });

            spellChain.EnqueueChain();

            return;
        }
Example #27
0
        /// <summary>
        /// This method is used to pick items off the world - out of 3D space and into our inventory or to a wielded slot.
        /// It checks the use case needed, sends the appropriate response messages.   In addition, it will move to objects
        /// that are out of range in the attemp to pick them up.   It will call update apperiance if needed and you have
        /// wielded an item from the ground. Og II
        /// </summary>
        /// <param name="container"></param>
        /// <param name="itemGuid"></param>
        /// <param name="placement"></param>
        /// <param name="iidPropertyId"></param>
        private void PickupItem(Container container, ObjectGuid itemGuid, int placement, PropertyInstanceId iidPropertyId)
        {
            // Logical operations:
            // !! FIXME: How to handle repeat on condition?
            // while (!objectInRange)
            //   try Move to object
            // !! FIXME: How to handle conditional
            // Try acquire from landblock
            // if acquire successful:
            //   add to container
            ActionChain pickUpItemChain = new ActionChain();

            // Move to the object
            pickUpItemChain.AddChain(CreateMoveToChain(itemGuid, PickUpDistance));

            // Pick up the object
            // Start pickup animation
            pickUpItemChain.AddAction(this, () =>
            {
                var motion = new UniversalMotion(MotionStance.Standing);
                motion.MovementData.ForwardCommand = (uint)MotionCommand.Pickup;
                CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange,
                                                  new GameMessageUpdatePosition(this),
                                                  new GameMessageUpdateMotion(Guid,
                                                                              Sequences.GetCurrentSequence(SequenceType.ObjectInstance),
                                                                              Sequences, motion));
            });
            // Wait for animation to progress
            var motionTable           = DatManager.PortalDat.ReadFromDat <MotionTable>(MotionTableId);
            var pickupAnimationLength = motionTable.GetAnimationLength(MotionCommand.Pickup);

            pickUpItemChain.AddDelaySeconds(pickupAnimationLength);

            // Ask landblock to transfer item
            // pickUpItemChain.AddAction(CurrentLandblock, () => CurrentLandblock.TransferItem(itemGuid, containerGuid));
            if (container.Guid.IsPlayer())
            {
                CurrentLandblock.QueueItemTransfer(pickUpItemChain, itemGuid, container.Guid);
            }
            else
            {
                CurrentLandblock.ScheduleItemTransferInContainer(pickUpItemChain, itemGuid, (Container)GetInventoryItem(container.Guid));
            }

            // Finish pickup animation
            pickUpItemChain.AddAction(this, () =>
            {
                // If success, the item is in our inventory:
                WorldObject item = GetInventoryItem(itemGuid);

                if (item.ContainerId != Guid.Full)
                {
                    //Burden += item.Burden ?? 0;

                    if (item.WeenieType == WeenieType.Coin)
                    {
                        UpdateCurrencyClientCalculations(WeenieType.Coin);
                    }
                }

                if (item is Container itemAsContainer)
                {
                    Session.Network.EnqueueSend(new GameEventViewContents(Session, itemAsContainer));

                    foreach (var packItem in itemAsContainer.Inventory)
                    {
                        Session.Network.EnqueueSend(new GameMessageCreateObject(packItem.Value));
                        UpdateCurrencyClientCalculations(WeenieType.Coin);
                    }
                }

                // Update all our stuff if we succeeded
                if (item != null)
                {
                    item.SetPropertiesForContainer(placement);
                    // FIXME(ddevec): I'm not 100% sure which of these need to be broadcasts, and which are local sends...
                    var motion = new UniversalMotion(MotionStance.Standing);
                    if (iidPropertyId == PropertyInstanceId.Container)
                    {
                        Session.Network.EnqueueSend(
                            ////new GameMessagePrivateUpdatePropertyInt(Session.Player.Sequences, PropertyInt.EncumbranceVal, UpdateBurden()),
                            new GameMessageSound(Guid, Sound.PickUpItem, 1.0f),
                            new GameMessageUpdateInstanceId(itemGuid, container.Guid, iidPropertyId),
                            new GameMessagePutObjectInContainer(Session, container.Guid, item, placement));
                    }
                    else
                    {
                        AddToWieldedObjects(item, container, (EquipMask)placement);
                        Session.Network.EnqueueSend(new GameMessageSound(Guid, Sound.WieldObject, (float)1.0),
                                                    new GameMessageObjDescEvent(this),
                                                    new GameMessageUpdateInstanceId(container.Guid, itemGuid, PropertyInstanceId.Wielder),
                                                    new GameEventWieldItem(Session, itemGuid.Full, placement));
                    }

                    CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange,
                                                      new GameMessageUpdateMotion(Guid, Sequences.GetCurrentSequence(SequenceType.ObjectInstance), Sequences, motion),
                                                      new GameMessagePickupEvent(item));

                    if (iidPropertyId == PropertyInstanceId.Wielder)
                    {
                        CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessageObjDescEvent(this));
                    }

                    // TODO: Og II - check this later to see if it is still required.
                    Session.Network.EnqueueSend(new GameMessageUpdateObject(item));
                }
                // If we didn't succeed, just stand up and be ashamed of ourself
                else
                {
                    var motion = new UniversalMotion(MotionStance.Standing);

                    CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange,
                                                      new GameMessageUpdateMotion(Guid,
                                                                                  Sequences.GetCurrentSequence(SequenceType.ObjectInstance),
                                                                                  Sequences, motion));
                    // CurrentLandblock.EnqueueBroadcast(self shame);
                }
            });
            // Set chain to run
            pickUpItemChain.EnqueueChain();
        }
Example #28
0
        /// <summary>
        /// Sends a death message broadcast all players on the landblock? that a killer has a victim
        /// </summary>
        /// <remarks>
        /// TODO:
        ///     1. Figure out who all receieves death messages, on what landblock and at what order -
        ///         Example: Does the players around the vicitm receive the message or do the players at the lifestone receieve the message, or both?
        /// </remarks>
        /// <param name="deathMessage"></param>
        /// <param name="victimId"></param>
        public void ActionBroadcastKill(string deathMessage, ObjectGuid victimId, ObjectGuid killerId)
        {
            var deathBroadcast = new GameMessagePlayerKilled(deathMessage, victimId, killerId);

            CurrentLandblock.EnqueueBroadcast(Location, Landblock.OutdoorChatRange, deathBroadcast);
        }
Example #29
0
        public void DoFinishBarber(ClientMessage message)
        {
            // Read the payload sent from the client...
            PaletteBaseId       = message.Payload.ReadUInt32();
            HeadObject          = message.Payload.ReadUInt32();
            HairTexture         = message.Payload.ReadUInt32();
            DefaultHairTexture  = message.Payload.ReadUInt32();
            EyesTexture         = message.Payload.ReadUInt32();
            DefaultEyesTexture  = message.Payload.ReadUInt32();
            NoseTexture         = message.Payload.ReadUInt32();
            DefaultNoseTexture  = message.Payload.ReadUInt32();
            MouthTexture        = message.Payload.ReadUInt32();
            DefaultMouthTexture = message.Payload.ReadUInt32();
            SkinPalette         = message.Payload.ReadUInt32();
            HairPalette         = message.Payload.ReadUInt32();
            EyesPalette         = message.Payload.ReadUInt32();
            SetupTableId        = message.Payload.ReadUInt32();

            uint option_bound = message.Payload.ReadUInt32(); // Supress Levitation - Empyrean Only
            uint option_unk   = message.Payload.ReadUInt32(); // Unknown - Possibly set aside for future use?

            // Check if Character is Empyrean, and if we need to set/change/send new motion table
            if (Heritage == 9)
            {
                // These are the motion tables for Empyrean float and not-float (one for each gender). They are hard-coded into the client.
                const uint EmpyreanMaleFloatMotionDID   = 0x0900020Bu;
                const uint EmpyreanFemaleFloatMotionDID = 0x0900020Au;
                const uint EmpyreanMaleMotionDID        = 0x0900020Eu;
                const uint EmpyreanFemaleMotionDID      = 0x0900020Du;

                // Check for the Levitation option for Empyrean. Shadow crown and Undead flames are handled by client.
                if (Gender == 1) // Male
                {
                    if (option_bound == 1 && MotionTableId != EmpyreanMaleMotionDID)
                    {
                        MotionTableId = EmpyreanMaleMotionDID;
                        Session.Network.EnqueueSend(new GameMessagePrivateUpdateDataID(this, PropertyDataId.MotionTable, (uint)MotionTableId));
                    }
                    else if (option_bound == 0 && MotionTableId != EmpyreanMaleFloatMotionDID)
                    {
                        MotionTableId = EmpyreanMaleFloatMotionDID;
                        Session.Network.EnqueueSend(new GameMessagePrivateUpdateDataID(this, PropertyDataId.MotionTable, (uint)MotionTableId));
                    }
                }
                else // Female
                {
                    if (option_bound == 1 && MotionTableId != EmpyreanFemaleMotionDID)
                    {
                        MotionTableId = EmpyreanFemaleMotionDID;
                        Session.Network.EnqueueSend(new GameMessagePrivateUpdateDataID(this, PropertyDataId.MotionTable, (uint)MotionTableId));
                    }
                    else if (option_bound == 0 && MotionTableId != EmpyreanFemaleFloatMotionDID)
                    {
                        MotionTableId = EmpyreanFemaleFloatMotionDID;
                        Session.Network.EnqueueSend(new GameMessagePrivateUpdateDataID(this, PropertyDataId.MotionTable, (uint)MotionTableId));
                    }
                }
            }


            // Broadcast updated character appearance
            CurrentLandblock.EnqueueBroadcast(
                Location,
                Landblock.MaxObjectRange,
                new GameMessageObjDescEvent(this));
        }
Example #30
0
        /// <summary>
        /// Creates the Magic projectile spells for Life, War, and Void Magic
        /// </summary>
        /// <param name="caster"></param>
        /// <param name="target"></param>
        /// <param name="spellId"></param>
        /// <param name="projectileWcid"></param>
        /// <param name="lifeProjectileDamage"></param>
        private void CreateSpellProjectile(WorldObject caster, WorldObject target, uint spellId, uint projectileWcid, uint lifeProjectileDamage = 0)
        {
            SpellProjectile spellProjectile = WorldObjectFactory.CreateNewWorldObject(projectileWcid) as SpellProjectile;

            spellProjectile.Setup(spellId);

            var origin = caster.Location.ToGlobal();

            if (spellProjectile.SpellType == SpellProjectile.ProjectileSpellType.Arc)
            {
                origin.Z += caster.Height;
            }
            else
            {
                origin.Z += caster.Height * 2.0f / 3.0f;
            }

            var dest = target.Location.ToGlobal();

            dest.Z += target.Height / 2.0f;

            var direction = Vector3.Normalize(dest - origin);

            // This is not perfect but is close to values that retail used. TODO: revisit this later.
            origin += direction * (caster.PhysicsObj.GetRadius() + spellProjectile.PhysicsObj.GetRadius());

            float time;
            var   dist  = (dest - origin).Length();
            float speed = 15f;

            if (spellProjectile.SpellType == SpellProjectile.ProjectileSpellType.Bolt)
            {
                speed = GetStationaryVelocity(15f, dist);
            }
            else if (spellProjectile.SpellType == SpellProjectile.ProjectileSpellType.Streak)
            {
                speed = GetStationaryVelocity(45f, dist);
            }
            else if (spellProjectile.SpellType == SpellProjectile.ProjectileSpellType.Arc)
            {
                speed = GetStationaryVelocity(40f, dist);
            }

            // TODO: Implement target leading for non arc spells
            // Also: velocity seems to increase when target is moving away from the caster and decrease when
            // the target is moving toward the caster. This still needs more research.

            var velocity = direction * speed;

            if (spellProjectile.SpellType == SpellProjectile.ProjectileSpellType.Arc)
            {
                spellProjectile.Velocity = GetSpellProjectileVelocity(origin, dest, speed, out time);
            }
            else
            {
                spellProjectile.Velocity = new AceVector3(velocity.X, velocity.Y, velocity.Z);
                var velocityLength = spellProjectile.Velocity.Get().Length();
                time = dist / velocityLength;
            }
            spellProjectile.FlightTime = time;

            var loc = caster.Location;

            origin = loc.Pos;
            if (spellProjectile.SpellType == SpellProjectile.ProjectileSpellType.Arc)
            {
                origin.Z += caster.Height;
            }
            else
            {
                origin.Z += caster.Height * 2.0f / 3.0f;
            }
            origin += direction * (caster.PhysicsObj.GetRadius() + spellProjectile.PhysicsObj.GetRadius());

            spellProjectile.Location             = new ACE.Entity.Position(loc.LandblockId.Raw, origin.X, origin.Y, origin.Z, loc.Rotation.X, loc.Rotation.Y, loc.Rotation.Z, loc.RotationW);
            spellProjectile.ParentWorldObject    = (Creature)this;
            spellProjectile.TargetGuid           = target.Guid;
            spellProjectile.LifeProjectileDamage = lifeProjectileDamage;

            LandblockManager.AddObject(spellProjectile);
            CurrentLandblock.EnqueueBroadcast(spellProjectile.Location, new GameMessageScript(spellProjectile.Guid, ACE.Entity.Enum.PlayScript.Launch, spellProjectile.PlayscriptIntensity));

            // TODO : removed when real server projectile tracking and collisions are implemented
            var actionChain = new ActionChain();

            actionChain.AddDelaySeconds(spellProjectile.FlightTime);
            actionChain.AddAction(spellProjectile, () => spellProjectile.HandleOnCollide(spellProjectile.TargetGuid));
            actionChain.EnqueueChain();
        }