Esempio n. 1
0
        public void ActOnJoin(ObjectGuid playerId)
        {
            if (active)
                return;

            active = true;
            Player player = CurrentLandblock?.GetObject(playerId) as Player;

            // team is either 0 or 1. -1 means failed to join
            var msgJoinResponse = new GameEventJoinGameResponse(player.Session, Guid.Full, 1);

            // 0 or 1 for winning team. -1 is used for stalemate, -2 (and gameId of 0) is used to exit game mode in client
            // var msgGameOver = new GameEventGameOver(player.Session, 0, -2);

            // player.Session.Network.EnqueueSend(msgJoinResponse, msgGameOver);
            player.Session.Network.EnqueueSend(msgJoinResponse);

            // 0xA9B2002E [135.97 133.313 94.4447] 1 0 0 0 (holtburg game location)

            // Drudges

            var drudgeRook1 = WorldObjectFactory.CreateNewWorldObject("drudgerook") as GamePiece;
            drudgeRook1.Location = new Position(Location.Cell, Location.PositionX - 3.5f, Location.PositionY - 3.5f, Location.PositionZ - 0.09788f, 0, 0, 0, 1);
            drudgeRook1.EnterWorld();

            var drudgeKnight1 = WorldObjectFactory.CreateNewWorldObject("drudgeknight") as GamePiece;
            drudgeKnight1.Location = new Position(Location.Cell, Location.PositionX - 2.5f, Location.PositionY - 3.5f, Location.PositionZ - 0.09771f, 0, 0, 0, 1);
            drudgeKnight1.EnterWorld();

            var drudgeBishop1 = WorldObjectFactory.CreateNewWorldObject("drudgebishop") as GamePiece;
            drudgeBishop1.Location = new Position(Location.Cell, Location.PositionX - 1.5f, Location.PositionY - 3.5f, Location.PositionZ - 0.09753f, 0, 0, 0, 1);
            drudgeBishop1.EnterWorld();

            var drudgeQueen = WorldObjectFactory.CreateNewWorldObject("drudgequeen") as GamePiece;            
            drudgeQueen.Location = new Position(Location.Cell, Location.PositionX - 0.5f, Location.PositionY - 3.5f, Location.PositionZ - 0.09735f, 0, 0, 0, 1);
            drudgeQueen.EnterWorld();

            var drudgeKing = WorldObjectFactory.CreateNewWorldObject("drudgeking") as GamePiece;
            drudgeKing.Location = new Position(Location.Cell, Location.PositionX + 0.5f, Location.PositionY - 3.5f, Location.PositionZ - 0.09718f, 0, 0, 0, 1);
            drudgeKing.EnterWorld();

            var drudgeBishop2 = WorldObjectFactory.CreateNewWorldObject("drudgebishop") as GamePiece;
            drudgeBishop2.Location = new Position(Location.Cell, Location.PositionX + 1.5f, Location.PositionY - 3.5f, Location.PositionZ - 0.09753f, 0, 0, 0, 1);
            drudgeBishop2.EnterWorld();

            var drudgeKnight2 = WorldObjectFactory.CreateNewWorldObject("drudgeknight") as GamePiece;
            drudgeKnight2.Location = new Position(Location.Cell, Location.PositionX + 2.5f, Location.PositionY - 3.5f, Location.PositionZ - 0.09771f, 0, 0, 0, 1);
            drudgeKnight2.EnterWorld();

            var drudgeRook2 = WorldObjectFactory.CreateNewWorldObject("drudgerook") as GamePiece;
            drudgeRook2.Location = new Position(Location.Cell, Location.PositionX + 3.5f, Location.PositionY - 3.5f, Location.PositionZ - 0.09788f, 0, 0, 0, 1);
            drudgeRook2.EnterWorld();

            var drudgePawn1 = WorldObjectFactory.CreateNewWorldObject("drudgepawn") as GamePiece;
            drudgePawn1.Location = new Position(Location.Cell, Location.PositionX - 3.5f, Location.PositionY - 2.5f, Location.PositionZ - 0.09788f, 0, 0, 0, 1);
            drudgePawn1.EnterWorld();

            var drudgePawn2 = WorldObjectFactory.CreateNewWorldObject("drudgepawn") as GamePiece;
            drudgePawn2.Location = new Position(Location.Cell, Location.PositionX - 2.5f, Location.PositionY - 2.5f, Location.PositionZ - 0.09771f, 0, 0, 0, 1);
            drudgePawn2.EnterWorld();

            var drudgePawn3 = WorldObjectFactory.CreateNewWorldObject("drudgepawn") as GamePiece;
            drudgePawn3.Location = new Position(Location.Cell, Location.PositionX - 1.5f, Location.PositionY - 2.5f, Location.PositionZ - 0.09753f, 0, 0, 0, 1);
            drudgePawn3.EnterWorld();

            var drudgePawn4 = WorldObjectFactory.CreateNewWorldObject("drudgepawn") as GamePiece;
            drudgePawn4.Location = new Position(Location.Cell, Location.PositionX - 0.5f, Location.PositionY - 2.5f, Location.PositionZ - 0.09735f, 0, 0, 0, 1);
            drudgePawn4.EnterWorld();

            var drudgePawn5 = WorldObjectFactory.CreateNewWorldObject("drudgepawn") as GamePiece;
            drudgePawn5.Location = new Position(Location.Cell, Location.PositionX + 0.5f, Location.PositionY - 2.5f, Location.PositionZ - 0.09718f, 0, 0, 0, 1);
            drudgePawn5.EnterWorld();

            var drudgePawn6 = WorldObjectFactory.CreateNewWorldObject("drudgepawn") as GamePiece;
            drudgePawn6.Location = new Position(Location.Cell, Location.PositionX + 1.5f, Location.PositionY - 2.5f, Location.PositionZ - 0.09753f, 0, 0, 0, 1);
            drudgePawn6.EnterWorld();

            var drudgePawn7 = WorldObjectFactory.CreateNewWorldObject("drudgepawn") as GamePiece;
            drudgePawn7.Location = new Position(Location.Cell, Location.PositionX + 2.5f, Location.PositionY - 2.5f, Location.PositionZ - 0.09771f, 0, 0, 0, 1);
            drudgePawn7.EnterWorld();

            var drudgePawn8 = WorldObjectFactory.CreateNewWorldObject("drudgepawn") as GamePiece;
            drudgePawn8.Location = new Position(Location.Cell, Location.PositionX + 3.5f, Location.PositionY - 2.5f, Location.PositionZ - 0.09788f, 0, 0, 0, 1);
            drudgePawn8.EnterWorld();

            // Mosswarts

            var mosswartRook1 = WorldObjectFactory.CreateNewWorldObject("mosswartrook") as GamePiece;
            mosswartRook1.Location = new Position(Location.Cell, Location.PositionX - 3.5f, Location.PositionY + 3.5f, Location.PositionZ - 0.09788f, 0, 0, 1, 0);
            mosswartRook1.EnterWorld();

            var mosswartKnight1 = WorldObjectFactory.CreateNewWorldObject("mosswartknight") as GamePiece;
            mosswartKnight1.Location = new Position(Location.Cell, Location.PositionX - 2.5f, Location.PositionY + 3.5f, Location.PositionZ - 0.09771f, 0, 0, 1, 0);
            mosswartKnight1.EnterWorld();

            var mosswartBishop1 = WorldObjectFactory.CreateNewWorldObject("mosswartbishop") as GamePiece;
            mosswartBishop1.Location = new Position(Location.Cell, Location.PositionX - 1.5f, Location.PositionY + 3.5f, Location.PositionZ - 0.09753f, 0, 0, 1, 0);
            mosswartBishop1.EnterWorld();

            var mosswartQueen = WorldObjectFactory.CreateNewWorldObject("mosswartqueen") as GamePiece;
            mosswartQueen.Location = new Position(Location.Cell, Location.PositionX - 0.5f, Location.PositionY + 3.5f, Location.PositionZ - 0.09735f, 0, 0, 1, 0);
            mosswartQueen.EnterWorld();

            var mosswartKing = WorldObjectFactory.CreateNewWorldObject("mosswartking") as GamePiece;
            mosswartKing.Location = new Position(Location.Cell, Location.PositionX + 0.5f, Location.PositionY + 3.5f, Location.PositionZ - 0.09718f, 0, 0, 1, 0);
            mosswartKing.EnterWorld();

            var mosswartBishop2 = WorldObjectFactory.CreateNewWorldObject("mosswartbishop") as GamePiece;
            mosswartBishop2.Location = new Position(Location.Cell, Location.PositionX + 1.5f, Location.PositionY + 3.5f, Location.PositionZ - 0.09753f, 0, 0, 1, 0);
            mosswartBishop2.EnterWorld();

            var mosswartKnight2 = WorldObjectFactory.CreateNewWorldObject("mosswartknight") as GamePiece;
            mosswartKnight2.Location = new Position(Location.Cell, Location.PositionX + 2.5f, Location.PositionY + 3.5f, Location.PositionZ - 0.09771f, 0, 0, 1, 0);
            mosswartKnight2.EnterWorld();

            var mosswartRook2 = WorldObjectFactory.CreateNewWorldObject("mosswartrook") as GamePiece;
            mosswartRook2.Location = new Position(Location.Cell, Location.PositionX + 3.5f, Location.PositionY + 3.5f, Location.PositionZ - 0.09788f, 0, 0, 1, 0);
            mosswartRook2.EnterWorld();

            var mosswartPawn1 = WorldObjectFactory.CreateNewWorldObject("mosswartpawn") as GamePiece;
            mosswartPawn1.Location = new Position(Location.Cell, Location.PositionX - 3.5f, Location.PositionY + 2.5f, Location.PositionZ - 0.09788f, 0, 0, 1, 0);
            mosswartPawn1.EnterWorld();

            var mosswartPawn2 = WorldObjectFactory.CreateNewWorldObject("mosswartpawn") as GamePiece;
            mosswartPawn2.Location = new Position(Location.Cell, Location.PositionX - 2.5f, Location.PositionY + 2.5f, Location.PositionZ - 0.09771f, 0, 0, 1, 0);
            mosswartPawn2.EnterWorld();

            var mosswartPawn3 = WorldObjectFactory.CreateNewWorldObject("mosswartpawn") as GamePiece;
            mosswartPawn3.Location = new Position(Location.Cell, Location.PositionX - 1.5f, Location.PositionY + 2.5f, Location.PositionZ - 0.09753f, 0, 0, 1, 0);
            mosswartPawn3.EnterWorld();

            var mosswartPawn4 = WorldObjectFactory.CreateNewWorldObject("mosswartpawn") as GamePiece;
            mosswartPawn4.Location = new Position(Location.Cell, Location.PositionX - 0.5f, Location.PositionY + 2.5f, Location.PositionZ - 0.09735f, 0, 0, 1, 0);
            mosswartPawn4.EnterWorld();

            var mosswartPawn5 = WorldObjectFactory.CreateNewWorldObject("mosswartpawn") as GamePiece;
            mosswartPawn5.Location = new Position(Location.Cell, Location.PositionX + 0.5f, Location.PositionY + 2.5f, Location.PositionZ - 0.09718f, 0, 0, 1, 0);
            mosswartPawn5.EnterWorld();

            var mosswartPawn6 = WorldObjectFactory.CreateNewWorldObject("mosswartpawn") as GamePiece;
            mosswartPawn6.Location = new Position(Location.Cell, Location.PositionX + 1.5f, Location.PositionY + 2.5f, Location.PositionZ - 0.09753f, 0, 0, 1, 0);
            mosswartPawn6.EnterWorld();

            var mosswartPawn7 = WorldObjectFactory.CreateNewWorldObject("mosswartpawn") as GamePiece;
            mosswartPawn7.Location = new Position(Location.Cell, Location.PositionX + 2.5f, Location.PositionY + 2.5f, Location.PositionZ - 0.09771f, 0, 0, 1, 0);
            mosswartPawn7.EnterWorld();

            var mosswartPawn8 = WorldObjectFactory.CreateNewWorldObject("mosswartpawn") as GamePiece;
            mosswartPawn8.Location = new Position(Location.Cell, Location.PositionX + 3.5f, Location.PositionY + 2.5f, Location.PositionZ - 0.09788f, 0, 0, 1, 0);
            mosswartPawn8.EnterWorld();

            // For HellsWrath...
            ActionChain gdlChain = new ActionChain();
            gdlChain.AddDelaySeconds(5);
            gdlChain.AddAction(this, () =>
            {
                drudgeRook1.Kill();
                drudgeBishop1.Kill();
                drudgeKnight1.Kill();
                drudgeQueen.Kill();
                drudgeKing.Kill();
                drudgeBishop2.Kill();
                drudgeKnight2.Kill();
                drudgeRook2.Kill();

                drudgePawn1.Kill();
                drudgePawn2.Kill();
                drudgePawn3.Kill();
                drudgePawn4.Kill();
                drudgePawn5.Kill();
                drudgePawn6.Kill();
                drudgePawn7.Kill();
                drudgePawn8.Kill();

                mosswartRook1.Kill();
                mosswartBishop1.Kill();
                mosswartKnight1.Kill();
                mosswartQueen.Kill();
                mosswartKing.Kill();
                mosswartBishop2.Kill();
                mosswartKnight2.Kill();
                mosswartRook2.Kill();

                mosswartPawn1.Kill();
                mosswartPawn2.Kill();
                mosswartPawn3.Kill();
                mosswartPawn4.Kill();
                mosswartPawn5.Kill();
                mosswartPawn6.Kill();
                mosswartPawn7.Kill();
                mosswartPawn8.Kill();

                var msgGameOver = new GameEventGameOver(player.Session, Guid.Full, 0);
                player.Session.Network.EnqueueSend(msgGameOver);
            });
            gdlChain.AddDelaySeconds(2);
            gdlChain.AddAction(this, () =>
            {
                byte[] msg = Convert.FromBase64String("Z2FtZXNkZWFkbG9s");
                var popupGDL = new GameEventPopupString(player.Session, System.Text.Encoding.UTF8.GetString(msg, 0, msg.Length));
                var msgGameOver2 = new GameEventGameOver(player.Session, 0, -2);
                player.Session.Network.EnqueueSend(popupGDL, msgGameOver2);
                player.ChessGamesLost++;
                player.ChessTotalGames++;               
                active = false;
            });
            gdlChain.EnqueueChain();
        }
Esempio n. 2
0
        List<ActionChain> DoAction(Player p, Board board, 
            Func<List<Piece>,IEnumerable<ActionPair>> checkActionsFn,
            Action<Board,ActionPair> actionFn)
        {
            List<ActionChain> actions = new List<ActionChain> (4096);

            List<Piece> myPieces = new List<Piece> ();
            foreach (Piece pc in board.Pieces.Values)
            {
            if (pc.Owner == p)
            {
                myPieces.Add (pc);
            }
            }

            foreach (ActionPair move in checkActionsFn(myPieces))
            {
            ActionChain chain = new ActionChain ();
            chain.actions.Add (move);
            Board moveBoard = Board.AIClone (board);
            actionFn (moveBoard, move);
            chain.Board = moveBoard;

            actions.Add (chain);
            }

            ActionChain skipChain = new ActionChain ();
            skipChain.actions.Add (new ActionPair () {action = ActionTaken.SKIPPED});
            skipChain.Board = Board.AIClone (board);
            actions.Add (skipChain);

            return actions;
        }
