Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GH-591] Allow movement while executing skills #592

Merged
merged 13 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 22 additions & 6 deletions apps/arena/lib/arena/game/player.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ defmodule Arena.Game.Player do
Module for interacting with Player entity
"""

alias Arena.GameUpdater
alias Arena.GameTracker
alias Arena.Utils
alias Arena.Game.Effect
Expand Down Expand Up @@ -168,17 +169,25 @@ defmodule Arena.Game.Player do
game_state

skill ->
GameUpdater.broadcast_player_block_movement(game_state.game_id, player.id, skill.block_movement)
Nico-Sanchez marked this conversation as resolved.
Show resolved Hide resolved

{auto_aim?, skill_direction} =
skill_params.target
|> Skill.maybe_auto_aim(skill, player, targetable_players(game_state.players))

execution_duration = calculate_duration(skill, player.position, skill_direction, auto_aim?)
Process.send_after(self(), {:block_actions, player.id}, execution_duration)

if skill.block_movement do
send(self(), {:block_movement, player.id, true})
Process.send_after(self(), {:block_movement, player.id, false}, execution_duration)
end

action =
%{
action: skill_key_execution_action(skill_key),
duration: execution_duration + skill.activation_delay_ms
duration: execution_duration + skill.activation_delay_ms,
direction: skill_direction
}
|> maybe_add_destination(game_state, player, skill_direction, skill)

Expand All @@ -205,8 +214,7 @@ defmodule Arena.Game.Player do
player =
add_action(player, action)
|> apply_skill_cooldown(skill_key, skill)
|> put_in([:direction], skill_direction |> Utils.normalize())
|> put_in([:is_moving], false)
Nico-Sanchez marked this conversation as resolved.
Show resolved Hide resolved
|> maybe_face_player_towards_direction(skill_direction, skill.block_movement)
|> put_in([:aditional_info, :last_skill_triggered], System.monotonic_time(:millisecond))

put_in(game_state, [:players, player.id], player)
Expand All @@ -215,8 +223,8 @@ defmodule Arena.Game.Player do
end

# This is a messy solution to get a mechanic result before actually running the mechanic since the client needed the
# position in wich the player will spawn when the skill start and not when we actually execute the teleport
# this is also optimistic since we asume the destination will be always available
# position in which the player will spawn when the skill start and not when we actually execute the teleport
# this is also optimistic since we assume the destination will be always available
defp maybe_add_destination(action, game_state, player, skill_direction, %{mechanics: [{:teleport, teleport}]}) do
target_position = %{
x: player.position.x + skill_direction.x * teleport.range,
Expand All @@ -231,11 +239,19 @@ defmodule Arena.Game.Player do

defp maybe_add_destination(action, _, _, _, _), do: action

defp maybe_face_player_towards_direction(player, skill_direction, true) do
player
|> put_in([:direction], skill_direction |> Utils.normalize())
|> put_in([:is_moving], false)
end

defp maybe_face_player_towards_direction(player, _skill_direction, _), do: player

@doc """

Receives a player that owns the damage and the damage number

to calculate the real damage we'll use the config "power_up_damage_modifier" multipling that with base damage of the
to calculate the real damage we'll use the config "power_up_damage_modifier" multiplying that with base damage of the
ability and multiply that with the amount of power ups that a player has then adding that to the base damage resulting
in the real damage

Expand Down
29 changes: 18 additions & 11 deletions apps/arena/lib/arena/game/skill.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ defmodule Arena.Game.Skill do
end)
end

def do_mechanic(game_state, entity, {:circle_hit, circle_hit}, _skill_params) do
circle_center_position = get_position_with_offset(entity.position, entity.direction, circle_hit.offset)
def do_mechanic(game_state, entity, {:circle_hit, circle_hit}, %{skill_direction: skill_direction} = _skill_params) do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change will potentially break the traps feature, since we do not have the attacks logic isolated from the skills, lets create an issue to refactor this

circle_center_position = get_position_with_offset(entity.position, skill_direction, circle_hit.offset)
circular_damage_area = Entities.make_circular_area(entity.id, circle_center_position, circle_hit.range)

