void HandleGenesis(LogEntry line)
        {
            // genesis handling, purpose:
            // remembering genesis casts so smilexamine can be allowed to update traits,
            // even though it would normally be blocked by sanity check

            //[2013-08-02] [23:08:54] You cast Genesis on Old fat Jollyhalim.
            if (Regex.IsMatch(line.Content, @".+ cast", RegexOptions.Compiled))
            {
                grangerDebug.Log("Found maybe genesis log event: " + line);
                // New matcher after creature cages update.
                Match match = Regex.Match(line.Content,
                                          @"(?:You cast|.+ casts) Genesis on(?: a| an| the|) (.+)\.",
                                          RegexOptions.Compiled);
                if (!match.Success)
                {
                    // Message version for older WU servers.
                    // This version was introduced in caves update.
                    match = Regex.Match(line.Content, @"(?:You cast|.+ casts) 'Genesis' on(?: a| an| the) (.+)\.", RegexOptions.Compiled);
                }
                if (!match.Success)
                {
                    // Message version for older WU servers.
                    match = Regex.Match(line.Content, @"(?:You cast|.+ casts) 'Genesis' on (.+)\.", RegexOptions.Compiled);
                }
                if (match.Success)
                {
                    string prefixedCreatureName = match.Groups[1].Value;
                    string creatureName         = GrangerHelpers.ExtractCreatureName(prefixedCreatureName);
                    grangerDebug.Log(string.Format("Recognized Genesis cast on: {0} (raw name: {1})",
                                                   creatureName,
                                                   prefixedCreatureName));
                    parentModule.Settings.AddGenesisCast(DateTime.Now, creatureName);
                }
            }
        }
        public void HandleLogEvent(string line)
        {
            // Smile emote triggers processing of new creature.
            // If previous processing is still active, it should be finalized.
            if (line.StartsWith("You smile at", StringComparison.Ordinal))
            {
                debugLogger.Log("smile cond: " + line);
                AttemptToStartProcessing(line);
            }

            // While processing creature, log events are parsed and valid data buffered into the current buffer.
            if (isProcessing)
            {
                //[20:23:18] It has fleeter movement than normal. It has a strong body. It has lightning movement. It can carry more than average. It seems overly aggressive.
                if (!verifyList.Traits && CreatureTrait.CanThisBeTraitLogMessage(line))
                {
                    debugLogger.Log("found maybe trait line: " + line);
                    var extractedTraits = GrangerHelpers.ParseTraitsFromLine(line);
                    foreach (var trait in extractedTraits)
                    {
                        debugLogger.Log("found trait: " + trait);
                        creatureBuffer.Traits.Add(trait);
                        verifyList.Traits = true;
                    }
                    debugLogger.Log("trait parsing finished");
                    if (creatureBuffer.InspectSkill == 0 && creatureBuffer.Traits.Count > 0)
                    {
                        var message =
                            String.Format(
                                "{0} ({1}) can see traits, but Granger found no Animal Husbandry skill for him. Is this a bug? Creature will be added anyway.",
                                playerMan.PlayerName, creatureBuffer.Server);
                        logger.Error(message);
                        trayPopups.Schedule(message, "POSSIBLE PROBLEM", 5000);
                    }
                }
                //[20:23:18] She is very strong and has a good reserve of fat.
                if (line.StartsWith("He", StringComparison.Ordinal) && !verifyList.Gender)
                {
                    creatureBuffer.IsMale = true;
                    verifyList.Gender     = true;
                    debugLogger.Log("creature set to male");
                }
                if (line.StartsWith("She", StringComparison.Ordinal) && !verifyList.Gender)
                {
                    creatureBuffer.IsMale = false;
                    verifyList.Gender     = true;
                    debugLogger.Log("creature set to female");
                }
                //[22:34:28] His mother is the old fat Painthop. His father is the venerable fat Starkclip.
                //[22:34:28] Her mother is the old fat Painthop. Her father is the venerable fat Starkclip.
                if (IsParentIdentifyingLine(line) && !verifyList.Parents)
                {
                    debugLogger.Log("found maybe parents line");

                    Match motherMatch = ParseMother(line);
                    if (motherMatch.Success)
                    {
                        string mother = motherMatch.Groups["g"].Value;
                        mother = GrangerHelpers.ExtractCreatureName(mother);
                        creatureBuffer.MotherName = mother;
                        debugLogger.Log("mother set to: " + mother);
                    }
                    Match fatherMatch = ParseFather(line);
                    if (fatherMatch.Success)
                    {
                        string father = fatherMatch.Groups["g"].Value;
                        father = GrangerHelpers.ExtractCreatureName(father);
                        creatureBuffer.FatherName = father;
                        debugLogger.Log("father set to: " + father);
                    }
                    verifyList.Parents = true;
                    debugLogger.Log("finished parsing parents line");
                }
                //[20:23:18] It is being taken care of by Darkprincevale.
                if (line.Contains("It is being taken care") && !verifyList.CaredBy)
                {
                    debugLogger.Log("found maybe take care of line");
                    Match caredby = Regex.Match(line, @"care of by (\w+)");
                    if (caredby.Success)
                    {
                        creatureBuffer.CaredBy = caredby.Groups[1].Value;
                        debugLogger.Log("cared set to: " + creatureBuffer.CaredBy);
                    }
                    verifyList.CaredBy = true;
                    debugLogger.Log("finished parsing care line");
                }
                //[17:11:42] She will deliver in about 4 days.
                //[17:11:42] She will deliver in about 1 day.
                if (line.Contains("She will deliver in") && !verifyList.Pregnant)
                {
                    debugLogger.Log("found maybe pregnant line");
                    Match match = Regex.Match(line, @"She will deliver in about (\d+)");
                    if (match.Success)
                    {
                        double length = Double.Parse(match.Groups[1].Value) + 1D;
                        creatureBuffer.PregnantUntil = DateTime.Now + TimeSpan.FromDays(length);
                        debugLogger.Log("found creature to be pregnant, estimated delivery: " + creatureBuffer.PregnantUntil);
                    }
                    verifyList.Pregnant = true;
                    debugLogger.Log("finished parsing pregnant line");
                }
                //[20:58:26] A foal skips around here merrily
                //[01:59:09] This calf looks happy and free.
                if ((line.Contains("A foal skips around here merrily") ||
                     line.Contains("This calf looks happy and free") ||
                     line.Contains("A small cuddly ball of fluff")) &&
                    !verifyList.Foalization)
                {
                    debugLogger.Log("applying foalization to the creature");
                    try
                    {
                        creatureBuffer.Age     = CreatureAge.Foalize(creatureBuffer.Age);
                        verifyList.Foalization = true;
                    }
                    catch (InvalidOperationException exception)
                    {
                        logger.Error(exception, "The creature appears to be a foal, but has invalid age for a foal!");
                    }
                }
                //[20:57:27] It has been branded by and belongs to the settlement of Silver Hill Estate.
                if (line.Contains("It has been branded") && !verifyList.Branding)
                {
                    debugLogger.Log("found maybe branding line");
                    Match match = Regex.Match(line, @"belongs to the settlement of (.+)\.");
                    if (match.Success)
                    {
                        string settlementName = match.Groups[1].Value;
                        creatureBuffer.BrandedBy = settlementName;
                        debugLogger.Log("found creature to be branded for: " + creatureBuffer.BrandedBy);
                        verifyList.Branding = true;
                    }
                }
                //[11:43:35] Its colour is ash.
                if (line.Contains("Its colour is"))
                {
                    debugLogger.Log("found maybe color line");
                    Match match = Regex.Match(line, @"Its colour is (.+)\.");
                    if (match.Success)
                    {
                        string colorName = match.Groups[1].Value;
                        creatureBuffer.ColorWurmLogText = colorName;
                        debugLogger.Log("found creature to have color: " + creatureBuffer.ColorWurmLogText);
                        verifyList.Branding = true;
                    }
                }
            }
        }
        void AttemptToStartProcessing(string line)
        {
            debugLogger.Log("attempting to start processing creature due to line: " + line);
            // Apply previous processing, if still active.
            VerifyAndApplyProcessing();

            try
            {
                debugLogger.Log("extracting object name");

                // [20:48:42] You smile at the Adolescent diseased Mountainheart.
                // This regex preserves condition from before WO Rift update, where determiner was not present.
                // This is kept, because WU servers cannot be guaranteed to have been updated by their administrators.
                Match match = Regex.Match(line,
                                          @"You smile at (a|an|the) (?<g>.+)\.|You smile at (?<g>.+)\.",
                                          RegexOptions.IgnoreCase | RegexOptions.Compiled);
                string objectNameWithPrefixes = string.Empty;
                if (match.Success)
                {
                    objectNameWithPrefixes = match.Groups["g"].Value;
                }

                if (GrangerHelpers.HasAgeInName(objectNameWithPrefixes, ignoreCase: true))
                {
                    debugLogger.Log("object assumed to be a creature");
                    var server = playerMan.CurrentServer;
                    var skill  = playerMan.CurrentServerAhSkill;

                    if (grangerSettings.RequireServerAndSkillToBeKnownForSmilexamine &&
                        (server == null || skill == null))
                    {
                        trayPopups.Schedule(
                            "Server or AH skill level unknown for " + playerMan.PlayerName +
                            ". If WA was just started, give it a few seconds. (This check can be disabled in Granger options)", "CAN'T PROCESS CREATURE", 5000);
                        debugLogger.Log(string.Format(
                                            "processing creature cancelled, AH skill or server group unknown for player {0} (skill: {1} ; server: {2}",
                                            playerMan.PlayerName, skill, server));
                    }
                    else
                    {
                        debugLogger.Log("building new creature object and moving to processor");

                        isProcessing        = true;
                        startedProcessingOn = DateTime.Now;
                        verifyList          = new ValidationList();
                        creatureBuffer      = new CreatureBuffer
                        {
                            Name         = GrangerHelpers.ExtractCreatureName(objectNameWithPrefixes),
                            Age          = GrangerHelpers.ExtractCreatureAge(objectNameWithPrefixes),
                            Server       = server,
                            InspectSkill = skill ?? 0,
                        };

                        var fat = GrangerHelpers.TryParseCreatureNameIfLineContainsFat(objectNameWithPrefixes);
                        if (fat != null)
                        {
                            creatureBuffer.SecondaryInfo = CreatureEntity.SecondaryInfoTag.Fat;
                        }

                        var starving = GrangerHelpers.TryParseCreatureNameIfLineContainsStarving(objectNameWithPrefixes);
                        if (starving != null)
                        {
                            creatureBuffer.SecondaryInfo = CreatureEntity.SecondaryInfoTag.Starving;
                        }

                        var diseased = GrangerHelpers.TryParseCreatureNameIfLineContainsDiseased(objectNameWithPrefixes);
                        if (diseased != null)
                        {
                            creatureBuffer.SecondaryInfo = CreatureEntity.SecondaryInfoTag.Diseased;
                        }

                        verifyList.Name = true;
                        debugLogger.Log("finished building");
                    }
                }
                else
                {
                    debugLogger.Log(objectNameWithPrefixes + " was not recognized as a named creature.");
                }
            }
            catch (Exception exception)
            {
                debugLogger.Log("! Granger: error while BeginProcessing, event: " + line, true, exception);
            }
        }