Esempio n. 3
0
        public void ExecuteEmote(BiotaPropertiesEmote emote, BiotaPropertiesEmoteAction emoteAction, ActionChain actionChain, WorldObject sourceObject = null, WorldObject targetObject = null)
        {
            var player = targetObject as Player;

            switch ((EmoteType)emoteAction.Type)
            {
            case EmoteType.Say:

                actionChain.AddDelaySeconds(emoteAction.Delay);
                actionChain.AddAction(sourceObject, () =>
                {
                    sourceObject.CurrentLandblock.EnqueueBroadcast(sourceObject.Location, new GameMessageCreatureMessage(emoteAction.Message, sourceObject.Name, sourceObject.Guid.Full, ChatMessageType.Emote));
                });
                break;

            case EmoteType.Motion:

                if (emote.Category != (uint)EmoteCategory.Vendor && emote.Style != null)
                {
                    var startingMotion = new UniversalMotion((MotionStance)emote.Style, new MotionItem((MotionCommand)emote.Substyle));
                    var motion         = new UniversalMotion((MotionStance)emote.Style, new MotionItem((MotionCommand)emoteAction.Motion, emoteAction.Extent));

                    if (sourceObject.CurrentMotionState.Stance != startingMotion.Stance)
                    {
                        if (sourceObject.CurrentMotionState.Stance == MotionStance.Invalid)
                        {
                            actionChain.AddDelaySeconds(emoteAction.Delay);
                            actionChain.AddAction(sourceObject, () =>
                            {
                                sourceObject.DoMotion(startingMotion);
                                sourceObject.CurrentMotionState = startingMotion;
                            });
                        }
                    }
                    else
                    {
                        if (sourceObject.CurrentMotionState.Commands.Count > 0 && sourceObject.CurrentMotionState.Commands[0].Motion == startingMotion.Commands[0].Motion)
                        {
                            actionChain.AddDelaySeconds(emoteAction.Delay);
                            actionChain.AddAction(sourceObject, () =>
                            {
                                sourceObject.DoMotion(motion);
                                sourceObject.CurrentMotionState = motion;
                            });
                            actionChain.AddDelaySeconds(DatManager.PortalDat.ReadFromDat <DatLoader.FileTypes.MotionTable>(sourceObject.MotionTableId).GetAnimationLength((MotionCommand)emoteAction.Motion));
                            if (motion.Commands[0].Motion != MotionCommand.Sleeping && motion.Commands[0].Motion != MotionCommand.Sitting)     // this feels like it can be handled better, somehow?
                            {
                                actionChain.AddAction(sourceObject, () =>
                                {
                                    sourceObject.DoMotion(startingMotion);
                                    sourceObject.CurrentMotionState = startingMotion;
                                });
                            }
                        }
                    }
                }
                else
                {
                    var motion = new UniversalMotion(MotionStance.Standing, new MotionItem((MotionCommand)emoteAction.Motion, emoteAction.Extent));

                    actionChain.AddDelaySeconds(emoteAction.Delay);
                    actionChain.AddAction(sourceObject, () =>
                    {
                        sourceObject.DoMotion(motion);
                        sourceObject.CurrentMotionState = motion;
                    });
                }

                break;

            case EmoteType.Tell:
                actionChain.AddDelaySeconds(emoteAction.Delay);
                actionChain.AddAction(sourceObject, () =>
                {
                    player.Session.Network.EnqueueSend(new GameMessageHearDirectSpeech(sourceObject, emoteAction.Message, player, ChatMessageType.Tell));
                });
                break;

            case EmoteType.TurnToTarget:
                actionChain.AddDelaySeconds(emoteAction.Delay);
                var creature = sourceObject is Creature ? (Creature)sourceObject : null;
                actionChain.AddAction(sourceObject, () =>
                {
                    creature.Rotate(player);
                });
                actionChain.AddDelaySeconds(creature.GetRotateDelay(player));
                break;

            case EmoteType.AwardXP:
                actionChain.AddDelaySeconds(emoteAction.Delay);
                actionChain.AddAction(sourceObject, () =>
                {
                    if (player != null)
                    {
                        player.EarnXP((long)emoteAction.Amount64);
                        player.Session.Network.EnqueueSend(new GameMessageSystemChat("You've earned " + emoteAction.Amount64 + " experience.", ChatMessageType.System));
                    }
                });
                break;

            case EmoteType.Give:
                actionChain.AddAction(sourceObject, () =>
                {
                    if (player != null)
                    {
                        uint weenie      = (uint)emoteAction.WeenieClassId;
                        WorldObject item = WorldObjectFactory.CreateNewWorldObject(weenie);
                        if (emoteAction.WeenieClassId != null)
                        {
                            if (emoteAction.StackSize > 1)
                            {
                                item.StackSize = (ushort)emoteAction.StackSize;
                                player.Session.Network.EnqueueSend(new GameMessageSystemChat(WorldObject.Name + " gives you " + emoteAction.StackSize + " " + item.Name + ".", ChatMessageType.System));
                            }
                            else
                            {
                                player.Session.Network.EnqueueSend(new GameMessageSystemChat(WorldObject.Name + " gives you " + item.Name + ".", ChatMessageType.System));
                            }
                            var success = player.TryCreateInInventoryWithNetworking(item);
                        }
                    }
                });
                break;

            case EmoteType.UpdateQuest:
                //This is for the quest NPC's. This will be filled out when quests are added.
                break;

            case EmoteType.Turn:
                actionChain.AddDelaySeconds(emoteAction.Delay);
                creature = sourceObject is Creature ? (Creature)sourceObject : null;
                var pos = new Position(creature.Location.Cell, creature.Location.PositionX, creature.Location.PositionY, creature.Location.PositionZ, emoteAction.AnglesX ?? 0, emoteAction.AnglesY ?? 0, emoteAction.AnglesZ ?? 0, emoteAction.AnglesW ?? 0);
                actionChain.AddAction(sourceObject, () =>
                {
                    creature.TurnTo(pos);
                });
                actionChain.AddDelaySeconds(creature.GetTurnToDelay(pos));
                break;

            case EmoteType.Activate:
                creature = sourceObject is Creature ? (Creature)sourceObject : null;
                actionChain.AddDelaySeconds(emoteAction.Delay);
                actionChain.AddAction(sourceObject, () =>
                {
                    if ((creature.ActivationTarget ?? 0) > 0)
                    {
                        var activationTarget = creature.CurrentLandblock.GetObject(new ObjectGuid(creature.ActivationTarget ?? 0));
                        activationTarget.ActOnUse(creature);
                    }
                });
                break;

            default:
                log.Debug($"EmoteManager.Execute - Encountered Unhandled EmoteType {(EmoteType)emoteAction.Type} for {sourceObject.Name} ({sourceObject.WeenieClassId})");
                break;
            }
        }
Esempio n. 4
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 ApplyComsumable(string consumableName, Sound sound, ConsumableBuffType buffType, uint?boostAmount, uint?spellDID)
        {
            uint spellId = spellDID ?? 0;

            GameMessageSystemChat buffMessage;
            MotionCommand         motionCommand;

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

            var soundEvent = new GameMessageSound(Guid, sound, 1.0f);
            var motion     = new UniversalMotion(MotionStance.NonCombat, new MotionItem(motionCommand));

            EnqueueBroadcastMotion(motion);

            if (buffType == ConsumableBuffType.Spell)
            {
                bool result = false;
                if (spellId != 0)
                {
                    result = CreateSingleSpell(spellId);
                }

                if (!result)
                {
                    buffMessage = new GameMessageSystemChat($"Consuming {consumableName} attempted to apply a spell not yet fully implemented.", ChatMessageType.System);
                }
                else
                {
                    buffMessage = new GameMessageSystemChat($"{consumableName} applies {DatManager.PortalDat.SpellTable.Spells[spellId].Name} on you.", ChatMessageType.Craft);
                }
            }
            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);

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

            Session.Network.EnqueueSend(soundEvent, buffMessage);

            // Wait for animation
            var motionChain           = new ActionChain();
            var motionTable           = DatManager.PortalDat.ReadFromDat <MotionTable>((uint)MotionTableId);
            var motionAnimationLength = motionTable.GetAnimationLength(MotionCommand.Eat);

            motionChain.AddDelaySeconds(motionAnimationLength);

            // Return to standing position after the animation delay
            motionChain.AddAction(this, () => EnqueueBroadcastMotion(new UniversalMotion(MotionStance.NonCombat)));
            motionChain.EnqueueChain();
        }
Esempio n. 5
0
        /// <summary>
        /// Called every ~5 secs for equipped mana consuming items
        /// </summary>
        public void ManaConsumersTick()
        {
            if (!EquippedObjectsLoaded)
            {
                return;
            }

            var EquippedManaConsumers = EquippedObjects.Where(k =>
                                                              (k.Value.IsAffecting ?? false) &&
                                                              //k.Value.ManaRate.HasValue &&
                                                              k.Value.ItemMaxMana.HasValue &&
                                                              k.Value.ItemCurMana.HasValue &&
                                                              k.Value.ItemCurMana.Value > 0).ToList();

            foreach (var k in EquippedManaConsumers)
            {
                var item = k.Value;

                // this was a bug in lootgen until 7/11/2019, mostly for clothing/armor/shields
                // tons of existing items on servers are in this bugged state, where they aren't ticking mana.
                // this retroactively fixes them when equipped
                // items such as Impious Staff are excluded from this via IsAffecting

                if (item.ManaRate == null)
                {
                    item.ManaRate = LootGenerationFactory.GetManaRate(item);
                    log.Warn($"{Name}.ManaConsumersTick(): {k.Value.Name} ({k.Value.Guid}) fixed missing ManaRate");
                }

                var rate = item.ManaRate.Value;

                if (LumAugItemManaUsage != 0)
                {
                    rate *= GetNegativeRatingMod(LumAugItemManaUsage * 5);
                }

                if (!item.ItemManaConsumptionTimestamp.HasValue)
                {
                    item.ItemManaConsumptionTimestamp = DateTime.UtcNow;
                }
                DateTime mostRecentBurn = item.ItemManaConsumptionTimestamp.Value;

                var timePerBurn = -1 / rate;

                var secondsSinceLastBurn = (DateTime.UtcNow - mostRecentBurn).TotalSeconds;

                var delta = secondsSinceLastBurn / timePerBurn;

                var deltaChopped = (int)Math.Floor(delta);
                var deltaExtra   = delta - deltaChopped;

                if (deltaChopped <= 0)
                {
                    continue;
                }

                var timeToAdd = (int)Math.Floor(deltaChopped * timePerBurn);
                item.ItemManaConsumptionTimestamp = mostRecentBurn + new TimeSpan(0, 0, timeToAdd);
                var manaToBurn = Math.Min(item.ItemCurMana.Value, deltaChopped);
                deltaChopped      = Math.Clamp(deltaChopped, 0, 10);
                item.ItemCurMana -= deltaChopped;

                if (item.ItemCurMana < 1 || item.ItemCurMana == null)
                {
                    item.IsAffecting = false;
                    var msg   = new GameMessageSystemChat($"Your {item.Name} is out of Mana.", ChatMessageType.Magic);
                    var sound = new GameMessageSound(Guid, Sound.ItemManaDepleted);
                    Session.Network.EnqueueSend(msg, sound);
                    if (item.WielderId != null)
                    {
                        if (item.Biota.BiotaPropertiesSpellBook != null)
                        {
                            // unsure if these messages / sounds were ever sent in retail,
                            // or if it just purged the enchantments invisibly
                            // doing a delay here to prevent 'SpellExpired' sounds from overlapping with 'ItemManaDepleted'
                            var actionChain = new ActionChain();
                            actionChain.AddDelaySeconds(2.0f);
                            actionChain.AddAction(this, () =>
                            {
                                for (int i = 0; i < item.Biota.BiotaPropertiesSpellBook.Count; i++)
                                {
                                    RemoveItemSpell(item, (uint)item.Biota.BiotaPropertiesSpellBook.ElementAt(i).Spell);
                                }
                            });
                            actionChain.EnqueueChain();
                        }
                    }
                }
                else
                {
                    // get time until empty
                    var secondsUntilEmpty = ((item.ItemCurMana - deltaExtra) * timePerBurn);
                    if (secondsUntilEmpty <= 120 && (!item.ItemManaDepletionMessageTimestamp.HasValue || (DateTime.UtcNow - item.ItemManaDepletionMessageTimestamp.Value).TotalSeconds > 120))
                    {
                        item.ItemManaDepletionMessageTimestamp = DateTime.UtcNow;
                        Session.Network.EnqueueSend(new GameMessageSystemChat($"Your {item.Name} is low on Mana.", ChatMessageType.Magic));
                    }
                }
            }
        }
Esempio n. 6
0
        public override void OnUse(Session session)
        {
            bool   success    = true;
            string failReason = "You are unable to read the scroll.";

            switch (Power)
            {
            // research: http://asheron.wikia.com/wiki/Announcements_-_2002/06_-_Castling
            case spellLevel2:     // Level 2
            case spellLevel3:     // Level 3
            case spellLevel4:     // Level 4
            case spellLevel5:     // Level 5
            case spellLevel6:     // Level 6
                if (session.Player.CanReadScroll(School, Power))
                {
                    success = true;
                }
                else
                {
                    success    = false;
                    failReason = "You are not skilled enough in the inscribed spell's school of magic to understand the writing on this scroll.";
                }
                break;

            default:     // Level 1 or Level 7+ never fail
                success = true;
                break;
            }

            if (!session.Player.UnknownSpell(SpellId))
            {
                success    = false;
                failReason = "You already know the spell inscribed upon this scroll.";
            }

            ActionChain readScrollChain = new ActionChain();

            readScrollChain.AddAction(session.Player, () => session.Player.HandleActionMotion(motionReading));
            readScrollChain.AddDelaySeconds(2);

            if (success)
            {
                readScrollChain.AddAction(session.Player, () => session.Player.LearnSpell(SpellId));
                readScrollChain.AddAction(session.Player, () => session.Player.HandleActionMotion(motionReady));
                var removeObjMessage = new GameMessageRemoveObject(this);
                var destroyMessage   = new GameMessageSystemChat("The scroll is destroyed.", ChatMessageType.Magic);
                readScrollChain.AddAction(session.Player, () => session.Network.EnqueueSend(destroyMessage, removeObjMessage));
                readScrollChain.AddAction(session.Player, () => session.Player.RemoveWorldObjectFromInventory(Guid));
            }
            else
            {
                readScrollChain.AddDelaySeconds(2);
                readScrollChain.AddAction(session.Player, () => session.Player.HandleActionMotion(motionReady));
                var failMessage = new GameMessageSystemChat($"{failReason}", ChatMessageType.Magic);
                readScrollChain.AddAction(session.Player, () => session.Network.EnqueueSend(failMessage));
            }
            var sendUseDoneEvent = new GameEventUseDone(session.Player.Session);

            readScrollChain.AddAction(session.Player, () => session.Network.EnqueueSend(sendUseDoneEvent));
            readScrollChain.EnqueueChain();
        }
