Пример #1
0
        /// <summary>
        /// Called upon server start to load all GameTalents into a master dictionary.
        /// </summary>
        /// <returns>True upon successful load.</returns>
        public static bool LoadTalents()
        {
            try
            {
                foreach (Type t in System.Reflection.Assembly.GetExecutingAssembly().GetTypes())
                {
                    if (Array.IndexOf(t.GetInterfaces(), typeof(ITalentHandler)) > -1)
                    {
                        TalentAttribute attr   = (TalentAttribute)t.GetCustomAttributes(typeof(TalentAttribute), true)[0];
                        GameTalent      talent = new GameTalent(attr.Command, attr.Name, attr.Description, attr.IsPassive, attr.MinimumLevel, attr.PerformanceCost, attr.PurchasePrice,
                                                                attr.DownTime, attr.IsAvailableAtMentor, attr.Usages, attr.Professions, attr.Entities, (ITalentHandler)Activator.CreateInstance(t));

                        // Add the GameTalent to a dictionary.
                        if (!GameTalentDictionary.ContainsKey(talent.Command))
                        {
                            GameTalentDictionary.Add(talent.Command, talent);
                        }
                        else
                        {
                            Utils.Log("GameTalent already exists: " + talent.Command, Utils.LogType.SystemWarning);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Utils.LogException(e);
                return(false);
            }
            return(true);
        }
Пример #2
0
        // args: left/right targetID
        public bool OnPerform(Character chr, string args)
        {
            if (args == null || args == "")
            {
                chr.WriteToDisplay("Who do you want to Battle Charge?");
                return(false);
            }

            if (!MeetsRequirements(chr, null))
            {
                return(false);
            }

            string[] sArgs = args.Split(" ".ToCharArray());

            Character target = GameSystems.Targeting.TargetAquisition.AcquireTarget(chr, args, GameWorld.Cell.DEFAULT_VISIBLE_DISTANCE, 0);

            // safety net
            if (target == null)
            {
                return(false);
            }

            if (target.CurrentCell != chr.CurrentCell)
            {
                if (!PathTest.SuccessfulPathTest(PathTest.RESERVED_NAME_JUMPKICKCOMMAND, chr.CurrentCell, target.CurrentCell))
                {
                    chr.WriteToDisplay(GameSystems.Text.TextManager.PATH_IS_BLOCKED);
                    return(false);
                }
            }

            if (GameWorld.Cell.GetCellDistance(chr.X, chr.Y, target.X, target.Y) < 1)
            {
                chr.WriteToDisplay("Your target is too close for you to charge into battle.");
                return(false);
            }

            chr.WriteToDisplay("You charge into battle!");
            target.WriteToDisplay(chr.GetNameForActionResult() + " charges you!");

            chr.CommandType = CommandTasker.CommandType.BattleCharge;
            chr.CurrentCell = target.CurrentCell;
            Combat.DoCombat(chr, target, chr.RightHand);
            // TODO: emit battle charge sound

            // Battle charge with a shield does an automatic bash.
            if (chr.HasTalent(GameTalent.TALENTS.Bash) && chr.LeftHand != null && chr.LeftHand.baseType == eItemBaseType.Shield)
            {
                GameTalent gtShieldBash = GameTalent.GameTalentDictionary[GameTalent.TALENTS.Bash.ToString().ToLower()];

                if (gtShieldBash.MeetsPerformanceCost(chr) && gtShieldBash.Handler.OnPerform(chr, args))
                {
                    gtShieldBash.SuccessfulPerformance(chr);
                }
            }

            return(true);
        }
Пример #3
0
        /// <summary>
        /// Interpret incoming command. To be moved to a Command Manager or GameCommand in the near future.
        /// </summary>
        /// <param name="command"></param>
        /// <param name="args"></param>
        /// <returns>False if invalid command. True if the command was completed.</returns>
        public bool InterpretCommand(string command, string args)
        {
            var i           = 0;
            var sCmdAndArgs = command + " " + args;
            var newArgs     = "";

            // Dead characters can only rest or quit.
            if (_chr.IsDead && command.ToLower() != "rest" && command.ToLower() != "quit")
            {
                _chr.WriteToDisplay("You are dead, you can either wait to be resurrected or rest.");
                return(true);
            }

            #region If a command is being interpreted then the character is no longer resting or meditating.
            if (_chr.IsResting && !_chr.IsMeditating)
            {
                if (command.ToLower() != "rest" &&
                    !command.StartsWith(((char)27).ToString()) &&
                    !command.StartsWith("show"))
                {
                    _chr.WriteToDisplay("You are no longer resting.");

                    _chr.IsResting = false;
                }
            }

            if (_chr.IsMeditating)
            {
                // using the "meditate" command while meditating will cancel meditation
                if (command.ToLower() != "memorize" &&
                    !command.StartsWith(((char)27).ToString()) && // protocol command
                    !command.StartsWith("show"))
                {
                    _chr.WriteToDisplay("You are no longer meditating.");
                    _chr.IsResting    = false;
                    _chr.IsMeditating = false;
                }
            }
            #endregion

            // Any command while peeking will be an automatic rest and break the character out of the trance.
            if (_chr.IsPeeking)
            {
                command = "rest";
                args    = "";
            }

            #region If wizard eye
            // Only movement, look, rest and again are acceptable commands when in wizard eye.
            if (_chr.IsWizardEye)
            {
                command = command.ToLower();
                switch (command.ToLower())
                {
                case "n":
                case "north":
                case "s":
                case "south":
                case "e":
                case "east":
                case "w":
                case "west":
                case "ne":
                case "northeast":
                case "nw":
                case "northwest":
                case "se":
                case "southeast":
                case "sw":
                case "southwest":
                case "d":
                case "down":
                case "u":
                case "up":
                case "a":
                case "again":
                case "l":
                case "look":
                case "rest":
                    break;

                default:
                    _chr.WriteToDisplay("You cannot use that command while polymorphed.");
                    return(true);
                }
            }
            #endregion

            if (_chr.protocol == DragonsSpineMain.Instance.Settings.DefaultProtocol)
            {
                if (ProtocolYuusha.CheckGameCommand(_chr, command, args))
                {
                    return(true);
                }
            }

            // catch some commands before they go through the parser

            #region If Speech. Command starts with a / or a " while in game.
            if (command.StartsWith("/") || command.StartsWith("\""))
            {
                if (!_chr.IsImmortal && _chr.HasEffect(Effect.EffectTypes.Silence))
                {
                    _chr.WriteToDisplay("You have been silenced and are unable to speak.");
                    return(true);
                }

                if (args.IndexOf("/!") != -1)
                {
                    _chr.SendShout(_chr.Name + ": " + args.Substring(0, args.IndexOf("/!")));
                    if (_chr.IsPC)
                    {
                        _chr.WriteToDisplay("You shout: " + args.Substring(0, args.IndexOf("/!")));
                        Utils.Log(_chr.Name + ": " + args.Substring(0, args.IndexOf("/!")), Utils.LogType.PlayerChat);
                    }
                    return(true);
                }
                else if (args.IndexOf("\"!") != -1)
                {
                    _chr.SendShout(_chr.Name + ": " + args.Substring(0, args.IndexOf("\"!")));
                    if (_chr.IsPC)
                    {
                        _chr.WriteToDisplay("You shout: " + args.Substring(0, args.IndexOf("\"!")));
                        Utils.Log(_chr.Name + ": " + args.Substring(0, args.IndexOf("\"!")), Utils.LogType.PlayerChat);
                    }
                    return(true);
                }
                else
                {
                    _chr.SendToAllInSight(_chr.Name + ": " + args);
                    if (_chr.IsPC)
                    {
                        _chr.WriteToDisplay("You say: " + args);
                        Utils.Log(_chr.Name + ": " + args, Utils.LogType.PlayerChat);
                    }
                    return(true);
                }
            }
            #endregion

            #region NPC interaction. Command ends with a comma (,)
            else if (command.EndsWith(","))// && !command.ToLower().StartsWith("all"))
            {
                if (!_chr.IsImmortal && _chr.HasEffect(Effect.EffectTypes.Silence))
                {
                    _chr.WriteToDisplay("You have been silenced and are unable to speak.");
                    return(true);
                }

                try
                {
                    // djinn, take halberd
                    // djinn, take 2 halberd
                    // 2 djinn, take 2 halberd
                    // all, follow me

                    string targetName = command.Substring(0, command.IndexOf(",")); // definitely going to be a comma

                    string[] targetArgs = targetName.Split(" ".ToCharArray());      // if this is longer than 1 in length probably using #

                    args = args.Trim();

                    string[] sArgs = args.Split(" ".ToCharArray());

                    if (String.IsNullOrEmpty(sArgs[0]) || sArgs.Length == 0)
                    {
                        return(false);
                    }

                    string order = sArgs[0];

                    args = args.Replace(order, "");

                    args = args.Trim();

                    #region All, do something
                    if (command.ToLower().StartsWith("all"))
                    {
                        if (_chr.Pets == null || _chr.Pets.Count == 0)
                        {
                            _chr.WriteToDisplay("There is nothing here to interact with.");
                            return(true);
                        }

                        bool interactPositive = false;

                        foreach (NPC pet in new List <NPC>(_chr.Pets))
                        {
                            if (TargetAcquisition.FindTargetInView(_chr, pet) != null)
                            {
                                interactPositive = AI.Interact(_chr, pet, order, args);
                            }
                        }

                        return(interactPositive);
                    }
                    #endregion

                    Character target = null;

                    var countTo = 0;

                    // Not using ALL, try 2 <target>, do something.
                    if (targetArgs.Length > 1 && Int32.TryParse(targetArgs[0], out countTo))
                    {
                        target = TargetAcquisition.FindTargetInView(_chr, targetArgs[1].ToLower(), countTo);
                    }

                    // Not using ALL, try <target>, do something.
                    if (target == null && targetArgs.Length == 1)
                    {
                        target = TargetAcquisition.FindTargetInView(_chr, targetArgs[0].ToLower(), 1);

                        if (target == null)
                        {
                            target = TargetAcquisition.FindTargetInView(_chr, targetName, false, false);
                        }
                    }

                    if (target == null)
                    {
                        _chr.WriteToDisplay("You do not see " + targetName + " here.");
                        return(true);
                    }
                    else
                    {
                        return(AI.Interact(_chr, target, order, args));
                    }
                }
                catch (Exception e)
                {
                    Utils.LogException(e);
                    return(false);
                }
            }
            #endregion
            else
            {
                int andStrPos = 0;

                #region Check for command joining, split them then parse and int
                // If command has the word "and" for joining two commands.
                // 9/24/2019 We don't still need this.
                //if (_chr.PCState == Globals.ePlayerState.PLAYING && sCmdAndArgs.IndexOf(" and ") != -1 && command.ToLower() != "tell" && )
                //    sCmdAndArgs = sCmdAndArgs.Replace(" and ", ";");

                andStrPos = sCmdAndArgs.IndexOf(";", 0, sCmdAndArgs.Length);

                if (andStrPos > 0)
                {
                    //Break out the two commands
                    string[] sCommands = sCmdAndArgs.Split(";".ToCharArray());

                    if (sCommands[0].Length > 0)
                    {
                        //get the command and the args
                        sCommands[0] = sCommands[0].Trim();//.ToLower();

                        string[] sArgss = sCommands[0].Split(" ".ToCharArray());

                        for (i = 1; i <= sArgss.GetUpperBound(0); i++)
                        {
                            newArgs = newArgs + " " + sArgss[i];
                        }

                        ParseCommand(_chr, sArgss[0].ToString().Trim(), newArgs.Trim());
                        //chr.FirstJoinedCommand = chr.CommandsProcessed[0];
                        //chr.FirstJoinedCommand = chr.CommandType;
                    }

                    if (sCommands[1].Length > 0)
                    {
                        //get the command and the args
                        sCommands[1] = sCommands[1].Trim();//.ToLower();

                        string[] s2Argss = sCommands[1].Split(" ".ToCharArray());

                        newArgs = "";

                        for (i = 1; i <= s2Argss.GetUpperBound(0); i++)
                        {
                            if (s2Argss[i].ToLower() != "it")
                            {
                                newArgs = newArgs + " " + s2Argss[i];
                            }
                            else
                            {
                                string[] sArgss = sCommands[0].Split(" ".ToCharArray());
                                newArgs = newArgs + " " + sArgss[1];
                            }
                        }

                        ParseCommand(_chr, s2Argss[0].ToString().Trim(), newArgs.Trim());
                        //chr.FirstJoinedCommand = CommandType.None;
                    }

                    return(true);
                }
                #endregion

                if (command.StartsWith("$"))
                {
                    if (command.Contains("list"))
                    {
                        args = "list";
                    }
                    else if (command.Length > 1 && command.Length < 4)
                    {
                        args = command.Substring(1, command.Length - 1) + " " + args;
                        args.Trim();
                    }

                    command = "macro";
                }

                // lower case
                command = command.ToLower();

                #region Check command aliases and change the command if an alias is found.
                if (GameCommand.GameCommandAliases.ContainsKey(command))
                {
                    command = GameCommand.GameCommandAliases[command];
                }
                else if (GameCommand.GameCommandAliases.ContainsKey(command + " " + args))
                {
                    command = GameCommand.GameCommandAliases[command + " " + args];
                }
                #endregion

                // check for the command in the dictionary
                if (GameCommand.GameCommandDictionary.ContainsKey(command))
                {
                    // non player characters make no checks to perform commands
                    if (!(_chr is PC))
                    {
                        return(GameCommand.GameCommandDictionary[command].Handler.OnCommand(_chr, args));
                    }

                    GameCommand gc = GameCommand.GameCommandDictionary[command];

                    // check player ImpLevel and the command may be executed while playing the game
                    if ((_chr as PC).ImpLevel >= (Globals.eImpLevel)gc.PrivLevel &&
                        Array.IndexOf(gc.States, _chr.PCState) > -1)
                    {
                        _chr.CommandWeight += gc.Weight;

                        return(GameCommand.GameCommandDictionary[command].Handler.OnCommand(_chr, args));
                    }

                    return(false);
                }
                else if (Talents.GameTalent.GameTalentDictionary.ContainsKey(command))
                {
                    Talents.GameTalent gameTalent = Talents.GameTalent.GameTalentDictionary[command];

                    // immortal flag added for testing purposes
                    if ((_chr.IsImmortal || _chr.talentsDictionary.ContainsKey(command)) && !gameTalent.IsPassive)
                    {
                        if (_chr.IsImmortal || (DateTime.UtcNow - gameTalent.DownTime >= _chr.talentsDictionary[command]))
                        {
                            if (!gameTalent.MeetsPerformanceCost(_chr))
                            {
                                _chr.WriteToDisplay("You do not have enough stamina to perform the " + gameTalent.Name + " talent.");
                                return(true);
                            }

                            if (!Talents.GameTalent.GameTalentDictionary[command].Handler.OnPerform(_chr, args))
                            {
                                _chr.WriteToDisplay("Talent not performed.");
                            }
                            else
                            {
                                gameTalent.SuccessfulPerformance(_chr);
                            }
                        }
                        else
                        {
                            int roundsRemaining = Utils.TimeSpanToRounds(gameTalent.DownTime - (DateTime.UtcNow - _chr.talentsDictionary[command]));
                            _chr.WriteToDisplay("Talent timer has not reset yet. It will be available " + (roundsRemaining > 0 ? "in " + roundsRemaining : "next") + " round" + (roundsRemaining > 1 ? "s" : "") + ".");
                        }
                    }
                    else if (_chr.talentsDictionary.ContainsKey(command) && gameTalent.IsPassive)
                    {
                        _chr.WriteToDisplay(gameTalent.Name + " is a passive talent.");
                    }
                    else
                    {
                        _chr.WriteToDisplay("You do not know how to perform the " + gameTalent.Name + " talent.");
                    }

                    return(true);
                }
                else // command does not exist in the dictionary
                {
                    MethodInfo[] methodInfo = typeof(CommandTasker).GetMethods();

                    try
                    {
                        foreach (MethodInfo m in methodInfo)
                        {
                            int length = m.Name.Length;
                            if (m.Name.IndexOf("_") != -1)
                            {
                                length = m.Name.IndexOf("_");
                            }
                            if (m.Name.ToLower().Substring(0, length) == command)
                            {
                                _chr.CommandWeight += 1; // add one to the command weight

                                object[] obj = new object[1];

                                obj[0] = args;

                                try
                                {
                                    m.Invoke(this, obj);
                                }
                                catch (Exception e)
                                {
                                    Utils.LogException(e);
                                }
                                return(true);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        _chr.WriteToDisplay("Error processing your command. Please report this.");
                        Utils.Log("Failure at Command.interpretCommand(" + command + ", " + args + ")", Utils.LogType.SystemFailure);
                        Utils.LogException(e);
                        return(false);
                    }
                }
            }

            #region Spell Chant Exists
            if (_chr.spellDictionary.ContainsValue(command.ToLower() + " " + args.ToLower()))
            {
                if (!_chr.IsImmortal && _chr.InUnderworld)
                {
                    _chr.WriteToDisplay(TextManager.COMMAND_NOT_UNDERSTOOD);
                    return(true);
                }

                if (!_chr.IsImmortal && _chr.HasEffect(Effect.EffectTypes.Silence))
                {
                    _chr.WriteToDisplay("You have been silenced and are unable to warm spells.");
                    return(true);
                }

                if (_chr.preppedSpell != null) // TODO talent here to automatically clear prepped spell
                {
                    _chr.WriteToDisplay("You already have a spell warmed. Either cast it or rest to clear your mind.");
                    return(true);
                }
                else
                {
                    _chr.CommandWeight += 3;

                    if (_chr.CommandWeight == 3)
                    {
                        _chr.CommandType = CommandType.Chant;
                        foreach (int spellID in _chr.spellDictionary.Keys)
                        {
                            if (_chr.spellDictionary[spellID] == (command.ToLower() + " " + args.ToLower()))
                            {
                                _chr.WarmSpell(spellID);
                                break;
                            }
                        }

                        //if(_chr is PC)
                        //    World.magicCordThisRound.Add(_chr.FacetID + "|" + _chr.LandID + "|" + _chr.MapID + "|" + _chr.X + "|" + _chr.Y + "|" + _chr.Z);

                        _chr.PreppedRound = DragonsSpineMain.GameRound;
                        int  bitcount = 0;
                        Cell curCell  = null;
                        // this is the same logic from chr.sendToAllInSight, however we add spell info in some situations
                        // loop through all visible cells

                        for (int ypos = -3; ypos <= 3; ypos += 1)
                        {
                            for (int xpos = -3; xpos <= 3; xpos += 1)
                            {
                                if (Cell.CellRequestInBounds(_chr.CurrentCell, xpos, ypos))
                                {
                                    if (_chr.CurrentCell.visCells[bitcount]) // check the PC list, and char list of the cell
                                    {
                                        curCell = Cell.GetCell(_chr.FacetID, _chr.LandID, _chr.MapID, _chr.X + xpos, _chr.Y + ypos, _chr.Z);

                                        if (curCell != null)
                                        {
                                            foreach (Character character in curCell.Characters.Values)                    // search for the character in the charlist of the cell
                                            {
                                                if (character != _chr && character is PC)                                 // players sending messages to other players
                                                {
                                                    if (Array.IndexOf((character as PC).ignoreList, _chr.UniqueID) == -1) // ignore list
                                                    {
                                                        if ((_chr.Group != null && _chr.preppedSpell != null && _chr.Group.GroupMemberIDList.Contains(character.UniqueID)) ||
                                                            (character as PC).ImpLevel >= Globals.eImpLevel.GM ||
                                                            character.HasEffect(Effect.EffectTypes.Gnostikos))
                                                        {
                                                            character.WriteToDisplay(_chr.Name + ": " + command + " " + args + " <" + _chr.preppedSpell.Name + ">");
                                                        }
                                                        else
                                                        {
                                                            character.WriteToDisplay(_chr.Name + ": " + command + " " + args);
                                                        }
                                                    }
                                                }
                                                else if (character != _chr && character.IsPC && !_chr.IsPC) // non players sending messages to other players
                                                {
                                                    character.WriteToDisplay(_chr.Name + ": " + command + " " + args);
                                                }

                                                //TODO: else... detect spell casting by sensitive NPC
                                            }
                                        }
                                    }
                                    bitcount++;
                                }
                            }
                        }
                    }
                    else
                    {
                        _chr.WriteToDisplay("Warming a spell requires your full concentration.");
                    }
                }
                return(true);
            }
            #endregion

            Utils.Log(_chr.GetLogString() + " Invalid command: " + command + " args: " + args, Utils.LogType.CommandFailure);
            _chr.WriteToDisplay("I don't understand your command. For a full list of game commands visit the Dragon's Spine forums.");
            return(false);
        }