Skip to content

Commit

Permalink
Add shinko (#973)
Browse files Browse the repository at this point in the history
* Apply skill effects to target entities when applying damage to them

* Add shinko to the characters list

* Add shinko skills and params in seeds

* Add underscore to discard unused variable in seeds

* Fix Shinko ulti params and make his pool effects affect enemies even when they escape it

* Make projectiles able to apply an effect on enemies and fix a function taking wrong variable (old effect)

* Fix Shinko basic attack params in seeds

* Add new boolean to effects to differentiate effects inside pool only vs effects still valid outside them

* Fix credo

* Fix credo moving code to new function

* feat: add checkbox (#975)

---------

Co-authored-by: Tomás Villegas <[email protected]>
  • Loading branch information
Nico-Sanchez and tvillegas98 authored Nov 4, 2024
1 parent 54e9ba0 commit 6d10ab4
Show file tree
Hide file tree
Showing 8 changed files with 240 additions and 24 deletions.
48 changes: 37 additions & 11 deletions apps/arena/lib/arena/game/effect.ex
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,14 @@ defmodule Arena.Game.Effect do
cond do
Map.has_key?(game_state.players, entity_id) ->
update_in(game_state, [:players, entity_id, :aditional_info, :effects], fn current_effects ->
Enum.reject(current_effects, fn effect -> effect.owner_id == owner_id end)
# Here we remove all effects from owner if they only apply there (pools for now).
Enum.reject(current_effects, fn effect -> effect.owner_id == owner_id and effect.disabled_outside_pool end)
end)

Map.has_key?(game_state.crates, entity_id) ->
update_in(game_state, [:crates, entity_id, :aditional_info, :effects], fn current_effects ->
Enum.reject(current_effects, fn effect -> effect.owner_id == owner_id end)
# Here we remove all effects from owner if they only apply there (pools for now).
Enum.reject(current_effects, fn effect -> effect.owner_id == owner_id and effect.disabled_outside_pool end)
end)

true ->
Expand Down Expand Up @@ -177,7 +179,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
update_effect_mechanic_value_in_effect(effect, mechanic, :last_application_time, now)
update_effect_mechanic_value_in_effect(current_effect, mechanic, :last_application_time, now)
else
current_effect
end
Expand Down Expand Up @@ -229,20 +231,19 @@ defmodule Arena.Game.Effect do
end

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)
Map.get(effect, :player_owner_id, get_entity_player_owner_id(game_state, effect.owner_id))
|> case do
nil ->
entity

pool ->
pool_owner = Map.get(game_state.players, pool.aditional_info.owner_id)
real_damage = Player.calculate_real_damage(pool_owner, damage_params.damage)
owner_id ->
owner = Map.get(game_state.players, owner_id)
real_damage = Player.calculate_real_damage(owner, damage_params.damage)

send(self(), {:damage_done, pool_owner.id, real_damage})
send(self(), {:damage_done, owner_id, real_damage})

Entities.take_damage(entity, real_damage, pool_owner.id)
Entities.take_damage(entity, real_damage, owner_id)
|> add_player_owner_of_effect_to_entity(effect.id, owner_id)
end
end

Expand Down Expand Up @@ -279,6 +280,31 @@ defmodule Arena.Game.Effect do
entity
end

defp get_entity_player_owner_id(game_state, owner_id) do
# Append here entities that apply effects. For now are pools and projectiles.
damage_entity =
Map.merge(game_state.projectiles, game_state.pools)
|> Map.get(owner_id)

if is_nil(damage_entity) do
nil
else
damage_entity.aditional_info.owner_id
end
end

defp add_player_owner_of_effect_to_entity(entity, effect_id, owner_id) do
update_in(entity, [:aditional_info, :effects], fn effects ->
Enum.map(effects, fn current_effect ->
if current_effect.id == effect_id do
Map.put(current_effect, :player_owner_id, owner_id)
else
current_effect
end
end)
end)
end

defp add_effect_to_entity(game_state, entity, effect, owner_id, start_action_removal_in_ms) do
now = System.monotonic_time(:millisecond)

Expand Down
29 changes: 24 additions & 5 deletions apps/arena/lib/arena/game/skill.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,13 @@ defmodule Arena.Game.Skill do

entity_player_owner = get_entity_player_owner(game_state, entity)

deal_damage_to_game_entities(game_state, entity_player_owner, circular_damage_area, circle_hit.damage)
apply_damage_and_effects_to_entities(
game_state,
entity_player_owner,
circular_damage_area,
circle_hit.damage,
circle_hit.effect
)
|> maybe_move_player(entity, circle_hit[:move_by])
end

Expand All @@ -48,7 +54,7 @@ defmodule Arena.Game.Skill do
cone_area = Entities.make_polygon(entity.id, triangle_points)
entity_player_owner = get_entity_player_owner(game_state, entity)

deal_damage_to_game_entities(game_state, entity_player_owner, cone_area, cone_hit.damage)
apply_damage_and_effects_to_entities(game_state, entity_player_owner, cone_area, cone_hit.damage)
|> maybe_move_player(entity, cone_hit[:move_by])
end

Expand Down Expand Up @@ -318,7 +324,7 @@ defmodule Arena.Game.Skill do

entity_player_owner = get_entity_player_owner(game_state, entity)

deal_damage_to_game_entities(game_state, entity_player_owner, polygon_damage_area, polygon_hit.damage)
apply_damage_and_effects_to_entities(game_state, entity_player_owner, polygon_damage_area, polygon_hit.damage)
end

def handle_skill_effects(game_state, player, effect, execution_duration_ms) do
Expand Down Expand Up @@ -436,14 +442,27 @@ defmodule Arena.Game.Skill do
direction
end

defp deal_damage_to_game_entities(game_state, player, skill_entity, damage) do
defp apply_damage_and_effects_to_entities(game_state, player, skill_entity, damage, effect \\ nil) do
# Players
alive_players =
Player.alive_players(game_state.players)
|> Map.filter(fn {_, alive_player} -> alive_player.id != player.id end)

collided_players = Physics.check_collisions(skill_entity, alive_players)

# Apply effects to players
game_state =
if is_nil(effect) do
game_state
else
Enum.reduce(collided_players, game_state, fn collided_player_id, game_state ->
collided_player = Map.get(game_state.players, collided_player_id)
Effect.put_effect_to_entity(game_state, collided_player, skill_entity.id, effect)
end)
end

players =
Physics.check_collisions(skill_entity, alive_players)
collided_players
|> Enum.reduce(game_state.players, fn player_id, players_acc ->
real_damage = Player.calculate_real_damage(player, damage)

Expand Down
2 changes: 1 addition & 1 deletion apps/arena_load_test/lib/arena_load_test/socket_handler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ defmodule ArenaLoadTest.SocketHandler do
# This is enough for now. Will request bots from the bots app in future iterations.
# https://github.com/lambdaclass/mirra_backend/issues/410
defp get_random_active_character() do
["muflus", "h4ck", "uma", "valtimer", "kenzu", "otix"]
["muflus", "h4ck", "uma", "valtimer", "kenzu", "otix", "shinko"]
|> Enum.random()
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ defmodule ConfiguratorWeb.CustomComponents do
<.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[:disabled_outside_pool]} type="checkbox" label="Disabled outside pool" />
<.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]}>
Expand Down
4 changes: 4 additions & 0 deletions apps/game_backend/lib/game_backend/curse_of_mirra/effect.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ defmodule GameBackend.CurseOfMirra.Effect do
:allow_multiple_effects,
:consume_projectile,
:effect_mechanics,
:disabled_outside_pool,
:name
]}
embedded_schema do
Expand All @@ -22,6 +23,7 @@ defmodule GameBackend.CurseOfMirra.Effect do
field(:one_time_application, :boolean)
field(:allow_multiple_effects, :boolean)
field(:consume_projectile, :boolean)
field(:disabled_outside_pool, :boolean)
embeds_many(:effect_mechanics, EffectMechanic)
end