Esempio n. 7
0
        public void InqCategory(EmoteCategory categoryId, BiotaPropertiesEmoteAction emoteAction, WorldObject sourceObject, WorldObject targetObject, ActionChain actionChain, bool useRNG = false)
        {
            var rng = useRNG ? Physics.Common.Random.RollDice(0.0f, 1.0f) : 0.0f;

            var result = sourceObject.Biota.BiotaPropertiesEmote.FirstOrDefault(e => e.Category == (uint)categoryId && e.Quest == emoteAction.Message && rng <= e.Probability);

            if (result == null)
            {
                return;
            }

            foreach (var action in result.BiotaPropertiesEmoteAction)
            {
                actionChain.AddAction(sourceObject, () =>
                {
                    ExecuteEmote(result, action, actionChain, sourceObject, targetObject);
                });
            }
        }
Esempio n. 8
0
 public ActionChain(ActionChain link)
 {
     actions.AddRange (link.actions);
 }
Esempio n. 9
0
        private void FinalizeTrade(Player target)
        {
            if (!VerifyTrade_BusyState(target) || !VerifyTrade_Inventory(target))
            {
                return;
            }

            IsBusy        = true;
            target.IsBusy = true;

            TradeTransferInProgress        = true;
            target.TradeTransferInProgress = true;

            Session.Network.EnqueueSend(new GameEventCommunicationTransientString(Session, "The items are being traded"));
            target.Session.Network.EnqueueSend(new GameEventCommunicationTransientString(target.Session, "The items are being traded"));

            var tradedItems = new Collection <(Biota biota, ReaderWriterLockSlim rwLock)>();

            var myEscrow     = new List <WorldObject>();
            var targetEscrow = new List <WorldObject>();

            foreach (ObjectGuid itemGuid in ItemsInTradeWindow)
            {
                if (TryRemoveFromInventoryWithNetworking(itemGuid, out var wo, RemoveFromInventoryAction.TradeItem) || TryDequipObjectWithNetworking(itemGuid, out wo, DequipObjectAction.TradeItem))
                {
                    targetEscrow.Add(wo);

                    tradedItems.Add((wo.Biota, wo.BiotaDatabaseLock));
                }
            }

            foreach (ObjectGuid itemGuid in target.ItemsInTradeWindow)
            {
                if (target.TryRemoveFromInventoryWithNetworking(itemGuid, out var wo, RemoveFromInventoryAction.TradeItem) || target.TryDequipObjectWithNetworking(itemGuid, out wo, DequipObjectAction.TradeItem))
                {
                    myEscrow.Add(wo);

                    tradedItems.Add((wo.Biota, wo.BiotaDatabaseLock));
                }
            }

            var actionChain = new ActionChain();

            actionChain.AddDelaySeconds(0.5f);
            actionChain.AddAction(CurrentLandblock, () =>
            {
                foreach (var wo in myEscrow)
                {
                    TryCreateInInventoryWithNetworking(wo);
                }

                foreach (var wo in targetEscrow)
                {
                    target.TryCreateInInventoryWithNetworking(wo);
                }

                Session.Network.EnqueueSend(new GameEventWeenieError(Session, WeenieError.TradeComplete));
                target.Session.Network.EnqueueSend(new GameEventWeenieError(target.Session, WeenieError.TradeComplete));

                TradeTransferInProgress        = false;
                target.TradeTransferInProgress = false;

                IsBusy        = false;
                target.IsBusy = false;

                DatabaseManager.Shard.SaveBiotasInParallel(tradedItems, null);

                HandleActionResetTrade(Guid);
                target.HandleActionResetTrade(target.Guid);
            });

            actionChain.EnqueueChain();
        }
Esempio n. 10
0
        /// <summary>
        /// Broadcasts the player death animation, updates vitae, and sends network messages for player death
        /// Queues the action to call TeleportOnDeath and enter portal space soon
        /// </summary>
        protected override void Die(DamageHistoryInfo lastDamager, DamageHistoryInfo topDamager)
        {
            if (topDamager?.Guid == Guid && IsPKType)
            {
                var topDamagerOther = DamageHistory.GetTopDamager(false);

                if (topDamagerOther != null && topDamagerOther.IsPlayer)
                {
                    topDamager = topDamagerOther;
                }
            }

            UpdateVital(Health, 0);
            NumDeaths++;
            suicideInProgress = false;

            // TODO: instead of setting IsBusy here,
            // eventually all of the places that check for states such as IsBusy || Teleporting
            // might want to use a common function, and IsDead should return a separate error
            IsBusy = true;

            // killer = top damager for looting rights
            if (topDamager != null)
            {
                KillerId = topDamager.Guid.Full;
            }

            // broadcast death animation
            var deathAnim = new Motion(MotionStance.NonCombat, MotionCommand.Dead);

            EnqueueBroadcastMotion(deathAnim);

            // create network messages for player death
            var msgHealthUpdate = new GameMessagePrivateUpdateAttribute2ndLevel(this, Vital.Health, 0);

            // TODO: death sounds? seems to play automatically in client
            // var msgDeathSound = new GameMessageSound(Guid, Sound.Death1, 1.0f);
            var msgNumDeaths = new GameMessagePrivateUpdatePropertyInt(this, PropertyInt.NumDeaths, NumDeaths);

            // send network messages for player death
            Session.Network.EnqueueSend(msgHealthUpdate, msgNumDeaths);

            if (lastDamager?.Guid == Guid) // suicide
            {
                var msgSelfInflictedDeath = new GameEventWeenieError(Session, WeenieError.YouKilledYourself);
                Session.Network.EnqueueSend(msgSelfInflictedDeath);
            }

            // update vitae
            // players who died in a PKLite fight do not accrue vitae
            if (!IsPKLiteDeath(topDamager))
            {
                InflictVitaePenalty();
            }

            if (IsPKDeath(topDamager) || AugmentationSpellsRemainPastDeath == 0)
            {
                var msgPurgeEnchantments = new GameEventMagicPurgeEnchantments(Session);
                EnchantmentManager.RemoveAllEnchantments();
                Session.Network.EnqueueSend(msgPurgeEnchantments);
            }

            // wait for the death animation to finish
            var dieChain   = new ActionChain();
            var animLength = DatManager.PortalDat.ReadFromDat <MotionTable>(MotionTableId).GetAnimationLength(MotionCommand.Dead);

            dieChain.AddDelaySeconds(animLength + 1.0f);

            dieChain.AddAction(this, () =>
            {
                CreateCorpse(topDamager);

                ThreadSafeTeleportOnDeath(); // enter portal space

                SetLifestoneProtection();

                if (IsPKDeath(topDamager) || IsPKLiteDeath(topDamager))
                {
                    SetMinimumTimeSincePK();
                }

                IsBusy = false;
            });

            dieChain.EnqueueChain();
        }
