From cfd8eaaa88cfb81372b8f8e7bb7d9b8ba6a1b70a Mon Sep 17 00:00:00 2001 From: agustinesco Date: Mon, 12 Aug 2024 16:59:08 -0300 Subject: [PATCH 01/14] Add effect to consumable items --- apps/arena/lib/arena/configuration.ex | 23 +++ apps/arena/lib/arena/entities.ex | 2 +- apps/arena/lib/arena/game/player.ex | 7 +- apps/arena/priv/config.json | 90 ----------- .../lib/game_backend/curse_of_mirra/effect.ex | 87 +++++++++++ .../lib/game_backend/items/consumable_item.ex | 7 +- .../lib/game_backend/units/skills/mechanic.ex | 2 + ...5457_alter_tables_for_effect_migration.exs | 12 ++ priv/repo/seeds.exs | 141 ++++++++++++++++-- 9 files changed, 263 insertions(+), 108 deletions(-) create mode 100644 apps/game_backend/lib/game_backend/curse_of_mirra/effect.ex create mode 100644 apps/game_backend/priv/repo/migrations/20240812185457_alter_tables_for_effect_migration.exs diff --git a/apps/arena/lib/arena/configuration.ex b/apps/arena/lib/arena/configuration.ex index 0858aea4a..04ec9f9a2 100644 --- a/apps/arena/lib/arena/configuration.ex +++ b/apps/arena/lib/arena/configuration.ex @@ -35,6 +35,10 @@ defmodule Arena.Configuration do |> Map.update!(:characters, fn characters -> parse_characters_config(characters) end) + |> Map.update!(:items, fn items -> + parse_items_config(items) + end) + |> IO.inspect(limit: :infinity) end defp get_client_config() do @@ -59,6 +63,12 @@ defmodule Arena.Configuration do end) end + defp parse_items_config(items) do + Enum.map(items, fn item -> + %{item | effect: parse_effect(item.effect)} + end) + end + defp parse_skill_config(%{cooldown_mechanism: "stamina", stamina_cost: cost} = skill_config) when cost >= 0 do skill_config = parse_combo_config(skill_config) mechanics = parse_mechanics_config(skill_config.mechanics) @@ -209,6 +219,19 @@ defmodule Arena.Configuration do } end + defp parse_effect(effect) do + Map.update!(effect, :effect_mechanics, fn effect_mechanics -> + Enum.map(effect_mechanics, fn effect_mechanic -> + %{ + effect_mechanic + | decrease_by: maybe_to_float(effect_mechanic.decrease_by), + modifier: maybe_to_float(effect_mechanic.modifier), + force: maybe_to_float(effect_mechanic.force) + } + end) + end) + end + defp parse_position(%{x: x, y: y}) do %{x: maybe_to_float(x), y: maybe_to_float(y)} end diff --git a/apps/arena/lib/arena/entities.ex b/apps/arena/lib/arena/entities.ex index adaa207d6..b59eeaf08 100644 --- a/apps/arena/lib/arena/entities.ex +++ b/apps/arena/lib/arena/entities.ex @@ -204,7 +204,7 @@ defmodule Arena.Entities do is_moving: false, aditional_info: %{ name: config.name, - effects: config.effects, + effect: config.effect, mechanics: config.mechanics, pull_immunity: true } diff --git a/apps/arena/lib/arena/game/player.ex b/apps/arena/lib/arena/game/player.ex index 86aa5831f..1dcc7a788 100644 --- a/apps/arena/lib/arena/game/player.ex +++ b/apps/arena/lib/arena/game/player.ex @@ -354,17 +354,14 @@ defmodule Arena.Game.Player do player.aditional_info.inventory != nil end - def use_item(player, game_state, game_config) do + def use_item(player, game_state) do case player.aditional_info.inventory do nil -> game_state item -> game_state = - Enum.reduce(item.effects, game_state, fn effect_name, game_state_acc -> - effect = Enum.find(game_config.effects, fn %{name: name} -> name == effect_name end) - Effect.put_effect_to_entity(game_state_acc, player, player.id, effect) - end) + Effect.put_effect_to_entity(game_state, player, player.id, item.effect) |> put_in([:players, player.id, :aditional_info, :inventory], nil) Item.do_mechanics(game_state, player, item.mechanics) diff --git a/apps/arena/priv/config.json b/apps/arena/priv/config.json index 778da8b03..bc57a94e9 100644 --- a/apps/arena/priv/config.json +++ b/apps/arena/priv/config.json @@ -108,60 +108,6 @@ } } }, - { - "name": "golden_clock_effect", - "duration_ms": 9000, - "remove_on_action": false, - "one_time_application": true, - "allow_multiple_effects": true, - "effect_mechanics": { - "reduce_stamina_interval": { - "decrease_by": 0.5, - "execute_multiple_times": false, - "effect_delay_ms": 0 - }, - "refresh_stamina": { - "effect_delay_ms": 0, - "execute_multiple_times": false - }, - "reduce_cooldowns_duration": { - "multiplier": 0.5, - "execute_multiple_times": false, - "effect_delay_ms": 0 - }, - "refresh_cooldowns": { - "effect_delay_ms": 0, - "execute_multiple_times": false - } - } - }, - { - "name": "magic_boots_effect", - "duration_ms": 8000, - "remove_on_action": false, - "one_time_application": true, - "allow_multiple_effects": true, - "effect_mechanics": { - "speed_boost": { - "modifier": 0.5, - "effect_delay_ms": 0, - "execute_multiple_times": false - } - } - }, - { - "name": "mirra_blessing_effect", - "duration_ms": 7000, - "remove_on_action": false, - "one_time_application": true, - "allow_multiple_effects": true, - "effect_mechanics": { - "damage_immunity": { - "effect_delay_ms": 0, - "execute_multiple_times": false - } - } - }, { "name": "denial_of_service", "remove_on_action": false, @@ -175,35 +121,6 @@ } } }, - { - "name": "giant_effect", - "duration_ms": 9000, - "remove_on_action": false, - "one_time_application": true, - "allow_multiple_effects": true, - "effect_mechanics": { - "modify_radius": { - "modifier": 0.4, - "effect_delay_ms": 0, - "execute_multiple_times": false - }, - "damage_change": { - "modifier": 0.25, - "effect_delay_ms": 0, - "execute_multiple_times": true - }, - "speed_boost": { - "modifier": -0.25, - "effect_delay_ms": 0, - "execute_multiple_times": false - }, - "defense_change": { - "modifier": 0.4, - "effect_delay_ms": 0, - "execute_multiple_times": true - } - } - }, { "name": "whirlwind", "duration_ms": 5000, @@ -229,13 +146,6 @@ "execute_multiple_times": false } } - }, - { - "name": "polymorph_effect", - "duration_ms": 9000, - "remove_on_action": true, - "one_time_application": true, - "effect_mechanics": {} } ], "crates": [ diff --git a/apps/game_backend/lib/game_backend/curse_of_mirra/effect.ex b/apps/game_backend/lib/game_backend/curse_of_mirra/effect.ex new file mode 100644 index 000000000..58cf40dfd --- /dev/null +++ b/apps/game_backend/lib/game_backend/curse_of_mirra/effect.ex @@ -0,0 +1,87 @@ +defmodule GameBackend.CurseOfMirra.Effect do + @moduledoc """ + """ + use GameBackend.Schema + alias __MODULE__.EffectMechanic + import Ecto.Changeset + + @derive {Jason.Encoder, + only: [ + :duration_ms, + :remove_on_action, + :one_time_application, + :allow_multiple_effects, + :consume_projectile, + :effect_mechanics + ]} + embedded_schema do + field(:duration_ms, :integer) + field(:remove_on_action, :boolean) + field(:one_time_application, :boolean) + field(:allow_multiple_effects, :boolean) + field(:consume_projectile, :boolean) + embeds_many(:effect_mechanics, EffectMechanic) + end + + def changeset(position, attrs) do + position + |> cast(attrs, [ + :duration_ms, + :remove_on_action, + :one_time_application, + :allow_multiple_effects, + :consume_projectile + ]) + |> validate_required([ + :remove_on_action, + :one_time_application, + :allow_multiple_effects + ]) + |> cast_embed(:effect_mechanics) + end + + defmodule EffectMechanic do + @moduledoc """ + EffectMechanic embedded schema to be used by Effect + """ + use GameBackend.Schema + + @derive {Jason.Encoder, + only: [ + :name, + :decrease_by, + :modifier, + :execute_multiple_times, + :damage, + :effect_delay_ms, + :force + ]} + embedded_schema do + field(:name, :string) + field(:decrease_by, :decimal) + field(:modifier, :decimal) + field(:force, :decimal) + field(:execute_multiple_times, :boolean) + field(:damage, :integer) + field(:effect_delay_ms, :integer) + end + + def changeset(position, attrs) do + position + |> cast(attrs, [ + :name, + :decrease_by, + :modifier, + :execute_multiple_times, + :damage, + :effect_delay_ms, + :force + ]) + |> validate_required([ + :name, + :execute_multiple_times, + :effect_delay_ms + ]) + end + end +end diff --git a/apps/game_backend/lib/game_backend/items/consumable_item.ex b/apps/game_backend/lib/game_backend/items/consumable_item.ex index 6730c7dc7..756d33bf8 100644 --- a/apps/game_backend/lib/game_backend/items/consumable_item.ex +++ b/apps/game_backend/lib/game_backend/items/consumable_item.ex @@ -7,7 +7,7 @@ defmodule GameBackend.Items.ConsumableItem do alias GameBackend.Configuration.Version - @derive {Jason.Encoder, only: [:name, :radius, :effects, :mechanics]} + @derive {Jason.Encoder, only: [:name, :radius, :effects, :mechanics, :effect]} schema "consumable_items" do field(:active, :boolean, default: false) field(:name, :string) @@ -17,13 +17,16 @@ defmodule GameBackend.Items.ConsumableItem do belongs_to(:version, Version) + embeds_one(:effect, GameBackend.CurseOfMirra.Effect) + timestamps(type: :utc_datetime) end @doc false def changeset(consumable_item, attrs) do consumable_item - |> cast(attrs, [:name, :radius, :mechanics, :active, :effects, :version_id]) + |> cast(attrs, [:name, :radius, :mechanics, :active, :version_id]) |> validate_required([:name, :radius]) + |> cast_embed(:effect) end end diff --git a/apps/game_backend/lib/game_backend/units/skills/mechanic.ex b/apps/game_backend/lib/game_backend/units/skills/mechanic.ex index 92d5bdfa5..bf2192885 100644 --- a/apps/game_backend/lib/game_backend/units/skills/mechanic.ex +++ b/apps/game_backend/lib/game_backend/units/skills/mechanic.ex @@ -38,6 +38,7 @@ defmodule GameBackend.Units.Skills.Mechanic do belongs_to(:on_arrival_mechanic, __MODULE__) belongs_to(:parent_mechanic, __MODULE__, foreign_key: :parent_mechanic_id) embeds_one(:on_collide_effects, OnCollideEffects) + embeds_one(:effect, GameBackend.CurseOfMirra.Effect) end def mechanic_types(), do: [:apply_effects_to, :passive_effects] @@ -75,6 +76,7 @@ defmodule GameBackend.Units.Skills.Mechanic do |> cast_assoc(:on_arrival_mechanic, with: &assoc_changeset/2) |> cast_assoc(:on_explode_mechanics, with: &assoc_changeset/2) |> cast_embed(:on_collide_effects) + |> cast_embed(:effect) end defp assoc_changeset(struct, params) do diff --git a/apps/game_backend/priv/repo/migrations/20240812185457_alter_tables_for_effect_migration.exs b/apps/game_backend/priv/repo/migrations/20240812185457_alter_tables_for_effect_migration.exs new file mode 100644 index 000000000..411ce11e7 --- /dev/null +++ b/apps/game_backend/priv/repo/migrations/20240812185457_alter_tables_for_effect_migration.exs @@ -0,0 +1,12 @@ +defmodule GameBackend.Repo.Migrations.AlterTablesForEffectMigration do + use Ecto.Migration + + def change do + alter table(:consumable_items) do + add :effect, :map + end + alter table(:mechanics) do + add :effect, :map + end + end +end diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs index 1a58536e2..b76759dc1 100644 --- a/priv/repo/seeds.exs +++ b/priv/repo/seeds.exs @@ -310,6 +310,22 @@ quickslash_3 = %{ } ## Skills +denial_of_service = + %{ + name: "denial_of_service", + remove_on_action: false, + one_time_application: true, + allow_multiple_effects: true, + effect_mechanics: [ + %{ + name: "damage", + damage: 17, + effect_delay_ms: 220, + execute_multiple_times: true + } + ] + } + skills = [ %{ "name" => "muflus_crush", @@ -331,7 +347,6 @@ skills = [ "offset" => 400 } ], - "effects_to_apply" => [], "version_id" => version.id }, %{ @@ -394,7 +409,6 @@ skills = [ "can_pick_destination" => false, "block_movement" => true, "mechanics" => [multi_shoot], - "effects_to_apply" => [], "version_id" => version.id }, %{ @@ -439,9 +453,7 @@ skills = [ "range" => 1200.0, "shape" => "circle", "vertices" => [], - "effects_to_apply" => [ - "denial_of_service" - ] + "effect" => denial_of_service } ], "effects_to_apply" => [], @@ -823,60 +835,169 @@ game_configuration_1 = %{ {:ok, _game_configuration_1} = GameBackend.Configuration.create_game_configuration(game_configuration_1) +golden_clock_effect = %{ + name: "golden_clock_effect", + duration_ms: 9000, + remove_on_action: false, + one_time_application: true, + allow_multiple_effects: true, + effect_mechanics: [ + %{ + name: "reduce_stamina_interval", + modifier: 0.5, + effect_delay_ms: 0, + execute_multiple_times: false + }, + %{ + name: "refresh_stamina", + effect_delay_ms: 0, + execute_multiple_times: false + }, + %{ + name: "reduce_cooldowns_duration", + modifier: 0.5, + effect_delay_ms: 0, + execute_multiple_times: false + }, + %{ + name: "refresh_cooldowns", + effect_delay_ms: 0, + execute_multiple_times: false + } + ] +} + golden_clock_params = %{ active: true, name: "golden_clock", radius: 200.0, mechanics: %{}, - effects: ["golden_clock_effect"], + effect: golden_clock_effect, version_id: version.id } {:ok, _golden_clock} = GameBackend.Items.create_consumable_item(golden_clock_params) +magic_boots_effect = + %{ + name: "magic_boots_effect", + duration_ms: 8000, + remove_on_action: false, + one_time_application: true, + allow_multiple_effects: true, + effect_mechanics: [ + %{ + name: "speed_boost", + modifier: 0.5, + effect_delay_ms: 0, + execute_multiple_times: false + } + ] + } + magic_boots_params = %{ active: true, name: "magic_boots", radius: 200.0, mechanics: %{}, - effects: ["magic_boots_effect"], + effect: magic_boots_effect, version_id: version.id } {:ok, _magic_boots} = GameBackend.Items.create_consumable_item(magic_boots_params) +mirra_blessing_effect = + %{ + name: "mirra_blessing_effect", + duration_ms: 7000, + remove_on_action: false, + one_time_application: true, + allow_multiple_effects: true, + effect_mechanics: [ + %{ + name: "damage_immunity", + effect_delay_ms: 0, + execute_multiple_times: false + } + ] + } + mirra_blessing_params = %{ active: true, name: "mirra_blessing", radius: 200.0, mechanics: %{}, - effects: ["mirra_blessing_effect"], + effect: mirra_blessing_effect, version_id: version.id } {:ok, _mirra_blessing} = GameBackend.Items.create_consumable_item(mirra_blessing_params) +giant_effect = + %{ + name: "giant_effect", + duration_ms: 9000, + remove_on_action: false, + one_time_application: true, + allow_multiple_effects: true, + effect_mechanics: [ + %{ + name: "modify_radius", + modifier: 0.4, + effect_delay_ms: 0, + execute_multiple_times: false + }, + %{ + name: "damage_change", + modifier: 0.25, + effect_delay_ms: 0, + execute_multiple_times: true + }, + %{ + name: "speed_boost", + modifier: -0.25, + effect_delay_ms: 0, + execute_multiple_times: false + }, + %{ + name: "defense_change", + modifier: 0.4, + effect_delay_ms: 0, + execute_multiple_times: true + } + ] + } + giant_fruit_params = %{ active: true, name: "giant", radius: 200.0, mechanics: %{}, - effects: ["giant_effect"], + effect: giant_effect, version_id: version.id } {:ok, _giant_fruit} = GameBackend.Items.create_consumable_item(giant_fruit_params) +polymorph_effect = %{ + name: "polymorph_effect", + duration_ms: 9000, + remove_on_action: true, + one_time_application: true, + allow_multiple_effects: true, + effect_mechanics: [] +} + polymorph_params = %{ active: false, name: "polymorph", radius: 200.0, mechanics: %{}, - effects: ["polymorph_effect"] + effect: polymorph_effect } {:ok, _polymorph} = From 9ce33e4b0c46df351ba7c41bed1cac0f16276c8f Mon Sep 17 00:00:00 2001 From: agustinesco Date: Mon, 12 Aug 2024 18:04:52 -0300 Subject: [PATCH 02/14] Fix effect handling for items --- apps/arena/lib/arena/configuration.ex | 4 +- apps/arena/lib/arena/game/effect.ex | 79 +++++++++++-------- apps/arena/lib/arena/game/player.ex | 2 +- apps/arena/lib/arena/game_updater.ex | 2 +- .../lib/game_backend/curse_of_mirra/effect.ex | 13 +-- 5 files changed, 54 insertions(+), 46 deletions(-) diff --git a/apps/arena/lib/arena/configuration.ex b/apps/arena/lib/arena/configuration.ex index 04ec9f9a2..d033d78c1 100644 --- a/apps/arena/lib/arena/configuration.ex +++ b/apps/arena/lib/arena/configuration.ex @@ -38,7 +38,6 @@ defmodule Arena.Configuration do |> Map.update!(:items, fn items -> parse_items_config(items) end) - |> IO.inspect(limit: :infinity) end defp get_client_config() do @@ -224,8 +223,7 @@ defmodule Arena.Configuration do Enum.map(effect_mechanics, fn effect_mechanic -> %{ effect_mechanic - | decrease_by: maybe_to_float(effect_mechanic.decrease_by), - modifier: maybe_to_float(effect_mechanic.modifier), + | modifier: maybe_to_float(effect_mechanic.modifier), force: maybe_to_float(effect_mechanic.force) } end) diff --git a/apps/arena/lib/arena/game/effect.ex b/apps/arena/lib/arena/game/effect.ex index 1cc2539a0..2a54837c5 100644 --- a/apps/arena/lib/arena/game/effect.ex +++ b/apps/arena/lib/arena/game/effect.ex @@ -82,19 +82,19 @@ defmodule Arena.Game.Effect do end) end - defp apply_stat_modifier(player, {:damage_change, damage_change}) do + defp apply_stat_modifier(player, %{name: "damage_change"} = damage_change) do update_in(player, [:aditional_info, :bonus_damage], fn bonus_damage -> bonus_damage + damage_change.modifier end) end - defp apply_stat_modifier(player, {:defense_change, defense_change}) do + defp apply_stat_modifier(player, %{name: "defense_change"} = defense_change) do update_in(player, [:aditional_info, :bonus_defense], fn bonus_defense -> min(1.0, bonus_defense + defense_change.modifier) end) end - defp apply_stat_modifier(player, {:reduce_stamina_interval, reduce_stamina_interval}) do + defp apply_stat_modifier(player, %{name: "reduce_stamina_interval"} = reduce_stamina_interval) do stamina_speedup_by = - (player.aditional_info.stamina_interval * reduce_stamina_interval.decrease_by) + (player.aditional_info.stamina_interval * reduce_stamina_interval.modifier) |> round() new_stamina_interval = player.aditional_info.stamina_interval - stamina_speedup_by @@ -102,26 +102,26 @@ defmodule Arena.Game.Effect do put_in(player, [:aditional_info, :stamina_interval], new_stamina_interval) end - defp apply_stat_modifier(player, {:reduce_cooldowns_duration, reduce_cooldowns_duration}) do - put_in(player, [:aditional_info, :cooldown_multiplier], reduce_cooldowns_duration.multiplier) + defp apply_stat_modifier(player, %{name: "reduce_cooldowns_duration"} = reduce_cooldowns_duration) do + put_in(player, [:aditional_info, :cooldown_multiplier], reduce_cooldowns_duration.modifier) end - defp apply_stat_modifier(player, {:speed_boost, speed_boost}) do + defp apply_stat_modifier(player, %{name: "speed_boost"} = speed_boost) do case player.aditional_info.forced_movement do true -> player false -> %{player | speed: player.speed * (1 + speed_boost.modifier)} end end - defp apply_stat_modifier(player, {:modify_radius, modify_radius}) do + defp apply_stat_modifier(player, %{name: "modify_radius"} = modify_radius) do %{player | radius: player.radius * (1 + modify_radius.modifier)} end - defp apply_stat_modifier(player, {:damage_immunity, _damage_immunity}) do + defp apply_stat_modifier(player, %{name: "damage_immunity"} = _damage_immunity) do put_in(player, [:aditional_info, :damage_immunity], true) end - defp apply_stat_modifier(player, {:pull_immunity, _damage_immunity}) do + defp apply_stat_modifier(player, %{name: "pull_immunity"} = _damage_immunity) do put_in(player, [:aditional_info, :pull_immunity], true) end @@ -129,21 +129,6 @@ defmodule Arena.Game.Effect do player end - @doc """ - This function finds an updates the given attributes of an effect in a player list of effects - """ - def put_in_effect(player, effect, keys, value) do - update_in(player, [:aditional_info, :effects], fn effects -> - Enum.map(effects, fn current_effect -> - if current_effect.id == effect.id do - put_in(current_effect, keys, value) - else - current_effect - end - end) - end) - end - @doc """ Receives the game state. Gets the desired entities to apply effects to. @@ -168,24 +153,48 @@ defmodule Arena.Game.Effect do defp apply_effect_mechanic(entity, effect, game_state) do now = System.monotonic_time(:millisecond) - Enum.reduce(effect.effect_mechanics, entity, fn {mechanic_name, mechanic_params} = mechanic, entity -> + Enum.reduce(effect.effect_mechanics, entity, fn mechanic, entity -> execute_multiple_times? = - mechanic_params.execute_multiple_times or is_nil(Map.get(mechanic_params, :last_application_time)) + mechanic.execute_multiple_times or is_nil(Map.get(mechanic, :last_application_time)) enough_time_passed? = - is_nil(Map.get(mechanic_params, :last_application_time)) or - now - Map.get(mechanic_params, :last_application_time) >= mechanic_params.effect_delay_ms + is_nil(Map.get(mechanic, :last_application_time)) or + now - Map.get(mechanic, :last_application_time) >= mechanic.effect_delay_ms if execute_multiple_times? and enough_time_passed? do do_effect_mechanics(game_state, entity, effect, mechanic) - |> put_in_effect(effect, [:effect_mechanics, mechanic_name, :last_application_time], now) + |> update_effect_mechanic_last_application_time(effect, mechanic, now) else entity end end) end - defp do_effect_mechanics(game_state, entity, effect, {:pull, pull_params}) do + @doc """ + This function finds an updates the given attributes of an effect in a player list of effects + """ + def update_effect_mechanic_last_application_time(player, effect, mechanic, now) do + update_in(player, [:aditional_info, :effects], fn effects -> + Enum.map(effects, fn current_effect -> + if current_effect.id == effect.id do + effect + |> update_in([:effect_mechanics], fn effect_mechanics -> + Enum.map(effect_mechanics, fn effect_mechanic -> + if effect_mechanic.name == mechanic.name do + Map.put(effect_mechanic, :last_application_time, now) + else + effect_mechanic + end + end) + end) + else + current_effect + end + end) + end) + end + + defp do_effect_mechanics(game_state, entity, effect, %{name: "pull"} = pull_params) do case Map.get(game_state.pools, effect.owner_id) do nil -> entity @@ -215,7 +224,7 @@ defmodule Arena.Game.Effect do end end - defp do_effect_mechanics(game_state, entity, effect, {:damage, damage_params}) do + defp do_effect_mechanics(game_state, entity, effect, %{name: "damage"} = damage_params) do # TODO not all effects may come from pools entities, maybe we should update this when we implement other skills that # applies this effect Map.get(game_state.pools, effect.owner_id) @@ -234,7 +243,7 @@ defmodule Arena.Game.Effect do end end - defp do_effect_mechanics(game_state, entity, _effect, {:buff_pool, buff_attributes}) do + defp do_effect_mechanics(game_state, entity, _effect, %{name: "buff_pool"} = buff_attributes) do Map.get(game_state.pools, entity.id) |> case do nil -> @@ -254,11 +263,11 @@ defmodule Arena.Game.Effect do end end - defp do_effect_mechanics(_game_state, entity, _effect, {:refresh_stamina, _refresh_stamina}) do + defp do_effect_mechanics(_game_state, entity, _effect, %{name: "refresh_stamina"} = _refresh_stamina) do Entities.refresh_stamina(entity) end - defp do_effect_mechanics(_game_state, entity, _effect, {:refresh_cooldowns, _refresh_cooldowns}) do + defp do_effect_mechanics(_game_state, entity, _effect, %{name: "refresh_cooldowns"} = _refresh_cooldowns) do Entities.refresh_cooldowns(entity) end diff --git a/apps/arena/lib/arena/game/player.ex b/apps/arena/lib/arena/game/player.ex index 1dcc7a788..673cb3add 100644 --- a/apps/arena/lib/arena/game/player.ex +++ b/apps/arena/lib/arena/game/player.ex @@ -371,7 +371,7 @@ defmodule Arena.Game.Player do def invisible?(player) do get_in(player, [:aditional_info, :effects]) |> Enum.any?(fn effect -> - Enum.any?(effect.effect_mechanics, fn {mechanic, _} -> mechanic == :invisible end) + Enum.any?(effect.effect_mechanics, fn mechanic -> mechanic.name == "invisible" end) end) end diff --git a/apps/arena/lib/arena/game_updater.ex b/apps/arena/lib/arena/game_updater.ex index 94972c390..f9d3d313d 100644 --- a/apps/arena/lib/arena/game_updater.ex +++ b/apps/arena/lib/arena/game_updater.ex @@ -158,7 +158,7 @@ defmodule Arena.GameUpdater do def handle_cast({:use_item, player_id, _timestamp}, state) do game_state = get_in(state, [:game_state, :players, player_id]) - |> Player.use_item(state.game_state, state.game_config) + |> Player.use_item(state.game_state) {:noreply, %{state | game_state: game_state}} end diff --git a/apps/game_backend/lib/game_backend/curse_of_mirra/effect.ex b/apps/game_backend/lib/game_backend/curse_of_mirra/effect.ex index 58cf40dfd..55780a509 100644 --- a/apps/game_backend/lib/game_backend/curse_of_mirra/effect.ex +++ b/apps/game_backend/lib/game_backend/curse_of_mirra/effect.ex @@ -12,9 +12,11 @@ defmodule GameBackend.CurseOfMirra.Effect do :one_time_application, :allow_multiple_effects, :consume_projectile, - :effect_mechanics + :effect_mechanics, + :name ]} embedded_schema do + field(:name, :string) field(:duration_ms, :integer) field(:remove_on_action, :boolean) field(:one_time_application, :boolean) @@ -30,12 +32,14 @@ defmodule GameBackend.CurseOfMirra.Effect do :remove_on_action, :one_time_application, :allow_multiple_effects, - :consume_projectile + :consume_projectile, + :name ]) |> validate_required([ :remove_on_action, :one_time_application, - :allow_multiple_effects + :allow_multiple_effects, + :name ]) |> cast_embed(:effect_mechanics) end @@ -49,7 +53,6 @@ defmodule GameBackend.CurseOfMirra.Effect do @derive {Jason.Encoder, only: [ :name, - :decrease_by, :modifier, :execute_multiple_times, :damage, @@ -58,7 +61,6 @@ defmodule GameBackend.CurseOfMirra.Effect do ]} embedded_schema do field(:name, :string) - field(:decrease_by, :decimal) field(:modifier, :decimal) field(:force, :decimal) field(:execute_multiple_times, :boolean) @@ -70,7 +72,6 @@ defmodule GameBackend.CurseOfMirra.Effect do position |> cast(attrs, [ :name, - :decrease_by, :modifier, :execute_multiple_times, :damage, From 8d60b8eab2b4969f71d59d5478fb6bb3d7da989f Mon Sep 17 00:00:00 2001 From: agustinesco Date: Mon, 12 Aug 2024 18:22:49 -0300 Subject: [PATCH 03/14] Fix pool effects --- apps/arena/lib/arena/configuration.ex | 3 ++- apps/arena/lib/arena/entities.ex | 2 +- apps/arena/lib/arena/game_updater.ex | 13 ++++------ .../curse_of_mirra/map_configuration.ex | 9 +++---- priv/repo/seeds.exs | 24 ++++++++++++++----- 5 files changed, 31 insertions(+), 20 deletions(-) diff --git a/apps/arena/lib/arena/configuration.ex b/apps/arena/lib/arena/configuration.ex index d033d78c1..a4238753c 100644 --- a/apps/arena/lib/arena/configuration.ex +++ b/apps/arena/lib/arena/configuration.ex @@ -214,7 +214,8 @@ defmodule Arena.Configuration do pool | position: parse_position(pool.position), vertices: Enum.map(pool.vertices, &parse_position/1), - radius: maybe_to_float(pool.radius) + radius: maybe_to_float(pool.radius), + effect: parse_effect(pool.effect) } end diff --git a/apps/arena/lib/arena/entities.ex b/apps/arena/lib/arena/entities.ex index b59eeaf08..0724709f5 100644 --- a/apps/arena/lib/arena/entities.ex +++ b/apps/arena/lib/arena/entities.ex @@ -176,7 +176,7 @@ defmodule Arena.Entities do }, is_moving: false, aditional_info: %{ - effects_to_apply: pool_params.effects_to_apply, + effect_to_apply: pool_params.effect, owner_id: pool_params.owner_id, effects: [], stat_multiplier: 0, diff --git a/apps/arena/lib/arena/game_updater.ex b/apps/arena/lib/arena/game_updater.ex index f9d3d313d..f4644eb93 100644 --- a/apps/arena/lib/arena/game_updater.ex +++ b/apps/arena/lib/arena/game_updater.ex @@ -265,7 +265,7 @@ defmodule Arena.GameUpdater do |> explode_projectiles() # Pools |> add_pools_collisions() - |> handle_pools(state.game_config) + |> handle_pools() |> remove_expired_pools(now) # Crates |> handle_destroyed_crates() @@ -1627,13 +1627,13 @@ defmodule Arena.GameUpdater do end end - defp handle_pools(%{pools: pools, crates: crates, players: players} = game_state, game_config) do + defp handle_pools(%{pools: pools, crates: crates, players: players} = game_state) do entities = Map.merge(crates, players) Enum.reduce(pools, game_state, fn {_pool_id, pool}, game_state -> Enum.reduce(entities, game_state, fn {entity_id, entity}, acc -> if entity_id in pool.collides_with and pool.aditional_info.status == :READY do - add_pool_effects(acc, game_config, entity, pool) + add_pool_effects(acc, entity, pool) else Effect.remove_owner_effects(acc, entity_id, pool.id) end @@ -1641,14 +1641,11 @@ defmodule Arena.GameUpdater do end) end - defp add_pool_effects(game_state, game_config, entity, pool) do + defp add_pool_effects(game_state, entity, pool) do if entity.id == pool.aditional_info.owner_id do game_state else - Enum.reduce(pool.aditional_info.effects_to_apply, game_state, fn effect_name, game_state -> - effect = Enum.find(game_config.effects, fn effect -> effect.name == effect_name end) - Effect.put_effect_to_entity(game_state, entity, pool.id, effect) - end) + Effect.put_effect_to_entity(game_state, entity, pool.id, pool.aditional_info.effect_to_apply) end end diff --git a/apps/game_backend/lib/game_backend/curse_of_mirra/map_configuration.ex b/apps/game_backend/lib/game_backend/curse_of_mirra/map_configuration.ex index 7e0b7472d..58f3de567 100644 --- a/apps/game_backend/lib/game_backend/curse_of_mirra/map_configuration.ex +++ b/apps/game_backend/lib/game_backend/curse_of_mirra/map_configuration.ex @@ -88,22 +88,23 @@ defmodule GameBackend.CurseOfMirra.MapConfiguration do alias GameBackend.CurseOfMirra.MapConfiguration use GameBackend.Schema - @derive {Jason.Encoder, only: [:name, :position, :radius, :shape, :vertices, :effects_to_apply]} + @derive {Jason.Encoder, only: [:name, :position, :radius, :shape, :vertices, :effect]} embedded_schema do field(:name, :string) field(:radius, :decimal) field(:shape, Ecto.Enum, values: [:circle, :polygon]) - field(:effects_to_apply, {:array, :string}) + embeds_one(:effect, GameBackend.CurseOfMirra.Effect) embeds_one(:position, Position) embeds_many(:vertices, Position) end def changeset(position, attrs) do position - |> cast(attrs, [:name, :radius, :shape, :effects_to_apply]) + |> cast(attrs, [:name, :radius, :shape]) |> cast_embed(:position) + |> cast_embed(:effect) |> cast_embed(:vertices, drop_param: :vertices_drop, sort_param: :vertices_sort) - |> validate_required([:name, :position, :radius, :shape, :effects_to_apply]) + |> validate_required([:name, :position, :radius, :shape, :effect]) |> MapConfiguration.validate_shape() end end diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs index b76759dc1..f5b2ffc73 100644 --- a/priv/repo/seeds.exs +++ b/priv/repo/seeds.exs @@ -1003,6 +1003,22 @@ polymorph_params = %{ {:ok, _polymorph} = GameBackend.Items.create_consumable_item(polymorph_params) +slow_field_effect = %{ + name: "slow_field_effect", + duration_ms: 9000, + remove_on_action: true, + one_time_application: true, + allow_multiple_effects: true, + effect_mechanics: [ + %{ + name: "speed_boost", + modifier: -0.5, + effect_delay_ms: 0, + execute_multiple_times: false + } + ] +} + map_config = %{ name: "Araban", radius: 5520.0, @@ -2586,9 +2602,7 @@ map_config = %{ y: -1184.0 } ], - effects_to_apply: [ - "slow_field" - ] + effect: slow_field_effect }, %{ name: "sand pool north", @@ -2616,9 +2630,7 @@ map_config = %{ y: 2434.0 } ], - effects_to_apply: [ - "slow_field" - ] + effect: slow_field_effect } ], version_id: version.id From 1add79ffa0df6518488026f1eee4eee52c29397e Mon Sep 17 00:00:00 2001 From: agustinesco Date: Mon, 12 Aug 2024 19:10:55 -0300 Subject: [PATCH 04/14] Add effects for skills --- apps/arena/lib/arena/configuration.ex | 13 +- apps/arena/lib/arena/game/player.ex | 2 +- apps/arena/lib/arena/game/skill.ex | 10 +- apps/arena/lib/arena/game_updater.ex | 4 +- apps/arena/priv/config.json | 75 ------------ .../lib/game_backend/units/skills/mechanic.ex | 2 - .../lib/game_backend/units/skills/skill.ex | 4 +- ...5457_alter_tables_for_effect_migration.exs | 6 + priv/repo/seeds.exs | 113 ++++++++++++------ 9 files changed, 101 insertions(+), 128 deletions(-) diff --git a/apps/arena/lib/arena/configuration.ex b/apps/arena/lib/arena/configuration.ex index a4238753c..e0d483372 100644 --- a/apps/arena/lib/arena/configuration.ex +++ b/apps/arena/lib/arena/configuration.ex @@ -71,18 +71,18 @@ defmodule Arena.Configuration do defp parse_skill_config(%{cooldown_mechanism: "stamina", stamina_cost: cost} = skill_config) when cost >= 0 do skill_config = parse_combo_config(skill_config) mechanics = parse_mechanics_config(skill_config.mechanics) - %{skill_config | mechanics: mechanics} + %{skill_config | mechanics: mechanics, effect_to_apply: parse_effect(skill_config.effect_to_apply)} end defp parse_skill_config(%{cooldown_mechanism: "time", cooldown_ms: cooldown} = skill_config) when cooldown >= 0 do skill_config = parse_combo_config(skill_config) mechanics = parse_mechanics_config(skill_config.mechanics) - %{skill_config | mechanics: mechanics} + %{skill_config | mechanics: mechanics, effect_to_apply: parse_effect(skill_config.effect_to_apply)} end defp parse_skill_config(%{cooldown_mechanism: "mana", mana_cost: cost} = skill_config) when cost >= 0 do mechanics = parse_mechanics_config(skill_config.mechanics) - %{skill_config | mechanics: mechanics} + %{skill_config | mechanics: mechanics, effect_to_apply: parse_effect(skill_config.effect_to_apply)} end defp parse_skill_config(skill_config) do @@ -154,7 +154,8 @@ defmodule Arena.Configuration do range: maybe_to_float(mechanic.range), speed: maybe_to_float(mechanic.speed), on_arrival_mechanic: parse_mechanic_config(mechanic.on_arrival_mechanic), - on_explode_mechanics: parse_mechanics_config(mechanic.on_explode_mechanics) + on_explode_mechanics: parse_mechanics_config(mechanic.on_explode_mechanics), + effect: parse_effect(mechanic.effect) } end @@ -219,6 +220,10 @@ defmodule Arena.Configuration do } end + defp parse_effect(nil) do + nil + end + defp parse_effect(effect) do Map.update!(effect, :effect_mechanics, fn effect_mechanics -> Enum.map(effect_mechanics, fn effect_mechanic -> diff --git a/apps/arena/lib/arena/game/player.ex b/apps/arena/lib/arena/game/player.ex index 673cb3add..99a1c17fa 100644 --- a/apps/arena/lib/arena/game/player.ex +++ b/apps/arena/lib/arena/game/player.ex @@ -259,7 +259,7 @@ defmodule Arena.Game.Player do Process.send_after( self(), - {:delayed_effect_application, player.id, Map.get(skill, :effects_to_apply), skill.execution_duration_ms}, + {:delayed_effect_application, player.id, Map.get(skill, :effect_to_apply), skill.execution_duration_ms}, skill.activation_delay_ms ) diff --git a/apps/arena/lib/arena/game/skill.ex b/apps/arena/lib/arena/game/skill.ex index c3d5cf52f..db5f96934 100644 --- a/apps/arena/lib/arena/game/skill.ex +++ b/apps/arena/lib/arena/game/skill.ex @@ -2,7 +2,6 @@ defmodule Arena.Game.Skill do @moduledoc """ Module for handling skills """ - alias Arena.GameUpdater alias Arena.Game.Effect alias Arena.{Entities, Utils} alias Arena.Game.{Player, Crate} @@ -378,13 +377,8 @@ defmodule Arena.Game.Skill do %{game_state | players: players} end - def handle_skill_effects(game_state, player, effects, execution_duration_ms, game_config) do - effects_to_apply = - GameUpdater.get_effects_from_config(effects, game_config) - - Enum.reduce(effects_to_apply, game_state, fn effect, game_state -> - Effect.put_effect_to_entity(game_state, player, player.id, execution_duration_ms, effect) - end) + def handle_skill_effects(game_state, player, effect, execution_duration_ms) do + Effect.put_effect_to_entity(game_state, player, player.id, execution_duration_ms, effect) end defp calculate_angle_directions(amount, angle_between, base_direction) do diff --git a/apps/arena/lib/arena/game_updater.ex b/apps/arena/lib/arena/game_updater.ex index f4644eb93..be1dcd978 100644 --- a/apps/arena/lib/arena/game_updater.ex +++ b/apps/arena/lib/arena/game_updater.ex @@ -406,11 +406,11 @@ defmodule Arena.GameUpdater do {:noreply, state} end - def handle_info({:delayed_effect_application, player_id, effects_to_apply, execution_duration_ms}, state) do + def handle_info({:delayed_effect_application, player_id, effect_to_apply, execution_duration_ms}, state) do player = Map.get(state.game_state.players, player_id) game_state = - Skill.handle_skill_effects(state.game_state, player, effects_to_apply, execution_duration_ms, state.game_config) + Skill.handle_skill_effects(state.game_state, player, effect_to_apply, execution_duration_ms) {:noreply, %{state | game_state: game_state}} end diff --git a/apps/arena/priv/config.json b/apps/arena/priv/config.json index bc57a94e9..535657a06 100644 --- a/apps/arena/priv/config.json +++ b/apps/arena/priv/config.json @@ -57,42 +57,6 @@ } }, "effects": [ - { - "name": "invisible", - "duration_ms": 4000, - "remove_on_action": true, - "one_time_application": false, - "allow_multiple_effects": true, - "effect_mechanics": { - "invisible": { - "execute_multiple_times": true, - "effect_delay_ms": 0 - }, - "speed_boost": { - "modifier": 0.25, - "effect_delay_ms": 0, - "execute_multiple_times": false - } - } - }, - { - "name": "singularity", - "remove_on_action": false, - "one_time_application": true, - "allow_multiple_effects": true, - "effect_mechanics": { - "pull": { - "force": 15.0, - "effect_delay_ms": 0, - "execute_multiple_times": true - }, - "damage": { - "damage": 13, - "effect_delay_ms": 400, - "execute_multiple_times": true - } - } - }, { "name": "buff_singularity", "remove_on_action": false, @@ -107,45 +71,6 @@ "execute_multiple_times": false } } - }, - { - "name": "denial_of_service", - "remove_on_action": false, - "one_time_application": true, - "allow_multiple_effects": true, - "effect_mechanics": { - "damage": { - "damage": 17, - "effect_delay_ms": 220, - "execute_multiple_times": true - } - } - }, - { - "name": "whirlwind", - "duration_ms": 5000, - "remove_on_action": false, - "one_time_application": false, - "effect_mechanics": { - "defense_change": { - "modifier": 0.75, - "effect_delay_ms": 0, - "execute_multiple_times": false - } - } - }, - { - "name": "slow_field", - "remove_on_action": false, - "one_time_application": true, - "allow_multiple_effects": false, - "effect_mechanics": { - "speed_boost": { - "modifier": -0.50, - "effect_delay_ms": 0, - "execute_multiple_times": false - } - } } ], "crates": [ diff --git a/apps/game_backend/lib/game_backend/units/skills/mechanic.ex b/apps/game_backend/lib/game_backend/units/skills/mechanic.ex index bf2192885..3e9f31cce 100644 --- a/apps/game_backend/lib/game_backend/units/skills/mechanic.ex +++ b/apps/game_backend/lib/game_backend/units/skills/mechanic.ex @@ -12,7 +12,6 @@ defmodule GameBackend.Units.Skills.Mechanic do field(:angle_between, :decimal) field(:damage, :integer) field(:duration_ms, :integer) - field(:effects_to_apply, {:array, :string}) field(:interval_ms, :integer) field(:move_by, :decimal) field(:name, :string) @@ -56,7 +55,6 @@ defmodule GameBackend.Units.Skills.Mechanic do :angle_between, :damage, :duration_ms, - :effects_to_apply, :interval_ms, :move_by, :name, diff --git a/apps/game_backend/lib/game_backend/units/skills/skill.ex b/apps/game_backend/lib/game_backend/units/skills/skill.ex index 8f4075653..e0f2d4067 100644 --- a/apps/game_backend/lib/game_backend/units/skills/skill.ex +++ b/apps/game_backend/lib/game_backend/units/skills/skill.ex @@ -28,13 +28,13 @@ defmodule GameBackend.Units.Skills.Skill do field(:max_autoaim_range, :integer) field(:stamina_cost, :integer) field(:mana_cost, :integer) - field(:effects_to_apply, {:array, :string}) field(:type, Ecto.Enum, values: [:basic, :dash, :ultimate]) belongs_to(:buff, Buff) belongs_to(:next_skill, __MODULE__) has_many(:mechanics, Mechanic, on_replace: :delete) belongs_to(:version, Version) + embeds_one(:effect_to_apply, GameBackend.CurseOfMirra.Effect) timestamps() end @@ -64,7 +64,6 @@ defmodule GameBackend.Units.Skills.Skill do :max_autoaim_range, :stamina_cost, :mana_cost, - :effects_to_apply, :type, :version_id ]) @@ -73,6 +72,7 @@ defmodule GameBackend.Units.Skills.Skill do |> foreign_key_constraint(:characters, name: "characters_basic_skill_id_fkey") |> cooldown_mechanism_validation() |> validate_combo_fields() + |> cast_embed(:effect_to_apply) end defp cooldown_mechanism_validation(changeset) do diff --git a/apps/game_backend/priv/repo/migrations/20240812185457_alter_tables_for_effect_migration.exs b/apps/game_backend/priv/repo/migrations/20240812185457_alter_tables_for_effect_migration.exs index 411ce11e7..d558a5a1a 100644 --- a/apps/game_backend/priv/repo/migrations/20240812185457_alter_tables_for_effect_migration.exs +++ b/apps/game_backend/priv/repo/migrations/20240812185457_alter_tables_for_effect_migration.exs @@ -7,6 +7,12 @@ defmodule GameBackend.Repo.Migrations.AlterTablesForEffectMigration do end alter table(:mechanics) do add :effect, :map + remove :effects_to_apply + end + + alter table(:skills) do + add :effect_to_apply, :map + remove :effects_to_apply end end end diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs index f5b2ffc73..d174bb2d4 100644 --- a/priv/repo/seeds.exs +++ b/priv/repo/seeds.exs @@ -235,6 +235,82 @@ default_version_params = %{ {:ok, version} = GameBackend.Configuration.create_version(default_version_params) +singularity_effect = %{ + name: "singularity", + remove_on_action: false, + one_time_application: true, + allow_multiple_effects: true, + effect_mechanics: [ + %{ + name: "pull", + force: 15.0, + effect_delay_ms: 0, + execute_multiple_times: true + }, + %{ + name: "damage", + damage: 13, + effect_delay_ms: 400, + execute_multiple_times: true + } + ] +} + +denial_of_service = + %{ + name: "denial_of_service", + remove_on_action: false, + one_time_application: true, + allow_multiple_effects: true, + effect_mechanics: [ + %{ + name: "damage", + damage: 17, + effect_delay_ms: 220, + execute_multiple_times: true + } + ] + } + +invisible_effect = + %{ + name: "invisible", + duration_ms: 4000, + remove_on_action: true, + one_time_application: false, + allow_multiple_effects: true, + effect_mechanics: [ + %{ + name: "invisible", + execute_multiple_times: true, + effect_delay_ms: 0 + }, + %{ + name: "speed_boost", + modifier: 0.25, + effect_delay_ms: 0, + execute_multiple_times: false + } + ] + } + +whirlwind_effect = + %{ + name: "whirlwind", + duration_ms: 5000, + remove_on_action: false, + one_time_application: false, + allow_multiple_effects: true, + effect_mechanics: [ + %{ + name: "defense_change", + modifier: 0.75, + effect_delay_ms: 0, + execute_multiple_times: false + } + ] + } + ## Mechanics multi_shoot = %{ "type" => "multi_shoot", @@ -257,9 +333,7 @@ singularity = %{ "range" => 1200.0, "shape" => "circle", "vertices" => [], - "effects_to_apply" => [ - "singularity" - ] + "effect" => singularity_effect } simple_shoot = %{ @@ -310,21 +384,6 @@ quickslash_3 = %{ } ## Skills -denial_of_service = - %{ - name: "denial_of_service", - remove_on_action: false, - one_time_application: true, - allow_multiple_effects: true, - effect_mechanics: [ - %{ - name: "damage", - damage: 17, - effect_delay_ms: 220, - execute_multiple_times: true - } - ] - } skills = [ %{ @@ -456,7 +515,6 @@ skills = [ "effect" => denial_of_service } ], - "effects_to_apply" => [], "version_id" => version.id }, %{ @@ -481,7 +539,6 @@ skills = [ "offset" => 200 } ], - "effects_to_apply" => [], "version_id" => version.id }, %{ @@ -504,9 +561,7 @@ skills = [ "offset" => 0 } ], - "effects_to_apply" => [ - "invisible" - ] + "effect_to_apply" => invisible_effect }, %{ "name" => "uma_sneak", @@ -527,7 +582,6 @@ skills = [ "duration_ms" => 250 } ], - "effects_to_apply" => [], "version_id" => version.id }, %{ @@ -543,7 +597,6 @@ skills = [ "can_pick_destination" => true, "block_movement" => true, "mechanics" => [singularity], - "effects_to_apply" => [], "version_id" => version.id }, %{ @@ -567,7 +620,6 @@ skills = [ "duration_ms" => 150 } ], - "effects_to_apply" => [], "version_id" => version.id }, %{ @@ -583,7 +635,6 @@ skills = [ "can_pick_destination" => false, "block_movement" => true, "mechanics" => [simple_shoot], - "effects_to_apply" => [], "version_id" => version.id }, %{ @@ -601,7 +652,6 @@ skills = [ "can_pick_destination" => false, "block_movement" => true, "mechanics" => [quickslash_1], - "effects_to_apply" => [], "version_id" => version.id }, %{ @@ -619,7 +669,6 @@ skills = [ "can_pick_destination" => false, "block_movement" => true, "mechanics" => [quickslash_2], - "effects_to_apply" => [], "version_id" => version.id }, %{ @@ -637,7 +686,6 @@ skills = [ "can_pick_destination" => false, "block_movement" => true, "mechanics" => [quickslash_3], - "effects_to_apply" => [], "version_id" => version.id }, %{ @@ -662,9 +710,7 @@ skills = [ "offset" => 0 } ], - "effects_to_apply" => [ - "whirlwind" - ], + "effect_to_apply" => whirlwind_effect, "version_id" => version.id }, %{ @@ -688,7 +734,6 @@ skills = [ "on_arrival_mechanic" => %{} } ], - "effects_to_apply" => [], "version_id" => version.id } ] From 92917006414eb73552e237720ec7b140b6a10c16 Mon Sep 17 00:00:00 2001 From: agustinesco Date: Mon, 12 Aug 2024 19:28:47 -0300 Subject: [PATCH 05/14] Fix credo complain --- apps/arena/lib/arena/game/effect.ex | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/apps/arena/lib/arena/game/effect.ex b/apps/arena/lib/arena/game/effect.ex index 2a54837c5..9f4b34516 100644 --- a/apps/arena/lib/arena/game/effect.ex +++ b/apps/arena/lib/arena/game/effect.ex @@ -177,16 +177,7 @@ defmodule Arena.Game.Effect do update_in(player, [:aditional_info, :effects], fn effects -> Enum.map(effects, fn current_effect -> if current_effect.id == effect.id do - effect - |> update_in([:effect_mechanics], fn effect_mechanics -> - Enum.map(effect_mechanics, fn effect_mechanic -> - if effect_mechanic.name == mechanic.name do - Map.put(effect_mechanic, :last_application_time, now) - else - effect_mechanic - end - end) - end) + update_effect_mechanic_value_in_effect(effect, mechanic, :last_application_time, now) else current_effect end @@ -194,6 +185,19 @@ defmodule Arena.Game.Effect do end) end + defp update_effect_mechanic_value_in_effect(effect, mechanic, key, value) do + effect + |> update_in([:effect_mechanics], fn effect_mechanics -> + Enum.map(effect_mechanics, fn effect_mechanic -> + if effect_mechanic.name == mechanic.name do + Map.put(effect_mechanic, key, value) + else + effect_mechanic + end + end) + end) + end + defp do_effect_mechanics(game_state, entity, effect, %{name: "pull"} = pull_params) do case Map.get(game_state.pools, effect.owner_id) do nil -> From 10bfc7278adc57e697fa3deb6ee706e72ed545f0 Mon Sep 17 00:00:00 2001 From: agustinesco Date: Mon, 12 Aug 2024 20:06:53 -0300 Subject: [PATCH 06/14] Fix on collide effects --- apps/arena/lib/arena/configuration.ex | 12 ++++++- apps/arena/lib/arena/entities.ex | 2 +- apps/arena/lib/arena/game_updater.ex | 33 +++++-------------- apps/arena/priv/config.json | 17 ---------- .../lib/game_backend/curse_of_mirra/effect.ex | 10 ++++-- .../skills/mechanics/on_collide_effects.ex | 5 +-- priv/repo/seeds.exs | 22 +++++++++++-- 7 files changed, 51 insertions(+), 50 deletions(-) diff --git a/apps/arena/lib/arena/configuration.ex b/apps/arena/lib/arena/configuration.ex index e0d483372..f3e479b44 100644 --- a/apps/arena/lib/arena/configuration.ex +++ b/apps/arena/lib/arena/configuration.ex @@ -154,6 +154,7 @@ defmodule Arena.Configuration do range: maybe_to_float(mechanic.range), speed: maybe_to_float(mechanic.speed), on_arrival_mechanic: parse_mechanic_config(mechanic.on_arrival_mechanic), + on_collide_effects: parse_on_collide_effects_config(mechanic.on_collide_effects), on_explode_mechanics: parse_mechanics_config(mechanic.on_explode_mechanics), effect: parse_effect(mechanic.effect) } @@ -230,12 +231,21 @@ defmodule Arena.Configuration do %{ effect_mechanic | modifier: maybe_to_float(effect_mechanic.modifier), - force: maybe_to_float(effect_mechanic.force) + force: maybe_to_float(effect_mechanic.force), + stat_multiplier: maybe_to_float(effect_mechanic.stat_multiplier) } end) end) end + defp parse_on_collide_effects_config(nil) do + nil + end + + defp parse_on_collide_effects_config(on_collide_effect) do + %{on_collide_effect | effect: parse_effect(on_collide_effect.effect)} + end + defp parse_position(%{x: x, y: y}) do %{x: maybe_to_float(x), y: maybe_to_float(y)} end diff --git a/apps/arena/lib/arena/entities.ex b/apps/arena/lib/arena/entities.ex index 0724709f5..87a1ff08d 100644 --- a/apps/arena/lib/arena/entities.ex +++ b/apps/arena/lib/arena/entities.ex @@ -98,7 +98,7 @@ defmodule Arena.Entities do remove_on_collision: config_params.remove_on_collision, on_explode_mechanics: Map.get(config_params, :on_explode_mechanics), pull_immunity: true, - on_collide_effects: Map.get(config_params, :on_collide_effects) + on_collide_effect: Map.get(config_params, :on_collide_effects) }, collides_with: [] } diff --git a/apps/arena/lib/arena/game_updater.ex b/apps/arena/lib/arena/game_updater.ex index be1dcd978..d42182143 100644 --- a/apps/arena/lib/arena/game_updater.ex +++ b/apps/arena/lib/arena/game_updater.ex @@ -254,7 +254,7 @@ defmodule Arena.GameUpdater do |> recover_mana() |> resolve_players_collisions_with_power_ups() |> resolve_players_collisions_with_items() - |> resolve_projectiles_effects_on_collisions(state.game_config) + |> resolve_projectiles_effects_on_collisions() |> apply_zone_damage_to_players(state.game_config.game) |> update_visible_players(state.game_config) |> update_bounties_states(state) @@ -1233,28 +1233,24 @@ defmodule Arena.GameUpdater do obstacles: obstacles, pools: pools, crates: crates - } = game_state, - game_config + } = game_state ) do Enum.reduce(projectiles, game_state, fn {_projectile_id, projectile}, game_state -> - case get_in(projectile, [:aditional_info, :on_collide_effects]) do + case get_in(projectile, [:aditional_info, :on_collide_effect]) do nil -> game_state - on_collide_effects -> + on_collide_effect -> entities_map = Map.merge(pools, obstacles) |> Map.merge(players) |> Map.merge(projectiles) |> Map.merge(crates) - effects_to_apply = - get_effects_from_config(on_collide_effects.effects, game_config) - entities_map |> Map.take(projectile.collides_with) |> get_entities_to_apply(projectile) - |> apply_effect_to_entities(effects_to_apply, game_state, projectile) + |> apply_effect_to_entities(on_collide_effect.effect, game_state, projectile) end end) end @@ -1739,22 +1735,19 @@ defmodule Arena.GameUpdater do projectile.aditional_info.owner_id == entity.aditional_info.owner_id apply_to_entity_type? = - Atom.to_string(entity.category) in projectile.aditional_info.on_collide_effects.apply_effect_to_entity_type + Atom.to_string(entity.category) in projectile.aditional_info.on_collide_effect.apply_effect_to_entity_type apply_to_entity_type? and entity_owned_or_player? end) end - defp apply_effect_to_entities(entities, effects, game_state, projectile) do + defp apply_effect_to_entities(entities, effect, game_state, projectile) do Enum.reduce(entities, game_state, fn {_entity_id, entity}, game_state -> game_state = - Enum.reduce(effects, game_state, fn effect, game_state -> - Effect.put_effect_to_entity(game_state, entity, projectile.id, effect) - end) + Effect.put_effect_to_entity(game_state, entity, projectile.id, effect) remove_projectile_on_collision? = - Enum.any?(effects, fn effect -> effect.consume_projectile end) or - projectile.aditional_info.status == :CONSUMED + effect.consume_projectile or projectile.aditional_info.status == :CONSUMED if remove_projectile_on_collision? do consumed_projectile = put_in(projectile, [:aditional_info, :status], :CONSUMED) @@ -1794,14 +1787,6 @@ defmodule Arena.GameUpdater do defp get_entity_path(%{category: :trap}), do: :traps defp get_entity_path(%{category: :crate}), do: :crates - def get_effects_from_config([], _game_config), do: [] - - def get_effects_from_config(effect_list, game_config) do - Enum.map(effect_list, fn effect_name -> - Enum.find(game_config.effects, fn effect -> effect.name == effect_name end) - end) - end - defp put_player_position(%{positions: positions} = game_state, player_id) do next_position = Application.get_env(:arena, :players_needed_in_match) - Enum.count(positions) diff --git a/apps/arena/priv/config.json b/apps/arena/priv/config.json index 535657a06..c2a90a580 100644 --- a/apps/arena/priv/config.json +++ b/apps/arena/priv/config.json @@ -56,23 +56,6 @@ "activation_delay_ms": 500 } }, - "effects": [ - { - "name": "buff_singularity", - "remove_on_action": false, - "one_time_application": true, - "consume_projectile": true, - "allow_multiple_effects": true, - "effect_mechanics": { - "buff_pool": { - "stat_multiplier": 0.1, - "additive_duration_add_ms": 1000, - "effect_delay_ms": 0, - "execute_multiple_times": false - } - } - } - ], "crates": [ { "position": { diff --git a/apps/game_backend/lib/game_backend/curse_of_mirra/effect.ex b/apps/game_backend/lib/game_backend/curse_of_mirra/effect.ex index 55780a509..46a8c70e3 100644 --- a/apps/game_backend/lib/game_backend/curse_of_mirra/effect.ex +++ b/apps/game_backend/lib/game_backend/curse_of_mirra/effect.ex @@ -57,7 +57,9 @@ defmodule GameBackend.CurseOfMirra.Effect do :execute_multiple_times, :damage, :effect_delay_ms, - :force + :force, + :additive_duration_add_ms, + :stat_multiplier ]} embedded_schema do field(:name, :string) @@ -66,6 +68,8 @@ defmodule GameBackend.CurseOfMirra.Effect do field(:execute_multiple_times, :boolean) field(:damage, :integer) field(:effect_delay_ms, :integer) + field(:additive_duration_add_ms, :integer) + field(:stat_multiplier, :decimal) end def changeset(position, attrs) do @@ -76,7 +80,9 @@ defmodule GameBackend.CurseOfMirra.Effect do :execute_multiple_times, :damage, :effect_delay_ms, - :force + :force, + :additive_duration_add_ms, + :stat_multiplier ]) |> validate_required([ :name, diff --git a/apps/game_backend/lib/game_backend/units/skills/mechanics/on_collide_effects.ex b/apps/game_backend/lib/game_backend/units/skills/mechanics/on_collide_effects.ex index 7e7979cc6..c655520ef 100644 --- a/apps/game_backend/lib/game_backend/units/skills/mechanics/on_collide_effects.ex +++ b/apps/game_backend/lib/game_backend/units/skills/mechanics/on_collide_effects.ex @@ -10,12 +10,13 @@ defmodule GameBackend.Units.Skills.Mechanics.OnCollideEffects do @primary_key false embedded_schema do field(:apply_effect_to_entity_type, {:array, :string}) - field(:effects, {:array, :string}) + embeds_one(:effect, GameBackend.CurseOfMirra.Effect) end @doc false def changeset(targeting_strategy, attrs \\ %{}) do targeting_strategy - |> cast(attrs, [:apply_effect_to_entity_type, :effects]) + |> cast(attrs, [:apply_effect_to_entity_type]) + |> cast_embed(:effect) end end diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs index d174bb2d4..5bf975402 100644 --- a/priv/repo/seeds.exs +++ b/priv/repo/seeds.exs @@ -311,6 +311,24 @@ whirlwind_effect = ] } +buff_singularity_effect = + %{ + name: "buff_singularity", + remove_on_action: false, + one_time_application: true, + consume_projectile: true, + allow_multiple_effects: true, + effect_mechanics: [ + %{ + name: "buff_pool", + stat_multiplier: 0.1, + additive_duration_add_ms: 1000, + effect_delay_ms: 0, + execute_multiple_times: false + } + ] + } + ## Mechanics multi_shoot = %{ "type" => "multi_shoot", @@ -356,9 +374,7 @@ simple_shoot = %{ "apply_effect_to_entity_type" => [ "pool" ], - "effects" => [ - "buff_singularity" - ] + "effect" => buff_singularity_effect } } From e63f4a6768016e13ccd72512c53908734b99f6e9 Mon Sep 17 00:00:00 2001 From: agustinesco Date: Tue, 13 Aug 2024 12:47:05 -0300 Subject: [PATCH 07/14] Add effect show and editing to configurator app --- apps/configurator/lib/configurator_web.ex | 1 + .../components/custom_components.ex | 89 +++++++++++++++++++ .../custom_components/effect_form.html.heex | 1 + .../consumable_item_html/show.html.heex | 5 +- .../controllers/skill_html/index.html.heex | 1 + .../skill_html/mechanic_show.html.heex | 1 - .../nested_mechanic_inputs.html.heex | 10 +-- .../controllers/skill_html/show.html.heex | 2 + .../skill_html/skill_form.html.heex | 3 + .../skill_mechanic_inputs.html.heex | 10 +-- .../live/consumable_items/form.html.heex | 9 +- .../lib/game_backend/curse_of_mirra/effect.ex | 20 ++++- 12 files changed, 126 insertions(+), 26 deletions(-) create mode 100644 apps/configurator/lib/configurator_web/components/custom_components.ex create mode 100644 apps/configurator/lib/configurator_web/components/custom_components/effect_form.html.heex diff --git a/apps/configurator/lib/configurator_web.ex b/apps/configurator/lib/configurator_web.ex index e823dadc1..e3624a477 100644 --- a/apps/configurator/lib/configurator_web.ex +++ b/apps/configurator/lib/configurator_web.ex @@ -84,6 +84,7 @@ defmodule ConfiguratorWeb do import Phoenix.HTML # Core UI components and translation import ConfiguratorWeb.CoreComponents + import ConfiguratorWeb.CustomComponents # Shortcut for generating JS commands alias Phoenix.LiveView.JS diff --git a/apps/configurator/lib/configurator_web/components/custom_components.ex b/apps/configurator/lib/configurator_web/components/custom_components.ex new file mode 100644 index 000000000..ba27e8c72 --- /dev/null +++ b/apps/configurator/lib/configurator_web/components/custom_components.ex @@ -0,0 +1,89 @@ +defmodule ConfiguratorWeb.CustomComponents do + import ConfiguratorWeb.CoreComponents + use Phoenix.Component + + def effect_show(%{effect: nil} = assigns) do + ~H""" + <.button type="button" phx-click={show_modal("no-effect")}>Show effect + <.modal id="no-effect"> +

No Effect

+ + """ + end + + def effect_show(assigns) do + ~H""" + <.button type="button" phx-click={show_modal("effect-show-#{@effect.id}")}>Show effect + <.modal id={"effect-show-#{@effect.id}"}> + <.list> + <:item title="Name"><%= @effect.name %> + <:item title="Duration ms"><%= @effect.duration_ms %> + <:item title="Remove on action"><%= @effect.remove_on_action %> + <:item title="Apply effect once"><%= @effect.one_time_application %> + <:item title="Allow more that one effect instance"><%= @effect.allow_multiple_effects %> + <:item title="Consume projectile"><%= @effect.consume_projectile %> + + <%= for effect_mechanic <- @effect.effect_mechanics do %> +
+
+ <.list> + <:item title="Name"><%= effect_mechanic.name %> + <:item title="Modifier"><%= effect_mechanic.modifier %> + <:item title="Force"><%= effect_mechanic.force %> + <:item title="Execute multiple times"><%= effect_mechanic.execute_multiple_times %> + <:item title="Damage"><%= effect_mechanic.damage %> + <:item title="Effect delay ms"><%= effect_mechanic.effect_delay_ms %> + <:item title="Additive duration add ms"><%= effect_mechanic.additive_duration_add_ms %> + <:item title="Stat multiplier"><%= effect_mechanic.stat_multiplier %> + +
+
+ <% end %> + + """ + end + + attr :form, :map, required: true + attr :field, :atom, required: true + + def effect_form(assigns) do + ~H""" + <.button type="button" phx-click={show_modal("effect-form")}>Edit effect + <.modal id="effect-form"> + <.inputs_for :let={effect_f} field={@form[@field]}> + <.input field={effect_f[:name]} type="text" label="Name" /> + <.input field={effect_f[:duration_ms]} type="number" label="Effect duration" /> + <.input field={effect_f[:remove_on_action]} type="checkbox" label="Remove effect on action" /> + <.input field={effect_f[:one_time_application]} type="checkbox" label="Apply effect once" /> + <.input field={effect_f[:allow_multiple_effects]} type="checkbox" label="Allow more that one effect instance" /> + <.input field={effect_f[:consume_projectile]} type="checkbox" label="Consume projectile" /> + <.inputs_for :let={mechanics_form} field={effect_f[:effect_mechanics]}> +
+
+ <.input + field={mechanics_form[:name]} + type="select" + label="Effect mechanic name" + prompt="-- Choose a value --" + options={Ecto.Enum.values(GameBackend.CurseOfMirra.Effect.EffectMechanic, :name)} + /> + <.input field={mechanics_form[:modifier]} type="number" label="Modifier" step="any" /> + <.input field={mechanics_form[:force]} type="number" label="Force" step="any" /> + <.input field={effect_f[:execute_multiple_times]} type="checkbox" label="Execute mechanic multiple times" /> + <.input field={mechanics_form[:damage]} type="number" label="Damage amount" /> + <.input field={mechanics_form[:effect_delay_ms]} type="number" label="Mechanich delay" /> + <.input field={mechanics_form[:additive_duration_add_ms]} type="number" label="Additive duration to add ms" /> + <.input + field={mechanics_form[:stat_multiplier]} + type="number" + label="Stat multiplier" + step="Start multiplier" + /> +
+
+ + + + """ + end +end diff --git a/apps/configurator/lib/configurator_web/components/custom_components/effect_form.html.heex b/apps/configurator/lib/configurator_web/components/custom_components/effect_form.html.heex new file mode 100644 index 000000000..e1fb92818 --- /dev/null +++ b/apps/configurator/lib/configurator_web/components/custom_components/effect_form.html.heex @@ -0,0 +1 @@ +<.simple_form :let={f} for={@changeset} action={@action}> diff --git a/apps/configurator/lib/configurator_web/controllers/consumable_item_html/show.html.heex b/apps/configurator/lib/configurator_web/controllers/consumable_item_html/show.html.heex index 8de92a8c8..5e171f89a 100644 --- a/apps/configurator/lib/configurator_web/controllers/consumable_item_html/show.html.heex +++ b/apps/configurator/lib/configurator_web/controllers/consumable_item_html/show.html.heex @@ -5,6 +5,7 @@ <.link href={~p"/consumable_items/#{@consumable_item}/edit"}> <.button>Edit Consumable item + <.effect_show effect={@consumable_item.effect} /> @@ -21,10 +22,6 @@
Radius
<%= @consumable_item.radius %>
-
-
Effects
-
<%= @consumable_item.effects %>
-
<.back navigate={~p"/consumable_items"}>Back to Consumable Items diff --git a/apps/configurator/lib/configurator_web/controllers/skill_html/index.html.heex b/apps/configurator/lib/configurator_web/controllers/skill_html/index.html.heex index d8dd38823..8277231e4 100644 --- a/apps/configurator/lib/configurator_web/controllers/skill_html/index.html.heex +++ b/apps/configurator/lib/configurator_web/controllers/skill_html/index.html.heex @@ -29,6 +29,7 @@ <%= for mechanic <- skill.mechanics do %> <.mechanic_show mechanic={mechanic} /> + <.effect_show effect={mechanic.effect} /> <%= if not is_nil(mechanic.on_arrival_mechanic) do %> <.button type="button" phx-click={show_modal("on-arrival-mechanic-modal")}>Show on arrival mechanic diff --git a/apps/configurator/lib/configurator_web/controllers/skill_html/mechanic_show.html.heex b/apps/configurator/lib/configurator_web/controllers/skill_html/mechanic_show.html.heex index 7b2705cf1..af5b99a41 100644 --- a/apps/configurator/lib/configurator_web/controllers/skill_html/mechanic_show.html.heex +++ b/apps/configurator/lib/configurator_web/controllers/skill_html/mechanic_show.html.heex @@ -12,7 +12,6 @@ <:item title="Range"><%= @mechanic.range %> <:item title="Remove on collision"><%= @mechanic.remove_on_collision %> <:item title="Speed"><%= @mechanic.speed %> - <:item title="Effects to apply"><%= @mechanic.effects_to_apply %> <:item title="Shape of entity"><%= @mechanic.shape %> <:item title="vertices"><%= Jason.encode!(@mechanic.vertices) %> diff --git a/apps/configurator/lib/configurator_web/controllers/skill_html/nested_mechanic_inputs.html.heex b/apps/configurator/lib/configurator_web/controllers/skill_html/nested_mechanic_inputs.html.heex index bd6f1a431..cdf5325ed 100644 --- a/apps/configurator/lib/configurator_web/controllers/skill_html/nested_mechanic_inputs.html.heex +++ b/apps/configurator/lib/configurator_web/controllers/skill_html/nested_mechanic_inputs.html.heex @@ -19,11 +19,7 @@ <.input field={fp[:range]} type="number" label="Range" /> <.input field={fp[:remove_on_collision]} type="checkbox" label="Remove on collision" /> <.input field={fp[:speed]} type="number" label="speed" /> - <.input - field={fp[:effects_to_apply]} - type="select" - label="Effects to apply" - multiple - options={["singularity", "denial_of_service", "invisible"]} - /> + <%= if fp.data.effect do %> + <.effect_form form={fp} field={:effect} /> + <% end %> diff --git a/apps/configurator/lib/configurator_web/controllers/skill_html/show.html.heex b/apps/configurator/lib/configurator_web/controllers/skill_html/show.html.heex index 83afc6587..6cbe8715d 100644 --- a/apps/configurator/lib/configurator_web/controllers/skill_html/show.html.heex +++ b/apps/configurator/lib/configurator_web/controllers/skill_html/show.html.heex @@ -5,6 +5,7 @@ <.link href={~p"/skills/#{@skill}/edit"}> <.button>Edit skill + <.effect_show effect={@skill.effect_to_apply} /> @@ -31,6 +32,7 @@ <%= for mechanic <- @skill.mechanics do %> <.mechanic_show mechanic={mechanic} /> + <.effect_show effect={mechanic.effect} /> <.button type="button" phx-click={show_modal("on-arrival-mechanic-modal")}>Show on arrival mechanic <.modal id="on-arrival-mechanic-modal"> diff --git a/apps/configurator/lib/configurator_web/controllers/skill_html/skill_form.html.heex b/apps/configurator/lib/configurator_web/controllers/skill_html/skill_form.html.heex index b06d9fa4b..9b4c1f498 100644 --- a/apps/configurator/lib/configurator_web/controllers/skill_html/skill_form.html.heex +++ b/apps/configurator/lib/configurator_web/controllers/skill_html/skill_form.html.heex @@ -36,6 +36,9 @@ <.input field={f[:mana_cost]} type="number" label="Mana cost" /> <.skill_mechanic_inputs skill_form={f} /> + <%= if f.data.effect_to_apply do %> + <.effect_form form={f} field={:effect_to_apply} /> + <% end %> <:actions> <.button>Save Skill diff --git a/apps/configurator/lib/configurator_web/controllers/skill_html/skill_mechanic_inputs.html.heex b/apps/configurator/lib/configurator_web/controllers/skill_html/skill_mechanic_inputs.html.heex index da2a8d6c6..373609007 100644 --- a/apps/configurator/lib/configurator_web/controllers/skill_html/skill_mechanic_inputs.html.heex +++ b/apps/configurator/lib/configurator_web/controllers/skill_html/skill_mechanic_inputs.html.heex @@ -25,13 +25,9 @@ <.input field={fp[:range]} type="number" label="Range" /> <.input field={fp[:remove_on_collision]} type="checkbox" label="Remove on collision" /> <.input field={fp[:speed]} type="number" label="speed" /> - <.input - field={fp[:effects_to_apply]} - type="select" - label="Effects to apply" - multiple - options={["singularity", "denial_of_service", "invisible"]} - /> + <%= if fp.data.effect do %> + <.effect_form form={fp} field={:effect} /> + <% end %> <.input field={fp[:shape]} type="select" label="Shape of entity to spawn" options={["circle", "polygon"]} /> <.input field={fp[:vertices]} type="text" label="Vertices" value={Jason.encode!(fp.data.vertices)} /> diff --git a/apps/configurator/lib/configurator_web/live/consumable_items/form.html.heex b/apps/configurator/lib/configurator_web/live/consumable_items/form.html.heex index f93282144..3b98e92ba 100644 --- a/apps/configurator/lib/configurator_web/live/consumable_items/form.html.heex +++ b/apps/configurator/lib/configurator_web/live/consumable_items/form.html.heex @@ -12,12 +12,9 @@ <.input field={f[:name]} type="text" label="Name" /> <.input field={f[:radius]} type="number" label="Radius" step="any" /> <.input field={f[:active]} type="checkbox" label="Active" /> - <.input - field={f[:effects]} - type="select" - multiple - options={["golden_clock_effect", "magic_boots_effect", "mirra_blessing_effect", "giant_effect", "polymorph_effect"]} - /> + <%= if @consumable_item.effect do %> + <.effect_form form={f} field={:effect} /> + <% end %> <:actions> <.button>Save Consumable item diff --git a/apps/game_backend/lib/game_backend/curse_of_mirra/effect.ex b/apps/game_backend/lib/game_backend/curse_of_mirra/effect.ex index 46a8c70e3..151cc58ad 100644 --- a/apps/game_backend/lib/game_backend/curse_of_mirra/effect.ex +++ b/apps/game_backend/lib/game_backend/curse_of_mirra/effect.ex @@ -62,7 +62,25 @@ defmodule GameBackend.CurseOfMirra.Effect do :stat_multiplier ]} embedded_schema do - field(:name, :string) + field(:name, Ecto.Enum, + values: [ + :damage_change, + :defense_change, + :reduce_stamina_interval, + :reduce_cooldowns_duration, + :speed_boost, + :modify_radius, + :damage_immunity, + :pull_immunity, + :pull, + :damage, + :buff_pool, + :refresh_stamina, + :refresh_cooldowns, + :invisible + ] + ) + field(:modifier, :decimal) field(:force, :decimal) field(:execute_multiple_times, :boolean) From 2075b9a8a1c3de855863c7da2125c4498fd4753d Mon Sep 17 00:00:00 2001 From: agustinesco Date: Tue, 13 Aug 2024 12:55:51 -0300 Subject: [PATCH 08/14] Add module doc to custom components --- .../lib/configurator_web/components/custom_components.ex | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/configurator/lib/configurator_web/components/custom_components.ex b/apps/configurator/lib/configurator_web/components/custom_components.ex index ba27e8c72..97a61f160 100644 --- a/apps/configurator/lib/configurator_web/components/custom_components.ex +++ b/apps/configurator/lib/configurator_web/components/custom_components.ex @@ -1,4 +1,8 @@ defmodule ConfiguratorWeb.CustomComponents do + @moduledoc """ + Custom components to render shared templates + """ + import ConfiguratorWeb.CoreComponents use Phoenix.Component From 869be30428d5c3524afc7ea68d6552eb5fcd9c32 Mon Sep 17 00:00:00 2001 From: agustinesco Date: Tue, 10 Sep 2024 14:14:38 -0300 Subject: [PATCH 09/14] Remove unused function --- apps/arena/lib/arena/configuration.ex | 17 ++++++----------- .../lib/game_backend/items/consumable_item.ex | 2 +- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/apps/arena/lib/arena/configuration.ex b/apps/arena/lib/arena/configuration.ex index 48cc769a6..c96c728b4 100644 --- a/apps/arena/lib/arena/configuration.ex +++ b/apps/arena/lib/arena/configuration.ex @@ -71,7 +71,12 @@ defmodule Arena.Configuration do defp parse_items_config(items) do Enum.map(items, fn item -> - %{item | effect: parse_effect(item.effect)} + %{ + item + | effect: parse_effect(item.effect), + radius: maybe_to_float(item.radius), + mechanics: parse_mechanics_config(item.mechanics) + } end) end @@ -217,16 +222,6 @@ defmodule Arena.Configuration do %{mechanics | polygon_hit: %{polygon_hit | vertices: Enum.map(polygon_hit.vertices, &parse_position/1)}} end - defp parse_items_config(items) do - Enum.map(items, fn item -> - %{ - item - | radius: maybe_to_float(item.radius), - mechanics: parse_mechanics_config(item.mechanics) - } - end) - end - defp parse_effect(nil) do nil end diff --git a/apps/game_backend/lib/game_backend/items/consumable_item.ex b/apps/game_backend/lib/game_backend/items/consumable_item.ex index fe6e5665a..ffd899d84 100644 --- a/apps/game_backend/lib/game_backend/items/consumable_item.ex +++ b/apps/game_backend/lib/game_backend/items/consumable_item.ex @@ -27,7 +27,7 @@ defmodule GameBackend.Items.ConsumableItem do @doc false def changeset(consumable_item, attrs) do consumable_item - |> cast(attrs, [:name, :radius, :mechanics, :active, :version_id]) + |> cast(attrs, [:name, :radius, :active, :version_id]) |> validate_required([:name, :radius]) |> cast_assoc(:mechanics) |> cast_embed(:effect) From 01cac21aac9197a6565935e2b01d4378b0080249 Mon Sep 17 00:00:00 2001 From: agustinesco Date: Tue, 10 Sep 2024 15:20:16 -0300 Subject: [PATCH 10/14] Delete json code --- apps/arena/lib/arena/configuration.ex | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/apps/arena/lib/arena/configuration.ex b/apps/arena/lib/arena/configuration.ex index c96c728b4..e8b1a6ba0 100644 --- a/apps/arena/lib/arena/configuration.ex +++ b/apps/arena/lib/arena/configuration.ex @@ -8,16 +8,7 @@ defmodule Arena.Configuration do end def get_game_config() do - {:ok, config_json} = - Application.app_dir(:arena, "priv/config.json") - |> File.read() - - config = Jason.decode!(config_json, [{:keys, :atoms}]) - client_config = get_client_config() - - config - |> Map.merge(get_current_game_configuration()) - |> Map.put(:client_config, client_config) + get_current_game_configuration() end defp get_current_game_configuration do @@ -47,14 +38,6 @@ defmodule Arena.Configuration do end) end - defp get_client_config() do - {:ok, config_json} = - Application.app_dir(:arena, "priv/client_config.json") - |> File.read() - - Jason.decode!(config_json, [{:keys, :atoms}]) - end - defp parse_characters_config(characters) do Enum.map(characters, fn character -> character_skills = %{ From 8fbd96d99002db2ed294e555caa9d3bbcd886619 Mon Sep 17 00:00:00 2001 From: agustinesco Date: Tue, 10 Sep 2024 16:29:26 -0300 Subject: [PATCH 11/14] Fix client config get --- apps/arena/lib/arena/configuration.ex | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/apps/arena/lib/arena/configuration.ex b/apps/arena/lib/arena/configuration.ex index e8b1a6ba0..8e83f645c 100644 --- a/apps/arena/lib/arena/configuration.ex +++ b/apps/arena/lib/arena/configuration.ex @@ -8,7 +8,10 @@ defmodule Arena.Configuration do end def get_game_config() do + client_config = get_client_config() + get_current_game_configuration() + |> Map.put(:client_config, client_config) end defp get_current_game_configuration do @@ -38,6 +41,14 @@ defmodule Arena.Configuration do end) end + defp get_client_config() do + {:ok, config_json} = + Application.app_dir(:arena, "priv/client_config.json") + |> File.read() + + Jason.decode!(config_json, [{:keys, :atoms}]) + end + defp parse_characters_config(characters) do Enum.map(characters, fn character -> character_skills = %{ From ff637220b9bd7f18d9df97af2f2291a2b08035c9 Mon Sep 17 00:00:00 2001 From: agustinesco Date: Wed, 11 Sep 2024 11:28:36 -0300 Subject: [PATCH 12/14] Fix skill immunity --- apps/arena/lib/arena/game/player.ex | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/apps/arena/lib/arena/game/player.ex b/apps/arena/lib/arena/game/player.ex index ce1924d07..9a8950a20 100644 --- a/apps/arena/lib/arena/game/player.ex +++ b/apps/arena/lib/arena/game/player.ex @@ -590,16 +590,18 @@ defmodule Arena.Game.Player do duration_ms: skill.execution_duration_ms, remove_on_action: false, one_time_application: true, - effect_mechanics: %{ - damage_immunity: %{ - execute_multiple_times: false, - effect_delay_ms: 0 + effect_mechanics: [ + %{ + name: "damage_immunity", + effect_delay_ms: 0, + execute_multiple_times: false }, - pull_immunity: %{ - execute_multiple_times: false, - effect_delay_ms: 0 + %{ + name: "pull_immunity", + effect_delay_ms: 0, + execute_multiple_times: false } - } + ] } player = Map.get(game_state.players, player_id) From 728b1a2e5c0a410da5ac2f784a20884d29d88237 Mon Sep 17 00:00:00 2001 From: agustinesco Date: Wed, 11 Sep 2024 11:42:43 -0300 Subject: [PATCH 13/14] Fix valtimer basic buffing pool --- apps/arena/lib/arena/configuration.ex | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/apps/arena/lib/arena/configuration.ex b/apps/arena/lib/arena/configuration.ex index 8e83f645c..79b23848b 100644 --- a/apps/arena/lib/arena/configuration.ex +++ b/apps/arena/lib/arena/configuration.ex @@ -162,7 +162,8 @@ defmodule Arena.Configuration do on_arrival_mechanic: parse_mechanic_config(mechanic.on_arrival_mechanic), on_explode_mechanics: parse_mechanics_config(mechanic.on_explode_mechanics), parent_mechanic: parse_mechanic_config(mechanic.parent_mechanic), - effect: parse_effect(mechanic.effect) + effect: parse_effect(mechanic.effect), + on_collide_effects: parse_on_collide_effects(mechanic.on_collide_effects) } end @@ -216,6 +217,17 @@ defmodule Arena.Configuration do %{mechanics | polygon_hit: %{polygon_hit | vertices: Enum.map(polygon_hit.vertices, &parse_position/1)}} end + defp parse_on_collide_effects(nil) do + nil + end + + defp parse_on_collide_effects(on_collide_effects) do + %{ + on_collide_effects + | effect: parse_effect(on_collide_effects.effect) + } + end + defp parse_effect(nil) do nil end From a937b00e86af3c77535f5c7a72fa7fd3b7409296 Mon Sep 17 00:00:00 2001 From: agustinesco Date: Wed, 11 Sep 2024 12:05:19 -0300 Subject: [PATCH 14/14] Fix otix seeds --- priv/repo/seeds.exs | 100 +++++++++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 38 deletions(-) diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs index 315b726be..c53371927 100644 --- a/priv/repo/seeds.exs +++ b/priv/repo/seeds.exs @@ -329,6 +329,27 @@ buff_singularity_effect = ] } +inferno_effect = %{ + name: "inferno", + remove_on_action: false, + one_time_application: true, + allow_multiple_effects: true, + effect_mechanics: [ + %{ + name: "speed_boost", + modifier: -0.60, + effect_delay_ms: 0, + execute_multiple_times: false + }, + %{ + name: "damage", + damage: 13, + effect_delay_ms: 400, + execute_multiple_times: true + } + ] +} + ## Mechanics multi_shoot = %{ "type" => "multi_shoot", @@ -399,6 +420,43 @@ quickslash_3 = %{ "offset" => 400 } +inferno = %{ + "name" => "inferno", + "type" => "spawn_pool", + "activation_delay" => 250, + "duration_ms" => 8000, + "radius" => 400.0, + "range" => 0.0, + "shape" => "circle", + "vertices" => [], + "effect" => inferno_effect +} + +otix_carbonthrow_mechanic = %{ + "type" => "simple_shoot", + "speed" => 1.8, + "duration_ms" => 0, + "remove_on_collision" => false, + "projectile_offset" => 0, + "radius" => 250.0, + "damage" => 0, + "range" => 700, + "on_explode_mechanics" => [ + %{ + "type" => "circle_hit", + "damage" => 58, + "range" => 250.0, + "offset" => 0 + } + ] +} + +otix_magma_rush_mechanic = %{ + "type" => "dash", + "speed" => 4.0, + "duration_ms" => 250 +} + ## Skills skills = [ @@ -765,26 +823,8 @@ skills = [ "can_pick_destination" => true, "block_movement" => true, "mechanics" => [ - %{ - "type" => "simple_shoot", - "speed" => 1.8, - "duration_ms" => 0, - "remove_on_collision" => false, - "projectile_offset" => 0, - "radius" => 250.0, - "damage" => 0, - "range" => 700, - "on_explode_mechanics" => [ - %{ - "type" => "circle_hit", - "damage" => 58, - "range" => 250.0, - "offset" => 0 - } - ] - } - ], - "effects_to_apply" => [] + otix_carbonthrow_mechanic + ] }, %{ "name" => "otix_magma_rush", @@ -799,11 +839,7 @@ skills = [ "can_pick_destination" => false, "block_movement" => true, "mechanics" => [ - %{ - "type" => "dash", - "speed" => 4.0, - "duration_ms" => 250 - } + otix_magma_rush_mechanic ] }, %{ @@ -819,19 +855,7 @@ skills = [ "can_pick_destination" => false, "block_movement" => true, "mechanics" => [ - %{ - "name" => "inferno", - "type" => "spawn_pool", - "activation_delay" => 250, - "duration_ms" => 8000, - "radius" => 400.0, - "range" => 0.0, - "shape" => "circle", - "vertices" => [], - "effects_to_apply" => [ - "inferno" - ] - } + inferno ] } ]