private static bool CheckTargetPosValid(ResultSet resultSet, Vector2i targetPos, EntityID user)
        {
            var game = (RetroDungeoneerGame)RB.Game;

            if (!game.map.IsInFOV(targetPos) || !game.map.IsInFOV(user.e.pos))
            {
                if (user.e.isPlayer)
                {
                    resultSet.AddMessage(C.FSTR.Set("You cannot target a tile outside of your field of view."));
                }

                return(false);
            }

            var tile = game.map.terrain[targetPos.x, targetPos.y];

            if (tile.blocked)
            {
                if (user.e.isPlayer)
                {
                    resultSet.AddMessage(C.FSTR.Set("You cannot target a blocking tile."));
                }

                return(false);
            }

            return(true);
        }
Exemple #2
0
        /// <summary>
        /// Toggle equipped status of entity, this will generate the proper result to potential add or remove the entity
        /// from the equipment array
        /// </summary>
        /// <param name="resultSet">Result</param>
        /// <param name="equippableEntity">Entity to equip</param>
        public void ToggleEquip(ResultSet resultSet, EntityID equippableEntity)
        {
            if (equippableEntity.e == null || equippableEntity.e.equippable == null)
            {
                return;
            }

            var slot = equippableEntity.e.equippable.slot;

            if (equipment[(int)slot] == equippableEntity)
            {
                resultSet.AddDequipped(owner, equippableEntity);
                resultSet.AddMessage(
                    C.FSTR.Set(C.STR_COLOR_NAME).Append(owner.e.name).Append("@- dequipped the ").Append(C.STR_COLOR_NAME).Append(equipment[(int)slot].e.name).Append("@-."));

                equipment[(int)slot] = EntityID.empty;
            }
            else
            {
                if (!equipment[(int)slot].isEmpty)
                {
                    resultSet.AddDequipped(owner, equipment[(int)slot]);
                    resultSet.AddMessage(
                        C.FSTR.Set(C.STR_COLOR_NAME).Append(owner.e.name).Append("@- dequipped the ").Append(C.STR_COLOR_NAME).Append(equipment[(int)slot].e.name).Append("@-."));
                }

                equipment[(int)slot] = equippableEntity;
                resultSet.AddEquipped(owner, equipment[(int)slot]);
                resultSet.AddMessage(
                    C.FSTR.Set(C.STR_COLOR_NAME).Append(owner.e.name).Append("@- equipped the ").Append(C.STR_COLOR_NAME).Append(equippableEntity.e.name).Append("@-."));
            }
        }
        /// <summary>
        /// Teleport
        /// </summary>
        /// <param name="resultSet">Result set</param>
        /// <param name="caster">Caster</param>
        /// <param name="targetPos">Target position</param>
        /// <returns>True if successful</returns>
        public static bool Teleport(ResultSet resultSet, EntityID caster, Vector2i targetPos)
        {
            var game = (RetroDungeoneerGame)RB.Game;

            if (!CheckTargetPosValid(resultSet, targetPos, caster))
            {
                return(false);
            }

            if ((targetPos - caster.e.pos).Magnitude() > 8)
            {
                if (caster.e.isPlayer)
                {
                    resultSet.AddMessage(C.FSTR.Set("Target location is too far to teleport to."));
                    return(false);
                }
            }

            if (!EntityFunctions.GetBlockingEntityAtPos(targetPos).isEmpty || game.map.IsBlocked(targetPos))
            {
                if (caster.e.isPlayer)
                {
                    resultSet.AddMessage(C.FSTR.Set("Target location is blocked, you can't teleport there!"));
                    return(false);
                }
            }

            EffectManager.Instance.AddEffect(new EffectTeleport(caster.e.pos, targetPos));
            caster.e.pos = targetPos;
            resultSet.AddMessage(C.FSTR.Set(C.STR_COLOR_NAME).Append(caster.e.name).Append("@- teleported!"));

            return(true);
        }
Exemple #4
0
        /// <summary>
        /// Add item to the inventory
        /// </summary>
        /// <param name="resultSet">Result</param>
        /// <param name="item">Item to add</param>
        public void AddItem(ResultSet resultSet, EntityID item)
        {
            int emptySlot = -1;

            for (int i = 0; i < items.Length; i++)
            {
                if (items[i].isEmpty)
                {
                    emptySlot = i;
                    break;
                }
            }

            if (emptySlot == -1)
            {
                if (resultSet != null)
                {
                    resultSet.AddMessage(C.FSTR.Set("You cannot carry any more, your inventory is full!"));
                }
            }
            else
            {
                if (resultSet != null)
                {
                    resultSet.AddMessage(C.FSTR.Set("You pickup the ").Append(C.STR_COLOR_NAME).Append(item.e.name).Append("@-!"));
                    resultSet.AddItemAdded(item);
                }

                items[emptySlot] = item;
            }
        }