Esempio n. 11
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 ApplyComsumable(string consumableName, Sound sound, ConsumableBuffType buffType, uint?boostAmount, uint?spellDID)
        {
            GameMessageSystemChat buffMessage;
            MotionCommand         motionCommand;

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

            var soundEvent = new GameMessageSound(Guid, sound, 1.0f);
            var motion     = new UniversalMotion(MotionStance.Standing, new MotionItem(motionCommand));

            DoMotion(motion);

            if (buffType == ConsumableBuffType.Spell)
            {
                // Null check for safety
                if (spellDID == null)
                {
                    spellDID = 0;
                }

                // TODO: Handle spell cast
                buffMessage = new GameMessageSystemChat($"Consuming {consumableName} 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;
                }

                uint updatedVitalAmount = creatureVital.Current + (uint)boostAmount;

                if (updatedVitalAmount > creatureVital.MaxValue)
                {
                    updatedVitalAmount = creatureVital.MaxValue;
                }

                boostAmount = updatedVitalAmount - creatureVital.Current;

                UpdateVital(creatureVital, updatedVitalAmount);

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

            Session.Network.EnqueueSend(soundEvent, buffMessage);

            // Wait for animation
            var motionChain           = new ActionChain();
            var motionTable           = DatManager.PortalDat.ReadFromDat <MotionTable>((uint)MotionTableId);
            var motionAnimationLength = motionTable.GetAnimationLength(MotionCommand.Eat);

            motionChain.AddDelaySeconds(motionAnimationLength);

            // Return to standing position after the animation delay
            motionChain.AddAction(this, () => DoMotion(new UniversalMotion(MotionStance.Standing)));
            motionChain.EnqueueChain();
        }
Esempio n. 12
0
        public void LogOut_Inner(bool clientSessionTerminatedAbruptly = false)
        {
            IsLoggingOut = true;

            if (Fellowship != null)
            {
                FellowshipQuit(false);
            }

            if (IsTrading && TradePartner != null)
            {
                var tradePartner = PlayerManager.GetOnlinePlayer(TradePartner);

                if (tradePartner != null)
                {
                    tradePartner.HandleActionCloseTradeNegotiations();
                }
            }

            if (!clientSessionTerminatedAbruptly)
            {
                if (PropertyManager.GetBool("use_turbine_chat").Item)
                {
                    if (GetCharacterOption(CharacterOption.ListenToGeneralChat))
                    {
                        LeaveTurbineChatChannel("General");
                    }
                    if (GetCharacterOption(CharacterOption.ListenToTradeChat))
                    {
                        LeaveTurbineChatChannel("Trade");
                    }
                    if (GetCharacterOption(CharacterOption.ListenToLFGChat))
                    {
                        LeaveTurbineChatChannel("LFG");
                    }
                    if (GetCharacterOption(CharacterOption.ListenToRoleplayChat))
                    {
                        LeaveTurbineChatChannel("Roleplay");
                    }
                    if (GetCharacterOption(CharacterOption.ListenToAllegianceChat) && Allegiance != null)
                    {
                        LeaveTurbineChatChannel("Allegiance");
                    }
                    if (GetCharacterOption(CharacterOption.ListenToSocietyChat) && Society != FactionBits.None)
                    {
                        LeaveTurbineChatChannel("Society");
                    }
                }
            }

            if (CurrentActivePet != null)
            {
                CurrentActivePet.Destroy();
            }

            if (CurrentLandblock != null)
            {
                var logout = new Motion(MotionStance.NonCombat, MotionCommand.LogOut);
                EnqueueBroadcastMotion(logout);

                EnqueueBroadcastPhysicsState();

                var logoutChain = new ActionChain();

                var   motionTable           = DatManager.PortalDat.ReadFromDat <MotionTable>((uint)MotionTableId);
                float logoutAnimationLength = motionTable.GetAnimationLength(MotionCommand.LogOut);
                logoutChain.AddDelaySeconds(logoutAnimationLength);

                // remove the player from landblock management -- after the animation has run
                logoutChain.AddAction(this, () =>
                {
                    if (CurrentLandblock == null)
                    {
                        log.Debug($"0x{Guid}:{Name}.LogOut_Inner.logoutChain: CurrentLandblock is null, unable to remove from a landblock...");
                        if (Location != null)
                        {
                            log.Debug($"0x{Guid}:{Name}.LogOut_Inner.logoutChain: Location is not null, Location = {Location.ToLOCString()}");
                        }
                    }

                    CurrentLandblock?.RemoveWorldObject(Guid, false);
                    SetPropertiesAtLogOut();
                    SavePlayerToDatabase();
                    PlayerManager.SwitchPlayerFromOnlineToOffline(this);
                });

                // close any open landblock containers (chests / corpses)
                if (LastOpenedContainerId != ObjectGuid.Invalid)
                {
                    var container = CurrentLandblock.GetObject(LastOpenedContainerId) as Container;

                    if (container != null)
                    {
                        container.Close(this);
                    }
                }

                logoutChain.EnqueueChain();
            }
            else
            {
                log.Debug($"0x{Guid}:{Name}.LogOut_Inner: CurrentLandblock is null");
                if (Location != null)
                {
                    log.Debug($"0x{Guid}:{Name}.LogOut_Inner: Location is not null, Location = {Location.ToLOCString()}");
                    var validLoadedLandblock = LandblockManager.GetLandblock(Location.LongObjCellID, false);
                    if (validLoadedLandblock.GetObject(Guid.Full) != null)
                    {
                        log.Debug($"0x{Guid}:{Name}.LogOut_Inner: Player is still on landblock, removing...");
                        validLoadedLandblock.RemoveWorldObject(Guid, false);
                    }
                    else
                    {
                        log.Debug($"0x{Guid}:{Name}.LogOut_Inner: Player is not found on the landblock Location references.");
                    }
                }
                else
                {
                    log.Debug($"0x{Guid}:{Name}.LogOut_Inner: Location is null");
                }
                SetPropertiesAtLogOut();
                SavePlayerToDatabase();
                PlayerManager.SwitchPlayerFromOnlineToOffline(this);
            }
        }
Esempio n. 13
0
        public void HandleActionEnterPkLite()
        {
            // ensure permanent npk
            if (PlayerKillerStatus != PlayerKillerStatus.NPK || MinimumTimeSincePk != null)
            {
                Session.Network.EnqueueSend(new GameEventWeenieError(Session, WeenieError.OnlyNonPKsMayEnterPKLite));
                return;
            }

            if (TooBusyToRecall)
            {
                Session.Network.EnqueueSend(new GameEventWeenieError(Session, WeenieError.YoureTooBusy));
                return;
            }

            EnqueueBroadcast(new GameMessageSystemChat($"{Name} is looking for a fight!", ChatMessageType.Broadcast), LocalBroadcastRange);

            // perform pk lite entry motion / effect

            IsBusy = true;

            var prevStance = CurrentMotionState.Stance;

            var actionChain = new ActionChain();

            var animTime = 0.0f;

            animTime += EnqueueMotion_Force(actionChain, MotionStance.NonCombat, MotionCommand.EnterPKLite);

            actionChain.AddAction(this, () =>
            {
                if (PropertyManager.GetBool("allow_pkl_bump").Item)
                {
                    // check for collisions
                    PlayerKillerStatus = PlayerKillerStatus.PKLite;

                    var colliding = PhysicsObj.ethereal_check_for_collisions();

                    if (colliding)
                    {
                        // try initial placement
                        var result = PhysicsObj.SetPositionSimple(PhysicsObj.Position, true, Location.Instance);

                        if (result == SetPositionError.OK)
                        {
                            // handle landblock update?
                            SyncLocation();

                            // force broadcast
                            Sequences.GetNextSequence(SequenceType.ObjectForcePosition);
                            SendUpdatePosition();
                        }
                    }
                }
                UpdateProperty(this, PropertyInt.PlayerKillerStatus, (int)PlayerKillerStatus.PKLite, true);

                Session.Network.EnqueueSend(new GameEventWeenieError(Session, WeenieError.YouAreNowPKLite));
            });

            // return to previous stance, if applicable
            if (prevStance != MotionStance.NonCombat)
            {
                animTime += EnqueueMotion_Force(actionChain, prevStance, MotionCommand.Ready, MotionCommand.NonCombat);
            }

            actionChain.AddAction(this, () => IsBusy = false);

            actionChain.EnqueueChain();
        }
Esempio n. 14
0
        /// <summary>
        /// Recursively called to determine the utility of every move available up to MAX_PLIES
        /// </summary>
        float MinMax(int depth, ActionChain continuesChain)
        {
            List<ActionChain> turnActions = PlayOneTurn (TurnTaker (depth), continuesChain.Board);
            NodesEvaluated += turnActions.Count;

            turnActions.ForEach (node => ScoringFn (depth, node));

            if (Controlling == TurnTaker (depth))
            {
            return turnActions.Max (node => node.score);
            }
            else
            {
            return turnActions.Min (node => node.score);
            }
        }
Esempio n. 15
0
        public void InqProperty(bool?prop, BiotaPropertiesEmoteAction emoteAction, WorldObject sourceObject, WorldObject targetObject, ActionChain actionChain)
        {
            var inRange = prop != null && prop.Value;

            InqPropertyInner(emoteAction, inRange, sourceObject, targetObject, actionChain);
        }
Esempio n. 16
0
        /// <summary>
        /// Determine a score by applying the scoring function, looking up the database, or recursing deeper.
        /// </summary>
        void ScoringFn(int depth, ActionChain node)
        {
            byte[] dbrec = new byte[4];

            bool isTerminal = ApplyCutoff (node, depth);

            if (!isTerminal)
            {
            bool storedInDB = DB.Get (node.Board.GUID (), out dbrec);

            if (storedInDB)
            {
                node.score = BitConverter.ToSingle (dbrec, 0);
            }
            else
            {
                node.score = MinMax (depth + 1, node);

                // Store the score if it was obtained from a full search only
                if (depth == 0 && KeepSearching)
                {
                    RecordNodeInDB (node.Board, node.score);
                }
            }
            }

            node.ClearBoard ();
        }
Esempio n. 17
0
        public void InqProperty(double?prop, BiotaPropertiesEmoteAction emoteAction, WorldObject sourceObject, WorldObject targetObject, ActionChain actionChain)
        {
            var inRange = prop != null && (prop.Value >= emoteAction.MinDbl && prop.Value <= emoteAction.MaxDbl);

            InqPropertyInner(emoteAction, inRange, sourceObject, targetObject, actionChain);
        }
Esempio n. 18
0
        public static void UseObjectOnTarget(Player player, WorldObject source, WorldObject target)
        {
            var recipe = DatabaseManager.World.GetCachedCookbook(source.WeenieClassId, target.WeenieClassId);

            if (recipe == null)
            {
                var message = new GameMessageSystemChat($"The {source.Name} cannot be used on the {target.Name}.", ChatMessageType.Craft);
                player.Session.Network.EnqueueSend(message);
                player.SendUseDoneEvent();
                return;
            }

            ActionChain   craftChain     = new ActionChain();
            CreatureSkill skill          = null;
            bool          skillSuccess   = true; // assume success, unless there's a skill check
            double        percentSuccess = 1;

            UniversalMotion motion = new UniversalMotion(MotionStance.Standing, new MotionItem(MotionCommand.ClapHands));

            craftChain.AddAction(player, () => player.HandleActionMotion(motion));
            var motionTable          = DatManager.PortalDat.ReadFromDat <MotionTable>(player.MotionTableId);
            var craftAnimationLength = motionTable.GetAnimationLength(MotionCommand.ClapHands);

            craftChain.AddDelaySeconds(craftAnimationLength);

            craftChain.AddAction(player, () =>
            {
                if (recipe.Recipe.Skill > 0 && recipe.Recipe.Difficulty > 0)
                {
                    // there's a skill associated with this
                    Skill skillId = (Skill)recipe.Recipe.Skill;

                    // this shouldn't happen, but sanity check for unexpected nulls
                    skill = player.GetCreatureSkill(skillId);

                    if (skill == null)
                    {
                        log.Warn("Unexpectedly missing skill in Recipe usage");
                        player.SendUseDoneEvent();
                        return;
                    }

                    percentSuccess = skill.GetPercentSuccess(recipe.Recipe.Difficulty); //FIXME: Pretty certain this is broken
                }

                if (skill != null)
                {
                    if (skill.AdvancementClass == SkillAdvancementClass.Untrained)
                    {
                        var message = new GameEventWeenieError(player.Session, WeenieError.YouAreNotTrainedInThatTradeSkill);
                        player.Session.Network.EnqueueSend(message);
                        player.SendUseDoneEvent(WeenieError.YouAreNotTrainedInThatTradeSkill);
                        return;
                    }
                }

                // straight skill check, if applicable
                if (skill != null)
                {
                    skillSuccess = _random.NextDouble() < percentSuccess;
                }


                if (skillSuccess)
                {
                    bool destroyTarget = _random.NextDouble() < recipe.Recipe.SuccessDestroyTargetChance;
                    bool destroySource = _random.NextDouble() < recipe.Recipe.SuccessDestroySourceChance;

                    if (destroyTarget)
                    {
                        if (target.OwnerId == player.Guid.Full || player.GetInventoryItem(target.Guid) != null)
                        {
                            player.TryRemoveItemFromInventoryWithNetworking(target, (ushort)recipe.Recipe.SuccessDestroyTargetAmount);
                        }
                        else if (target.WielderId == player.Guid.Full)
                        {
                            if (!player.TryRemoveItemWithNetworking(target))
                            {
                                throw new Exception($"Failed to remove {target.Name} from player inventory.");
                            }
                        }
                        else
                        {
                            target.Destroy();
                        }

                        if (!String.IsNullOrEmpty(recipe.Recipe.SuccessDestroyTargetMessage))
                        {
                            var destroyMessage = new GameMessageSystemChat(recipe.Recipe.SuccessDestroyTargetMessage, ChatMessageType.Craft);
                            player.Session.Network.EnqueueSend(destroyMessage);
                        }
                    }

                    if (destroySource)
                    {
                        if (source.OwnerId == player.Guid.Full || player.GetInventoryItem(target.Guid) != null)
                        {
                            player.TryRemoveItemFromInventoryWithNetworking(source, (ushort)recipe.Recipe.SuccessDestroySourceAmount);
                        }
                        else if (source.WielderId == player.Guid.Full)
                        {
                            if (!player.TryRemoveItemWithNetworking(source))
                            {
                                throw new Exception($"Failed to remove {source.Name} from player inventory.");
                            }
                        }
                        else
                        {
                            source.Destroy();
                        }

                        if (!String.IsNullOrEmpty(recipe.Recipe.SuccessDestroySourceMessage))
                        {
                            var destroyMessage = new GameMessageSystemChat(recipe.Recipe.SuccessDestroySourceMessage, ChatMessageType.Craft);
                            player.Session.Network.EnqueueSend(destroyMessage);
                        }
                    }

                    if (recipe.Recipe.SuccessWCID > 0)
                    {
                        var wo = WorldObjectFactory.CreateNewWorldObject(recipe.Recipe.SuccessWCID);

                        if (wo != null)
                        {
                            if (recipe.Recipe.SuccessAmount > 1)
                            {
                                wo.StackSize = (ushort)recipe.Recipe.SuccessAmount;
                            }

                            player.TryCreateInInventoryWithNetworking(wo);
                        }
                    }

                    var message = new GameMessageSystemChat(recipe.Recipe.SuccessMessage, ChatMessageType.Craft);
                    player.Session.Network.EnqueueSend(message);
                }
                else
                {
                    bool destroyTarget = _random.NextDouble() < recipe.Recipe.FailDestroyTargetChance;
                    bool destroySource = _random.NextDouble() < recipe.Recipe.FailDestroySourceChance;

                    if (destroyTarget)
                    {
                        if (target.OwnerId == player.Guid.Full || player.GetInventoryItem(target.Guid) != null)
                        {
                            player.TryRemoveItemFromInventoryWithNetworking(target, (ushort)recipe.Recipe.FailDestroyTargetAmount);
                        }
                        else if (target.WielderId == player.Guid.Full)
                        {
                            if (!player.TryRemoveItemWithNetworking(target))
                            {
                                throw new Exception($"Failed to remove {target.Name} from player inventory.");
                            }
                        }
                        else
                        {
                            target.Destroy();
                        }

                        if (!String.IsNullOrEmpty(recipe.Recipe.FailDestroyTargetMessage))
                        {
                            var destroyMessage = new GameMessageSystemChat(recipe.Recipe.FailDestroyTargetMessage, ChatMessageType.Craft);
                            player.Session.Network.EnqueueSend(destroyMessage);
                        }
                    }

                    if (destroySource)
                    {
                        if (source.OwnerId == player.Guid.Full || player.GetInventoryItem(target.Guid) != null)
                        {
                            player.TryRemoveItemFromInventoryWithNetworking(source, (ushort)recipe.Recipe.FailDestroySourceAmount);
                        }
                        else if (source.WielderId == player.Guid.Full)
                        {
                            if (!player.TryRemoveItemWithNetworking(source))
                            {
                                throw new Exception($"Failed to remove {source.Name} from player inventory.");
                            }
                        }
                        else
                        {
                            source.Destroy();
                        }

                        if (!String.IsNullOrEmpty(recipe.Recipe.FailDestroySourceMessage))
                        {
                            var destroyMessage = new GameMessageSystemChat(recipe.Recipe.FailDestroySourceMessage, ChatMessageType.Craft);
                            player.Session.Network.EnqueueSend(destroyMessage);
                        }
                    }

                    if (recipe.Recipe.FailWCID > 0)
                    {
                        var wo = WorldObjectFactory.CreateNewWorldObject(recipe.Recipe.FailWCID);

                        if (wo != null)
                        {
                            if (recipe.Recipe.FailAmount > 1)
                            {
                                wo.StackSize = (ushort)recipe.Recipe.FailAmount;
                            }

                            player.TryCreateInInventoryWithNetworking(wo);
                        }
                    }

                    var message = new GameMessageSystemChat(recipe.Recipe.FailMessage, ChatMessageType.Craft);
                    player.Session.Network.EnqueueSend(message);
                }

                player.SendUseDoneEvent();
            });

            craftChain.EnqueueChain();
        }
Esempio n. 19
0
 public void InqProperty(string prop, BiotaPropertiesEmoteAction emoteAction, WorldObject sourceObject, WorldObject targetObject, ActionChain actionChain)
 {
     if (prop == null)
     {
         return;
     }
     InqPropertyInner(emoteAction, true, sourceObject, targetObject, actionChain);
 }
Esempio n. 20
0
        /// <summary>
        /// Called on player login
        /// If a player has any skills trained that require updates from ACE-World-16-Patches,
        /// ensure these updates are installed, and if they aren't, send a helpful message to player with instructions for installation
        /// </summary>
        public void HandleDBUpdates()
        {
            // dirty fighting
            var dfSkill = GetCreatureSkill(Skill.DirtyFighting);

            if (dfSkill.AdvancementClass >= SkillAdvancementClass.Trained)
            {
                foreach (var spellID in SpellExtensions.DirtyFightingSpells)
                {
                    var spell = new Server.Entity.Spell(spellID);
                    if (spell.NotFound)
                    {
                        var actionChain = new ActionChain();
                        actionChain.AddDelaySeconds(3.0f);
                        actionChain.AddAction(this, () =>
                        {
                            Session.Network.EnqueueSend(new GameMessageSystemChat("To install Dirty Fighting, please apply the latest patches from https://github.com/ACEmulator/ACE-World-16PY-Patches", ChatMessageType.Broadcast));
                        });
                        actionChain.EnqueueChain();
                    }
                    break;  // performance improvement: only check first spell
                }
            }

            // void magic
            var voidSkill = GetCreatureSkill(Skill.VoidMagic);

            if (voidSkill.AdvancementClass >= SkillAdvancementClass.Trained)
            {
                foreach (var spellID in SpellExtensions.VoidMagicSpells)
                {
                    var spell = new Server.Entity.Spell(spellID);
                    if (spell.NotFound)
                    {
                        var actionChain = new ActionChain();
                        actionChain.AddDelaySeconds(3.0f);
                        actionChain.AddAction(this, () =>
                        {
                            Session.Network.EnqueueSend(new GameMessageSystemChat("To install Void Magic, please apply the latest patches from https://github.com/ACEmulator/ACE-World-16PY-Patches", ChatMessageType.Broadcast));
                        });
                        actionChain.EnqueueChain();
                    }
                    break;  // performance improvement: only check first spell (measured 102ms to check 75 uncached void spells)
                }
            }

            // summoning
            var summoning = GetCreatureSkill(Skill.Summoning);

            if (summoning.AdvancementClass >= SkillAdvancementClass.Trained)
            {
                uint essenceWCID = 48878;
                var  weenie      = DatabaseManager.World.GetCachedWeenie(essenceWCID);
                if (weenie == null)
                {
                    var actionChain = new ActionChain();
                    actionChain.AddDelaySeconds(3.0f);
                    actionChain.AddAction(this, () =>
                    {
                        Session.Network.EnqueueSend(new GameMessageSystemChat("To install Summoning, please apply the latest patches from https://github.com/ACEmulator/ACE-World-16PY-Patches", ChatMessageType.Broadcast));
                    });
                    actionChain.EnqueueChain();
                }
            }
        }
Esempio n. 21
0
        public void InqPropertyInner(BiotaPropertiesEmoteAction emoteAction, bool inRange, WorldObject sourceObject, WorldObject targetObject, ActionChain actionChain)
        {
            var category = inRange ? EmoteCategory.TestSuccess : EmoteCategory.TestFailure;
            var useRNG   = !inRange; // ??

            InqCategory(category, emoteAction, sourceObject, targetObject, actionChain, useRNG);
        }
Esempio n. 22
0
        public static void HandleCharacterForcedDelete(Session session, params string[] parameters)
        {
            var characterName = string.Join(" ", parameters);

            var foundPlayer = PlayerManager.FindByName(characterName, out var isOnline);

            if (foundPlayer == null)
            {
                CommandHandlerHelper.WriteOutputInfo(session, $"There is no character named {characterName} in the database.", ChatMessageType.Broadcast);
                return;
            }

            if (isOnline && foundPlayer is Player player)
            {
                player.Character.DeleteTime     = (ulong)Time.GetUnixTime();
                player.Character.IsDeleted      = true;
                player.CharacterChangesDetected = true;
                player.Session.LogOffPlayer(true);
                PlayerManager.HandlePlayerDelete(player.Character.Id);

                var success = PlayerManager.ProcessDeletedPlayer(player.Character.Id);
                if (success)
                {
                    CommandHandlerHelper.WriteOutputInfo(session, $"Successfully {(isOnline ? "booted and " : "")}deleted character {foundPlayer.Name} (0x{foundPlayer.Guid}).", ChatMessageType.Broadcast);
                }
                else
                {
                    CommandHandlerHelper.WriteOutputInfo(session, $"Unable to {(isOnline ? "boot and " : "")}delete character {foundPlayer.Name} (0x{foundPlayer.Guid}) due to PlayerManager failure.", ChatMessageType.Broadcast);
                }
            }
            else
            {
                var existingCharId = foundPlayer.Guid.Full; //DatabaseManager.Shard.BaseDatabase.GetCharacterStubByName(foundPlayer.Name).Id;

                DatabaseManager.Shard.GetCharacter(existingCharId, character =>
                {
                    if (character != null)
                    {
                        character.DeleteTime = (ulong)Time.GetUnixTime();
                        character.IsDeleted  = true;
                        DatabaseManager.Shard.SaveCharacter(character, new ReaderWriterLockSlim(), result =>
                        {
                            if (result)
                            {
                                var deleteOfflineChain = new ActionChain();
                                deleteOfflineChain.AddAction(WorldManager.ActionQueue, () => PlayerManager.HandlePlayerDelete(character.Id));
                                deleteOfflineChain.AddDelayForOneTick();
                                deleteOfflineChain.AddAction(WorldManager.ActionQueue, () =>
                                {
                                    var success = PlayerManager.ProcessDeletedPlayer(character.Id);
                                    if (success)
                                    {
                                        CommandHandlerHelper.WriteOutputInfo(session, $"Successfully {(isOnline ? "booted and " : "")}deleted character {foundPlayer.Name} (0x{foundPlayer.Guid}).", ChatMessageType.Broadcast);
                                    }
                                    else
                                    {
                                        CommandHandlerHelper.WriteOutputInfo(session, $"Unable to {(isOnline ? "boot and " : "")}delete character {foundPlayer.Name} (0x{foundPlayer.Guid}) due to PlayerManager failure.", ChatMessageType.Broadcast);
                                    }
                                });
                                deleteOfflineChain.EnqueueChain();
                            }
                            else
                            {
                                CommandHandlerHelper.WriteOutputInfo(session, $"Unable to {(isOnline ? "boot and " : "")}delete character {foundPlayer.Name} (0x{foundPlayer.Guid}) due to shard database SaveCharacter failure.", ChatMessageType.Broadcast);
                            }
                        });
                    }
                    else
                    {
                        CommandHandlerHelper.WriteOutputInfo(session, $"Unable to {(isOnline ? "boot and " : "")}delete character {foundPlayer.Name} (0x{foundPlayer.Guid}) due to shard database GetCharacter failure.", ChatMessageType.Broadcast);
                    }
                });
            }
        }
Esempio n. 23
0
        public void ExecuteEmote(BiotaPropertiesEmote emote, BiotaPropertiesEmoteAction emoteAction, ActionChain actionChain, WorldObject sourceObject = null, WorldObject targetObject = null)
        {
            var player         = targetObject as Player;
            var creature       = sourceObject as Creature;
            var targetCreature = targetObject as Creature;

            var emoteType = (EmoteType)emoteAction.Type;

            //if (emoteType != EmoteType.Motion && emoteType != EmoteType.Turn && emoteType != EmoteType.Move)
            //Console.WriteLine($"ExecuteEmote({emoteType})");

            var text = emoteAction.Message;

            switch ((EmoteType)emoteAction.Type)
            {
            case EmoteType.Act:
                // short for 'acting' text
                var message = Replace(text, sourceObject, targetObject);
                sourceObject?.EnqueueBroadcast(new GameMessageSystemChat(message, ChatMessageType.Broadcast), 30.0f);
                break;

            case EmoteType.Activate:
                actionChain.AddDelaySeconds(emoteAction.Delay);
                actionChain.AddAction(sourceObject, () =>
                {
                    if (creature != null && (creature.ActivationTarget ?? 0) > 0)
                    {
                        var activationTarget = creature.CurrentLandblock?.GetObject(creature.ActivationTarget ?? 0);
                        activationTarget?.ActOnUse(creature);
                    }
                });
                break;

            case EmoteType.AddCharacterTitle:

                // emoteAction.Stat == null for all EmoteType.AddCharacterTitle entries in current db?
                if (player != null)
                {
                    player.AddTitle((CharacterTitle)emoteAction.Stat);
                }
                break;

            case EmoteType.AddContract:

                //if (player != null)
                //Contracts werent in emote table
                //player.AddContract(emoteAction.Stat);
                break;

            case EmoteType.AdminSpam:

                var players = WorldManager.GetAll();
                foreach (var onlinePlayer in players)
                {
                    onlinePlayer.Network.EnqueueSend(new GameMessageSystemChat(text, ChatMessageType.AdminTell));
                }
                break;

            case EmoteType.AwardLevelProportionalSkillXP:

                if (player != null)
                {
                    player.GrantLevelProportionalSkillXP((Skill)emoteAction.Stat, emoteAction.Percent ?? 0, (ulong)emoteAction.Max);
                }
                break;

            case EmoteType.AwardLevelProportionalXP:

                if (player != null)
                {
                    player.GrantLevelProportionalXp(emoteAction.Percent ?? 0, (ulong)emoteAction.Max);
                }
                break;

            case EmoteType.AwardLuminance:

                if (player != null)
                {
                    player.GrantLuminance((long)emoteAction.Amount);
                }
                break;

            case EmoteType.AwardNoShareXP:

                actionChain.AddDelaySeconds(emoteAction.Delay);
                actionChain.AddAction(sourceObject, () =>
                {
                    if (player != null)
                    {
                        player.EarnXP((long)emoteAction.Amount64);
                        player.Session.Network.EnqueueSend(new GameMessageSystemChat("You've earned " + emoteAction.Amount64 + " experience.", ChatMessageType.Broadcast));
                    }
                });
                break;

            case EmoteType.AwardSkillPoints:

                if (player != null)
                {
                    player.AwardSkillPoints((Skill)emoteAction.Stat, (uint)emoteAction.Amount, true);
                }
                break;

            case EmoteType.AwardSkillXP:

                if (player != null)
                {
                    player.RaiseSkillGameAction((Skill)emoteAction.Stat, (uint)emoteAction.Amount, true);
                }
                break;

            case EmoteType.AwardTrainingCredits:

                if (player != null)
                {
                    player.AddSkillCredits((int)emoteAction.Amount, true);
                }
                break;

            case EmoteType.AwardXP:

                actionChain.AddDelaySeconds(emoteAction.Delay);
                actionChain.AddAction(sourceObject, () =>
                {
                    if (player != null)
                    {
                        player.EarnXP((long)emoteAction.Amount64);
                        player.Session.Network.EnqueueSend(new GameMessageSystemChat("You've earned " + emoteAction.Amount64 + " experience.", ChatMessageType.Broadcast));
                    }
                });
                break;

            case EmoteType.BLog:
                // only one test drudge used this emoteAction.
                break;

            case EmoteType.CastSpell:

                if (WorldObject is Player)
                {
                    (WorldObject as Player).CreatePlayerSpell((uint)emoteAction.SpellId);
                }

                else if (WorldObject is Creature)
                {
                    (WorldObject as Creature).CreateCreatureSpell(player.Guid, (uint)emoteAction.SpellId);
                }

                break;

            case EmoteType.CastSpellInstant:

                var spellTable = DatManager.PortalDat.SpellTable;
                var spell      = spellTable.Spells[(uint)emoteAction.SpellId];
                actionChain.AddAction(sourceObject, () =>
                {
                    if (spell.TargetEffect > 0)
                    {
                        creature.CreateCreatureSpell(targetObject.Guid, (uint)emoteAction.SpellId);
                    }
                    else
                    {
                        creature.CreateCreatureSpell((uint)emoteAction.SpellId);
                    }
                });
                break;

            case EmoteType.CloseMe:
                targetObject.Close(WorldObject);
                break;

            case EmoteType.CreateTreasure:
                break;

            case EmoteType.DecrementIntStat:

                var id   = (PropertyInt)emoteAction.Stat;
                var prop = player.GetProperty(id);
                if (prop != null)
                {
                    player.SetProperty(id, prop.Value - 1);
                }
                break;

            case EmoteType.DecrementMyQuest:
                break;

            case EmoteType.DecrementQuest:
                // Used as part of the test drudge for events
                break;

            case EmoteType.DeleteSelf:
                sourceObject.CurrentLandblock?.RemoveWorldObject(sourceObject.Guid, false);
                break;

            case EmoteType.DirectBroadcast:
                text = Replace(emoteAction.Message, WorldObject, targetObject);
                if (player != null)
                {
                    player.Session.Network.EnqueueSend(new GameMessageSystemChat(text, ChatMessageType.Broadcast));
                }
                break;

            case EmoteType.EraseMyQuest:
                break;

            case EmoteType.EraseQuest:

                if (player != null)
                {
                    player.QuestManager.Erase(emoteAction.Message);
                }
                break;

            case EmoteType.FellowBroadcast:

                text = emoteAction.Message;
                if (player != null)
                {
                    var fellowship = player.Fellowship;
                    if (fellowship == null)
                    {
                        player.Session.Network.EnqueueSend(new GameMessageSystemChat(text, ChatMessageType.Broadcast));
                    }
                    else
                    {
                        foreach (var fellow in fellowship.FellowshipMembers)
                        {
                            fellow.Session.Network.EnqueueSend(new GameMessageSystemChat(text, ChatMessageType.Broadcast));
                        }
                    }
                }
                break;

            case EmoteType.Generate:

                uint wcid = (uint)emoteAction.WeenieClassId;
                var  item = WorldObjectFactory.CreateNewWorldObject((wcid));
                break;

            case EmoteType.Give:

                bool success = false;
                if (player != null && emoteAction.WeenieClassId != null)
                {
                    actionChain.AddAction(sourceObject, () =>
                    {
                        item          = WorldObjectFactory.CreateNewWorldObject((uint)emoteAction.WeenieClassId);
                        var stackSize = emoteAction.StackSize ?? 1;
                        var stackMsg  = "";
                        if (stackSize > 1)
                        {
                            item.StackSize = (ushort)stackSize;
                            stackMsg       = stackSize + " ";   // pluralize?
                        }
                        success = player.TryCreateInInventoryWithNetworking(item);

                        // transaction / rollback on failure?
                        if (success)
                        {
                            var msg   = new GameMessageSystemChat($"{WorldObject.Name} gives you {stackMsg}{item.Name}.", ChatMessageType.Broadcast);
                            var sound = new GameMessageSound(player.Guid, Sound.ReceiveItem, 1);
                            player.Session.Network.EnqueueSend(msg, sound);
                        }
                    });
                }
                break;

            case EmoteType.Goto:

                var rng        = Physics.Common.Random.RollDice(0.0f, 1.0f);
                var firstEmote = sourceObject.Biota.BiotaPropertiesEmote.FirstOrDefault(e => e.Category == (uint)EmoteCategory.GotoSet && rng < e.Probability);
                foreach (var action in firstEmote.BiotaPropertiesEmoteAction)
                {
                    actionChain.AddAction(player, () =>
                    {
                        ExecuteEmote(firstEmote, action, actionChain, sourceObject, targetObject);
                    });
                }
                break;

            case EmoteType.IncrementIntStat:

                if (player == null || emoteAction.Stat == null)
                {
                    break;
                }

                id   = (PropertyInt)emoteAction.Stat;
                prop = player.GetProperty(id);
                if (prop != null)
                {
                    player.SetProperty(id, prop.Value + 1);
                }
                break;

            case EmoteType.IncrementMyQuest:
                break;

            case EmoteType.IncrementQuest:

                if (player != null)
                {
                    player.QuestManager.Increment(emoteAction.Message);
                }
                break;

            case EmoteType.InflictVitaePenalty:
                if (player != null)
                {
                    player.VitaeCpPool++;                       // TODO: full path
                }
                break;

            case EmoteType.InqAttributeStat:

                if (targetCreature != null)
                {
                    var attr = targetCreature.GetCreatureAttribute((PropertyAttribute)emoteAction.Stat);
                    success = attr != null && attr.Ranks >= emoteAction.Min && attr.Ranks <= emoteAction.Max;
                    InqCategory(success ? EmoteCategory.TestSuccess : EmoteCategory.TestFailure, emoteAction, sourceObject, targetObject, actionChain);
                }
                break;

            case EmoteType.InqBoolStat:
                // This is only used with NPC's 24944 and 6386, which are dev tester npc's. Not worth the current effort.
                // Could also be post-ToD
                break;

            case EmoteType.InqContractsFull:
                // not part of the game at PY16?
                //if (player != null)
                //{
                //    var contracts = player.TrackedContracts;
                //    InqCategory(contracts.Count != 0 ? EmoteCategory.TestSuccess : EmoteCategory.TestFailure, emote);
                //}
                break;

            case EmoteType.InqEvent:

                var started = EventManager.IsEventStarted(emoteAction.Message);
                InqCategory(started ? EmoteCategory.EventSuccess : EmoteCategory.EventFailure, emoteAction, sourceObject, targetObject, actionChain);
                break;

            case EmoteType.InqFellowNum:
                InqCategory(player != null && player.Fellowship != null ? EmoteCategory.TestSuccess : EmoteCategory.TestNoFellow, emoteAction, sourceObject, targetObject, actionChain);
                break;

            case EmoteType.InqFellowQuest:
                // focusing on 1 person quests to begin with
                break;

            case EmoteType.InqFloatStat:
                //InqProperty(target.GetProperty((PropertyFloat)emote.Stat), emote);
                break;

            case EmoteType.InqInt64Stat:
                //InqProperty(target.GetProperty((PropertyInt64)emote.Stat), emote);
                break;

            case EmoteType.InqIntStat:

                if (emoteAction.Stat != 25)
                {
                    break;                              // ??
                }
                success = player.Level >= emoteAction.Min && player.Level <= emoteAction.Max;

                // rng for failure case?
                var useRNG = !success;

                InqCategory(success ? EmoteCategory.TestSuccess : EmoteCategory.TestFailure, emoteAction, sourceObject, targetObject, actionChain, useRNG);
                break;

            case EmoteType.InqMyQuest:
                break;

            case EmoteType.InqMyQuestBitsOff:
                break;

            case EmoteType.InqMyQuestBitsOn:
                break;

            case EmoteType.InqMyQuestSolves:
                break;

            case EmoteType.InqNumCharacterTitles:

                //if (player != null)
                //InqCategory(player.NumCharacterTitles != 0 ? EmoteCategory.TestSuccess : EmoteCategory.TestFailure, emote);
                break;

            case EmoteType.InqOwnsItems:

                //if (player != null)
                //InqCategory(player.Inventory.Count > 0 ? EmoteCategory.TestSuccess : EmoteCategory.TestFailure, emote);
                break;

            case EmoteType.InqPackSpace:

                //if (player != null)
                //{
                //    var freeSpace = player.ContainerCapacity > player.ItemCapacity;
                //    InqCategory(freeSpace ? EmoteCategory.TestSuccess : EmoteCategory.TestFailure, emote);
                //}
                break;

            case EmoteType.InqQuest:

                if (player != null)
                {
                    var hasQuest = player.QuestManager.HasQuest(emoteAction.Message);
                    InqCategory(hasQuest ? EmoteCategory.QuestSuccess : EmoteCategory.QuestFailure, emoteAction, sourceObject, targetObject, actionChain);
                }
                break;

            case EmoteType.InqQuestBitsOff:
                break;

            case EmoteType.InqQuestBitsOn:
                break;

            case EmoteType.InqQuestSolves:

                // should this be different from InqQuest?
                if (player != null)
                {
                    var hasQuest = player.QuestManager.HasQuest(emoteAction.Message);
                    InqCategory(hasQuest ? EmoteCategory.QuestSuccess : EmoteCategory.QuestFailure, emoteAction, sourceObject, targetObject, actionChain);
                }
                break;

            case EmoteType.InqRawAttributeStat:

                if (targetCreature != null)
                {
                    var attr = targetCreature.GetCreatureAttribute((PropertyAttribute)emoteAction.Stat);
                    success = attr != null && attr.Base >= emoteAction.Min && attr.Base <= emoteAction.Max;
                    InqCategory(success ? EmoteCategory.TestSuccess : EmoteCategory.TestFailure, emoteAction, sourceObject, targetObject, actionChain);
                }
                break;

            case EmoteType.InqRawSecondaryAttributeStat:

                if (targetCreature != null)
                {
                    var vital = targetCreature.GetCreatureVital((PropertyAttribute2nd)emoteAction.Stat);
                    success = vital != null && vital.Base >= emoteAction.Min && vital.Base <= emoteAction.Max;
                    InqCategory(success ? EmoteCategory.TestSuccess : EmoteCategory.TestFailure, emoteAction, sourceObject, targetObject, actionChain);
                }
                break;

            case EmoteType.InqRawSkillStat:

                if (targetCreature != null)
                {
                    var skill = targetCreature.GetCreatureSkill((Skill)emoteAction.Stat);
                    success = skill != null && skill.Base >= emoteAction.Min && skill.Base <= emoteAction.Max;
                    InqCategory(success ? EmoteCategory.TestSuccess : EmoteCategory.TestFailure, emoteAction, sourceObject, targetObject, actionChain);
                }
                break;

            case EmoteType.InqSecondaryAttributeStat:

                if (targetCreature != null)
                {
                    var vital = targetCreature.GetCreatureVital((PropertyAttribute2nd)emoteAction.Stat);
                    success = vital != null && vital.Ranks >= emoteAction.Min && vital.Ranks <= emoteAction.Max;
                    InqCategory(success ? EmoteCategory.TestSuccess : EmoteCategory.TestFailure, emoteAction, sourceObject, targetObject, actionChain);
                }
                break;

            case EmoteType.InqSkillSpecialized:

                if (targetCreature != null)
                {
                    var skill = targetCreature.GetCreatureSkill((Skill)emoteAction.Stat);
                    //InqProperty(skill.Status == SkillStatus.Specialized, emoteAction);
                }
                break;

            case EmoteType.InqSkillStat:

                if (targetCreature != null)
                {
                    var skill = targetCreature.GetCreatureSkill((Skill)emoteAction.Stat);
                    success = skill != null && skill.Ranks >= emoteAction.Min && skill.Ranks <= emoteAction.Max;
                    InqCategory(success ? EmoteCategory.TestSuccess : EmoteCategory.TestFailure, emoteAction, sourceObject, targetObject, actionChain);
                }
                break;

            case EmoteType.InqSkillTrained:

                if (targetCreature != null)
                {
                    var skill = targetCreature.GetCreatureSkill((Skill)emoteAction.Stat);
                    // TestNoQuality?
                    InqProperty(skill.AdvancementClass == SkillAdvancementClass.Trained || skill.AdvancementClass == SkillAdvancementClass.Specialized, emoteAction, sourceObject, targetObject, actionChain);
                }
                break;

            case EmoteType.InqStringStat:

                //InqProperty(targetCreature.GetProperty((PropertyString)emoteAction.Stat), emote);
                break;

            case EmoteType.InqYesNo:
                ConfirmationManager.ProcessConfirmation((uint)emoteAction.Stat, true);
                break;

            case EmoteType.Invalid:
                break;

            case EmoteType.KillSelf:

                if (targetCreature != null)
                {
                    targetCreature.Smite(targetCreature);
                }
                break;

            case EmoteType.LocalBroadcast:
                if (actionChain != null)
                {
                    actionChain.AddDelaySeconds(emoteAction.Delay);
                    actionChain.AddAction(sourceObject, () =>
                    {
                        sourceObject?.EnqueueBroadcast(new GameMessageCreatureMessage(emoteAction.Message, sourceObject.Name, sourceObject.Guid.Full, ChatMessageType.Broadcast));
                    });
                }
                else
                {
                    sourceObject.EnqueueBroadcast(new GameMessageCreatureMessage(emoteAction.Message, sourceObject.Name, sourceObject.Guid.Full, ChatMessageType.Broadcast));
                }
                break;

            case EmoteType.LocalSignal:
                break;

            case EmoteType.LockFellow:

                if (player != null && player.Fellowship != null)
                {
                    player.HandleActionFellowshipChangeOpenness(false);
                }

                break;

            case EmoteType.ForceMotion:     // TODO: figure out the difference
            case EmoteType.Motion:

                if (sourceObject == null || sourceObject.CurrentMotionState == null)
                {
                    break;
                }

                if (emote.Category != (uint)EmoteCategory.Vendor && emote.Style != null)
                {
                    var startingMotion = new UniversalMotion((MotionStance)emote.Style, new MotionItem((MotionCommand)emote.Substyle));
                    var motion         = new UniversalMotion((MotionStance)emote.Style, new MotionItem((MotionCommand)emoteAction.Motion, emoteAction.Extent));

                    if (sourceObject.CurrentMotionState.Stance != startingMotion.Stance)
                    {
                        if (sourceObject.CurrentMotionState.Stance == MotionStance.Invalid)
                        {
                            actionChain.AddDelaySeconds(emoteAction.Delay);
                            actionChain.AddAction(sourceObject, () =>
                            {
                                sourceObject.EnqueueBroadcastMotion(startingMotion);
                                sourceObject.CurrentMotionState = startingMotion;
                            });
                        }
                    }
                    else
                    {
                        if (sourceObject.CurrentMotionState.Commands.Count > 0 && sourceObject.CurrentMotionState.Commands[0].Motion == startingMotion.Commands[0].Motion)
                        {
                            actionChain.AddDelaySeconds(emoteAction.Delay);
                            actionChain.AddAction(sourceObject, () =>
                            {
                                sourceObject.EnqueueBroadcastMotion(motion);
                                sourceObject.CurrentMotionState = motion;
                            });
                            actionChain.AddDelaySeconds(DatManager.PortalDat.ReadFromDat <DatLoader.FileTypes.MotionTable>(sourceObject.MotionTableId).GetAnimationLength((MotionCommand)emoteAction.Motion));
                            if (motion.Commands[0].Motion != MotionCommand.Sleeping && motion.Commands[0].Motion != MotionCommand.Sitting)     // this feels like it can be handled better, somehow?
                            {
                                actionChain.AddAction(sourceObject, () =>
                                {
                                    sourceObject.EnqueueBroadcastMotion(startingMotion);
                                    sourceObject.CurrentMotionState = startingMotion;
                                });
                            }
                        }
                    }
                }
                else
                {
                    var motion = new UniversalMotion(MotionStance.NonCombat, new MotionItem((MotionCommand)emoteAction.Motion, emoteAction.Extent));

                    actionChain.AddDelaySeconds(emoteAction.Delay);
                    actionChain.AddAction(sourceObject, () =>
                    {
                        sourceObject.EnqueueBroadcastMotion(motion);
                        sourceObject.CurrentMotionState = motion;
                    });
                }

                break;

            case EmoteType.Move:

                // what is the difference between this and MoveToPos?
                // using MoveToPos logic for now...
                if (targetCreature != null)
                {
                    var currentPos = targetCreature.Location;

                    var newPos = new Position();
                    newPos.LandblockId = new LandblockId(currentPos.LandblockId.Raw);
                    newPos.Pos         = new Vector3(emoteAction.OriginX ?? currentPos.Pos.X, emoteAction.OriginY ?? currentPos.Pos.Y, emoteAction.OriginZ ?? currentPos.Pos.Z);

                    if (emoteAction.AnglesX == null || emoteAction.AnglesY == null || emoteAction.AnglesZ == null || emoteAction.AnglesW == null)
                    {
                        newPos.Rotation = new Quaternion(currentPos.Rotation.X, currentPos.Rotation.Y, currentPos.Rotation.Z, currentPos.Rotation.W);
                    }
                    else
                    {
                        newPos.Rotation = new Quaternion(emoteAction.AnglesX ?? 0, emoteAction.AnglesY ?? 0, emoteAction.AnglesZ ?? 0, emoteAction.AnglesW ?? 1);
                    }

                    if (emoteAction.ObjCellId != null)
                    {
                        newPos.LandblockId = new LandblockId(emoteAction.ObjCellId.Value);
                    }

                    targetCreature.MoveTo(newPos, targetCreature.GetRunRate());
                }
                break;

            case EmoteType.MoveHome:

                // TODO: call MoveToManager on server
                if (targetCreature != null)
                {
                    targetCreature.MoveTo(targetCreature.Home, targetCreature.GetRunRate());
                }
                break;

            case EmoteType.MoveToPos:

                if (targetCreature != null)
                {
                    var currentPos = targetCreature.Location;

                    var newPos = new Position();
                    newPos.LandblockId = new LandblockId(currentPos.LandblockId.Raw);
                    newPos.Pos         = new Vector3(emoteAction.OriginX ?? currentPos.Pos.X, emoteAction.OriginY ?? currentPos.Pos.Y, emoteAction.OriginZ ?? currentPos.Pos.Z);

                    if (emoteAction.AnglesX == null || emoteAction.AnglesY == null || emoteAction.AnglesZ == null || emoteAction.AnglesW == null)
                    {
                        newPos.Rotation = new Quaternion(currentPos.Rotation.X, currentPos.Rotation.Y, currentPos.Rotation.Z, currentPos.Rotation.W);
                    }
                    else
                    {
                        newPos.Rotation = new Quaternion(emoteAction.AnglesX ?? 0, emoteAction.AnglesY ?? 0, emoteAction.AnglesZ ?? 0, emoteAction.AnglesW ?? 1);
                    }

                    if (emoteAction.ObjCellId != null)
                    {
                        newPos.LandblockId = new LandblockId(emoteAction.ObjCellId.Value);
                    }

                    targetCreature.MoveTo(newPos, targetCreature.GetRunRate());
                }
                break;

            case EmoteType.OpenMe:

                sourceObject.Open(sourceObject);
                break;

            case EmoteType.PetCastSpellOnOwner:

                if (creature != null)
                {
                    creature.CreateCreatureSpell(targetObject.Guid, (uint)emoteAction.SpellId);
                }
                break;

            case EmoteType.PhysScript:

                // TODO: landblock broadcast
                if (sourceObject != null)
                {
                    sourceObject.PhysicsObj.play_script((PlayScript)emoteAction.PScript, 1.0f);
                }
                break;

            case EmoteType.PopUp:
                if (player != null)
                {
                    if ((ConfirmationType)emoteAction.Stat == ConfirmationType.Undefined)
                    {
                        player.Session.Network.EnqueueSend(new GameEventPopupString(player.Session, emoteAction.Message));
                    }
                    else
                    {
                        Confirmation confirm = new Confirmation((ConfirmationType)emoteAction.Stat, emoteAction.Message, sourceObject.Guid.Full, targetObject.Guid.Full);
                        ConfirmationManager.AddConfirmation(confirm);
                        player.Session.Network.EnqueueSend(new GameEventConfirmationRequest(player.Session, (ConfirmationType)emoteAction.Stat, confirm.ConfirmationID, confirm.Message));
                    }
                }
                break;

            case EmoteType.RemoveContract:

                if (player != null)
                {
                    player.HandleActionAbandonContract((uint)emoteAction.Stat);
                }
                break;

            case EmoteType.RemoveVitaePenalty:

                if (player != null)
                {
                    player.VitaeCpPool = 0;                         // TODO: call full path
                }
                break;

            case EmoteType.ResetHomePosition:

                //creature = sourceObject as Creature;
                //if (creature != null)
                //    creature.Home = emoteAction.Position;
                break;

            case EmoteType.Say:

                actionChain.AddDelaySeconds(emoteAction.Delay);
                actionChain.AddAction(sourceObject, () =>
                {
                    sourceObject?.EnqueueBroadcast(new GameMessageCreatureMessage(emoteAction.Message, sourceObject.Name, sourceObject.Guid.Full, ChatMessageType.Emote));
                });
                break;

            case EmoteType.SetAltRacialSkills:
                break;

            case EmoteType.SetBoolStat:
                targetObject.SetProperty((PropertyBool)emoteAction.Stat, emoteAction.Amount == 0 ? false : true);
                break;

            case EmoteType.SetEyePalette:
                if (creature != null)
                {
                    creature.EyesPaletteDID = (uint)emoteAction.Display;
                }
                break;

            case EmoteType.SetEyeTexture:
                if (creature != null)
                {
                    creature.EyesTextureDID = (uint)emoteAction.Display;
                }
                break;

            case EmoteType.SetFloatStat:
                targetObject.SetProperty((PropertyFloat)emoteAction.Stat, (float)emoteAction.Amount);
                break;

            case EmoteType.SetHeadObject:
                if (creature != null)
                {
                    creature.HeadObjectDID = (uint)emoteAction.Display;
                }
                break;

            case EmoteType.SetHeadPalette:
                break;

            case EmoteType.SetInt64Stat:
                player.SetProperty((PropertyInt)emoteAction.Stat, (int)emoteAction.Amount);
                break;

            case EmoteType.SetIntStat:
                player.SetProperty((PropertyInt)emoteAction.Stat, (int)emoteAction.Amount);
                break;

            case EmoteType.SetMouthPalette:
                break;

            case EmoteType.SetMouthTexture:
                creature = sourceObject as Creature;
                if (creature != null)
                {
                    creature.MouthTextureDID = (uint)emoteAction.Display;
                }
                break;

            case EmoteType.SetMyQuestBitsOff:
                break;

            case EmoteType.SetMyQuestBitsOn:
                break;

            case EmoteType.SetMyQuestCompletions:
                break;

            case EmoteType.SetNosePalette:
                break;

            case EmoteType.SetNoseTexture:
                creature = sourceObject as Creature;
                if (creature != null)
                {
                    creature.NoseTextureDID = (uint)emoteAction.Display;
                }
                break;

            case EmoteType.SetQuestBitsOff:
                break;

            case EmoteType.SetQuestBitsOn:
                break;

            case EmoteType.SetQuestCompletions:
                break;

            case EmoteType.SetSanctuaryPosition:

                //if (player != null)
                //player.Sanctuary = emote.Position;
                break;

            case EmoteType.Sound:
                targetObject.EnqueueBroadcast(new GameMessageSound(targetObject.Guid, (Sound)emoteAction.Sound, 1.0f));
                break;

            case EmoteType.SpendLuminance:
                if (player != null)
                {
                    player.SpendLuminance((long)emoteAction.Amount);
                }
                break;

            case EmoteType.StampFellowQuest:
                break;

            case EmoteType.StampMyQuest:
                break;

            case EmoteType.StampQuest:

                // work needs to be done here
                if (player != null)
                {
                    player.QuestManager.Add(emoteAction.Message);
                }
                break;

            case EmoteType.StartBarber:
                break;

            case EmoteType.StartEvent:

                EventManager.StartEvent(emoteAction.Message);
                break;

            case EmoteType.StopEvent:

                EventManager.StopEvent(emoteAction.Message);
                break;

            case EmoteType.TakeItems:

                if (player != null && emoteAction.WeenieClassId != null)
                {
                    item = WorldObjectFactory.CreateNewWorldObject((uint)emoteAction.WeenieClassId);
                    if (item == null)
                    {
                        break;
                    }

                    success = player.TryRemoveItemFromInventoryWithNetworking(item, (ushort)emoteAction.Amount);
                }
                break;

            case EmoteType.TeachSpell:

                if (player != null)
                {
                    player.LearnSpellWithNetworking((uint)emoteAction.SpellId);
                }
                break;

            case EmoteType.TeleportSelf:

                //if (WorldObject is Player)
                //(WorldObject as Player).Teleport(emote.Position);
                break;

            case EmoteType.TeleportTarget:

                //if (player != null)
                //player.Teleport(emote.Position);
                break;

            case EmoteType.Tell:
                actionChain.AddDelaySeconds(emoteAction.Delay);
                actionChain.AddAction(sourceObject, () =>
                {
                    player.Session.Network.EnqueueSend(new GameMessageHearDirectSpeech(sourceObject, emoteAction.Message, player, ChatMessageType.Tell));
                });
                break;

            case EmoteType.TellFellow:

                text = emoteAction.Message;
                if (player != null)
                {
                    var fellowship = player.Fellowship;
                    if (fellowship == null)
                    {
                        player.Session.Network.EnqueueSend(new GameMessageSystemChat(text, ChatMessageType.Tell));
                    }
                    else
                    {
                        foreach (var fellow in fellowship.FellowshipMembers)
                        {
                            fellow.Session.Network.EnqueueSend(new GameMessageSystemChat(text, ChatMessageType.Tell));
                        }
                    }
                }
                break;

            case EmoteType.TextDirect:

                if (player != null)
                {
                    // should these delays be moved to 1 place??
                    actionChain.AddDelaySeconds(emoteAction.Delay);
                    text = emoteAction.Message;         // no known instances of replace tokens in current text, but could be added in future
                    actionChain.AddAction(player, () =>
                    {
                        player.Session.Network.EnqueueSend(new GameMessageSystemChat(text, ChatMessageType.Broadcast));
                    });
                }
                break;

            case EmoteType.Turn:

                if (creature != null)
                {
                    actionChain.AddDelaySeconds(emoteAction.Delay);
                    var pos = new Position(creature.Location.Cell, creature.Location.PositionX, creature.Location.PositionY, creature.Location.PositionZ, emoteAction.AnglesX ?? 0, emoteAction.AnglesY ?? 0, emoteAction.AnglesZ ?? 0, emoteAction.AnglesW ?? 0);
                    actionChain.AddAction(creature, () =>
                    {
                        creature.TurnTo(pos);
                    });
                    var rotateTime = creature.GetRotateDelay(pos);
                    actionChain.AddDelaySeconds(rotateTime);
                }
                break;

            case EmoteType.TurnToTarget:

                if (creature != null && targetCreature != null)
                {
                    actionChain.AddDelaySeconds(emoteAction.Delay);
                    actionChain.AddAction(creature, () =>
                    {
                        creature.Rotate(targetCreature);
                    });
                    var rotateTime = creature.GetRotateDelay(targetCreature);
                    actionChain.AddDelaySeconds(rotateTime);
                }
                break;

            case EmoteType.UntrainSkill:

                if (player != null)
                {
                    player.UntrainSkill((Skill)emoteAction.Stat, 1);
                }
                break;

            case EmoteType.UpdateFellowQuest:
                break;

            case EmoteType.UpdateMyQuest:
                break;

            case EmoteType.UpdateQuest:

                // only delay seems to be with test NPC here
                // still, unsafe to use any emotes directly outside of a chain,
                // as they could be executed out-of-order
                if (player != null)
                {
                    var questName = emoteAction.Message;
                    player.QuestManager.Add(questName);
                    var hasQuest = player.QuestManager.HasQuest(questName);
                    InqCategory(hasQuest ? EmoteCategory.QuestSuccess : EmoteCategory.QuestFailure, emoteAction, sourceObject, targetObject, actionChain);
                }
                break;

            case EmoteType.WorldBroadcast:
                if (player != null)
                {
                    actionChain.AddDelaySeconds(emoteAction.Delay);
                    actionChain.AddAction(sourceObject, () =>
                    {
                        player.Session.Network.EnqueueSend(new GameMessageHearDirectSpeech(sourceObject, emoteAction.Message, player, ChatMessageType.WorldBroadcast));
                    });
                }
                break;

            default:
                log.Debug($"EmoteManager.Execute - Encountered Unhandled EmoteType {(EmoteType)emoteAction.Type} for {sourceObject.Name} ({sourceObject.WeenieClassId})");
                break;
            }
        }
Esempio n. 24
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();
        }
