Exemplo n.º 1
0
        public void createWanders(int count, GameMap map, int skillLevel)
        {
            int xSize = map.Map.XSize;
            int ySize = map.Map.YSize;

            int x, y;

            bool placed = false;

            for (int i = 0; i < count; i++)
            {
                while (!placed)
                {
                    x = n_Rand.Next(1, xSize - 1);
                    y = n_Rand.Next(1, ySize - 1);

                    if (!map.Map.Terrain[x, y].IsBlocking)
                    {
                        //createBatEnemy(new Vector2(x * 32, y * 32), skillLevel);
                        CharacterDef cDef = GameConfig.CharacterDefs["BAT"];
                        cDef.SkillLevel = skillLevel;
                        createCharacter(cDef, new Vector2(x * 32, y * 32));
                        placed = true;
                    }
                }

                placed = false;
            }
        }
Exemplo n.º 2
0
        public virtual void SetCharacter(int CharacterID, int FaceID = 0)
        {
            CharacterDef def = ResourceManager.GetPlayerDef(CharacterID);

            if (def == null)
            {
                if (characterImage != null)
                {
                    characterImage.gameObject.SetActive(false);
                }
                if (nameText != null)
                {
                    nameText.text = "";
                }
                speakingCharacter = null;
            }
            else
            {
                speakingCharacter = def;
                string characterName = def.CommonProperty.Name;

                SetCharacterImage(def.TalkPortrait[FaceID]);
                SetCharacterName(characterName, Color.blue);
            }
        }
Exemplo n.º 3
0
    // Start is called before the first frame update
    void Start()
    {
        startingChracter =
            new CharacterDef("Character_1", "Trubadur", EnemyType.Wolf, new Color32(215, 25, 28, 255));

        characterPool = new List <CharacterDef> {
            new CharacterDef("Character_2", "Bass2", EnemyType.AngryCloud, new Color32(253, 174, 97, 255)),
            new CharacterDef("Character_3", "Syna2", EnemyType.AngryWave, new Color32(255, 255, 191, 255)),
            new CharacterDef("Character_4", "Crash", EnemyType.AngryBoulder, new Color32(166, 217, 106, 255)),
            new CharacterDef("Character_5", "Flute", EnemyType.Hamster, new Color32(26, 150, 65, 255)),
        };
        characterPool.OrderBy(i => UnityEngine.Random.value).ToList();
        characterPool.Insert(0, startingChracter);

        audioSources = new List <AudioSource>();

        foreach (CharacterDef def in characterPool)
        {
            AudioSource source = gameObject.AddComponent <AudioSource>();
            source.clip = Resources.Load <AudioClip>(audioRoot + def.audioName);
            if (source.clip == null)
            {
                throw new NullReferenceException(source.clip.name);
            }
            source.mute = true;
            audioSources.Add(source);
        }

        //spawnTimer = spawnDelay;
    }
Exemplo n.º 4
0
 public void Setup(CharacterDef charDef)
 {
     gameObject.SetActive(true);
     _characterDef = charDef;
     for (int i = 0; i < _listButton.Count; ++i)
     {
         _listButton[i].gameObject.SetActive(_items[i].Archetype == charDef.Archetype);
     }
 }
Exemplo n.º 5
0
 void Awake()
 {
     if (Game.PlayerCharacter == null)
     {
         Game.PlayerCharacter = new Character(CharacterDef.Get("Widow Tarha"), ClassDef.Get("Necromancer"));
         //Game.PlayerCharacter.AddItem(ItemDef.Get("Steel Broadsword"));
         //Game.PlayerCharacter.AddItem(ItemDef.Get("Light Hammer"));
     }
 }
Exemplo n.º 6
0
    public void Setup(CharacterDef charDef, ClassDef classDef)
    {
        _characterDef = charDef;
        _classDef     = classDef;
        var saveName   = _characterDef.name;
        var firstSpace = _characterDef.name.IndexOf(' ');

        if (firstSpace > 0)
        {
            saveName = saveName.Substring(0, firstSpace);
        }
        _inputField.text = saveName + DateTime.Now.Year + DateTime.Now.Month.ToString().PadLeft(2, '0') + DateTime.Now.Day.ToString().PadLeft(2, '0');
        gameObject.SetActive(true);
    }