Exemple #5
0
        /// <summary>
        /// Make this entity attack another entity
        /// </summary>
        /// <param name="resultSet">Result</param>
        /// <param name="target">Target entity</param>
        public void Attack(ResultSet resultSet, EntityID target)
        {
            if (target.isEmpty)
            {
                return;
            }

            int damage = power - target.e.fighter.defense;

            if (damage > 0)
            {
                target.e.fighter.TakeDamage(resultSet, damage);
                resultSet.AddMessage(
                    C.FSTR.Clear()
                    .Append(C.STR_COLOR_NAME)
                    .Append(owner.e.name)
                    .Append("@- attacks ")
                    .Append(C.STR_COLOR_NAME)
                    .Append(target.e.name)
                    .Append("@- for ")
                    .Append(C.STR_COLOR_DAMAGE)
                    .Append(damage)
                    .Append("@- hit points."));
            }
            else
            {
                if (Random.Range(0, 3) == 0)
                {
                    resultSet.AddMessage(
                        C.FSTR.Clear()
                        .Append(C.STR_COLOR_NAME)
                        .Append(owner.e.name)
                        .Append("@- attacks ")
                        .Append(C.STR_COLOR_NAME)
                        .Append(target.e.name)
                        .Append("@- but does no damage."));
                }
                else
                {
                    damage = 1;
                    target.e.fighter.TakeDamage(resultSet, damage);
                    resultSet.AddMessage(
                        C.FSTR.Clear()
                        .Append(C.STR_COLOR_NAME)
                        .Append(owner.e.name)
                        .Append("@- hits ")
                        .Append(C.STR_COLOR_NAME)
                        .Append(target.e.name)
                        .Append("@- with a glancing blow for ")
                        .Append(C.STR_COLOR_DAMAGE)
                        .Append(damage)
                        .Append("@- hit points."));
                }
            }
        }
        /// <summary>
        /// Cast confuse
        /// </summary>
        /// <param name="resultSet">Result set</param>
        /// <param name="caster">Caster</param>
        /// <param name="targetPos">Target position</param>
        /// <returns>True if successful</returns>
        public static bool CastConfuse(ResultSet resultSet, EntityID caster, Vector2i targetPos)
        {
            var game = (RetroDungeoneerGame)RB.Game;

            if (!CheckTargetPosValid(resultSet, targetPos, caster))
            {
                return(false);
            }

            EntityID target = EntityID.empty;

            for (int i = 0; i < EntityStore.entities.Count; i++)
            {
                var eid = EntityStore.entities[i];
                var e   = eid.e;

                if (e.pos == targetPos)
                {
                    target = eid;
                    break;
                }
            }

            if (!target.isEmpty)
            {
                var confusedAi = new ConfusedMonster();
                confusedAi.previousAi    = target.e.ai;
                confusedAi.numberOfTurns = 10;

                target.e.ai = confusedAi;

                resultSet.AddMessage(
                    C.FSTR.Set("The eyes of the ").Append(C.STR_COLOR_NAME).Append(target.e.name).Append("@- look vacant, as it starts to stumble around!"));

                EffectManager.Instance.AddEffect(new EffectConfuse(target));

                RB.SoundPlay(game.assets.soundConfuse);

                return(true);
            }
            else
            {
                resultSet.AddMessage(
                    C.FSTR.Set("There is no targetable enemy at that location."));
            }

            return(false);
        }
Exemple #7
0
        /// <summary>
        /// Take a turn.
        /// </summary>
        /// <param name="resultSet">Result of taking a turn</param>
        /// <param name="target">Target entity being tracked by the Ai</param>
        public override void TakeTurn(ResultSet resultSet, EntityID target)
        {
            var game = (RetroDungeoneerGame)RB.Game;

            var monster = owner;

            // No aggro, see if we can aquire aggro
            if (!aggroed)
            {
                if (game.map.IsInFOV(monster.e.pos))
                {
                    float dist = monster.e.DistanceTo(target);
                    if (dist <= aggroRange)
                    {
                        aggroed      = true;
                        aggroTimeout = AGGRO_MAX_TIMEOUT;

                        resultSet.AddMessage(C.FSTR.Set("The ").Append(C.STR_COLOR_NAME).Append(owner.e.name).Append("@- spots you!"));

                        EffectManager.Instance.AddEffect(new EffectAggro(monster));

                        int aggroSound = UnityEngine.Random.Range(0, 2) == 0 ? C.SOUND_AGGRO1 : C.SOUND_AGGRO2;
                        SoundBank.Instance.SoundPlayDelayed(aggroSound, 0.66f, RandomUtils.RandomPitch(0.15f), UnityEngine.Random.Range(0, 8));
                    }
                }
            }
            else
            {
                if (aggroTimeout == 0)
                {
                    resultSet.AddMessage(C.FSTR.Set("The ").Append(C.STR_COLOR_NAME).Append(owner.e.name).Append("@- gives up the chase."));
                    aggroed = false;
                }
                else
                {
                    if (!game.map.IsInFOV(monster.e.pos) || monster.e.DistanceTo(target) > aggroRange)
                    {
                        aggroTimeout--;
                    }
                    else
                    {
                        aggroTimeout = AGGRO_MAX_TIMEOUT;
                    }

                    DoSkill(resultSet, target);
                }
            }
        }
Exemple #8
0
        /// <summary>
        /// Kill a monster
        /// </summary>
        /// <param name="resultSet">Result</param>
        /// <param name="monster">Monster entity</param>
        public static void KillMonster(ResultSet resultSet, EntityID monster)
        {
            var game = (RetroDungeoneerGame)RB.Game;

            var e = monster.e;

            if (e.ai != null)
            {
                e.ai.HandleDeath(resultSet);
            }

            e.sprite      = S.BONES;
            e.color       = new Color32(200, 200, 200, 255);
            e.blocks      = false;
            e.fighter     = null;
            e.ai          = null;
            e.renderOrder = RenderFunctions.RenderOrder.CORPSE;

            // Delete all equipment, this prevents paperDoll rendering on the grave
            e.equipment = null;

            C.FSTR.Set(e.name);
            e.name.Set("remains of ").Append(C.FSTR);

            resultSet.AddMessage(C.FSTR2.Set(C.STR_COLOR_NAME).Append(C.FSTR).Append("@- is ").Append(C.STR_COLOR_DEAD).Append("@w145dead@w000@-!"));

            RB.SoundPlay(game.assets.soundMonsterDeath, 1.0f, RandomUtils.RandomPitch(0.1f));
        }