Esempio n. 25
0
        /// <summary>
        /// Recalls you to your allegiance's Mansion or Villa
        /// </summary>
        public void HandleActionTeleToMansion()
        {
            //Console.WriteLine($"{Name}.HandleActionTeleToMansion()");

            if (RecallsDisabled)
            {
                Session.Network.EnqueueSend(new GameEventWeenieError(Session, WeenieError.ExitTrainingAcademyToUseCommand));
                return;
            }

            // check if player is in an allegiance
            if (Allegiance == null)
            {
                Session.Network.EnqueueSend(new GameEventWeenieError(Session, WeenieError.YouAreNotInAllegiance));
                return;
            }

            var allegianceHouse = Allegiance.GetHouse();

            if (allegianceHouse == null)
            {
                Session.Network.EnqueueSend(new GameEventWeenieError(Session, WeenieError.YourMonarchDoesNotOwnAMansionOrVilla));
                return;
            }

            if (allegianceHouse.HouseType < ACE.Entity.Enum.HouseType.Villa)
            {
                Session.Network.EnqueueSend(new GameEventWeenieError(Session, WeenieError.YourMonarchsHouseIsNotAMansionOrVilla));
                return;
            }

            // ensure allegiance housing has allegiance permissions enabled
            if (allegianceHouse.MonarchId == null)
            {
                Session.Network.EnqueueSend(new GameEventWeenieError(Session, WeenieError.YourMonarchHasClosedTheMansion));
                return;
            }

            if (CombatMode != CombatMode.NonCombat)
            {
                // this should be handled by a different thing, probably a function that forces player into peacemode
                var updateCombatMode = new GameMessagePrivateUpdatePropertyInt(this, PropertyInt.CombatMode, (int)CombatMode.NonCombat);
                SetCombatMode(CombatMode.NonCombat);
                Session.Network.EnqueueSend(updateCombatMode);
            }

            EnqueueBroadcast(new GameMessageSystemChat($"{Name} is recalling to the Allegiance housing.", ChatMessageType.Recall), 96.0f);
            EnqueueBroadcastMotion(motionHouseRecall);

            var startPos = new Position(Location);

            // Wait for animation
            var actionChain = new ActionChain();

            // Then do teleport
            var animLength = DatManager.PortalDat.ReadFromDat <MotionTable>(MotionTableId).GetAnimationLength(MotionCommand.HouseRecall);

            actionChain.AddDelaySeconds(animLength);
            actionChain.AddAction(this, () =>
            {
                var endPos = new Position(Location);
                if (startPos.SquaredDistanceTo(endPos) > RecallMoveThresholdSq)
                {
                    Session.Network.EnqueueSend(new GameEventWeenieError(Session, WeenieError.YouHaveMovedTooFar));
                    return;
                }

                Teleport(allegianceHouse.SlumLord.Location);
            });

            actionChain.EnqueueChain();
        }