Exemplo n.º 7
0
    // CONSTRUCTORS

    public Character(CharacterDef definition, ClassDef classDef)
    {
        Init();
        Definition = definition;
        Class      = classDef;
        foreach (var item in Class.StartingItems)
        {
            AddItem(item);
        }
        foreach (var skill in Class.StartingSkills)
        {
            LearnSkill(skill);
        }
    }
Exemplo n.º 8
0
        public Entity createCharacter(CharacterDef characterDef, Vector2 position)
        {
            Entity e = ecs_instance.create();

            ecs_instance.add_component(e, new Position(position, new Vector2(16)));
            ecs_instance.add_component(e, new Velocity(3f));
            ecs_instance.add_component(e, new AiBehavior(new WanderingEnemyBehavior(e, ecs_instance)));
            ecs_instance.add_component(e, new MapCollidable());
            ecs_instance.add_component(e, new Heading());
            ecs_instance.add_component(e, new Transform());
            ecs_instance.add_component(e, new Aggrivation());


            //create avatar
            ecs_instance.add_component(e, AnimationFactory.createAvatar(characterDef.AvatarDef.Name));

            //create info
            Information info = new Information();

            info.Name           = characterDef.InfoDef.Name;
            info.GeneralGroup   = characterDef.InfoDef.GeneralGroup;
            info.VariationGroup = characterDef.InfoDef.VariationGroup;
            info.UniqueGroup    = characterDef.InfoDef.UniqueGroup;
            ecs_instance.add_component(e, info);

            //create life
            Life life = new Life();

            life.IsAlive        = true;
            life.DeathLongevity = characterDef.LifeDef.DeathLongevity;
            ecs_instance.add_component(e, life);

            //create interactions
            Interactable interact = new Interactable();

            interact.SupportedInteractions = characterDef.SupportedInteractions;
            ecs_instance.add_component(e, interact);

            //create test equipment
            //FIXME:
            ItemFactory iFactory = new ItemFactory(ecs_instance);

            ecs_instance.add_component(e, iFactory.createTestEquipment());

            //setup knowledges
            Knowledges knowledges = new Knowledges();

            foreach (Knowledge knowledge in characterDef.KnowledgesDef.GeneralKnowledges)
            {
                Knowledge k = knowledge;
                k.Value = characterDef.SkillLevel;
                knowledges.GeneralKnowledge.Add(knowledge.Name, k);
            }

            foreach (Knowledge knowledge in characterDef.KnowledgesDef.VariationKnowledges)
            {
                knowledges.VariationKnowledge.Add(knowledge.Name, knowledge);
            }

            foreach (Knowledge knowledge in characterDef.KnowledgesDef.UniqueKnowledges)
            {
                knowledges.UniqueKnowledge.Add(knowledge.Name, knowledge);
            }
            ecs_instance.add_component(e, knowledges);

            //setup attributes
            Statistics statistics = new Statistics();

            statistics.Endurance         = characterDef.StatisticsDef.Endurance;
            statistics.Endurance.Value   = characterDef.SkillLevel;
            statistics.Focus             = characterDef.StatisticsDef.Focus;
            statistics.Focus.Value       = characterDef.SkillLevel;
            statistics.Mind              = characterDef.StatisticsDef.Mind;
            statistics.Mind.Value        = characterDef.SkillLevel;
            statistics.Muscle            = characterDef.StatisticsDef.Muscle;
            statistics.Muscle.Value      = characterDef.SkillLevel;
            statistics.Perception        = characterDef.StatisticsDef.Perception;
            statistics.Perception.Value  = characterDef.SkillLevel;
            statistics.Personality       = characterDef.StatisticsDef.Personality;
            statistics.Personality.Value = characterDef.SkillLevel;
            statistics.Quickness         = characterDef.StatisticsDef.Quickness;
            statistics.Quickness.Value   = characterDef.SkillLevel;
            ecs_instance.add_component(e, statistics);

            //create health
            Health health = new Health(statistics.Endurance.Value * 3);

            health.RecoveryAmmount = statistics.Endurance.Value / 5;
            health.RecoveryRate    = 1000;
            ecs_instance.add_component(e, health);

            //setup skills
            Skills skills = new Skills();

            skills.Avoidance       = characterDef.SkillsDef.Avoidance;
            skills.Melee           = characterDef.SkillsDef.Melee;
            skills.Ranged          = characterDef.SkillsDef.Ranged;
            skills.Ranged.Value    = characterDef.SkillLevel;
            skills.Avoidance.Value = characterDef.SkillLevel;
            skills.Melee.Value     = characterDef.SkillLevel;
            ecs_instance.add_component(e, skills);

            //setup factions
            Factions factions = new Factions();

            factions.OwnerFaction = characterDef.FactionsDef.OwnerFaction;
            foreach (Faction faction in characterDef.FactionsDef.Factions)
            {
                factions.KnownFactions.Add(faction.Name, faction);
            }
            ecs_instance.add_component(e, factions);

            Aggrivation aggro = new Aggrivation();

            ecs_instance.add_component(e, aggro);

            ecs_instance.add_component(e, EntityFactory.createLight(true, 3, new Vector3(position, 10), 0.5f, new Vector4(1, 1, .6f, 1)));

            ecs_instance.group_manager.add_entity_to_group("WANDERERS", e);

            ecs_instance.resolve(e);

            return(e);
        }
