Skip to content

Commit

Permalink
[GH-852] Configurator: Migrate effects config (#856)
Browse files Browse the repository at this point in the history
* Add effect to consumable items

* Fix effect handling for items

* Fix pool effects

* Add effects for skills

* Fix credo complain

* Fix on collide effects

* Add effect show and editing to configurator app

* Add module doc to custom components

* Remove unused function

* Delete json code

* Fix client config get

* Fix skill immunity

* Fix valtimer basic buffing pool

* Fix otix seeds
  • Loading branch information
agustinesco authored Sep 12, 2024
1 parent cf5f035 commit e8cb8d6
Show file tree
Hide file tree
Showing 26 changed files with 678 additions and 545 deletions.
61 changes: 43 additions & 18 deletions apps/arena/lib/arena/configuration.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,9 @@ 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())
get_current_game_configuration()
|> Map.put(:client_config, client_config)
end

Expand Down Expand Up @@ -69,21 +63,32 @@ defmodule Arena.Configuration do
end)
end

defp parse_items_config(items) do
Enum.map(items, fn item ->
%{
item
| effect: parse_effect(item.effect),
radius: maybe_to_float(item.radius),
mechanics: parse_mechanics_config(item.mechanics)
}
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)
%{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
Expand Down Expand Up @@ -156,7 +161,9 @@ defmodule Arena.Configuration do
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),
parent_mechanic: parse_mechanic_config(mechanic.parent_mechanic)
parent_mechanic: parse_mechanic_config(mechanic.parent_mechanic),
effect: parse_effect(mechanic.effect),
on_collide_effects: parse_on_collide_effects(mechanic.on_collide_effects)
}
end

Expand Down Expand Up @@ -210,13 +217,31 @@ 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)
}
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

defp parse_effect(effect) do
Map.update!(effect, :effect_mechanics, fn effect_mechanics ->
Enum.map(effect_mechanics, fn effect_mechanic ->
%{
effect_mechanic
| modifier: maybe_to_float(effect_mechanic.modifier),
force: maybe_to_float(effect_mechanic.force),
stat_multiplier: maybe_to_float(effect_mechanic.stat_multiplier)
}
end)
end)
end

Expand Down
6 changes: 3 additions & 3 deletions apps/arena/lib/arena/entities.ex
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,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: []
}
Expand Down Expand Up @@ -177,7 +177,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,
Expand Down Expand Up @@ -205,7 +205,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
}
Expand Down
83 changes: 48 additions & 35 deletions apps/arena/lib/arena/game/effect.ex
Original file line number Diff line number Diff line change
Expand Up @@ -82,68 +82,53 @@ 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

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

defp apply_stat_modifier(player, _) 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.
Expand All @@ -168,24 +153,52 @@ 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
update_effect_mechanic_value_in_effect(effect, mechanic, :last_application_time, now)
else
current_effect
end
end)
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 ->
entity
Expand Down Expand Up @@ -215,7 +228,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)
Expand All @@ -233,7 +246,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 ->
Expand All @@ -253,11 +266,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

Expand Down
30 changes: 14 additions & 16 deletions apps/arena/lib/arena/game/player.ex
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,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
)

Expand Down Expand Up @@ -361,19 +361,15 @@ 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)
|> maybe_update_player_item_effects_expires_at(player, effect)
end)
Effect.put_effect_to_entity(game_state, player, player.id, item.effect)
|> maybe_update_player_item_effects_expires_at(player, item.effect)
|> put_in([:players, player.id, :aditional_info, :inventory], nil)

Item.do_mechanics(game_state, player, item.mechanics)
Expand Down Expand Up @@ -591,16 +587,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)
Expand Down
10 changes: 2 additions & 8 deletions apps/arena/lib/arena/game/skill.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -322,13 +321,8 @@ defmodule Arena.Game.Skill do
deal_damage_to_game_entities(game_state, entity_player_owner, polygon_damage_area, polygon_hit.damage)
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
Expand Down
Loading

0 comments on commit e8cb8d6

Please sign in to comment.