Exemple #1
0
    /// <summary>
    /// Returns a random quest ID from QuestIdSkillRankList,
    /// based on the current Erinn day and the player's blacksmithing
    /// PTJ level/skill rank (via <paramref name="npc"/>).
    /// </summary>
    /// <param name="npc"></param>
    /// <returns>
    /// Will always return a quest ID of the given <paramref name="level"/>.
    /// However, if no job of the matching rank can be found,
    /// a job of next-highest rank will be returned.
    /// </returns>
    /// <remarks>
    /// As there are (at the time of writing) only jobs of rank F, C, B, and A,
    /// the ranks that are supplied to and returned from this method are as follows:
    /// <list type="table">
    ///     <listheader> <term>Supplied Rank</term> <term>Returned Rank</term> </listheader>
    ///     <item>       <term>(Unlearned)</term>   <term>rF</term>                </item>
    ///     <item>       <term>rN ~ rD</term>       <term>rF</term>                </item>
    ///     <item>       <term>rC ~ rA</term>       <term>[Same as supplied]</term></item>
    ///     <item>       <term>r9 and up</term>     <term>rA</term>                </item>
    /// </list>
    ///
    /// See also: http://wiki.mabinogiworld.com/view/Thread:Talk:Edern/Part-time_job_requests
    /// </remarks>
    public int RandomPtj(NpcScript npc)
    {
        // Determine player's Blacksmithing skill level
        var playerSkills = npc.Player.Skills;
        var skillRank    = playerSkills.Has(SkillId.Blacksmithing)
                        ? playerSkills.Get(SkillId.Blacksmithing).Info.Rank
                        : SkillRank.RF; // Default to RF jobs if player does not know Blacksmithing.
        var ptjQuestLevel = npc.GetPtjQuestLevel(JobType);

        Func <SkillRank, IEnumerable <int> > GetSameRankQuests = r => QuestIdSkillRankList
                                                                 .Where(pair => pair.Item2 == r) // Filter on skill rank
                                                                 .Select(pair => pair.Item1);    // Get resulting quest IDs
        Func <IEnumerable <int>, int> GetRandomIdOfTheDay = ids => ids.ElementAt(new Random(ErinnTime.Now.DateTimeStamp).Next(ids.Count()));

        var rankProbe         = skillRank;
        var sameLevelQuestIds = npc.GetLevelMatchingQuestIds(JobType, QuestIdSkillRankList.Select(pair => pair.Item1).ToArray());

        IEnumerable <int> matchingQuestIds;

        // Clamp on rank A, the most difficult job available.
        if (rankProbe > SkillRank.RA)
        {
            rankProbe = SkillRank.RA;
        }
        // Filter on skill rank, retrying on a lower rank if no results.
        while (rankProbe >= SkillRank.RC)
        {
            // Merge with filter on sameLevelQuestIds.
            matchingQuestIds = GetSameRankQuests(rankProbe).Where(id => sameLevelQuestIds.Contains(id));

            if (matchingQuestIds.Any())
            {
                return(GetRandomIdOfTheDay(matchingQuestIds));
            }
            else
            {
                --rankProbe;                 // Retry on lower rank.
            }
        }
        // Else no matching jobs at A, B, or C.

        // Try rank F jobs?
        matchingQuestIds = GetSameRankQuests(SkillRank.RF).Where(id => sameLevelQuestIds.Contains(id));
        if (matchingQuestIds.Any())
        {
            return(GetRandomIdOfTheDay(matchingQuestIds));
        }
        // Else no matching jobs at F.
        // If this point is reached,
        // we were not able to find a quest for the player.
        throw new Exception(string.Format("EdernPtjScript.RandomPtj: Unable to provide a quest for level:{0}, rank:{1}", ptjQuestLevel, skillRank));
    }