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 9 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
29 changes: 26 additions & 3 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,6 +169,20 @@ defmodule Arena.Game.Player do
game_state

skill ->
Process.send_after(
self(),
{:block_actions, player.id},
skill.execution_duration_ms
)
Nico-Sanchez marked this conversation as resolved.
Show resolved Hide resolved

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

Process.send_after(
self(),
{:block_movement, player.id, false},
skill.execution_duration_ms
)

{auto_aim?, skill_direction} =
skill_params.target
|> Skill.maybe_auto_aim(skill, player, targetable_players(game_state.players))
Expand All @@ -178,7 +193,8 @@ defmodule Arena.Game.Player do
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,10 +221,17 @@ 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
|> put_in([:aditional_info, :last_skill_triggered], System.monotonic_time(:millisecond))

player =
if skill.block_movement do
player
|> put_in([:direction], skill_direction |> Utils.normalize())
|> put_in([:is_moving], false)
else
player
end

put_in(game_state, [:players, player.id], player)
|> maybe_make_player_invincible(player.id, skill)
end
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
13 changes: 13 additions & 0 deletions apps/arena/priv/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,7 @@
"max_autoaim_range": 800,
"stamina_cost": 1,
"can_pick_destination": false,
"block_movement": true,
"mechanics": [
{
"circle_hit": {
Expand All @@ -889,6 +890,7 @@
"autoaim": true,
"max_autoaim_range": 1500,
"can_pick_destination": true,
"block_movement": true,
"mechanics": [
{
"spawn_pool": {
Expand All @@ -914,6 +916,7 @@
"autoaim": true,
"max_autoaim_range": 1500,
"can_pick_destination": true,
"block_movement": true,
"mechanics": [
{
"leap": {
Expand Down Expand Up @@ -941,6 +944,7 @@
"autoaim": true,
"max_autoaim_range": 1500,
"can_pick_destination": true,
"block_movement": true,
"mechanics": [
{
"spawn_pool": {
Expand All @@ -966,6 +970,7 @@
"max_autoaim_range": 1600,
"stamina_cost": 1,
"can_pick_destination": false,
"block_movement": true,
"mechanics": [
{
"multi_shoot": {
Expand All @@ -992,6 +997,7 @@
"autoaim": false,
"max_autoaim_range": 0,
"can_pick_destination": false,
"block_movement": true,
"mechanics": [
{
"dash": {
Expand All @@ -1011,6 +1017,7 @@
"autoaim": false,
"max_autoaim_range": 0,
"can_pick_destination": false,
"block_movement": true,
"mechanics": [
{
"dash": {
Expand All @@ -1030,6 +1037,7 @@
"max_autoaim_range": 800,
"stamina_cost": 1,
"can_pick_destination": false,
"block_movement": true,
"mechanics": [
{
"multi_circle_hit": {
Expand All @@ -1054,6 +1062,7 @@
"autoaim": true,
"max_autoaim_range": 0,
"can_pick_destination": false,
"block_movement": true,
"mechanics": [
{
"circle_hit": {
Expand All @@ -1077,6 +1086,7 @@
"autoaim": false,
"max_autoaim_range": 0,
"can_pick_destination": false,
"block_movement": true,
"mechanics": [
{
"dash": {
Expand All @@ -1098,6 +1108,7 @@
"autoaim": false,
"max_autoaim_range": 0,
"can_pick_destination": true,
"block_movement": true,
"stamina_cost": 1,
"mechanics": [
{
Expand All @@ -1119,6 +1130,7 @@
"autoaim": false,
"max_autoaim_range": 0,
"can_pick_destination": false,
"block_movement": true,
"mechanics": [
{
"dash": {
Expand All @@ -1139,6 +1151,7 @@
"max_autoaim_range": 1600,
"stamina_cost": 1,
"can_pick_destination": false,
"block_movement": true,
"mechanics": [
{
"simple_shoot": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,7 @@ defmodule ArenaLoadTest.Serialization.PlayerAction do
field(:action, 1, type: ArenaLoadTest.Serialization.PlayerActionType, enum: true)
field(:duration, 2, type: :uint64)
field(:destination, 3, type: ArenaLoadTest.Serialization.Position)
field(:direction, 4, type: ArenaLoadTest.Serialization.Position)
end

defmodule ArenaLoadTest.Serialization.Move do
Expand Down
1 change: 1 addition & 0 deletions apps/bot_manager/lib/protobuf/messages.pb.ex
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,7 @@ defmodule BotManager.Protobuf.PlayerAction do
field(:action, 1, type: BotManager.Protobuf.PlayerActionType, enum: true)
field(:duration, 2, type: :uint64)
field(:destination, 3, type: BotManager.Protobuf.Position)
field(:direction, 4, type: BotManager.Protobuf.Position)
end

defmodule BotManager.Protobuf.Move do
Expand Down
Loading
Loading