예제 #1
0
        public UserTechnology GetCheckPendingResearch(string userId)
        {
            var pending = context.UserTechnologies.Include("Technology")
                          .FirstOrDefault(x => x.UserId.Equals(userId) && x.StatusId == UserTechnologyStatusTypes.Pending);

            if (pending != null)
            {
                if ((DateTime.Now - pending.ResearchStartDate).TotalDays > pending.Technology.ResearchDays)
                {
                    pending.StatusId = UserTechnologyStatusTypes.Researched;

                    var tech = pending.Technology;
                    // notify user
                    var note = CommunicationService.CreateNotification(
                        userId,
                        "Your research is complete!",
                        $"You finished researching {tech.Name} and gained {tech.BoostAmount:P1} {tech.BoostTypeId}");

                    context.Notes.Add(note);

                    var qm = new QueueManager();
                    qm.QueueResearchCompleted(userId);

                    return(null);
                }
            }

            return(pending);
        }
예제 #2
0
        /// <summary>
        /// get player level accounting for any recent experience
        /// probably something like: 300x - 150
        /// </summary>
        /// <param name="userId">user id</param>
        /// <param name="db">db context</param>
        /// <param name="commit">whether or not to commit this single change to the db</param>
        /// <returns>player level after updating for experience</returns>
        public static int GetLevel(string userId, ApplicationDbContext db, bool commit = true)
        {
            var user = db.Users.Single(x => x.Id == userId);

            var experienceNeeded = BaseExperience * Math.Pow(user.Level, ExperienceFactor);

            if (user.Experience >= experienceNeeded)
            {
                // todo: probably queue this message
                var note = CommunicationService.CreateNotification(
                    user.Id,
                    $"You leveled up to {user.Level + 1}!",
                    $"You gained enough experience to level up to {user.Level + 1}. Higher levels means more perks--keep up the good work!");

                db.Notes.Add(note);
                db.SaveChanges();

                user.Level++;

                if (commit)
                {
                    db.SaveChanges();
                }
            }

            return(user.Level);
        }