Exemplo n.º 9
0
 public void InitTarget(CharacterDef def)
 {
     character = def;
 }
Exemplo n.º 10
0
    public Character(string saveStr)
    {
        var str = saveStr.Split('\n');

        int i = 0;

        if (int.TryParse(str[i], out int numPlayers))
        {
            NumPlayers = numPlayers;
        }
        else
        {
            Debug.LogWarning("Failed to initialize character!");
            return;
        }

        ++i;
        if (int.TryParse(str[i], out int act))
        {
            Act = act;
        }
        else
        {
            Debug.LogWarning("Failed to initialize character!");
            return;
        }

        Init();

        ++i;
        Definition = CharacterDef.Get(str[i]);

        ++i;
        Class = ClassDef.Get(str[i]);

        ++i;
        Damage = int.Parse(str[i]);

        ++i;
        Fatigue = int.Parse(str[i]);

        // Equipped
        ++i;
        var splitNames = str[i].Split(DELIMITER);

        foreach (var itemName in splitNames)
        {
            var item = ItemDef.Get(itemName);
            if (item != null)
            {
                AddItem(item);
                EquipItem(item);                 // unnecessary, but just in case
            }
        }

        // Unequipped
        ++i;
        splitNames = str[i].Split(DELIMITER);
        foreach (var itemName in splitNames)
        {
            var item = ItemDef.Get(itemName);
            if (item != null)
            {
                AddItem(item);
                UnequipItem(item);                 // unnecessary, but just in case
            }
        }

        // Skills
        ++i;
        splitNames = str[i].Split(DELIMITER);
        foreach (var skillName in splitNames)
        {
            var skill = SkillDef.Get(skillName);
            if (skill != null)
            {
                LearnSkill(skill);
            }
        }

        // Conditions
        ++i;
        splitNames = str[i].Split(DELIMITER);
        foreach (var condName in splitNames)
        {
            if (System.Enum.TryParse(condName, out Condition condition))
            {
                Conditions.Add(condition);
            }
        }
    }