Exemple #9
0
        /// <summary>
        /// Use item in the inventory, if its useable
        /// </summary>
        /// <param name="resultSet">Result</param>
        /// <param name="item">Item to use</param>
        /// <param name="useParams">Usage parameters</param>
        public void UseItem(ResultSet resultSet, EntityID item, Item.UseParams useParams)
        {
            var itemComp = item.e.item;

            // Not an item
            if (itemComp == null)
            {
                return;
            }

            var targetingReady = useParams.bool1;

            if (itemComp.targeting && !targetingReady && item.e.equippable == null)
            {
                resultSet.AddTargeting(item);
            }
            else
            {
                if (itemComp.useFunction == ItemFunction.NONE)
                {
                    if (item.e.equippable != null)
                    {
                        resultSet.AddEquip(owner, item);
                    }
                    else
                    {
                        resultSet.AddMessage(C.FSTR.Set("The ").Append(C.STR_COLOR_NAME).Append(item.e.name).Append("@- cannot be used"));
                    }
                }
                else
                {
                    itemComp.Use(resultSet, owner, useParams);
                }
            }
        }
Exemple #10
0
        /// <summary>
        /// Heal self
        /// </summary>
        /// <param name="resultSet">Result set</param>
        /// <param name="user">User</param>
        /// <param name="healingAmount">Healing amount</param>
        /// <returns>True if successful</returns>
        public static bool Heal(ResultSet resultSet, EntityID user, int healingAmount)
        {
            // May need to check if entity is a Player before printing anything
            if (user.e.fighter.hp == user.e.fighter.maxHp)
            {
                if (user.e.isPlayer)
                {
                    resultSet.AddMessage(C.FSTR.Set("You are already at full health."));
                }
            }
            else
            {
                user.e.fighter.Heal(resultSet, healingAmount);
                resultSet.AddMessage(C.FSTR.Set("Your wounds start to feel better!"));

                RB.SoundPlay(C.SOUND_DRINK, 1, RandomUtils.RandomPitch(0.1f));

                return(true);
            }

            return(false);
        }
Exemple #11
0
        /// <summary>
        /// Drop item on the ground from inventory
        /// </summary>
        /// <param name="resultSet">Result</param>
        /// <param name="item">Item to drop</param>
        public void DropItem(ResultSet resultSet, EntityID item)
        {
            DeleteItemFromList(item);

            item.e.pos = owner.e.pos;

            // Dequip item first if its currently equipped
            if (owner.e.equipment != null && item.e.equippable != null)
            {
                var slot = item.e.equippable.slot;
                if (owner.e.equipment.equipment[(int)slot] == item)
                {
                    owner.e.equipment.ToggleEquip(resultSet, item);
                }
            }

            resultSet.AddItemDropped(item);
            resultSet.AddMessage(C.FSTR.Set("You dropped the ").Append(C.STR_COLOR_NAME).Append(item.e.name).Append("@-."));
        }
        /// <summary>
        /// Take a turn.
        /// </summary>
        /// <param name="resultSet">Result of taking a turn</param>
        /// <param name="target">Target entity being tracked by the Ai</param>
        public override void TakeTurn(ResultSet resultSet, EntityID target)
        {
            if (numberOfTurns > 0)
            {
                var randomPos = owner.e.pos;
                randomPos.x += Random.Range(-1, 2);
                randomPos.y += Random.Range(-1, 2);

                if (randomPos != owner.e.pos)
                {
                    owner.e.MoveTowards(randomPos);
                }

                numberOfTurns--;
            }
            else
            {
                owner.e.ai = previousAi;
                resultSet.AddMessage(C.FSTR.Set("The ").Append(C.STR_COLOR_NAME).Append(owner.e.name).Append("@- is no longer confused!"));
            }
        }
