Skip to content

Commit

Permalink
[GH-591] Allow movement while executing skills (#592)
Browse files Browse the repository at this point in the history
* Split block movement from block actions

* use skill direction instead of player direction for mechanics

* Add direction to player action message

* Revert h4ck slingshot while moving

* Add missing param to do_mechanic call

* Fix skill direction on simple shoot and restore maybe_normalize

* Fix doc typos

* keep player pipe line

* Refactor block movement callback

* Send messages instead of broadcasting
  • Loading branch information
agustinesco authored May 21, 2024
1 parent 7190d51 commit b04170c
Show file tree
Hide file tree
Showing 11 changed files with 146 additions and 34 deletions.
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 @@ -169,17 +170,25 @@ defmodule Arena.Game.Player do
game_state

skill ->
GameUpdater.broadcast_player_block_movement(game_state.game_id, player.id, skill.block_movement)

{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 @@ -206,8 +215,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)
|> 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 @@ -216,8 +224,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 @@ -232,11 +240,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
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 @@ -239,7 +239,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 @@ -453,6 +453,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 @@ -465,6 +470,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 @@ -1005,7 +1014,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 @@ -552,6 +552,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

0 comments on commit b04170c

Please sign in to comment.