Esempio n. 26
0
        public void PlayerEnterWorld()
        {
            PlayerManager.SwitchPlayerFromOfflineToOnline(this);
            Teleporting = true;

            // Save the the LoginTimestamp
            var lastLoginTimestamp = Time.GetUnixTime();

            LoginTimestamp             = lastLoginTimestamp;
            LastTeleportStartTimestamp = lastLoginTimestamp;

            Character.LastLoginTimestamp = lastLoginTimestamp;
            Character.TotalLogins++;
            CharacterChangesDetected = true;

            Sequences.SetSequence(SequenceType.ObjectInstance, new UShortSequence((ushort)Character.TotalLogins));

            if (BarberActive)
            {
                BarberActive = false;
            }

            if (AllegianceNode != null)
            {
                AllegianceRank = (int)AllegianceNode.Rank;
            }
            else
            {
                AllegianceRank = null;
            }

            if (!Account15Days)
            {
                var accountTimeSpan = DateTime.UtcNow - Account.CreateTime;
                if (accountTimeSpan.TotalDays >= 15)
                {
                    Account15Days = true;
                }
            }

            if (PlayerKillerStatus == PlayerKillerStatus.PKLite && !PropertyManager.GetBool("pkl_server").Item)
            {
                PlayerKillerStatus = PlayerKillerStatus.NPK;

                var actionChain = new ActionChain();
                actionChain.AddDelaySeconds(3.0f);
                actionChain.AddAction(this, () =>
                {
                    Session.Network.EnqueueSend(new GameEventWeenieError(Session, WeenieError.YouAreNonPKAgain));
                });
                actionChain.EnqueueChain();
            }

            // SendSelf will trigger the entrance into portal space
            SendSelf();

            // Update or override certain properties sent to client.

            // bugged: do not send this here, or else a freshly loaded acclient will overrwrite the values
            // wait until first enter world is completed

            //SendPropertyUpdatesAndOverrides();

            if (PropertyManager.GetBool("use_turbine_chat").Item)
            {
                // Init the client with the chat channel ID's, and then notify the player that they've joined the associated channels.
                Session.Network.EnqueueSend(new GameEventWeenieError(Session, WeenieError.TurbineChatIsEnabled));

                if (GetCharacterOption(CharacterOption.ListenToAllegianceChat) && Allegiance != null)
                {
                    JoinTurbineChatChannel("Allegiance");
                }
                if (GetCharacterOption(CharacterOption.ListenToGeneralChat))
                {
                    JoinTurbineChatChannel("General");
                }
                if (GetCharacterOption(CharacterOption.ListenToTradeChat))
                {
                    JoinTurbineChatChannel("Trade");
                }
                if (GetCharacterOption(CharacterOption.ListenToLFGChat))
                {
                    JoinTurbineChatChannel("LFG");
                }
                if (GetCharacterOption(CharacterOption.ListenToRoleplayChat))
                {
                    JoinTurbineChatChannel("Roleplay");
                }
                if (GetCharacterOption(CharacterOption.ListenToSocietyChat) && Society != FactionBits.None)
                {
                    JoinTurbineChatChannel("Society");
                }
            }

            // check if vassals earned XP while offline
            HandleAllegianceOnLogin();
            HandleHouseOnLogin();

            // retail appeared to send the squelch list very early,
            // even before the CreatePlayer, but doing it here
            if (SquelchManager.HasSquelches)
            {
                SquelchManager.SendSquelchDB();
            }

            AuditItemSpells();
            AuditEquippedItems();

            HandleMissingXp();
            HandleSkillCreditRefund();
            HandleSkillTemplesReset();
            HandleSkillSpecCreditRefund();
            HandleFreeSkillResetRenewal();
            HandleFreeAttributeResetRenewal();

            HandleDBUpdates();

            if (ServerManager.ShutdownInitiated)
            {
                var actionChain = new ActionChain();
                actionChain.AddDelaySeconds(10.0f);
                actionChain.AddAction(this, () =>
                {
                    SendMessage(ServerManager.ShutdownNoticeText(), ChatMessageType.WorldBroadcast);
                });
                actionChain.EnqueueChain();
            }
        }