Exemple #13
0
        /// <summary>
        /// Kill the player
        /// </summary>
        /// <param name="resultSet">Result</param>
        /// <param name="player">Player entity</param>
        public static void KillPlayer(ResultSet resultSet, EntityID player)
        {
            var pe = player.e;

            pe.sprite = S.GRAVESTONE;
            pe.color  = new Color32(200, 200, 200, 255);
            C.FSTR.Set(pe.name);
            pe.name.Set("grave of ").Append(C.FSTR);
            pe.renderOrder = RenderFunctions.RenderOrder.CORPSE;

            // Delete all equipment, this prevents paperDoll rendering on the grave
            pe.equipment = null;

            resultSet.AddMessage(C.FSTR.Set("You ").Append(C.STR_COLOR_DEAD).Append("@w145died@w000@-!"));

            RB.SoundPlay(C.SOUND_PLAYER_DEATH, 1.0f);
            RB.MusicVolumeSet(1.0f);
            RB.MusicPlay(C.MUSIC_DEATH);

            EffectManager.Instance.AddEffect(new EffectPlayerDeath(player));
        }
        /// <summary>
        /// Cast lightning
        /// </summary>
        /// <param name="resultSet">Result set</param>
        /// <param name="caster">Caster</param>
        /// <param name="targetPos">Target pos</param>
        /// <param name="maxRange">Maximum spell range</param>
        /// <param name="damage">Damage</param>
        /// <returns>True if successful</returns>
        public static bool CastLightning(ResultSet resultSet, EntityID caster, Vector2i targetPos, int maxRange, int damage)
        {
            var game = (RetroDungeoneerGame)RB.Game;

            EntityID target      = EntityID.empty;
            float    closestDist = maxRange + 1;

            if (targetPos.x == -1)
            {
                // Find the closest target in range, and in FOV
                for (int i = 0; i < EntityStore.entities.Count; i++)
                {
                    var eid = EntityStore.entities[i];
                    var e   = eid.e;

                    if (e.fighter != null && eid != caster && game.map.IsInFOV(e.pos))
                    {
                        var dist = caster.e.DistanceTo(eid);

                        if (dist < closestDist)
                        {
                            target      = eid;
                            closestDist = dist;
                        }
                    }
                }
            }
            else
            {
                for (int i = 0; i < EntityStore.entities.Count; i++)
                {
                    var eid = EntityStore.entities[i];
                    var e   = eid.e;

                    if (e.pos == targetPos)
                    {
                        target = eid;
                        break;
                    }
                }
            }

            if (!target.isEmpty && CheckTargetPosValid(resultSet, target.e.pos, caster))
            {
                int actualDamage = (damage + caster.e.fighter.power) - target.e.fighter.defense;
                if (actualDamage == 0)
                {
                    actualDamage = 1;
                }

                target.e.fighter.TakeDamage(resultSet, actualDamage);
                resultSet.AddMessage(
                    C.FSTR.Set("A lightning bolt strikes the ").Append(C.STR_COLOR_NAME).Append(target.e.name).Append("@- with a loud thunder! The damage is ").Append(C.STR_COLOR_DAMAGE).Append(actualDamage).Append("@-."));

                EffectManager.Instance.AddEffect(new EffectLightning(caster, target));

                RB.SoundPlay(game.assets.soundLightning);

                return(true);
            }
            else
            {
                resultSet.AddMessage(C.FSTR.Set("No enemy is close enough to strike."));
            }

            return(false);
        }
        /// <summary>
        /// Shoot bow
        /// </summary>
        /// <param name="resultSet">Result set</param>
        /// <param name="caster">Caster</param>
        /// <param name="arrow">Arrow to shoot</param>
        /// <param name="maxRange">Max bow range</param>
        /// <param name="damage">Damage</param>
        /// <param name="targetPos">Target position</param>
        /// <returns>True if successful</returns>
        public static bool ShootBow(ResultSet resultSet, EntityID caster, EntityID arrow, int maxRange, int damage, Vector2i targetPos)
        {
            var game = (RetroDungeoneerGame)RB.Game;

            EntityID target      = EntityID.empty;
            float    closestDist = maxRange + 1;

            if (targetPos.x == -1)
            {
                // Find the closest target in range, and in FOV
                for (int i = 0; i < EntityStore.entities.Count; i++)
                {
                    var eid = EntityStore.entities[i];
                    var e   = eid.e;

                    if (e.fighter != null && eid != caster && game.map.IsInFOV(e.pos))
                    {
                        var dist = caster.e.DistanceTo(eid);

                        if (dist <= maxRange && dist < closestDist)
                        {
                            target      = eid;
                            closestDist = dist;
                        }
                    }
                }
            }
            else
            {
                for (int i = 0; i < EntityStore.entities.Count; i++)
                {
                    var eid = EntityStore.entities[i];
                    var e   = eid.e;

                    if (e.pos == targetPos)
                    {
                        target = eid;
                        break;
                    }
                }

                if (target.isEmpty)
                {
                    if (caster.e.isPlayer)
                    {
                        resultSet.AddMessage(C.FSTR.Set("There is no targetable enemy at that location."));
                    }

                    return(false);
                }
                else if (caster.e.DistanceTo(target) > maxRange)
                {
                    if (caster.e.isPlayer)
                    {
                        resultSet.AddMessage(C.FSTR.Set("The target is out of range of your weapon."));
                    }

                    return(false);
                }
            }

            if (!target.isEmpty && CheckTargetPosValid(resultSet, target.e.pos, caster))
            {
                int actualDamage = (damage + caster.e.fighter.power) - target.e.fighter.defense;
                if (actualDamage == 0)
                {
                    actualDamage = 1;
                }

                target.e.fighter.TakeDamage(resultSet, actualDamage);
                resultSet.AddMessage(
                    C.FSTR.Set("The ").Append(C.STR_COLOR_NAME).Append(arrow.e.name).Append("@- strikes the ").Append(C.STR_COLOR_NAME).Append(target.e.name).Append("@- with a thud. The damage is ").Append(C.STR_COLOR_DAMAGE).Append(actualDamage).Append("@-."));

                EffectManager.Instance.AddEffect(new EffectThrow(caster, target, Vector2i.zero, S.ARROW_SHOT, S.ARROW_SHOT_45, arrow.e.color, game.assets.soundBowShoot, game.assets.soundBowHit));

                return(true);
            }
            else
            {
                if (caster.e.isPlayer)
                {
                    resultSet.AddMessage(C.FSTR.Set("No enemy is close enough to shoot."));
                }
            }

            return(false);
        }