Expand All @@ -33,12 +35,14 @@ defmodule GameBackend.CurseOfMirra.Effect do
:one_time_application,
:allow_multiple_effects,
:consume_projectile,
:disabled_outside_pool,
:name
])
|> validate_required([
:remove_on_action,
:one_time_application,
:allow_multiple_effects,
:disabled_outside_pool,
:name
])
|> cast_embed(:effect_mechanics)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ defmodule GameBackend.Matches.ArenaMatchResult do
|> validate_inclusion(:result, ["win", "loss", "abandon"])
## TODO: This enums should actually be read from config
## https://github.com/lambdaclass/mirra_backend/issues/601
|> validate_inclusion(:character, ["h4ck", "muflus", "uma", "valtimer", "kenzu", "otix"])
|> validate_inclusion(:killed_by, ["h4ck", "muflus", "uma", "valtimer", "kenzu", "otix", "zone"])
|> validate_inclusion(:character, ["h4ck", "muflus", "uma", "valtimer", "kenzu", "otix", "shinko"])
|> validate_inclusion(:killed_by, ["h4ck", "muflus", "uma", "valtimer", "kenzu", "otix", "shinko", "zone"])
|> foreign_key_constraint(:user_id)
end
end
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<%= if assigns[:current_user_id] do %>
<.form :let={f} for={%{}} action={~p"/"}>
<.input field={f[:character]} name="character" label="Select a Character" type="select" options={["muflus", "h4ck", "uma", "valtimer", "kenzu", "otix"]} value=""/>
<.input field={f[:character]} name="character" label="Select a Character" type="select" options={["muflus", "h4ck", "uma", "valtimer", "kenzu", "otix", "shinko"]} value=""/>
<.input field={f[:user_id]} name="user_id" type="hidden" value={assigns[:user_id]}/>
<.button type="submit" name="game_mode" value="battle-royale">Play Battle Royal</.button>
<.button type="submit" name="game_mode" value="pair">Play Pair</.button>
Expand Down
Loading

0 comments on commit 6d10ab4

Please sign in to comment.