Ejemplo n.º 1
0
            public bool FindPath(TalentNode node, IEnumerable <TalentNode> characterTalents, IList <TalentNode> procesedNodes)
            {
                procesedNodes.Add(node);
                var(x, y) = TalentPositionHelper.GetCoordinatesFromPosition(node.Position);
                if ((Math.Abs(x - _centerX) == 1 && y == _centerY) || (Math.Abs(y - _centerY) == 1 && x == _centerX))
                {
                    return(true);
                }

                var leftTalent = characterTalents.FirstOrDefault(k =>
                {
                    var coordinates = TalentPositionHelper.GetCoordinatesFromPosition(k.Position);
                    return(coordinates.x == x + 1 && coordinates.y == y);
                });

                if (leftTalent != null && !procesedNodes.Contains(leftTalent) && FindPath(leftTalent, characterTalents, procesedNodes))
                {
                    return(true);
                }

                var rightTalent = characterTalents.FirstOrDefault(k =>
                {
                    var coordinates = TalentPositionHelper.GetCoordinatesFromPosition(k.Position);
                    return(coordinates.x == x - 1 && coordinates.y == y);
                });

                if (rightTalent != null && !procesedNodes.Contains(rightTalent) && FindPath(rightTalent, characterTalents, procesedNodes))
                {
                    return(true);
                }

                var topTalent = characterTalents.FirstOrDefault(k =>
                {
                    var coordinates = TalentPositionHelper.GetCoordinatesFromPosition(k.Position);
                    return(coordinates.x == x && coordinates.y == y - 1);
                });

                if (topTalent != null && !procesedNodes.Contains(topTalent) && FindPath(topTalent, characterTalents, procesedNodes))
                {
                    return(true);
                }

                var bottomTalent = characterTalents.FirstOrDefault(k =>
                {
                    var coordinates = TalentPositionHelper.GetCoordinatesFromPosition(k.Position);
                    return(coordinates.x == x && coordinates.y == y + 1);
                });

                if (bottomTalent != null && !procesedNodes.Contains(bottomTalent) && FindPath(bottomTalent, characterTalents, procesedNodes))
                {
                    return(true);
                }

                return(false);
            }
Ejemplo n.º 2
0
            public async Task <ActiveUserDto> Handle(GetActiveUserQuery request, CancellationToken cancellationToken)
            {
                var user = await _userManager.GetUserAsync(request.User);

                var statusInBattle = _battleService.IsUserInBattle(user.Id);
                var roster         = await _gameContext.Rosters.GetOneAsync(x => x.UserId == user.Id);

                IEnumerable <Character> characters;

                if (roster == null)
                {
                    roster = new Roster()
                    {
                        Id             = user.Id,
                        UserId         = user.Id,
                        Experience     = 0,
                        Seed           = user.Id.GetHashCode(),
                        TavernCapacity = 6,
                        BoughtPatrons  = new int[0]
                    };
                    _gameContext.Rosters.InsertOne(roster);
                    var userCharacter = new Character()
                    {
                        Id             = Guid.NewGuid().ToString(),
                        Deleted        = false,
                        IsKeyCharacter = true,
                        RosterId       = roster.Id,
                        Name           = user.ViewName,
                        ChosenTalents  = new int[0]
                    };
                    _gameContext.Characters.InsertOne(userCharacter);
                    characters = new Character[] { userCharacter };
                    await _gameContext.ApplyChangesAsync();
                }
                else
                {
                    characters = await _gameContext.Characters.GetAsync(x => x.RosterId == roster.Id && !x.Deleted);
                }

                var tavern = new List <CharacterForSaleDto>();

                for (int i = 1; i <= roster.TavernCapacity; i++)
                {
                    if (!roster.BoughtPatrons.Any(x => x == i))
                    {
                        tavern.Add(new CharacterForSaleDto()
                        {
                            Id = i
                        });
                    }
                }

                var talents = await _registryContext.TalentMap.GetAsync(x => true);

                return(new ActiveUserDto()
                {
                    Name = user.ViewName,
                    UniqueId = user.UserName,
                    Id = user.Id,
                    Email = user.Email,
                    State = statusInBattle ? UserState.Battle : UserState.Lobby,
                    Experience = roster.Experience,
                    Tavern = tavern,
                    Roster = characters.Select(x =>
                    {
                        return new CharacterDto()
                        {
                            Id = x.Id,
                            Name = x.Name,
                            IsKeyCharacter = x.IsKeyCharacter,
                            Talents = x.ChosenTalents.Select(k =>
                            {
                                var coordinates = TalentPositionHelper.GetCoordinatesFromPosition(k);
                                return new PointDto()
                                {
                                    X = coordinates.x,
                                    Y = coordinates.y
                                };
                            })
                        };
                    }),
                    TalentsMap = talents.Select(x =>
                    {
                        var position = TalentPositionHelper.GetCoordinatesFromPosition(x.Position);
                        return new TalentNodeDto()
                        {
                            X = position.x,
                            Y = position.y,
                            Name = x.Name,
                            Description = x.UniqueDescription,
                            Id = x.Id,
                            Speed = x.SpeedModifier,
                            Strength = x.StrengthModifier,
                            Willpower = x.WillpowerModifier,
                            Constitution = x.ConstitutionModifier,
                            Class = x.Class,
                            ClassPoints = x.ClassPoints,
                            Prerequisites = x.Prerequisites,
                            Exceptions = x.Exceptions,
                            SkillsAmount = x.SkillsAmount
                        };
                    })
                });
            }