Exemple #16
0
        private void HandlePlayerTurnKeys(ResultSet resultSet)
        {
            // Check if we should block all player input until all keys are up
            // This is useful to block player input when exiting menus
            if (mBlockMoveUntilKeyUp)
            {
                if (!AnyPlayerKeyDown())
                {
                    mBlockMoveUntilKeyUp = false;
                }
                else
                {
                    return;
                }
            }

            if (RB.ButtonPressed(RB.BTN_SYSTEM))
            {
                resultSet.AddExit();
                return;
            }

            if (RB.KeyPressed(KeyCode.I))
            {
                resultSet.AddShowInventory();
            }

            if (RB.KeyPressed(KeyCode.O))
            {
                resultSet.AddDropInventory();
            }

            if (RB.KeyPressed(KeyCode.P))
            {
                resultSet.AddShowCharacterScreen();
            }

            if (RB.KeyPressed(KeyCode.Return) || RB.KeyPressed(KeyCode.KeypadEnter))
            {
                resultSet.AddTakeStairs();
            }

            if (RB.KeyPressed(KeyCode.H))
            {
                resultSet.AddShowHelp();
            }

            Vector2i delta = Vector2i.zero;

            if (RB.KeyDown(KeyCode.W) || RB.KeyDown(KeyCode.Keypad8))
            {
                delta.y--;
            }
            else if (RB.KeyDown(KeyCode.S) || RB.KeyDown(KeyCode.Keypad2))
            {
                delta.y++;
            }
            else if (RB.KeyDown(KeyCode.A) || RB.KeyDown(KeyCode.Keypad4))
            {
                delta.x--;
            }
            else if (RB.KeyDown(KeyCode.D) || RB.KeyDown(KeyCode.Keypad6))
            {
                delta.x++;
            }
            else if (RB.KeyDown(KeyCode.Q) || RB.KeyDown(KeyCode.Keypad7))
            {
                delta.x--;
                delta.y--;
            }
            else if (RB.KeyDown(KeyCode.E) || RB.KeyDown(KeyCode.Keypad9))
            {
                delta.x++;
                delta.y--;
            }
            else if (RB.KeyDown(KeyCode.Z) || RB.KeyDown(KeyCode.Keypad1))
            {
                delta.x--;
                delta.y++;
            }
            else if (RB.KeyDown(KeyCode.C) || RB.KeyDown(KeyCode.Keypad3))
            {
                delta.x++;
                delta.y++;
            }

            if (delta.x > 1)
            {
                delta.x = 1;
            }
            else if (delta.x < -1)
            {
                delta.x = -1;
            }

            if (delta.y > 1)
            {
                delta.y = 1;
            }
            else if (delta.y < -1)
            {
                delta.y = -1;
            }

            if (delta.x == 0 && delta.y == 0)
            {
                mKeyRepeatStage = 0;
            }
            else
            {
                var ticksDelta = RB.Ticks - mLastMoveTimestamp;

                if (mKeyRepeatStage == 0 || (mKeyRepeatStage == 1 && ticksDelta > C.KEY_REPEAT_SPEED_STAGE1) || (mKeyRepeatStage > 1 && ticksDelta > C.KEY_REPEAT_SPEED_STAGE2))
                {
                    if (delta.x != 0 || delta.y != 0)
                    {
                        mKeyRepeatStage++;
                        mLastMoveTimestamp = RB.Ticks;
                        resultSet.AddMove(delta);
                    }
                }
            }

            // Wait
            if (RB.KeyPressed(KeyCode.X) || RB.KeyPressed(KeyCode.Keypad5))
            {
                resultSet.AddMove(Vector2i.zero);
            }

            if (RB.KeyPressed(KeyCode.G) || RB.KeyPressed(KeyCode.Keypad0))
            {
                resultSet.AddPickup(mPlayer);
            }

            if (RB.KeyPressed(KeyCode.F))
            {
                var ranged = mPlayer.e.equipment.equipment[(int)EquipmentSlot.Ranged];
                var arrow  = mPlayer.e.inventory.GetArrow();
                if (!ranged.isEmpty && !arrow.isEmpty)
                {
                    resultSet.AddTargeting(ranged);
                }
                else
                {
                    if (ranged.isEmpty)
                    {
                        resultSet.AddMessage(C.FSTR.Set("You do not have a ranged weapon equipped."));
                    }
                    else if (arrow.isEmpty)
                    {
                        resultSet.AddMessage(C.FSTR.Set("You do not have an arrow to shoot."));
                    }
                }
            }
        }