entity_player_owner = get_entity_player_owner(game_state, entity)
Expand Down Expand Up @@ -63,11 +63,11 @@ defmodule Arena.Game.Skill do
|> maybe_move_player(entity, circle_hit[:move_by])
end

def do_mechanic(game_state, entity, {:cone_hit, cone_hit}, _skill_params) do
def do_mechanic(game_state, entity, {:cone_hit, cone_hit}, %{skill_direction: skill_direction} = _skill_params) do
triangle_points =
Physics.calculate_triangle_vertices(
entity.position,
entity.direction,
skill_direction,
cone_hit.range,
cone_hit.angle
)
Expand Down Expand Up @@ -145,7 +145,12 @@ defmodule Arena.Game.Skill do
do_mechanic(game_state, entity, {:circle_hit, multi_circle_hit}, skill_params)
end

def do_mechanic(game_state, entity, {:dash, %{speed: speed, duration: duration}}, _skill_params) do
def do_mechanic(
game_state,
entity,
{:dash, %{speed: speed, duration: duration}},
%{skill_direction: skill_direction} = _skill_params
) do
Process.send_after(self(), {:stop_dash, entity.id, entity.aditional_info.base_speed}, duration)

## Modifying base_speed rather than speed because effects will reset the speed on game tick
Expand All @@ -154,6 +159,7 @@ defmodule Arena.Game.Skill do
entity
|> Map.put(:is_moving, true)
|> put_in([:aditional_info, :base_speed], speed)
|> put_in([:aditional_info, :direction], skill_direction)
|> put_in([:aditional_info, :forced_movement], true)

players = Map.put(game_state.players, entity.id, entity)
Expand Down Expand Up @@ -199,10 +205,10 @@ defmodule Arena.Game.Skill do
|> put_in([:projectiles, projectile.id], projectile)
end

def do_mechanic(game_state, entity, {:multi_shoot, multishot}, skill_params) do
def do_mechanic(game_state, entity, {:multi_shoot, multishot}, %{skill_direction: skill_direction} = skill_params) do
entity_player_owner = get_entity_player_owner(game_state, entity)

calculate_angle_directions(multishot.amount, multishot.angle_between, entity.direction)
calculate_angle_directions(multishot.amount, multishot.angle_between, skill_direction)
|> Enum.reduce(game_state, fn direction, game_state_acc ->
last_id = game_state_acc.last_id + 1

Expand All @@ -211,7 +217,7 @@ defmodule Arena.Game.Skill do
last_id,
get_position_with_offset(
entity_player_owner.position,
entity_player_owner.direction,
skill_direction,
multishot.projectile_offset
),
direction,
Expand All @@ -228,7 +234,7 @@ defmodule Arena.Game.Skill do
end)
end

def do_mechanic(game_state, entity, {:simple_shoot, simple_shoot}, skill_params) do
def do_mechanic(game_state, entity, {:simple_shoot, simple_shoot}, %{skill_direction: skill_direction} = skill_params) do
last_id = game_state.last_id + 1
entity_player_owner = get_entity_player_owner(game_state, entity)

Expand All @@ -237,10 +243,10 @@ defmodule Arena.Game.Skill do
last_id,
get_position_with_offset(
entity_player_owner.position,
entity_player_owner.direction,
skill_direction,
simple_shoot.projectile_offset
),
entity.direction,
skill_direction,
entity_player_owner.id,
skill_params.skill_key,
simple_shoot
Expand Down Expand Up @@ -371,6 +377,7 @@ defmodule Arena.Game.Skill do
true ->
nearest_entity_position_in_range =
Physics.nearest_entity_position_in_range(player, entities, skill.max_autoaim_range)
|> maybe_normalize(not skill.can_pick_destination)

{nearest_entity_position_in_range != player.direction, nearest_entity_position_in_range}

Expand Down
39 changes: 25 additions & 14 deletions apps/arena/lib/arena/game_socket_handler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ defmodule Arena.GameSocketHandler do
Map.put(state, :player_id, player_id)
|> Map.put(:enable, game_status == :RUNNING)
|> Map.put(:block_actions, false)
|> Map.put(:block_movement, false)
|> Map.put(:game_finished, game_status == :ENDED)
|> Map.put(:player_alive, true)