Esempio n. 27
0
        /// <summary>
        /// Handles the eviction process for a player house
        /// </summary>
        public static void HandleEviction(House house, uint playerGuid, bool multihouse = false, bool force = false)
        {
            // clear out slumlord inventory
            var slumlord = house.SlumLord;

            slumlord.ClearInventory(true);

            var player = PlayerManager.FindByGuid(playerGuid, out bool isOnline);

            if (!PropertyManager.GetBool("house_rent_enabled", true).Item&& !multihouse && !force)
            {
                // rent disabled, push forward
                var purchaseTime = (uint)(player.HousePurchaseTimestamp ?? 0);
                var nextRentTime = house.GetRentDue(purchaseTime);
                player.HouseRentTimestamp = (int)nextRentTime;

                log.Debug($"[HOUSE] HouseManager.HandleRentPaid({player.Name}): house rent disabled via config");

                // re-add item to queue
                AddRentQueue(player, house);
                return;
            }

            // handle eviction
            house.HouseOwner     = null;
            house.MonarchId      = null;
            house.HouseOwnerName = null;

            house.ClearPermissions();

            house.SaveBiotaToDatabase();

            // relink
            house.UpdateLinks();

            if (house.HasDungeon)
            {
                var dungeonHouse = house.GetDungeonHouse();
                if (dungeonHouse != null)
                {
                    dungeonHouse.UpdateLinks();
                }
            }

            // player slumlord 'off' animation
            slumlord.Off();

            // reset slumlord name
            slumlord.SetAndBroadcastName();

            slumlord.SaveBiotaToDatabase();

            // if evicting a multihouse owner's previous house,
            // no update for player properties
            if (player.HouseInstance == house.Guid.Full)
            {
                player.HouseId       = null;
                player.HouseInstance = null;
                //player.HousePurchaseTimestamp = null;
                player.HouseRentTimestamp = null;
            }
            else
            {
                log.Warn($"[HOUSE] HouseManager.HandleRentEviction({house.Guid}, {player.Name}, {multihouse}): house guids don't match {player.HouseInstance}");
            }

            house.ClearRestrictions();

            log.Debug($"[HOUSE] HouseManager.HandleRentEviction({player.Name})");

            if (multihouse)
            {
                RemoveRentQueue(house.Guid.Full);

                player.SaveBiotaToDatabase();

                return;
            }

            if (!isOnline)
            {
                // inform player of eviction when they log in
                var offlinePlayer = PlayerManager.GetOfflinePlayer(playerGuid);
                if (offlinePlayer == null)
                {
                    log.Warn($"[HOUSE] {player.Name}.HandleEviction(): couldn't find offline player");
                    return;
                }
                offlinePlayer.SetProperty(PropertyBool.HouseEvicted, true);
                offlinePlayer.SaveBiotaToDatabase();
                return;
            }

            var onlinePlayer = PlayerManager.GetOnlinePlayer(playerGuid);

            onlinePlayer.House = null;

            // send text message
            onlinePlayer.Session.Network.EnqueueSend(new GameMessageSystemChat("You've been evicted from your house!", ChatMessageType.Broadcast));
            onlinePlayer.RemoveDeed();

            onlinePlayer.SaveBiotaToDatabase();

            // clear house panel for online player
            var actionChain = new ActionChain();

            actionChain.AddDelaySeconds(3.0f);  // wait for slumlord inventory biotas above to save
            actionChain.AddAction(onlinePlayer, onlinePlayer.HandleActionQueryHouse);
            actionChain.EnqueueChain();
        }