Exemplo n.º 11
0
        private static void addCharToContent(char chr, CharacterDef characterDef, bool fixedWidth, bool bold, int[,] content, int left, int top, int textColor, int backColor)
        {
            // Actual width (and height) to be used
            int charWidth  = characterDef.getCharWidth(chr, fixedWidth, bold);        // Taking count 'fixedWidth' and 'bold'
            int charHeight = characterDef.getFontHeight();

            // Possible padding for non-fixed width text
            int charRealWidth;
            int paddingLeft;

            if (fixedWidth)
            {
                charRealWidth = characterDef.getCharWidth(chr, false, bold); // If not using fixed width
                paddingLeft   = (charWidth - charRealWidth) / 2;             // Padding around to make character always using same space
            }
            else
            {
                charRealWidth = charWidth;
                paddingLeft   = 0;
            }

            // Get character source and index
            object[] sourceAndIndex = characterDef.getSourceAndIndex(chr);

            // Unknown character?
            if (sourceAndIndex == null)
            {
                // Fill area with solid square
                for (int y = 0; y < charHeight; y++)
                {
                    for (int x = 0; x < charWidth; x++)
                    {
                        content[top + y, left + x] = textColor;
                    }
                }
                return;
            }

            // Copy character dots (plain without bold)
            string[,] source = (string[, ])(sourceAndIndex[0]);
            int index = (int)(sourceAndIndex[1]);

            for (int y = 0; y < charHeight; y++)
            {
                for (int x = 0; x < charWidth - (bold?1:0); x++)
                {
                    content[top + y, left + x] = ((x >= paddingLeft && x < paddingLeft + charRealWidth && x - paddingLeft < source[y, index].Length && source[y, index][x - paddingLeft] == '#') ? textColor : backColor);
                }
            }

            // Turn bold if needed
            if (bold)
            {
                bool[] boldCols = new bool[charWidth];               // 'charWidth' is minimum 2 because bolding is already taken count to width
                boldCols[0]             = false;
                boldCols[charWidth - 1] = true;
                if (charWidth > 2)
                {
                    boldCols[charWidth - 2] = true;
                    for (int x = 1; x < charWidth - 2; x++)
                    {
                        boldCols[x] = true;
                        bool oneOcc = false;
                        for (int y = 0; y < charHeight; y++)
                        {
                            if (content[top + y, left + x - 1] == textColor && content[top + y, left + x] == backColor && content[top + y, left + x + 1] == textColor)
                            {
                                if (oneOcc)
                                {
                                    boldCols[x] = false;
                                    break;
                                }
                                oneOcc = true;
                            }
                        }
                    }
                }
                for (int x = charWidth - 1; x >= 0; x--)
                {
                    if (boldCols[x])
                    {
                        for (int y = 0; y < charHeight; y++)
                        {
                            if (content[top + y, left + x - 1] == textColor)
                            {
                                content[top + y, left + x] = textColor;
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 12
0
        protected override void process(Entity entity)
        {
            Position         position  = (Position)p_PositionMapper.get(entity);
            Velocity         velocity  = (Velocity)p_VelocityMapper.get(entity);
            Heading          heading   = (Heading)p_HeadingMapper.get(entity);
            Position         mPosition = (Position)p_PositionMapper.get(p_Mouse);
            Transform        transform = (Transform)p_TransformMapper.get(entity);
            Character        character = (Character)p_CharacterMapper.get(entity);
            SpatialPartition spatial   = (SpatialPartition)p_SpatialMapper.get(p_Spatial);

            if (p_FirstRun)
            {
                spatial.QuadTree.setContentAtLocation(entity, position.Pos);
                p_LastNode = spatial.QuadTree.locateNode(position.Pos + position.Offset);
                p_FirstRun = false;
            }

            Vector2 pos  = position.Pos;
            float   vel  = velocity.Vel;
            Vector2 head = heading.getHeading();

            //reset direction
            int dirCount = 0;

            //reset animation
            //sprite.Column = 0;
            p_Moved = false;

            //toggle light?
            if (InputManager.isKeyToggled(Keys.L))
            {
                Light light = (Light)p_LightMapper.get(p_Mouse);
                if (light.IsEnabled)
                {
                    light.IsEnabled = false;
                }
                else
                {
                    light.IsEnabled = true;
                }
            }



            //move up?
            if (InputManager.isKeyPressed(Keys.W))
            {
                Vector2 dir = new Vector2(0, -1);

                head += dir;
                dirCount++;

                //sprite.Y = MOVE_UP;
                //sprite.X = p_Movement.updateFrame(ecs_instance.ElapsedTime);
                p_Moved = true;
            }

            //move down?
            if (InputManager.isKeyPressed(Keys.S))
            {
                Vector2 dir = new Vector2(0, 1);

                head += dir;
                dirCount++;

                //sprite.Y = MOVE_DOWN;
                //sprite.X = p_Movement.updateFrame(ecs_instance.ElapsedTime);
                p_Moved = true;
            }

            //move left?
            if (InputManager.isKeyPressed(Keys.A))
            {
                Vector2 dir = new Vector2(-1, 0);

                head += dir;
                dirCount++;

                //sprite.Y = MOVE_LEFT;
                //sprite.X = p_Movement.updateFrame(ecs_instance.ElapsedTime);
                p_Moved = true;
            }

            //move right?
            if (InputManager.isKeyPressed(Keys.D))
            {
                Vector2 dir = new Vector2(1, 0);

                head += dir;
                dirCount++;

                //sprite.Y = MOVE_RIGHT;
                //sprite.X = p_Movement.updateFrame(ecs_instance.ElapsedTime);
                p_Moved = true;
            }

            //move according to the correct speed
            if (dirCount > 1)
            {
                position.Pos = pos + head * vel * (float)Math.Sqrt(2) / 2;
            }
            else
            {
                position.Pos = pos + head * vel;
            }

            /*
             * Vector2 test = (mPosition.Pos + mPosition.Offset) - pos;
             * test.Normalize();
             *
             * float angle = VectorHelper.getAngle(new Vector2(1,0), test);
             *
             * if (angle >= 0.393f && angle < 1.178f) { sprite.Row = MOVE_UPRIGHT; }
             * else if (angle >= 1.178f && angle < 1.963f) { sprite.Row = MOVE_UP; }
             * else if (angle >= 1.963f && angle < 2.749f) { sprite.Row = MOVE_UPLEFT; }
             * else if (angle >= 2.749f && angle < 3.534f) { sprite.Row = MOVE_LEFT; }
             * else if (angle >= 3.534f && angle < 4.320f) { sprite.Row = MOVE_DOWNLEFT; }
             * else if (angle >= 4.320f && angle < 5.105f) { sprite.Row = MOVE_DOWN; }
             * else if (angle >= 5.105f && angle < 5.890f) { sprite.Row = MOVE_DOWNRIGHT; }
             * else if (angle >= 5.890f || angle < .393f) { sprite.Row = MOVE_RIGHT; }
             *
             * if(p_Moved)
             * sprite.Column = p_Movement.updateFrame(ecs_instance.ElapsedTime);
             */

            if (p_Moved)
            {
                character.CurrentAnimtaion = "MOVING";
            }

            //transform.Rotation = getAngle(pos, mPosition.getPosition());



            /*
             * if (InputManager.isLeftButtonClicked())
             * {
             *  EntityFactory ef = new EntityFactory(ecs_instance);
             *
             *  Vector2 dir = mPosition.getPosition() + mPosition.Offset - new Vector2(16) - pos;
             *
             *  dir.Normalize();
             *
             *  Transform trans = new Transform();
             *  trans.Rotation = -VectorHelper.getAngle(new Vector2(1, 0), dir);
             *  trans.RotationOrigin = new Vector2(16);
             *
             *  ef.createCollidingProjectile(pos + dir * 16, dir, 10f, 1000, ef.createLight(true, 35, new Vector3(pos + position.Offset, 10), 0.7f, Color.Purple.ToVector4()), trans, entity);
             *
             *  UtilFactory uf = new UtilFactory(ecs_instance);
             *  uf.createSound("audio\\effects\\fire", true,0.5f);
             * }*/

            p_LastFired += ecs_instance.ElapsedTime;

            if (InputManager.isLeftButtonDown() && (p_LastFired >= 3 * p_FireRate))
            {
                Target target = (Target)p_TargetMapper.get(p_Target);
                if (target.Active)
                {
                    p_LastFired = 0;

                    Position targetPos = (Position)p_PositionMapper.get(p_Target);

                    Vector2 dir = targetPos.Pos + targetPos.Offset - new Vector2(16) - pos;
                    dir.Normalize();

                    Transform trans = new Transform();
                    trans.Rotation       = -VectorHelper.getAngle(new Vector2(1, 0), dir);
                    trans.RotationOrigin = new Vector2(0, 16);

                    UtilFactory.createMeleeAction(pos + dir * 16, dir, trans, entity);
                }
            }

            if (InputManager.isRightButtonDown() && (p_LastFired >= p_FireRate))
            {
                Target target = (Target)p_TargetMapper.get(p_Target);
                if (target.Active)
                {
                    p_LastFired = 0;

                    Position targetPos = (Position)p_PositionMapper.get(p_Target);

                    Vector2 dir = targetPos.Pos + targetPos.Offset - new Vector2(16) - pos;
                    //Vector2 dir = mPosition.Pos + mPosition.Offset - new Vector2(16) - pos;// +new Vector2(-20 + (float)rand.NextDouble() * 40, -20 + (float)rand.NextDouble() * 40);

                    dir = VectorHelper.rotateVectorRadians(dir, -0.08726f + (float)rand.NextDouble() * 0.1745f);

                    dir.Normalize();

                    Transform trans = new Transform();
                    trans.Rotation       = -VectorHelper.getAngle(new Vector2(1, 0), dir);
                    trans.RotationOrigin = new Vector2(16);

                    EntityFactory.createCollidingProjectile(pos + dir * 16, dir, 10f, 1000, EntityFactory.createLight(true, 2, new Vector3(pos + position.Offset, 10), 0.7f, Color.OrangeRed.ToVector4()), trans, entity);

                    UtilFactory.createSound("audio\\effects\\fire", true, 0.5f);
                }
            }

            if (InputManager.isKeyToggled(Keys.B))
            {
                if (!p_StatWindowOpen)
                {
                    p_StatWindow = UIFactory.createStatWindow(entity, new Point(100, 100), new Point(300, 315), 20);

                    p_StatWindowOpen = true;
                }
                else
                {
                    ecs_instance.delete_entity(p_StatWindow);
                    p_StatWindowOpen = false;
                }
            }

            if (InputManager.isKeyToggled(Keys.I))
            {
                if (!p_InvWindowOpen)
                {
                    p_InvWindow     = UIFactory.createInventoryWindow(entity, new Point(300, 100), new Point(300, 300), 20, 10, 10);
                    p_InvWindowOpen = true;
                }
                else
                {
                    ecs_instance.delete_entity(p_InvWindow);
                    p_InvWindowOpen = false;
                }
            }


            if (InputManager.isKeyToggled(Keys.R))
            {
                List <Entity> locals = spatial.QuadTree.findAllWithinRange(pos, 300);
                if (locals.Count > 1)
                {
                    Target target = (Target)p_TargetMapper.get(p_Target);
                    Sprite sprite = (Sprite)p_SpriteMapper.get(p_Target);
                    sprite.Visible = true;
                    target.Active  = true;

                    Entity closest = null;
                    float  min     = float.MaxValue;

                    for (int i = 0; i < locals.Count; i++)
                    {
                        if (locals[i] == entity)
                        {
                            continue;
                        }

                        Position p = (Position)p_PositionMapper.get(locals[i]);

                        if (p == null)
                        {
                            continue;
                        }

                        float dist = Vector2.Distance(p.Pos, position.Pos);
                        if (dist < min)
                        {
                            closest = locals[i];
                            min     = dist;
                        }
                    }

                    target.TargetEntity = closest;
                }
            }

            if (!p_Moved)
            {
                p_Movement.reset();
                character.CurrentAnimtaion = "IDLE";
            }
            else
            {
                if (p_LastNode != null)
                {
                    p_LastNode.Contents.Remove(entity);
                }

                p_LastNode = spatial.QuadTree.setContentAtLocation(entity, pos + new Vector2(16, 16));
            }

            //TEST FUNCTIONS PAST HERE

            if (InputManager.isKeyPressed(Keys.Up))
            {
                transform.Rotation += 0.1f;
            }

            if (InputManager.isKeyPressed(Keys.Down))
            {
                transform.Rotation -= 0.1f;
            }

            if (InputManager.isKeyPressed(Keys.Left))
            {
                transform.RotationOrigin = new Vector2(16, 32);
            }

            if (InputManager.isKeyPressed(Keys.Right))
            {
                transform.RotationOrigin = new Vector2(0);
            }

            if (InputManager.isKeyPressed(Keys.P))
            {
                NPCFactory ef = new NPCFactory(ecs_instance);
                ef.createFollower(mPosition.Pos + mPosition.Offset - new Vector2(16), entity, rand.Next(50, 300));
            }

            if (InputManager.isKeyToggled(Keys.O))
            {
                NPCFactory ef = new NPCFactory(ecs_instance);
                //ef.createBatEnemy(mPosition.Pos + mPosition.Offset - new Vector2(16),15);
                CharacterDef cDef = GameConfig.CharacterDefs["BAT"];
                cDef.SkillLevel = 15;
                ef.createCharacter(cDef, mPosition.Pos + mPosition.Offset - new Vector2(16));
            }

            if (InputManager.isKeyToggled(Keys.U))
            {
                ActionDef def = GameConfig.ActionDefs["TEST_DMG"];
                ActionFactory.createAction(def, entity, entity);
            }
        }