Expand All @@ -51,11 +52,6 @@ defmodule Arena.GameSocketHandler do
{:ok, state}
end

@impl true
def websocket_handle(_, %{block_actions: true} = state) do
{:ok, state}
end

@impl true
def websocket_handle(:pong, state) do
last_ping_time = state.last_ping_time
Expand All @@ -75,21 +71,27 @@ defmodule Arena.GameSocketHandler do
{:reply, {:pong, ""}, state}
end

def websocket_handle({:binary, message}, state) do
def websocket_handle({:binary, message}, %{block_actions: block_actions, block_movement: block_movement} = state) do
case Serialization.GameAction.decode(message) do
%{action_type: {:attack, %{skill: skill, parameters: params}}, timestamp: timestamp} ->
GameUpdater.attack(state.game_pid, state.player_id, skill, params, timestamp)
unless block_actions do
GameUpdater.attack(state.game_pid, state.player_id, skill, params, timestamp)
end

%{action_type: {:use_item, _}, timestamp: timestamp} ->
GameUpdater.use_item(state.game_pid, state.player_id, timestamp)
unless block_actions do
GameUpdater.use_item(state.game_pid, state.player_id, timestamp)
end

%{action_type: {:move, %{direction: direction}}, timestamp: timestamp} ->
GameUpdater.move(
state.game_pid,
state.player_id,
{direction.x, direction.y},
timestamp
)
unless block_movement do
GameUpdater.move(
state.game_pid,
state.player_id,
{direction.x, direction.y},
timestamp
)
end

_ ->
{}
Expand Down Expand Up @@ -152,6 +154,15 @@ defmodule Arena.GameSocketHandler do
end
end

@impl true
def websocket_info({:block_movement, player_id, value}, state) do
if state.player_id == player_id do
{:ok, Map.put(state, :block_movement, value)}
else
{:ok, state}
end
end

@impl true
def websocket_info(message, state) do
Logger.info("You should not be here: #{inspect(message)}")
Expand Down
13 changes: 11 additions & 2 deletions apps/arena/lib/arena/game_updater.ex
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ defmodule Arena.GameUpdater do

game_state =
put_in(state.game_state, [:players, player_id], player)
|> Skill.do_mechanic(player, on_arrival_mechanic, %{})
|> Skill.do_mechanic(player, on_arrival_mechanic, %{skill_direction: player.direction})

{:noreply, %{state | game_state: game_state}}
end
Expand Down Expand Up @@ -447,6 +447,11 @@ defmodule Arena.GameUpdater do
{:noreply, state}
end

def handle_info({:block_movement, player_id, value}, state) do
broadcast_player_block_movement(state.game_state.game_id, player_id, value)
{:noreply, state}
end

##########################
# End callbacks
##########################
Expand All @@ -459,6 +464,10 @@ defmodule Arena.GameUpdater do
PubSub.broadcast(Arena.PubSub, game_id, {:block_actions, player_id, value})
end

def broadcast_player_block_movement(game_id, player_id, value) do
PubSub.broadcast(Arena.PubSub, game_id, {:block_movement, player_id, value})
end

# Broadcast game update to all players
defp broadcast_player_dead(game_id, player_id) do
PubSub.broadcast(Arena.PubSub, game_id, {:player_dead, player_id})
Expand Down Expand Up @@ -927,7 +936,7 @@ defmodule Arena.GameUpdater do
game_state,
projectile,
projectile.aditional_info.on_explode_mechanics,
%{}
%{skill_direction: projectile.direction}
)
else
game_state
Expand Down
1 change: 1 addition & 0 deletions apps/arena/lib/arena/serialization/messages.pb.ex
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,7 @@ defmodule Arena.Serialization.PlayerAction do
field(:action, 1, type: Arena.Serialization.PlayerActionType, enum: true)
field(:duration, 2, type: :uint64)
field(:destination, 3, type: Arena.Serialization.Position)
field(:direction, 4, type: Arena.Serialization.Position)
end

defmodule Arena.Serialization.Move do
Expand Down
Loading
Loading