From aa338d7abfa52d729e96ea3ce2f150faf71b79bf Mon Sep 17 00:00:00 2001 From: lotuuu Date: Tue, 14 May 2024 16:57:12 -0300 Subject: [PATCH 01/10] Add dungeon mode levels with max_units implementation --- apps/champions/lib/champions/battle.ex | 19 ++++- .../lib/game_backend/campaigns.ex | 9 +- .../lib/game_backend/campaigns/level.ex | 6 +- ...0514160226_add_dungeon_fields_to_level.exs | 9 ++ priv/repo/seeds.exs | 84 ++++++++++++++++++- 5 files changed, 118 insertions(+), 9 deletions(-) create mode 100644 apps/game_backend/priv/repo/migrations/20240514160226_add_dungeon_fields_to_level.exs diff --git a/apps/champions/lib/champions/battle.ex b/apps/champions/lib/champions/battle.ex index f5b77011a..a652b7c8d 100644 --- a/apps/champions/lib/champions/battle.ex +++ b/apps/champions/lib/champions/battle.ex @@ -11,6 +11,8 @@ defmodule Champions.Battle do alias GameBackend.Units alias GameBackend.Users + @default_max_units 6 + @doc """ Plays a level for a user, which means fighting its units with their selected ones. Returns `:win` or `:loss` accordingly, and updates the user's progress if they win.. @@ -21,8 +23,15 @@ defmodule Champions.Battle do {:level, {:ok, level}} <- {:level, Campaigns.get_level(level_id)}, {:super_campaign_progress, {:ok, %SuperCampaignProgress{level_id: current_level_id}}} <- {:super_campaign_progress, Campaigns.get_super_campaign_progress(user_id, level.campaign.super_campaign_id)}, - {:level_valid, true} <- {:level_valid, current_level_id == level_id} do - units = Units.get_selected_units(user_id) + {:level_valid, true} <- {:level_valid, current_level_id == level_id}, + units <- Units.get_selected_units(user_id), + {:max_units_met, true} <- {:max_units_met, Enum.count(units) <= (level.max_units || @default_max_units)} do + units = + if level.campaign.super_campaign.name == "Dungeon" do + apply_buffs(units, user_id) + else + units + end response = case Simulator.run_battle(units, level.units) do @@ -47,6 +56,12 @@ defmodule Champions.Battle do {:level, {:error, :not_found}} -> {:error, :level_not_found} {:super_campaign_progress, {:error, :not_found}} -> {:error, :super_campaign_progress_not_found} {:level_valid, false} -> {:error, :level_invalid} + {:max_units_met, false} -> {:error, :max_units_exceeded} end end + + # TODO: implement buffs [#CHoM-428] + defp apply_buffs(units, _user_id) do + units + end end diff --git a/apps/game_backend/lib/game_backend/campaigns.ex b/apps/game_backend/lib/game_backend/campaigns.ex index 43b70eb16..190722ebb 100644 --- a/apps/game_backend/lib/game_backend/campaigns.ex +++ b/apps/game_backend/lib/game_backend/campaigns.ex @@ -84,8 +84,8 @@ defmodule GameBackend.Campaigns do level = Repo.get(Level, level_id) |> Repo.preload([ - :campaign, :currency_rewards, + campaign: :super_campaign, units: [ :items, character: [basic_skill: [mechanics: :apply_effects_to], ultimate_skill: [mechanics: :apply_effects_to]] @@ -101,6 +101,13 @@ defmodule GameBackend.Campaigns do def get_user_super_campaign_progresses(user_id), do: Repo.all(from(cp in SuperCampaignProgress, where: cp.user_id == ^user_id, preload: [:level])) + @doc """ + Get a super campaign by id. + """ + def get_super_campaign(super_campaign_id) do + Repo.get(SuperCampaign, super_campaign_id) + end + @doc """ Get a campaign progress by user id and campaign id. Returns `{:error, :not_found}` if no progress is found. diff --git a/apps/game_backend/lib/game_backend/campaigns/level.ex b/apps/game_backend/lib/game_backend/campaigns/level.ex index f2f38a9b3..f82793410 100644 --- a/apps/game_backend/lib/game_backend/campaigns/level.ex +++ b/apps/game_backend/lib/game_backend/campaigns/level.ex @@ -17,8 +17,10 @@ defmodule GameBackend.Campaigns.Level do field(:level_number, :integer) field(:experience_reward, :integer) - belongs_to(:campaign, Campaign) + field(:max_units, :integer) has_many(:units, Unit, foreign_key: :campaign_level_id) + + belongs_to(:campaign, Campaign) has_many(:currency_rewards, CurrencyReward) has_many(:item_rewards, ItemReward) has_many(:unit_rewards, UnitReward) @@ -29,7 +31,7 @@ defmodule GameBackend.Campaigns.Level do @doc false def changeset(level, attrs \\ %{}) do level - |> cast(attrs, [:game_id, :level_number, :campaign_id, :experience_reward]) + |> cast(attrs, [:game_id, :level_number, :campaign_id, :experience_reward, :max_units]) |> cast_assoc(:units) |> cast_assoc(:currency_rewards) |> cast_assoc(:item_rewards) diff --git a/apps/game_backend/priv/repo/migrations/20240514160226_add_dungeon_fields_to_level.exs b/apps/game_backend/priv/repo/migrations/20240514160226_add_dungeon_fields_to_level.exs new file mode 100644 index 000000000..32bc3af2d --- /dev/null +++ b/apps/game_backend/priv/repo/migrations/20240514160226_add_dungeon_fields_to_level.exs @@ -0,0 +1,9 @@ +defmodule GameBackend.Repo.Migrations.AddDungeonFieldsToLevel do + use Ecto.Migration + + def change do + alter(table(:levels)) do + add(:max_units, :integer) + end + end +end diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs index b95581810..bae4c1cc2 100644 --- a/priv/repo/seeds.exs +++ b/priv/repo/seeds.exs @@ -14,7 +14,7 @@ alias GameBackend.Users.KalineTreeLevel curse_of_mirra_id = Utils.get_game_id(:curse_of_mirra) champions_of_mirra_id = Utils.get_game_id(:champions_of_mirra) -units_per_level = 5 +units_per_level = 6 {:ok, _skills} = Champions.Config.import_skill_config() @@ -159,12 +159,18 @@ rules = [ %{base_level: 50, scaler: 1.3, possible_factions: ["Merliot", "Otobi"], length: 20} ] -super_campaign = %{ +main_campaign = %{ game_id: champions_of_mirra_id, name: "Main Campaign" } -{_, super_campaign} = Campaigns.insert_super_campaign(super_campaign, returning: true) +dungeon_campaign = %{ + game_id: champions_of_mirra_id, + name: "Dungeon" +} + +{_, main_campaign} = Campaigns.insert_super_campaign(main_campaign, returning: true) +{_, dungeon_campaign} = Campaigns.insert_super_campaign(dungeon_campaign, returning: true) # Since insert_all doesn't accept assocs, we insert the levels first and then their units levels = @@ -173,7 +179,7 @@ levels = Campaigns.insert_campaign( %{ game_id: champions_of_mirra_id, - super_campaign_id: super_campaign.id, + super_campaign_id: main_campaign.id, campaign_number: campaign_index }, returning: true @@ -289,3 +295,73 @@ _dungeon_settlement_levels = dungeon_settlement_level end) + +# Since insert_all doesn't accept assocs, we insert the levels first and then their units +dungeon_levels = + Enum.flat_map(Enum.with_index(rules, 1), fn {campaign_rules, campaign_index} -> + {_, campaign} = + Campaigns.insert_campaign( + %{ + game_id: champions_of_mirra_id, + super_campaign_id: dungeon_campaign.id, + campaign_number: campaign_index + }, + returning: true + ) + + Enum.map(1..campaign_rules.length, fn level_index -> + %{ + game_id: champions_of_mirra_id, + campaign_id: campaign.id, + level_number: level_index, + experience_reward: 100 * level_index, + inserted_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second), + updated_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) + } + end) + end) + +{_, levels_without_units} = + Repo.insert_all(Level, dungeon_levels, returning: [:id, :level_number, :campaign_id]) + +units = + Enum.flat_map(Enum.with_index(levels_without_units, 0), fn {level, level_index} -> + campaign_number = Repo.get!(Campaign, level.campaign_id).campaign_number + campaign_rules = Enum.at(rules, campaign_number - 1) + + base_level = campaign_rules.base_level + level_scaler = campaign_rules.scaler + + possible_characters = Units.all_characters_from_factions(campaign_rules.possible_factions) + + agg_difficulty = (base_level * Math.pow(level_scaler, level_index)) |> round() + + units = + Enum.map(1..6, fn slot -> + Units.unit_params_for_level( + possible_characters, + div(agg_difficulty, units_per_level), + slot + ) + |> Map.put(:inserted_at, NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)) + |> Map.put(:updated_at, NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)) + end) + + # Add the remaining unit levels to match the level difficulty + level_units = + case rem(agg_difficulty, units_per_level) do + 0 -> + units + + missing_levels -> + Enum.reduce(0..missing_levels, units, fn index, units -> + List.update_at(units, index, fn unit -> %{unit | level: unit.level + 1} end) + end) + end + + Enum.map(level_units, fn unit_attrs -> + Map.put(unit_attrs, :campaign_level_id, level.id) + end) + end) + +Repo.insert_all(Unit, units, on_conflict: :nothing) From 51a29908da59a68b3d2d9e38e32c9836ee5a0736 Mon Sep 17 00:00:00 2001 From: lotuuu Date: Tue, 14 May 2024 17:33:20 -0300 Subject: [PATCH 02/10] Fix tests --- .../lib/game_backend/campaigns.ex | 7 ++++ apps/gateway/test/champions_test.exs | 37 +++++++++++++++---- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/apps/game_backend/lib/game_backend/campaigns.ex b/apps/game_backend/lib/game_backend/campaigns.ex index 190722ebb..ce42a3eeb 100644 --- a/apps/game_backend/lib/game_backend/campaigns.ex +++ b/apps/game_backend/lib/game_backend/campaigns.ex @@ -108,6 +108,13 @@ defmodule GameBackend.Campaigns do Repo.get(SuperCampaign, super_campaign_id) end + @doc """ + Get a super campaign by name and game_id. + """ + def get_super_campaign_by_name_and_game(name, game_id) do + Repo.get_by(SuperCampaign, name: name, game_id: game_id) + end + @doc """ Get a campaign progress by user id and campaign id. Returns `{:error, :not_found}` if no progress is found. diff --git a/apps/gateway/test/champions_test.exs b/apps/gateway/test/champions_test.exs index 5883765ad..7e73662e8 100644 --- a/apps/gateway/test/champions_test.exs +++ b/apps/gateway/test/champions_test.exs @@ -328,8 +328,15 @@ defmodule Gateway.Test.Champions do # Register user {:ok, user} = Users.register("battle_user") - # Get user's first SuperCampaignProgress - [super_campaign_progress | _] = user.super_campaign_progresses + # Get user's Main Campaign progress + main_super_campaign = + GameBackend.Campaigns.get_super_campaign_by_name_and_game( + "Main Campaign", + Utils.get_game_id(:champions_of_mirra) + ) + + {:ok, super_campaign_progress} = + GameBackend.Campaigns.get_super_campaign_progress(user.id, main_super_campaign.id) # Get the SuperCampaignProgress' Level level_id = super_campaign_progress.level_id @@ -357,8 +364,15 @@ defmodule Gateway.Test.Champions do GameBackend.Units.update_unit(unit, %{level: 9999}) end) - # Get user's first SuperCampaignProgress - [super_campaign_progress | _] = user.super_campaign_progresses + # Get user's progress in the main SuperCampaign + main_super_campaign = + GameBackend.Campaigns.get_super_campaign_by_name_and_game( + "Main Campaign", + Utils.get_game_id(:champions_of_mirra) + ) + + {:ok, super_campaign_progress} = + GameBackend.Campaigns.get_super_campaign_progress(user.id, main_super_campaign.id) # Get the SuperCampaignProgress' Level level_id = super_campaign_progress.level_id @@ -376,7 +390,8 @@ defmodule Gateway.Test.Champions do {:ok, advanced_user} = Users.get_user(user.id) - [advanced_super_campaign_progress | _] = advanced_user.super_campaign_progresses + {:ok, advanced_super_campaign_progress} = + GameBackend.Campaigns.get_super_campaign_progress(user.id, main_super_campaign.id) assert user.id == advanced_user.id assert advanced_super_campaign_progress.level_id != level_id @@ -389,10 +404,16 @@ defmodule Gateway.Test.Champions do # Register user {:ok, user} = Users.register("invalid_battle_user") - # Get user's first SuperCampaignProgress - [super_campaign_progress | _] = user.super_campaign_progresses + # Get user's Main Campaign progress + main_super_campaign = + GameBackend.Campaigns.get_super_campaign_by_name_and_game( + "Main Campaign", + Utils.get_game_id(:champions_of_mirra) + ) + + {:ok, super_campaign_progress} = + GameBackend.Campaigns.get_super_campaign_progress(user.id, main_super_campaign.id) - # Get the level of the SuperCampaignProgress next_level_id = super_campaign_progress.level_id # Get a Level that is not the next one in the SuperCampaignProgress From 2e6ee47ea1bde22b2ea6ad6d4d409c36e911bfee Mon Sep 17 00:00:00 2001 From: lotuuu Date: Tue, 14 May 2024 17:44:20 -0300 Subject: [PATCH 03/10] Send name in protobuf super_campaign_progress message --- .../lib/game_backend/campaigns.ex | 2 +- .../lib/gateway/champions_socket_handler.ex | 2 +- .../lib/gateway/serialization/gateway.pb.ex | 26 +++++++++---------- apps/serialization/gateway.proto | 2 +- 4 files changed, 15 insertions(+), 17 deletions(-) diff --git a/apps/game_backend/lib/game_backend/campaigns.ex b/apps/game_backend/lib/game_backend/campaigns.ex index ce42a3eeb..03cdb8a5a 100644 --- a/apps/game_backend/lib/game_backend/campaigns.ex +++ b/apps/game_backend/lib/game_backend/campaigns.ex @@ -99,7 +99,7 @@ defmodule GameBackend.Campaigns do Get all of a User's SuperCampaignProgresses. """ def get_user_super_campaign_progresses(user_id), - do: Repo.all(from(cp in SuperCampaignProgress, where: cp.user_id == ^user_id, preload: [:level])) + do: Repo.all(from(cp in SuperCampaignProgress, where: cp.user_id == ^user_id, preload: [:level, :super_campaign])) @doc """ Get a super campaign by id. diff --git a/apps/gateway/lib/gateway/champions_socket_handler.ex b/apps/gateway/lib/gateway/champions_socket_handler.ex index 8ff09c49f..57137c489 100644 --- a/apps/gateway/lib/gateway/champions_socket_handler.ex +++ b/apps/gateway/lib/gateway/champions_socket_handler.ex @@ -215,7 +215,7 @@ defmodule Gateway.ChampionsSocketHandler do level_id: super_campaign_progress.level_id, user_id: super_campaign_progress.user_id, campaign_id: super_campaign_progress.level.campaign_id, - super_campaign_id: super_campaign_progress.super_campaign_id + super_campaign_id: super_campaign_progress.super_campaign.name } end) diff --git a/apps/gateway/lib/gateway/serialization/gateway.pb.ex b/apps/gateway/lib/gateway/serialization/gateway.pb.ex index 61d851867..fc815ec9a 100644 --- a/apps/gateway/lib/gateway/serialization/gateway.pb.ex +++ b/apps/gateway/lib/gateway/serialization/gateway.pb.ex @@ -421,13 +421,12 @@ defmodule Gateway.Serialization.KalineTreeLevel do use Protobuf, syntax: :proto3, protoc_gen_elixir_version: "0.12.0" - field(:id, 1, type: :string) - field(:level, 2, type: :uint64) - field(:fertilizer_level_up_cost, 3, type: :uint64, json_name: "fertilizerLevelUpCost") - field(:gold_level_up_cost, 4, type: :uint64, json_name: "goldLevelUpCost") - field(:unlock_features, 5, repeated: true, type: :string, json_name: "unlockFeatures") + field(:level, 1, type: :uint64) + field(:fertilizer_level_up_cost, 2, type: :uint64, json_name: "fertilizerLevelUpCost") + field(:gold_level_up_cost, 3, type: :uint64, json_name: "goldLevelUpCost") + field(:unlock_features, 4, repeated: true, type: :string, json_name: "unlockFeatures") - field(:afk_reward_rates, 6, + field(:afk_reward_rates, 5, repeated: true, type: Gateway.Serialization.AfkRewardRate, json_name: "afkRewardRates" @@ -439,20 +438,19 @@ defmodule Gateway.Serialization.DungeonSettlementLevel do use Protobuf, syntax: :proto3, protoc_gen_elixir_version: "0.12.0" - field(:id, 1, type: :string) - field(:level, 2, type: :uint64) + field(:level, 1, type: :uint64) - field(:upgrade_costs, 3, + field(:upgrade_costs, 2, repeated: true, type: Gateway.Serialization.CurrencyCost, json_name: "upgradeCosts" ) - field(:max_dungeon, 4, type: :uint64, json_name: "maxDungeon") - field(:max_factional, 5, type: :uint64, json_name: "maxFactional") - field(:supply_limit, 6, type: :uint64, json_name: "supplyLimit") + field(:max_dungeon, 3, type: :uint64, json_name: "maxDungeon") + field(:max_factional, 4, type: :uint64, json_name: "maxFactional") + field(:supply_limit, 5, type: :uint64, json_name: "supplyLimit") - field(:afk_reward_rates, 7, + field(:afk_reward_rates, 6, repeated: true, type: Gateway.Serialization.AfkRewardRate, json_name: "afkRewardRates" @@ -479,7 +477,7 @@ defmodule Gateway.Serialization.SuperCampaignProgress do field(:user_id, 1, type: :string, json_name: "userId") field(:campaign_id, 2, type: :string, json_name: "campaignId") field(:level_id, 3, type: :string, json_name: "levelId") - field(:super_campaign_id, 4, type: :string, json_name: "superCampaignId") + field(:super_campaign_name, 4, type: :string, json_name: "superCampaignName") end defmodule Gateway.Serialization.AfkRewardRate do diff --git a/apps/serialization/gateway.proto b/apps/serialization/gateway.proto index 78679942b..729b6d991 100644 --- a/apps/serialization/gateway.proto +++ b/apps/serialization/gateway.proto @@ -205,7 +205,7 @@ syntax = "proto3"; string user_id = 1; string campaign_id = 2; string level_id = 3; - string super_campaign_id = 4; + string super_campaign_name = 4; } message AfkRewardRate { From 3f7c4966422fbce74f635a6efe0dbf29c66c722c Mon Sep 17 00:00:00 2001 From: lotuuu Date: Tue, 14 May 2024 17:48:26 -0300 Subject: [PATCH 04/10] Fix GetUserSuperCampaignProgresses --- apps/gateway/lib/gateway/champions_socket_handler.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/gateway/lib/gateway/champions_socket_handler.ex b/apps/gateway/lib/gateway/champions_socket_handler.ex index 57137c489..430c76ddc 100644 --- a/apps/gateway/lib/gateway/champions_socket_handler.ex +++ b/apps/gateway/lib/gateway/champions_socket_handler.ex @@ -215,7 +215,7 @@ defmodule Gateway.ChampionsSocketHandler do level_id: super_campaign_progress.level_id, user_id: super_campaign_progress.user_id, campaign_id: super_campaign_progress.level.campaign_id, - super_campaign_id: super_campaign_progress.super_campaign.name + super_campaign_name: super_campaign_progress.super_campaign.name } end) From 467f3afcde7ab70739f2f64d8061bd70cee3043c Mon Sep 17 00:00:00 2001 From: lotuuu Date: Tue, 14 May 2024 18:24:49 -0300 Subject: [PATCH 05/10] Add level validation --- apps/champions/lib/champions/battle.ex | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/apps/champions/lib/champions/battle.ex b/apps/champions/lib/champions/battle.ex index a652b7c8d..9f00633ef 100644 --- a/apps/champions/lib/champions/battle.ex +++ b/apps/champions/lib/champions/battle.ex @@ -5,9 +5,11 @@ defmodule Champions.Battle do require Logger + alias GameBackend.Users.DungeonSettlementLevel + alias GameBackend.Users.User alias Champions.Battle.Simulator alias GameBackend.Campaigns - alias GameBackend.Campaigns.SuperCampaignProgress + alias GameBackend.Campaigns.{Campaign, Level, SuperCampaign, SuperCampaignProgress} alias GameBackend.Units alias GameBackend.Users @@ -19,11 +21,11 @@ defmodule Champions.Battle do """ def fight_level(user_id, level_id) do with start_time <- :os.system_time(:millisecond), - {:user_exists, true} <- {:user_exists, Users.exists?(user_id)}, + {:user_exists, {:ok, user}} <- {:user_exists, Users.get_user(user_id)}, {:level, {:ok, level}} <- {:level, Campaigns.get_level(level_id)}, {:super_campaign_progress, {:ok, %SuperCampaignProgress{level_id: current_level_id}}} <- {:super_campaign_progress, Campaigns.get_super_campaign_progress(user_id, level.campaign.super_campaign_id)}, - {:level_valid, true} <- {:level_valid, current_level_id == level_id}, + {:level_valid, true} <- {:level_valid, level_valid?(level, current_level_id, user)}, units <- Units.get_selected_units(user_id), {:max_units_met, true} <- {:max_units_met, Enum.count(units) <= (level.max_units || @default_max_units)} do units = @@ -52,7 +54,7 @@ defmodule Champions.Battle do response else - {:user_exists, false} -> {:error, :user_not_found} + {:user_exists, _} -> {:error, :user_not_found} {:level, {:error, :not_found}} -> {:error, :level_not_found} {:super_campaign_progress, {:error, :not_found}} -> {:error, :super_campaign_progress_not_found} {:level_valid, false} -> {:error, :level_invalid} @@ -60,6 +62,22 @@ defmodule Champions.Battle do end end + defp level_valid?( + %Level{ + id: id, + campaign: %Campaign{super_campaign: %SuperCampaign{name: "Dungeon"}}, + level_number: level_number + }, + current_level_id, + %User{dungeon_settlement_level: %DungeonSettlementLevel{max_dungeon: max_dungeon}} + ) do + id == current_level_id && level_number <= max_dungeon + end + + defp level_valid?(%Level{id: id}, current_level_id, _) do + id == current_level_id + end + # TODO: implement buffs [#CHoM-428] defp apply_buffs(units, _user_id) do units From 519c9c1f5aacd7eb38fb006333de20a66b4807a9 Mon Sep 17 00:00:00 2001 From: lotuuu Date: Tue, 14 May 2024 18:27:15 -0300 Subject: [PATCH 06/10] Restore gateway.pb.ex --- .../lib/gateway/serialization/gateway.pb.ex | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/apps/gateway/lib/gateway/serialization/gateway.pb.ex b/apps/gateway/lib/gateway/serialization/gateway.pb.ex index fc815ec9a..744499a85 100644 --- a/apps/gateway/lib/gateway/serialization/gateway.pb.ex +++ b/apps/gateway/lib/gateway/serialization/gateway.pb.ex @@ -421,12 +421,13 @@ defmodule Gateway.Serialization.KalineTreeLevel do use Protobuf, syntax: :proto3, protoc_gen_elixir_version: "0.12.0" - field(:level, 1, type: :uint64) - field(:fertilizer_level_up_cost, 2, type: :uint64, json_name: "fertilizerLevelUpCost") - field(:gold_level_up_cost, 3, type: :uint64, json_name: "goldLevelUpCost") - field(:unlock_features, 4, repeated: true, type: :string, json_name: "unlockFeatures") + field(:id, 1, type: :string) + field(:level, 2, type: :uint64) + field(:fertilizer_level_up_cost, 3, type: :uint64, json_name: "fertilizerLevelUpCost") + field(:gold_level_up_cost, 4, type: :uint64, json_name: "goldLevelUpCost") + field(:unlock_features, 5, repeated: true, type: :string, json_name: "unlockFeatures") - field(:afk_reward_rates, 5, + field(:afk_reward_rates, 6, repeated: true, type: Gateway.Serialization.AfkRewardRate, json_name: "afkRewardRates" @@ -438,19 +439,20 @@ defmodule Gateway.Serialization.DungeonSettlementLevel do use Protobuf, syntax: :proto3, protoc_gen_elixir_version: "0.12.0" - field(:level, 1, type: :uint64) + field(:id, 1, type: :string) + field(:level, 2, type: :uint64) - field(:upgrade_costs, 2, + field(:upgrade_costs, 3, repeated: true, type: Gateway.Serialization.CurrencyCost, json_name: "upgradeCosts" ) - field(:max_dungeon, 3, type: :uint64, json_name: "maxDungeon") - field(:max_factional, 4, type: :uint64, json_name: "maxFactional") - field(:supply_limit, 5, type: :uint64, json_name: "supplyLimit") + field(:max_dungeon, 4, type: :uint64, json_name: "maxDungeon") + field(:max_factional, 5, type: :uint64, json_name: "maxFactional") + field(:supply_limit, 6, type: :uint64, json_name: "supplyLimit") - field(:afk_reward_rates, 6, + field(:afk_reward_rates, 7, repeated: true, type: Gateway.Serialization.AfkRewardRate, json_name: "afkRewardRates" From 1fbf82dfd45654be03988756f598b40e6eb6ce25 Mon Sep 17 00:00:00 2001 From: lotuuu Date: Tue, 14 May 2024 18:28:03 -0300 Subject: [PATCH 07/10] Sort aliases --- apps/champions/lib/champions/battle.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/champions/lib/champions/battle.ex b/apps/champions/lib/champions/battle.ex index 9f00633ef..95ed82c7a 100644 --- a/apps/champions/lib/champions/battle.ex +++ b/apps/champions/lib/champions/battle.ex @@ -5,13 +5,13 @@ defmodule Champions.Battle do require Logger - alias GameBackend.Users.DungeonSettlementLevel - alias GameBackend.Users.User alias Champions.Battle.Simulator alias GameBackend.Campaigns alias GameBackend.Campaigns.{Campaign, Level, SuperCampaign, SuperCampaignProgress} alias GameBackend.Units alias GameBackend.Users + alias GameBackend.Users.DungeonSettlementLevel + alias GameBackend.Users.User @default_max_units 6 From f0449f9523f1c866aa54570eb3bf91d6f8e0d4df Mon Sep 17 00:00:00 2001 From: lotuuu Date: Tue, 14 May 2024 18:39:56 -0300 Subject: [PATCH 08/10] Send super_campaign_name instead of super_campaign_id in Campaign proto message --- apps/game_backend/lib/game_backend/campaigns.ex | 2 +- .../lib/gateway/champions_socket_handler.ex | 15 +++++++++++++-- .../lib/gateway/serialization/gateway.pb.ex | 2 +- apps/serialization/gateway.proto | 2 +- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/apps/game_backend/lib/game_backend/campaigns.ex b/apps/game_backend/lib/game_backend/campaigns.ex index 03cdb8a5a..4e1c59da5 100644 --- a/apps/game_backend/lib/game_backend/campaigns.ex +++ b/apps/game_backend/lib/game_backend/campaigns.ex @@ -14,7 +14,7 @@ defmodule GameBackend.Campaigns do campaigns = Repo.all( from(c in Campaign, - preload: [levels: ^level_preload_query()], + preload: [:super_campaign, levels: ^level_preload_query()], order_by: [asc: c.campaign_number] ) ) diff --git a/apps/gateway/lib/gateway/champions_socket_handler.ex b/apps/gateway/lib/gateway/champions_socket_handler.ex index 430c76ddc..5146d2f68 100644 --- a/apps/gateway/lib/gateway/champions_socket_handler.ex +++ b/apps/gateway/lib/gateway/champions_socket_handler.ex @@ -105,7 +105,7 @@ defmodule Gateway.ChampionsSocketHandler do prepare_response({:error, reason}, nil) {:ok, campaigns} -> - prepare_response(%{campaigns: campaigns}, :campaigns) + prepare_response(%{campaigns: Enum.map(campaigns, &prepare_campaign/1)}, :campaigns) end end @@ -115,7 +115,9 @@ defmodule Gateway.ChampionsSocketHandler do prepare_response({:error, reason}, nil) {:ok, campaign} -> - prepare_response(campaign, :campaign) + campaign + |> prepare_campaign() + |> prepare_response(:campaign) end end @@ -243,6 +245,15 @@ defmodule Gateway.ChampionsSocketHandler do defp handle(unknown_request), do: Logger.warning("[Gateway.ChampionsSocketHandler] Received unknown request #{unknown_request}") + defp prepare_campaign(campaign) do + %{ + id: campaign.id, + super_campaign_name: campaign.super_campaign.name, + campaign_number: campaign.campaign_number, + levels: campaign.levels + } + end + defp prepare_step(step) do update_in(step, [:actions], fn actions -> Enum.map(actions, &prepare_action/1) diff --git a/apps/gateway/lib/gateway/serialization/gateway.pb.ex b/apps/gateway/lib/gateway/serialization/gateway.pb.ex index 744499a85..dabc52895 100644 --- a/apps/gateway/lib/gateway/serialization/gateway.pb.ex +++ b/apps/gateway/lib/gateway/serialization/gateway.pb.ex @@ -616,7 +616,7 @@ defmodule Gateway.Serialization.Campaign do use Protobuf, syntax: :proto3, protoc_gen_elixir_version: "0.12.0" field(:id, 1, type: :string) - field(:super_campaign_id, 2, type: :string, json_name: "superCampaignId") + field(:super_campaign_name, 2, type: :string, json_name: "superCampaignName") field(:campaign_number, 3, type: :uint32, json_name: "campaignNumber") field(:levels, 4, repeated: true, type: Gateway.Serialization.Level) end diff --git a/apps/serialization/gateway.proto b/apps/serialization/gateway.proto index f430cc5d8..65f03d15c 100644 --- a/apps/serialization/gateway.proto +++ b/apps/serialization/gateway.proto @@ -286,7 +286,7 @@ syntax = "proto3"; message Campaign { string id = 1; - string super_campaign_id = 2; + string super_campaign_name = 2; uint32 campaign_number = 3; repeated Level levels = 4; } From 6182a6de5fecc51ccf7ffb0b333e3eaf39855576 Mon Sep 17 00:00:00 2001 From: lotuuu Date: Wed, 15 May 2024 15:39:42 -0300 Subject: [PATCH 09/10] Fix get_campaign --- apps/game_backend/lib/game_backend/campaigns.ex | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/game_backend/lib/game_backend/campaigns.ex b/apps/game_backend/lib/game_backend/campaigns.ex index 4e1c59da5..ab0516c88 100644 --- a/apps/game_backend/lib/game_backend/campaigns.ex +++ b/apps/game_backend/lib/game_backend/campaigns.ex @@ -26,7 +26,9 @@ defmodule GameBackend.Campaigns do Get a campaign by id. """ def get_campaign(campaign_id) do - case Repo.one(from(c in Campaign, where: c.id == ^campaign_id, preload: [levels: ^level_preload_query()])) do + case Repo.one( + from(c in Campaign, where: c.id == ^campaign_id, preload: [:super_campaign, levels: ^level_preload_query()]) + ) do nil -> {:error, :not_found} campaign -> {:ok, Map.put(campaign, :levels, Enum.sort_by(campaign.levels, & &1.level_number))} end From 1d7a1db4d1ea70f1a523a1dd8edd7e0c624cbda0 Mon Sep 17 00:00:00 2001 From: lotuuu Date: Wed, 15 May 2024 17:46:45 -0300 Subject: [PATCH 10/10] Update dungeon seeds so they make more sense --- priv/repo/seeds.exs | 61 +++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs index bae4c1cc2..2f391eb3e 100644 --- a/priv/repo/seeds.exs +++ b/priv/repo/seeds.exs @@ -164,13 +164,15 @@ main_campaign = %{ name: "Main Campaign" } -dungeon_campaign = %{ +dungeon_super_campaign = %{ game_id: champions_of_mirra_id, name: "Dungeon" } {_, main_campaign} = Campaigns.insert_super_campaign(main_campaign, returning: true) -{_, dungeon_campaign} = Campaigns.insert_super_campaign(dungeon_campaign, returning: true) + +{_, dungeon_super_campaign} = + Campaigns.insert_super_campaign(dungeon_super_campaign, returning: true) # Since insert_all doesn't accept assocs, we insert the levels first and then their units levels = @@ -296,29 +298,35 @@ _dungeon_settlement_levels = dungeon_settlement_level end) +dungeon_rules = + %{ + base_level: 5, + scaler: 1.05, + possible_factions: ["Araban", "Kaline", "Merliot", "Otobi"], + length: 200 + } + # Since insert_all doesn't accept assocs, we insert the levels first and then their units -dungeon_levels = - Enum.flat_map(Enum.with_index(rules, 1), fn {campaign_rules, campaign_index} -> - {_, campaign} = - Campaigns.insert_campaign( - %{ - game_id: champions_of_mirra_id, - super_campaign_id: dungeon_campaign.id, - campaign_number: campaign_index - }, - returning: true - ) +{:ok, dungeon_campaign} = + Campaigns.insert_campaign( + %{ + game_id: champions_of_mirra_id, + super_campaign_id: dungeon_super_campaign.id, + campaign_number: 1 + }, + returning: true + ) - Enum.map(1..campaign_rules.length, fn level_index -> - %{ - game_id: champions_of_mirra_id, - campaign_id: campaign.id, - level_number: level_index, - experience_reward: 100 * level_index, - inserted_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second), - updated_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) - } - end) +dungeon_levels = + Enum.map(1..dungeon_rules.length, fn level_index -> + %{ + game_id: champions_of_mirra_id, + campaign_id: dungeon_campaign.id, + level_number: level_index, + experience_reward: 100 * level_index, + inserted_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second), + updated_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) + } end) {_, levels_without_units} = @@ -327,12 +335,11 @@ dungeon_levels = units = Enum.flat_map(Enum.with_index(levels_without_units, 0), fn {level, level_index} -> campaign_number = Repo.get!(Campaign, level.campaign_id).campaign_number - campaign_rules = Enum.at(rules, campaign_number - 1) - base_level = campaign_rules.base_level - level_scaler = campaign_rules.scaler + base_level = dungeon_rules.base_level + level_scaler = dungeon_rules.scaler - possible_characters = Units.all_characters_from_factions(campaign_rules.possible_factions) + possible_characters = Units.all_characters_from_factions(dungeon_rules.possible_factions) agg_difficulty = (base_level * Math.pow(level_scaler, level_index)) |> round()