Esempio n. 28
0
        /**
         * Test win conditions, depth, and external signals to check whether to cut off or not.
         *
         * Return true if terminal, else false.
         */
        bool ApplyCutoff(ActionChain node, int depth)
        {
            if (node.Board.Winner != null)
            {
            node.score = node.Board.Winner == Controlling ? IS_WIN : IS_LOSS;
            return true;
            }
            else if (depth >= SOFT_PLIES)
            {
            // iterative deepening exception for dangerous positions
            // TODO neaten up the logic
            if (node.Board.Pieces.Values.Any(piece => piece.Occupies.Type == BoardSquareType.EDGE) &&
                    depth < HARD_PLIES && KeepSearching)
            {
                        return false;
            }

            node.score = ScoreBoard (Controlling, node.Board);
            return true;
            }
            else if (KeepSearching == false)
            {
            // Disregard nodes that haven't yet been evaluated fully, fudge it
            // by returning an unfavourable score rather than eliminating it
            node.score = TurnTaker (depth) == Controlling ? IS_LOSS : IS_WIN;
            return true;
            }

            return false;
        }
Esempio n. 29
0
        /// <summary>
        /// Launches a missile attack from monster to target
        /// </summary>
        public void LaunchMissile()
        {
            //IsTurning = false;

            var weapon = GetEquippedMissileWeapon();

            if (weapon == null || AttackTarget == null)
            {
                return;
            }

            var ammo = weapon.IsAmmoLauncher ? GetEquippedAmmo() : weapon;

            if (ammo == null)
            {
                return;
            }

            // ensure direct line of sight
            if (!IsDirectVisible(AttackTarget))
            {
                NextAttackTime = Timers.RunningTime + 1.0f;
                return;
            }

            // should this be called each launch?
            AttackHeight = ChooseAttackHeight();

            var dist = GetDistanceToTarget();

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

            if (DebugMove)
            {
                Console.WriteLine($"[{Timers.RunningTime}] - {Name} ({Guid}) - LaunchMissile");
            }

            // get z-angle for aim motion
            var aimVelocity = GetAimVelocity(AttackTarget);

            var aimLevel = GetAimLevel(aimVelocity);

            // calculate projectile spawn pos and velocity
            var localOrigin = GetProjectileSpawnOrigin(ammo.WeenieClassId, aimLevel);

            var velocity = CalculateProjectileVelocity(localOrigin, AttackTarget, out Vector3 origin, out Quaternion orientation);

            //Console.WriteLine($"Velocity: {velocity}");

            // launch animation
            var actionChain = new ActionChain();
            var launchTime  = EnqueueMotion(actionChain, aimLevel);

            //Console.WriteLine("LaunchTime: " + launchTime);

            // launch projectile
            actionChain.AddAction(this, () =>
            {
                if (IsDead)
                {
                    return;
                }

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

                // TODO: monster stamina usage

                if (AttackTarget != null)
                {
                    var projectile = LaunchProjectile(weapon, ammo, AttackTarget, origin, orientation, velocity);
                    UpdateAmmoAfterLaunch(ammo);
                }
            });

            // will ammo be depleted?

            /*if (ammo.StackSize == null || ammo.StackSize <= 1)
             * {
             *  // compare monsters: lugianmontokrenegade /  sclavusse / zombielichtowerarcher
             *  actionChain.EnqueueChain();
             *  NextMoveTime = NextAttackTime = Timers.RunningTime + launchTime + MissileDelay;
             *  return;
             * }*/

            // reload animation
            var animSpeed  = GetAnimSpeed();
            var reloadTime = EnqueueMotion(actionChain, MotionCommand.Reload, animSpeed);

            //Console.WriteLine("ReloadTime: " + reloadTime);

            // reset for next projectile
            EnqueueMotion(actionChain, MotionCommand.Ready);

            var linkTime = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, MotionCommand.Reload, MotionCommand.Ready);

            if (weapon.IsThrownWeapon)
            {
                actionChain.EnqueueChain();

                actionChain = new ActionChain();
                actionChain.AddDelaySeconds(linkTime);
            }
            //Console.WriteLine($"Reload time: launchTime({launchTime}) + reloadTime({reloadTime}) + linkTime({linkTime})");

            actionChain.AddAction(this, () => EnqueueBroadcast(new GameMessageParentEvent(this, ammo, ACE.Entity.Enum.ParentLocation.RightHand,
                                                                                          ACE.Entity.Enum.Placement.RightHandCombat)));

            actionChain.EnqueueChain();

            var timeOffset = launchTime + reloadTime + linkTime;

            var missileDelay = MissileDelay;

            if (!weapon.IsAmmoLauncher)
            {
                missileDelay *= 1.5f;
            }

            NextMoveTime = NextAttackTime = Timers.RunningTime + timeOffset + missileDelay;
        }
Esempio n. 30
0
        bool IsStupidMove(ActionChain chain)
        {
            ActionPair moveProposal = chain.actions.Last ();

            if (moveProposal.action == ActionTaken.SKIPPED)
            {
            return false;
            }

            Board board = chain.Board;
            Piece movedPiece = board.Pieces [board.Squares [moveProposal.toLoc.x, moveProposal.toLoc.y]];

            if (movedPiece.Occupies.Adjacent
               .Any (square => square.Type == BoardSquareType.EDGE) &&
            movedPiece.Push.CheckPushes ().Count == 0)
            {
            return true;
            }
            else
            {
            return false;
            }
        }
Esempio n. 31
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 = 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;
                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;
                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, (int)CombatMode.Missile));
            }
        }
Esempio n. 32
0
        /// <summary>
        /// The base level minmax function, which utilises a different return type and parellelises the search
        /// </summary>
        ActionChain MinMax0(ActionChain baseChain)
        {
            List<ActionChain> turnActions = PlayOneTurn (Controlling, baseChain.Board);
            NodesEvaluated += turnActions.Count;

            // Since we're unlikely to be able to evaluate all nodes on a cold pass, evaluate them in order
            // of immediate potential in order to discover the most fruitful nodes first
            turnActions.ForEach(node => node.score = ScoreBoard(Controlling, node.Board));
            turnActions.Sort ((a,b) => {
            return a.score.CompareTo (b.score);}
            );

            // execute in parallel for speed boost, shuffle to introduce nondeterminism between same scores
            int nodesBatch = 100;
            Parallel.ForEach (Partitioner.Create (0, turnActions.Count, nodesBatch), range => {
            for (int i = range.Item1; i < range.Item2; i++)
            {
                ScoringFn (0, turnActions [i]);
            }
            }
            );

            turnActions.Shuffle ();

            turnActions.Sort ((a,b) => {
            return a.score.CompareTo (b.score);}
            );

            return turnActions.Last ();
        }
Esempio n. 33
0
        /// <summary>
        /// Launches a missile attack from monster to target
        /// </summary>
        public void LaunchMissile()
        {
            //IsTurning = false;

            var weapon = GetEquippedMissileWeapon();

            if (weapon == null || AttackTarget == null)
            {
                return;
            }

            var ammo = weapon.IsAmmoLauncher ? GetEquippedAmmo() : weapon;

            if (ammo == null)
            {
                return;
            }

            // ensure direct line of sight
            if (!IsDirectVisible(AttackTarget))
            {
                NextAttackTime = DateTime.UtcNow.AddSeconds(1.0f);
                return;
            }

            // should this be called each launch?
            AttackHeight = ChooseAttackHeight();

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

            // launch animation
            var actionChain = new ActionChain();
            var launchTime  = EnqueueMotion(actionChain, MotionCommand.AimLevel);
            //Console.WriteLine("LaunchTime: " + launchTime);

            // launch projectile
            float targetTime = 0.0f;

            actionChain.AddAction(this, () =>
            {
                var sound = GetLaunchMissileSound(weapon);
                EnqueueBroadcast(new GameMessageSound(Guid, sound, 1.0f));

                // TODO: monster stamina usage

                var projectile = LaunchProjectile(ammo, AttackTarget, out targetTime);
                UpdateAmmoAfterLaunch(ammo);
            });

            // will ammo be depleted?
            if (ammo.StackSize == 1)
            {
                actionChain.EnqueueChain();
                NextAttackTime = DateTime.UtcNow.AddSeconds(launchTime + MissileDelay);
                return;
            }

            // reload animation
            var reloadTime = EnqueueMotion(actionChain, MotionCommand.Reload);

            //Console.WriteLine("ReloadTime: " + reloadTime);

            // reset for next projectile
            EnqueueMotion(actionChain, MotionCommand.Ready);
            var linkTime = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, MotionCommand.Reload, MotionCommand.Ready);

            //Console.WriteLine("LinkTime: " + linkTime);

            actionChain.AddAction(this, () => EnqueueBroadcast(new GameMessageParentEvent(this, ammo, (int)ACE.Entity.Enum.ParentLocation.RightHand,
                                                                                          (int)ACE.Entity.Enum.Placement.RightHandCombat)));

            actionChain.EnqueueChain();

            var timeOffset = launchTime + reloadTime + linkTime;

            NextAttackTime = DateTime.UtcNow.AddSeconds(timeOffset + MissileDelay);
        }
Esempio n. 34
0
 void StoreBestAction(ActionChain best)
 {
     Instructions.Clear ();
     for (int i = 0; i < 3 && i < best.actions.Count; i++)
     {
     ActionPair pair = best.actions [i];
     if (pair.action == ActionTaken.SKIPPED)
     {
         DebugFn ("AI SKIP " + Master.Turn.Phase ());
         Instructions.Add (() => {
             Master.Turn.Control ().Skip ();});
     }
     else if (pair.action == ActionTaken.MOVED)
     {
         DebugFn ("AI MOVE " + pair.fromLoc.ToString () + " " + pair.toLoc.ToString ());
         Instructions.Add (() => {
             Master.Turn.Control ().Move (pair.fromLoc, pair.toLoc);});
     }
     else if (pair.action == ActionTaken.PUSHED)
     {
         DebugFn ("AI PUSH " + pair.fromLoc.ToString () + " " + pair.toLoc.ToString ());
         Instructions.Add (() => {
             Master.Turn.Control ().Push (pair.fromLoc, pair.toLoc); });
     }
     else
     {
         throw new Exception ("Unknown AI action");
     }
     }
 }
Esempio n. 35
0
File: Lock.cs Progetto: Zegeger/ACE
        public static void UseUnlocker(Player player, WorldObject unlocker, WorldObject target)
        {
            ActionChain chain = new ActionChain();

            chain.AddAction(player, () =>
            {
                if (unlocker.WeenieType == WeenieType.Lockpick &&
                    player.Skills[Skill.Lockpick].AdvancementClass != SkillAdvancementClass.Trained &&
                    player.Skills[Skill.Lockpick].AdvancementClass != SkillAdvancementClass.Specialized)
                {
                    player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, WeenieError.YouArentTrainedInLockpicking));
                    return;
                }
                if (target is Lock @lock)
                {
                    UnlockResults result = UnlockResults.IncorrectKey;
                    if (unlocker.WeenieType == WeenieType.Lockpick)
                    {
                        result = @lock.Unlock(player.Skills[Skill.Lockpick].Current);
                    }
                    else if (unlocker is Key woKey)
                    {
                        if (target is Door woDoor)
                        {
                            if (woDoor.LockCode == "") // the door isn't to be opened with keys
                            {
                                player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, WeenieError.YouCannotLockOrUnlockThat));
                                return;
                            }
                        }
                        result = @lock.Unlock(woKey.KeyCode);
                    }

                    switch (result)
                    {
                    case UnlockResults.UnlockSuccess:
                        if (unlocker.WeenieType == WeenieType.Lockpick)
                        {
                            player.HandleActionApplySoundEffect(Sound.Lockpicking);    // Sound.Lockpicking doesn't work via EnqueueBroadcastSound for some reason.
                        }
                        player.Session.Network.EnqueueSend(new GameMessageSystemChat($"You have successfully picked the lock! It is now unlocked.", ChatMessageType.Craft));
                        ConsumeUnlocker(player, unlocker);
                        break;

                    case UnlockResults.Open:
                        player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, WeenieError.YouCannotLockWhatIsOpen));
                        break;

                    case UnlockResults.AlreadyUnlocked:
                        player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, WeenieError.LockAlreadyUnlocked));
                        break;

                    case UnlockResults.PickLockFailed:
                        target.CurrentLandblock?.EnqueueBroadcastSound(target, Sound.PicklockFail);
                        ConsumeUnlocker(player, unlocker);
                        break;

                    case UnlockResults.CannotBePicked:
                        player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, WeenieError.YouCannotLockOrUnlockThat));
                        break;

                    case UnlockResults.IncorrectKey:
                        player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, WeenieError.KeyDoesntFitThisLock));
                        break;
                    }
                }
                else
                {
                    player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, WeenieError.YouCannotLockOrUnlockThat));
                }
            });

            chain.EnqueueChain();
        }
Esempio n. 36
0
 public void Link(ActionChain previous)
 {
     previous.ClearBoard ();
     List<ActionPair> newAction = new List<ActionPair> ();
     newAction.AddRange (previous.actions);
     newAction.AddRange (actions);
     actions = newAction;
 }
Esempio n. 37
0
        /// <summary>
        /// This is raised by Player.HandleActionUseItem.<para />
        /// The item should be in the players possession.
        /// </summary>
        public override void UseItem(Player player)
        {
            bool   success    = true;
            string failReason = "You are unable to read the scroll.";

            switch (Power)
            {
            // research: http://asheron.wikia.com/wiki/Announcements_-_2002/06_-_Castling
            case spellLevel2:     // Level 2
            case spellLevel3:     // Level 3
            case spellLevel4:     // Level 4
            case spellLevel5:     // Level 5
            case spellLevel6:     // Level 6
                if (!player.CanReadScroll(School, Power))
                {
                    success    = false;
                    failReason = "You are not skilled enough in the inscribed spell's school of magic to understand the writing on this scroll.";
                }
                break;
            }

            if (player.SpellIsKnown(SpellId))
            {
                success    = false;
                failReason = "You already know the spell inscribed upon this scroll.";
            }

            var actionChain = new ActionChain();

            actionChain
            .AddAction(player, () => player.EnqueueBroadcastMotion(motionReading))
            .AddDelaySeconds(2);

            if (success)
            {
                actionChain.AddAction(player, () =>
                {
                    player.LearnSpellWithNetworking(SpellId);
                    player.EnqueueBroadcastMotion(motionReady);

                    if (player.TryRemoveFromInventoryWithNetworking(this))
                    {
                        player.Session.Network.EnqueueSend(new GameMessageSystemChat("The scroll is destroyed.", ChatMessageType.Magic));
                        Destroy();
                    }
                });
            }
            else
            {
                actionChain
                .AddDelaySeconds(2)
                .AddAction(player, () =>
                {
                    player.EnqueueBroadcastMotion(motionReady);
                    player.Session.Network.EnqueueSend(new GameMessageSystemChat($"{failReason}", ChatMessageType.Magic));
                });
            }

            actionChain
            .AddAction(player, () => player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session)));

            actionChain.EnqueueChain();
        }