Ejemplo n.º 3
0
            public async Task <Unit> Handle(ChangeCharacterTalentsCommand request, CancellationToken cancellationToken)
            {
                var roster = await _gameContext.Rosters.GetOneAsync(x => x.UserId == request.UserId);

                if (roster == null)
                {
                    throw new NotFoundException("User is not found");
                }

                var character = await _gameContext.Characters.GetOneAsync(x => x.Id == request.CharacterId);

                if (character == null)
                {
                    throw new NotFoundException("Character is not found");
                }

                if (character.RosterId != roster.Id)
                {
                    throw new CannotPerformOperationException("Character is not belong to user");
                }

                var changedTalentPositions = request.Changes.Select(x => TalentPositionHelper.GetPositionFromCoordinates(x.X, x.Y)).ToList();
                var allTalentPositions     = character.ChosenTalents.Union(changedTalentPositions).Distinct().ToList();
                var allTalents             = await _registryContext.TalentMap.GetAsync(x => allTalentPositions.Contains(x.Position));

                var characterTalents = allTalents.Where(x => character.ChosenTalents.Contains(x.Position)).ToList();

                var strength     = BattleHelper.DefaultStrength;
                var willpower    = BattleHelper.DefaultWillpower;
                var constitution = BattleHelper.DefaultConstitution;
                var speed        = BattleHelper.DefaultSpeed;
                var skillsCount  = 1;
                var cost         = 0;
                var talentsCount = 0;

                characterTalents.ForEach(x =>
                {
                    strength     += x.StrengthModifier;
                    willpower    += x.WillpowerModifier;
                    constitution += x.ConstitutionModifier;
                    speed        += x.SpeedModifier;
                    skillsCount  += x.SkillsAmount;
                    talentsCount++;
                });

                var newTalents = new List <TalentNodeChangeDeclarationDto>();

                foreach (var change in request.Changes)
                {
                    var changePosition = TalentPositionHelper.GetPositionFromCoordinates(change.X, change.Y);

                    // Accessibility check
                    TalentNodeChangeDeclarationDto talent;
                    if ((talent = newTalents.FirstOrDefault(x => x.X == change.X && x.Y == change.Y)) != null)
                    {
                        if (change.State == talent.State)
                        {
                            throw new CannotPerformOperationException("Cannot do the same action with talent twice");
                        }

                        cost--;
                        newTalents.Remove(talent);
                    }
                    else
                    {
                        if (characterTalents.Any(x => x.Position == changePosition) == change.State)
                        {
                            throw new CannotPerformOperationException("Cannot do action with talent");
                        }

                        cost++;
                        newTalents.Add(change);
                    }

                    var changeTalent = allTalents.First(x => x.Position == changePosition);

                    // ConditionalsCheck
                    if (change.State)
                    {
                        if (!((Math.Abs(change.X - _centerX) == 1 && change.Y == _centerY) || (Math.Abs(change.Y - _centerY) == 1 && change.X == _centerX)) &&
                            !characterTalents.Any(x =>
                        {
                            var talentCoordinates = TalentPositionHelper.GetCoordinatesFromPosition(x.Position);
                            return((Math.Abs(change.X - talentCoordinates.x) == 1 && change.Y == talentCoordinates.y) ||
                                   (Math.Abs(change.Y - talentCoordinates.y) == 1 && change.X == talentCoordinates.x));
                        }))
                        {
                            throw new CannotPerformOperationException("Cannot pick remote talent");
                        }

                        if (changeTalent.Exceptions != null && characterTalents.Any(x => changeTalent.Exceptions.Contains(x.Id)))
                        {
                            throw new CannotPerformOperationException("Cannot add talent with unprocessible exceptions");
                        }

                        if (changeTalent.Prerequisites != null && changeTalent.Prerequisites.Any(x => !characterTalents.Any(t => t.Id == x)))
                        {
                            throw new CannotPerformOperationException("Cannot add talent with unresolved prerequisites");
                        }

                        talentsCount++;
                        strength     += changeTalent.StrengthModifier;
                        willpower    += changeTalent.WillpowerModifier;
                        constitution += changeTalent.ConstitutionModifier;
                        speed        += changeTalent.SpeedModifier;
                        skillsCount  += changeTalent.SkillsAmount;

                        characterTalents.Add(changeTalent);
                    }
                    else
                    {
                        talentsCount--;
                        strength     -= changeTalent.StrengthModifier;
                        willpower    -= changeTalent.WillpowerModifier;
                        constitution -= changeTalent.ConstitutionModifier;
                        speed        -= changeTalent.SpeedModifier;
                        skillsCount  -= changeTalent.SkillsAmount;

                        characterTalents.Remove(characterTalents.First(x => x.Position == changePosition));

                        var leftTalent = characterTalents.FirstOrDefault(x =>
                        {
                            var coordinates = TalentPositionHelper.GetCoordinatesFromPosition(x.Position);
                            return(coordinates.x == change.X + 1 && coordinates.y == change.Y);
                        });
                        var rightTalent = characterTalents.FirstOrDefault(x =>
                        {
                            var coordinates = TalentPositionHelper.GetCoordinatesFromPosition(x.Position);
                            return(coordinates.x == change.X - 1 && coordinates.y == change.Y);
                        });
                        var topTalent = characterTalents.FirstOrDefault(x =>
                        {
                            var coordinates = TalentPositionHelper.GetCoordinatesFromPosition(x.Position);
                            return(coordinates.x == change.X && coordinates.y == change.Y - 1);
                        });
                        var bottomTalent = characterTalents.FirstOrDefault(x =>
                        {
                            var coordinates = TalentPositionHelper.GetCoordinatesFromPosition(x.Position);
                            return(coordinates.x == change.X && coordinates.y == change.Y + 1);
                        });
                        if ((leftTalent != null && !FindPath(leftTalent, characterTalents, new List <TalentNode>())) ||
                            (rightTalent != null && !FindPath(rightTalent, characterTalents, new List <TalentNode>())) ||
                            (topTalent != null && !FindPath(topTalent, characterTalents, new List <TalentNode>())) ||
                            (bottomTalent != null && !FindPath(bottomTalent, characterTalents, new List <TalentNode>())))
                        {
                            throw new CannotPerformOperationException("Remains talents without bonds");
                        }
                    }

                    if (talentsCount > _talentsMaxCount)
                    {
                        throw new CannotPerformOperationException("Extra talents");
                    }

                    if (cost > roster.Experience)
                    {
                        throw new CannotPerformOperationException("Not enough money");
                    }

                    if (strength < 5 || willpower < 5 || constitution < 5 || speed < 5)
                    {
                        throw new CannotPerformOperationException("Stats cannot be less than five");
                    }

                    if (skillsCount > 5)
                    {
                        throw new CannotPerformOperationException("Skills amount cannot be more than 5");
                    }
                }

                foreach (var change in newTalents)
                {
                    if (change.State)
                    {
                        _gameContext.Characters.Update(
                            x => x.Id == character.Id,
                            Builders <Character> .Update.Push(k => k.ChosenTalents, TalentPositionHelper.GetPositionFromCoordinates(change.X, change.Y)));
                    }
                    else
                    {
                        _gameContext.Characters.Update(
                            x => x.Id == character.Id,
                            Builders <Character> .Update.Pull(k => k.ChosenTalents, TalentPositionHelper.GetPositionFromCoordinates(change.X, change.Y)));
                    }
                }

                _gameContext.Rosters.Update(
                    x => x.UserId == roster.UserId,
                    Builders <Roster> .Update.Set(k => k.Experience, roster.Experience - cost));

                await _gameContext.ApplyChangesAsync();

                return(Unit.Value);
            }