Exemple #17
0
        private void HandleResult(ResultSet resultSet, Result result, out bool tookTurn)
        {
            tookTurn = false;
            var game = (RetroDungeoneerGame)RB.Game;

            switch (result.type)
            {
            case Result.Type.Move:
            {
                Vector2i delta = result.veci1;
                if ((delta.x != 0 || delta.y != 0) && !mGameMap.IsBlocked(mPlayer.e.pos + delta))
                {
                    var destPos      = mPlayer.e.pos + delta;
                    var targetEntity = EntityFunctions.GetBlockingEntityAtPos(destPos);

                    if (!targetEntity.isEmpty)
                    {
                        mPlayer.e.fighter.Attack(mResultSet, targetEntity);
                    }
                    else
                    {
                        var  entities   = EntityFunctions.GetEntitiesAtPos(mPlayer.e.pos);
                        bool stuckInWeb = false;
                        for (int i = 0; i < entities.Count; i++)
                        {
                            if (entities[i].e.groundTrigger != null && entities[i].e.groundTrigger.type == GroundTrigger.GroundTriggerType.Web)
                            {
                                stuckInWeb = true;
                                break;
                            }
                        }

                        // Attempt to free from web
                        if (stuckInWeb)
                        {
                            if (Random.Range(0, 6) == 0)
                            {
                                stuckInWeb = false;
                                resultSet.AddMessage(C.FSTR.Set("You manage to free yourself from the web."));
                            }
                        }

                        if (!stuckInWeb)
                        {
                            mPlayer.e.Move(delta);
                            mFOVRecompute = true;

                            RB.SoundPlay(game.assets.soundFootStep, 0.66f, RandomUtils.RandomPitch(0.1f));

                            var entitesAtDest = EntityFunctions.GetEntitiesAtPos(mPlayer.e.pos);
                            for (int i = 0; i < entitesAtDest.Count; i++)
                            {
                                var trigger = entitesAtDest[i].e.groundTrigger;
                                if (trigger != null)
                                {
                                    trigger.Trigger(resultSet);
                                }
                            }
                        }
                        else
                        {
                            resultSet.AddMessage(C.FSTR.Set("You fail to free yourself from the web, keep trying."));
                            RB.SoundPlay(game.assets.soundWeb, 0.5f, RandomUtils.RandomPitch(0.1f));
                        }
                    }

                    mFloodRecompute = true;

                    tookTurn = true;
                }
                else if (delta.x == 0 && delta.y == 0)
                {
                    // Do nothing, wait
                    tookTurn = true;
                }
            }

            break;

            case Result.Type.Exit:
                if (mGameState == GameState.SHOW_INVENTORY ||
                    mGameState == GameState.DROP_INVENTORY ||
                    mGameState == GameState.SHOW_HELP ||
                    mGameState == GameState.CHARACTER_SCREEN)
                {
                    RB.SoundPlay(game.assets.soundMenuClose, 1, RandomUtils.RandomPitch(0.1f));
                    ChangeState(mPreviousGameState);
                }
                else if (mGameState == GameState.TARGETING)
                {
                    resultSet.AddTargetingCancelled();
                }
                else
                {
                    // Exit back to main menu
                    game.ChangeScene(SceneEnum.MAIN_MENU);
                }

                break;

            case Result.Type.Message:
                mConsole.Log(result.str1);
                break;

            case Result.Type.Dead:
                if (result.entity1 == mPlayer)
                {
                    DeathFunctions.KillPlayer(mResultSet, result.entity1);
                    ChangeState(GameState.PLAYER_DEAD);
                }
                else
                {
                    DeathFunctions.KillMonster(mResultSet, result.entity1);
                }

                break;

            case Result.Type.Pickup:
            {
                var receiver = result.entity1;
                if (receiver.e.inventory == null)
                {
                    break;
                }

                var entityList = EntityFunctions.GetEntitiesAtPos(receiver.e.pos);
                if (entityList != null)
                {
                    for (int j = 0; j < entityList.Count; j++)
                    {
                        var e = entityList[j].e;

                        if (e.item != null)
                        {
                            receiver.e.inventory.AddItem(resultSet, e.id);
                        }
                    }
                }
            }

            break;

            case Result.Type.ItemAdded:
                result.entity1.e.renderOrder = RenderFunctions.RenderOrder.HIDDEN;
                result.entity1.e.pos         = new Vector2i(-1, -1);

                RB.SoundPlay(game.assets.soundInventory, 1, RandomUtils.RandomPitch(0.1f));

                break;

            case Result.Type.ShowInventory:
                if (mGameState != GameState.SHOW_INVENTORY)
                {
                    ChangeState(GameState.SHOW_INVENTORY);
                }
                else
                {
                    ChangeState(mPreviousGameState);
                }

                break;

            case Result.Type.InventoryIndex:
            {
                var entity = result.entity1;
                var item   = entity.e.inventory.items[result.int1];

                mUseParams.Clear();
                mUseParams.map = mGameMap;

                if (mGameState == GameState.SHOW_INVENTORY)
                {
                    entity.e.inventory.UseItem(resultSet, item, mUseParams);
                }
                else if (mGameState == GameState.DROP_INVENTORY)
                {
                    entity.e.inventory.DropItem(resultSet, item);
                }
            }

            break;

            case Result.Type.Consumed:
            {
                var entity = result.entity1;
                var item   = result.entity2;

                entity.e.inventory.RemoveItem(resultSet, item);

                tookTurn = true;
            }

            break;

            case Result.Type.DropInventory:
                if (mGameState != GameState.DROP_INVENTORY)
                {
                    ChangeState(GameState.DROP_INVENTORY);
                }
                else
                {
                    ChangeState(mPreviousGameState);
                }

                break;

            case Result.Type.ItemDropped:
                result.entity1.e.renderOrder = RenderFunctions.RenderOrder.ITEM;
                tookTurn = true;

                RB.SoundPlay(game.assets.soundInventory, 1, RandomUtils.RandomPitch(0.1f));
                break;

            case Result.Type.Equip:
            {
                var equipper = result.entity1;
                var item     = result.entity2;

                if (equipper.e == null || equipper.e.equipment == null || item.e == null || item.e.equippable == null)
                {
                    break;
                }

                equipper.e.equipment.ToggleEquip(resultSet, item);
            }

            break;

            case Result.Type.Equipped:
            {
                var equipper = result.entity1;
                var item     = result.entity2;

                if (equipper.e == null || equipper.e.equipment == null || item.e == null || item.e.equippable == null)
                {
                    break;
                }

                RB.SoundPlay(game.assets.soundInventory, 1, RandomUtils.RandomPitch(0.1f));
            }

            break;

            case Result.Type.Dequipped:
            {
                var equipper = result.entity1;
                var item     = result.entity2;

                if (equipper.e == null || equipper.e.equipment == null || item.e == null || item.e.equippable == null)
                {
                    break;
                }

                RB.SoundPlay(game.assets.soundInventory, 1, RandomUtils.RandomPitch(0.1f));
            }

            break;

            case Result.Type.Targeting:
                // Set previous state to players turn to go back to players turn if targeting is cancelled
                mPreviousGameState = GameState.PLAYER_TURN;
                ChangeState(GameState.TARGETING);
                mTargetingItem = result.entity1;

                mConsole.Log(mTargetingItem.e.item.targetingMessage);
                break;

            case Result.Type.LeftClick:
            {
                if (mGameState == GameState.TARGETING && !mTargetingItem.isEmpty)
                {
                    var targetingPos = result.veci1;

                    if (mTargetingItem.e.equippable != null && mTargetingItem.e.equippable.slot == EquipmentSlot.Ranged)
                    {
                        var arrow = mPlayer.e.inventory.GetArrow();
                        if (SkillFunctions.ShootBow(resultSet, mPlayer, arrow, mTargetingItem.e.item.int2, mTargetingItem.e.item.int1, targetingPos))
                        {
                            mPlayer.e.inventory.RemoveItem(resultSet, arrow);
                            EntityStore.DestroyEntity(arrow);
                        }

                        ChangeState(GameState.ENEMY_TURN);
                    }
                    else
                    {
                        mUseParams.Clear();
                        mUseParams.map   = mGameMap;
                        mUseParams.veci1 = targetingPos;
                        mUseParams.bool1 = true;

                        mPlayer.e.inventory.UseItem(resultSet, mTargetingItem, mUseParams);
                    }
                }
            }

            break;

            case Result.Type.RightClick:
                if (mGameState == GameState.TARGETING)
                {
                    resultSet.AddTargetingCancelled();
                }

                break;

            case Result.Type.TargetingCancelled:
                ChangeState(GameState.PLAYER_TURN);
                mTargetingItem = EntityID.empty;
                mConsole.Log(C.FSTR.Set("Targeting cancelled."));
                break;

            case Result.Type.ShowHelp:
                if (mGameState != GameState.SHOW_HELP)
                {
                    ChangeState(GameState.SHOW_HELP);
                }
                else
                {
                    ChangeState(mPreviousGameState);
                }

                break;

            case Result.Type.TakeStairs:
            {
                int  i;
                bool foundStairs = false;

                var entityList = EntityFunctions.GetEntitiesAtPos(mPlayer.e.pos);
                if (entityList != null)
                {
                    for (i = 0; i < entityList.Count; i++)
                    {
                        var e = entityList[i].e;
                        if (e.stairs != null && e.stairs.type != Stairs.StairType.WELL_CLOSED)
                        {
                            EffectManager.Instance.Clear();

                            mGameMap.NextFloor(resultSet, mPlayer, mConsole);
                            mFOVRecompute   = true;
                            mFloodRecompute = true;

                            // Snap the camera to player
                            mCamera.SetPos(mPlayer);

                            foundStairs = true;

                            if (e.stairs.type == Stairs.StairType.STAIRS)
                            {
                                RB.SoundPlay(game.assets.soundStairs);

                                mPlayer.e.fighter.Heal(resultSet, mPlayer.e.fighter.maxHp / 2);
                                mConsole.Log(C.FSTR.Set("You take a moment to rest, and recover your strength."));
                            }
                            else if (e.stairs.type == Stairs.StairType.PORTAL)
                            {
                                RB.SoundPlay(game.assets.soundPortal);
                                mPlayer.e.fighter.Heal(resultSet, mPlayer.e.fighter.maxHp / 2);
                                mConsole.Log(C.FSTR.Set("You step into the mysterious portal..."));
                            }
                            else if (e.stairs.type == Stairs.StairType.WELL)
                            {
                                RB.SoundPlay(game.assets.soundJump);
                                mConsole.Log(C.FSTR.Set("You jump down the well into the darkness below..."));
                            }

                            if (mCurrentMusic != mGameMap.music)
                            {
                                RB.MusicPlay(mGameMap.music);
                                mCurrentMusic = mGameMap.music;
                            }

                            // Save the game after descending
                            DataLoaders.SaveGame(C.SAVE_FILENAME, mPlayer, mGameMap, mConsole, mGameState);

                            break;
                        }
                        else if (e.stairs != null && e.stairs.type == Stairs.StairType.WELL_CLOSED)
                        {
                            foundStairs = true;

                            mConsole.Log(C.FSTR.Set("You look down the well. That won't be necessary, not this time..."));
                        }
                    }
                }

                if (!foundStairs)
                {
                    mConsole.Log(C.FSTR.Set("There are no stairs here."));
                }
            }

            break;

            case Result.Type.Xp:
                int xp        = result.int1;
                var leveledUp = mPlayer.e.level.AddXp(xp);
                mConsole.Log(C.FSTR.Set("You gain ").Append(xp).Append(" experience points."));

                if (leveledUp)
                {
                    mConsole.Log(C.FSTR.Set("Your battle skills grow stronger! You reached level ").Append(mPlayer.e.level.currentLevel).Append("!"));
                    mPreviousGameState = mGameState;
                    ChangeState(GameState.LEVEL_UP);

                    mMenuLevelUp.ClearOptions();
                    mMenuLevelUp.AddOption(C.FSTR.Set("Constitution (+20 HP, from ").Append(mPlayer.e.fighter.maxHp).Append(")"));
                    mMenuLevelUp.AddOption(C.FSTR.Set("Strength (+1 attack, from ").Append(mPlayer.e.fighter.power).Append(")"));
                    mMenuLevelUp.AddOption(C.FSTR.Set("Agility (+1 defense, from ").Append(mPlayer.e.fighter.defense).Append(")"));

                    RB.SoundPlay(game.assets.soundLevelUp);
                }

                break;

            case Result.Type.LevelUp:
                var levelUp = (LevelUp)result.int1;

                switch (levelUp)
                {
                case LevelUp.Hp:
                    mPlayer.e.fighter.baseMaxHp += 20;
                    mPlayer.e.fighter.hp        += 20;
                    break;

                case LevelUp.Str:
                    mPlayer.e.fighter.basePower += 1;
                    break;

                case LevelUp.Def:
                    mPlayer.e.fighter.baseDefense += 1;
                    break;
                }

                mGameState = mPreviousGameState;

                break;

            case Result.Type.ShowCharacterScreen:
                mPreviousGameState = mGameState;
                ChangeState(GameState.CHARACTER_SCREEN);

                C.FSTR.Clear();
                C.FSTR.Append("@FFFFFFLevel: ").Append(C.STR_COLOR_NAME).Append(mPlayer.e.level.currentLevel).Append("\n");
                C.FSTR.Append("@FFFFFFExperience: ").Append(C.STR_COLOR_NAME).Append(mPlayer.e.level.currentXp).Append("\n");
                C.FSTR.Append("@FFFFFFExperience to Level: ").Append(C.STR_COLOR_NAME).Append(mPlayer.e.level.ExperienceToNextLevel()).Append("\n");
                C.FSTR.Append("@FFFFFFMaximum HP: ").Append(C.STR_COLOR_NAME).Append(mPlayer.e.fighter.maxHp).Append("\n");
                C.FSTR.Append("@FFFFFFAttack: ").Append(C.STR_COLOR_NAME).Append(mPlayer.e.fighter.power).Append("\n");
                C.FSTR.Append("@FFFFFFDefense: ").Append(C.STR_COLOR_NAME).Append(mPlayer.e.fighter.defense);
                mMenuCharacterScreen.SetSummary(C.FSTR);

                break;

            case Result.Type.BossDefeated:
                var boss = result.entity1;
                map.SpawnExitPortal(boss.e.pos);
                break;

            case Result.Type.GameWon:
            {
                var options = new List <SceneMessage.MessageBoxOption>();
                options.Add(new SceneMessage.MessageBoxOption(C.FSTR.Set("Return to Main Menu"), CloseGameWonMessageBox));

                C.FSTR.Set(C.STR_COLOR_DIALOG);
                C.FSTR.Append("You make it out of the forest clearing with adrenaline still pumping through your veins.");
                C.FSTR.Append("\n\n");
                C.FSTR.Append("Your adventure flashes through your mind and you realize you're not the same person you were before. ");
                C.FSTR.Append("The concerns you once had seem insignificant now.");
                C.FSTR.Append("\n\n");
                C.FSTR.Append("Moments later you calm down, and you find yourself wondering what lies at the bottom of other old wells...");
                C.FSTR.Append("\n\n");
                C.FSTR.Append(C.STR_COLOR_NAME);
                C.FSTR.Append("You've won!\nCongratulations!");

                game.ShowMessageBox(
                    C.FSTR2.Set("A New Life"),
                    C.FSTR,
                    options);
                break;
            }

            case Result.Type.FellDownWell:
            {
                var options = new List <SceneMessage.MessageBoxOption>();
                options.Add(new SceneMessage.MessageBoxOption(C.FSTR.Set("Continue"), CloseMessageBox));

                C.FSTR.Set(C.STR_COLOR_DIALOG);
                C.FSTR.Append("This is not what you expected. It seems that not only has the bottom of this well ran dry, it has collapsed into some old dungeon! ");
                C.FSTR.Append("There must be some way out of this place, there has to be.");
                C.FSTR.Append("\n\n");
                C.FSTR.Append("A sound of skittering creatures can be heard coming from the nearby rooms. ");
                C.FSTR.Append("You spot a rusty dagger lying beside you.");
                C.FSTR.Append("\n\n");
                C.FSTR.Append("Finding an exit may prove... difficult.");

                game.ShowMessageBox(
                    C.FSTR2.Set("Bottom of the Well"),
                    C.FSTR,
                    options);
                break;
            }

            case Result.Type.BossEncounter:
            {
                var options = new List <SceneMessage.MessageBoxOption>();
                options.Add(new SceneMessage.MessageBoxOption(C.FSTR.Set("Continue"), CloseMessageBox));

                C.FSTR.Set(C.STR_COLOR_DIALOG);
                C.FSTR.Append("Before you stands a towering golem. It lurches forward, slowly at first, as if it has not moved in ages.");
                C.FSTR.Append("\n\n");
                C.FSTR.Append(C.STR_COLOR_NAME);
                C.FSTR.Append("\"Who awakens the Gatekeeper?\"").Append(C.STR_COLOR_DIALOG).Append(" it belows.");
                C.FSTR.Append("\n\n");
                C.FSTR.Append("A Gatekeeper is just what you were looking for. This is your chance to escape the dungeon! You steady yourself, this will not be an easy fight.");

                game.ShowMessageBox(
                    C.FSTR2.Set("The Gatekeeper"),
                    C.FSTR,
                    options);
                break;
            }
            }
        }
        /// <summary>
        /// Cast fireball
        /// </summary>
        /// <param name="resultSet">Result set</param>
        /// <param name="caster">Caster</param>
        /// <param name="radius">Radius of explosion</param>
        /// <param name="damage">Damage</param>
        /// <param name="targetPos">Target position</param>
        /// <param name="hurtsCaster">True if explosion should hurt caster</param>
        /// <returns>True if successful</returns>
        public static bool CastFireball(ResultSet resultSet, EntityID caster, int radius, int damage, Vector2i targetPos, bool hurtsCaster)
        {
            var game = (RetroDungeoneerGame)RB.Game;
            var map  = game.map;

            if (!CheckTargetPosValid(resultSet, targetPos, caster))
            {
                return(false);
            }

            resultSet.AddMessage(
                C.FSTR.Set("The fireball explodes, burning everything within ").Append(C.STR_COLOR_NAME).Append(radius).Append("@- tiles!"));

            // Apply damage to all entities in range
            for (int x = targetPos.x - radius; x <= targetPos.x + radius; x++)
            {
                if (x < 0 || x >= map.size.width)
                {
                    continue;
                }

                for (int y = targetPos.y - radius; y <= targetPos.y + radius; y++)
                {
                    if (y < 0 || y >= map.size.height)
                    {
                        continue;
                    }

                    var pos   = new Vector2i(x, y);
                    var delta = pos - targetPos;
                    int dist  = UnityEngine.Mathf.RoundToInt(delta.Magnitude());

                    if (dist > radius)
                    {
                        continue;
                    }

                    var tile = map.terrain[x, y];

                    if (!tile.blocked)
                    {
                        var entities = EntityFunctions.GetEntitiesAtPos(new Vector2i(x, y));

                        for (int i = 0; i < entities.Count; i++)
                        {
                            if (entities[i] == caster && !hurtsCaster)
                            {
                                continue;
                            }

                            var e = entities[i].e;
                            if (e.fighter != null)
                            {
                                int actualDamage = (damage + caster.e.fighter.power) - e.fighter.defense;
                                if (actualDamage == 0)
                                {
                                    actualDamage = 1;
                                }

                                resultSet.AddMessage(
                                    C.FSTR.Set("The ").Append(C.STR_COLOR_NAME).Append(e.name).Append("@- got burned for ").Append(C.STR_COLOR_DAMAGE).Append(actualDamage).Append("@- hit points."));

                                e.fighter.TakeDamage(resultSet, actualDamage);
                            }
                        }

                        EffectManager.Instance.AddEffect(new EffectFlame(pos, dist * 4));
                    }
                }
            }

            RB.SoundPlay(game.assets.soundFireBall);

            return(true);
        }