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; } } }
private bool DoSkill(ResultSet resultSet, EntityID target) { if (mSkills.Count == 0) { return(false); } int skillIndex = RandomUtils.RandomChoiceIndex(mSkillChances); Skill randomSkill = mSkills[skillIndex]; // Check if there is a backup melee skill bool hasMeleeSkill = false; for (int i = 0; i < mSkills.Count; i++) { if (mSkills[i] == Skill.MeleeAttack) { hasMeleeSkill = true; break; } } var game = (RetroDungeoneerGame)RB.Game; bool skillResult = false; switch (randomSkill) { case Skill.MeleeAttack: return(SkillFunctions.MeleeAttack(resultSet, owner, target)); case Skill.CastWeb: skillResult = SkillFunctions.CastWeb(resultSet, owner, target.e.pos); break; case Skill.CastLightning: skillResult = SkillFunctions.CastLightning(resultSet, owner, target.e.pos, 6, 12); break; case Skill.ShootBow: { var arrow = owner.e.inventory.GetArrow(); if (!arrow.isEmpty) { skillResult = SkillFunctions.ShootBow(resultSet, owner, arrow, 6, 10, target.e.pos); if (skillResult) { owner.e.inventory.RemoveItem(null, arrow); EntityStore.DestroyEntity(arrow); } } } break; case Skill.CastRandomFireball: { int attempts = 40; while (attempts > 0) { var fireballPos = new Vector2i(target.e.pos.x, target.e.pos.y); fireballPos.x += Random.Range(-20, 21); fireballPos.y += Random.Range(-20, 21); if (game.map.IsInFOV(fireballPos)) { skillResult = SkillFunctions.CastFireball(resultSet, owner, 4, 10, fireballPos, false); break; } attempts--; } } break; case Skill.Teleport: { // Find a location to teleport on the furthest side of target from where the entity is now // Limited attempts are made, so this may not end up being furthest var furthestPos = new Vector2i(-1, -1); var furthestDist = 0.0f; int attempts = 40; Vector2i targetPos = target.e.pos; while (attempts > 0) { var randomPos = new Vector2i(Random.Range(targetPos.x - 1, targetPos.x + 2), Random.Range(targetPos.y - 1, targetPos.y + 2)); if (EntityFunctions.GetBlockingEntityAtPos(randomPos).isEmpty&& !game.map.IsBlocked(randomPos)) { float dist = (owner.e.pos - randomPos).SqrMagnitude(); if (dist > furthestDist) { furthestDist = dist; furthestPos = randomPos; } } attempts--; } if (furthestPos.x != -1) { skillResult = SkillFunctions.Teleport(resultSet, owner, furthestPos); } else { Debug.Log("Failed"); } } break; } if (skillResult == false && hasMeleeSkill) { skillResult = SkillFunctions.MeleeAttack(resultSet, owner, target); } return(skillResult); }