예제 #3
0
        public void ProcessEvents(ApplicationDbContext db, ApplicationUser user)
        {
            var territory = db.Territories
                            .Include(x => x.Players)
                            .FirstOrDefault(x => x.TerritoryId == user.TerritoryId);

            var now = DateTime.Now;

            if (territory != null)
            {
                // check resource updates
                if (territory.LastResourceCollection < DateTime.Now.AddHours(-1))
                {
                    // determine how many intervals
                    var elapsed      = DateTime.Now - territory.LastResourceCollection;
                    var hoursElapsed = elapsed.Hours;

                    // Get boosts from technology
                    var techBoosts = db.UserTechnologies
                                     .Include(x => x.Technology)
                                     .Where(x => x.UserId.Equals(user.Id) && x.StatusId == UserTechnologyStatusTypes.Researched)
                                     .ToList();

                    var civPop = territory.CivilianPopulation;

                    // todo: this sucks, refactor allocations into a table or something
                    var resourceMeta = db.Items.Where(x => x.IsCore.Equals(true))
                                       .Select(x => new ResourceMeta
                    {
                        ItemId = x.ItemId,
                        // this will be filled out momentarily
                        NewQuantity = 0,
                    })
                                       .ToList();

                    var userItems = user.Items
                                    .OrderByDescending(x => x.Item.MaxBoost)
                                    .ToList();

                    foreach (var resource in db.Items.Where(x => x.IsCore.Equals(true)))
                    {
                        var allocation = 0.0m;
                        // todo: this sucks, refactor allocations into a table or something
                        switch (resource.ItemId)
                        {
                        case 1: allocation = territory.WaterAllocation; break;

                        case 2: allocation = territory.FoodAllocation; break;

                        case 3: allocation = territory.WoodAllocation; break;

                        case 4: allocation = territory.StoneAllocation; break;

                        case 5: allocation = territory.OilAllocation; break;

                        case 6: allocation = territory.IronAllocation; break;
                        }

                        // get the useritem record
                        var resourceItem = user.Items.Single(x => x.ItemId == resource.ItemId);
                        // start with the boost from technologies
                        var boost = techBoosts
                                    .Where(x => x.Technology.BoostTypeId.Equals((BoostTypes)resource.ItemId))
                                    .Sum(x => x.Technology.BoostAmount);

                        // add any boost from items
                        var boostItems = userItems
                                         .Where(x => x.Item.BoostType == (BoostTypes)resource.ItemId)
                                         .Select(x => new BoostItem
                        {
                            BoostType = x.Item.BoostType,
                            MaxBoost  = x.Item.MaxBoost,
                            Quantity  = x.Quantity,
                        });

                        if (boostItems.Any())
                        {
                            boost += GetItemBoost((BoostTypes)resource.ItemId, boostItems.ToList(), allocation, civPop);
                        }
                        // do resource collection
                        resourceItem.Quantity += (int)((allocation + boost) * civPop * hoursElapsed);
                        resourceMeta.Single(x => x.ItemId == resource.ItemId).NewQuantity = resourceItem.Quantity;
                    }

                    // reset update time to the most recent hour to account for partial intervals
                    territory.LastResourceCollection = new DateTime(now.Year, now.Month, now.Day, now.Hour, 0, 0);

                    // queue a message to check for badges
                    var qm = new QueueManager();
                    qm.QueueResourceCollection(user.Id,
                                               resourceMeta.Single(x => x.ItemId == (int)ResourceTypes.Water).NewQuantity,
                                               resourceMeta.Single(x => x.ItemId == (int)ResourceTypes.Food).NewQuantity,
                                               resourceMeta.Single(x => x.ItemId == (int)ResourceTypes.Wood).NewQuantity,
                                               resourceMeta.Single(x => x.ItemId == (int)ResourceTypes.Stone).NewQuantity,
                                               resourceMeta.Single(x => x.ItemId == (int)ResourceTypes.Oil).NewQuantity,
                                               resourceMeta.Single(x => x.ItemId == (int)ResourceTypes.Iron).NewQuantity);
                }

                // check territory population growth
                if (territory.LastPopulationUpdate < DateTime.Now.AddHours(-24))
                {
                    var elapsed     = DateTime.Now - territory.LastPopulationUpdate;
                    var daysElapsed = elapsed.Days;

                    var noteText = string.Empty;

                    // Get boosts from technology
                    var populationBoosts = db.UserTechnologies.Where(x => x.UserId.Equals(user.Id) &&
                                                                     x.StatusId == UserTechnologyStatusTypes.Researched &&
                                                                     x.Technology.BoostTypeId == BoostTypes.Population)
                                           .Select(x => x.Technology.BoostAmount).ToList();

                    var growth = (int)(territory.CivilianPopulation * (territory.PopulationGrowthRate + populationBoosts.Sum()) * daysElapsed);

                    territory.CivilianPopulation += growth;

                    // reset update time to account for partial intervals
                    territory.LastPopulationUpdate = new DateTime(now.Year, now.Month, now.Day);

                    // notify user
                    var timeText = daysElapsed > 1 ? "recently" : "last night";
                    noteText = $"A few people from the outskirts found their way into your territory {timeText}. " +
                               $"Your population grew by {growth} to {territory.CivilianPopulation}. " +
                               "Your increased population will automatically help you gather more resources.";

                    var note = CommunicationService.CreateNotification(
                        user.Id,
                        $"Your civilian population grew by {growth} last night!",
                        noteText);

                    db.Notes.Add(note);
                }

                // check nightly attacks
                if (territory.LastNightlyAttack < DateTime.Now.AddHours(-24))
                {
                    var elapsed     = DateTime.Now - territory.LastNightlyAttack;
                    var daysElapsed = elapsed.Days;

                    var rand = new Random();

                    var log = new AttackLog
                    {
                        UserId = user.Id,
                    };

                    var survivals        = 0;
                    var attacks          = 0;
                    var populationLoss   = 0;
                    var resourceLossText = string.Empty;

                    // Calculate winPercentage
                    var defenseBoosts = db.UserTechnologies.Where(x => x.UserId.Equals(user.Id) &&
                                                                  x.StatusId == UserTechnologyStatusTypes.Researched &&
                                                                  x.Technology.BoostTypeId == BoostTypes.Defense)
                                        .Select(x => x.Technology.BoostAmount).ToList();
                    var winPercentage = 67 + (defenseBoosts.Sum() * 100);

                    for (var i = 0; i < daysElapsed; i++)
                    {
                        if (rand.Next(0, 100) > winPercentage)
                        {
                            attacks++;
                            log.WasAttacked = true;

                            // 1-2 nightly population loss for right now
                            // todo: boosts
                            populationLoss += rand.Next(0, 2) + 1;

                            // lose random resources
                            resourceLossText = ResourceService.RandomResource(user, false, false, 0.05);
                        }
                        else
                        {
                            survivals++;
                        }
                    }

                    // total population loss since last calculation
                    territory.CivilianPopulation -= populationLoss;

                    // reset update time to account for partial intervals
                    territory.LastNightlyAttack = new DateTime(now.Year, now.Month, now.Day);

                    if (attacks > 1)
                    {
                        log.Message = string.Format(
                            "Zombies have been pillaging your territory while you were away. You lost {0} {1}. {2}" +
                            $"Zombie Attacks: {attacks}. Thwarted attempts: {survivals}"
                            , populationLoss
                            , populationLoss == 1 ? "person" : "people"
                            , "You lost too many resources to count!");
                    }
                    else if (attacks == 1)
                    {
                        log.Message = string.Format(
                            "Zombies attacked your territory last night. You lost {0} {1}. {2}"
                            , populationLoss
                            , populationLoss == 1 ? "person" : "people"
                            , resourceLossText);
                    }
                    else if (attacks == 0)
                    {
                        log.Message = "Your territory survived all recent zombie attacks.";
                    }

                    var note = CommunicationService.CreateNotification(
                        user.Id,
                        "Recent Zombie Activity",
                        log.Message);

                    db.Notes.Add(note);

                    db.AttackLogs.Add(log);
                }
            }
        }