summaryrefslogtreecommitdiff |
diff options
Diffstat (limited to 'src/battle/mechanic')
4 files changed, 165 insertions, 52 deletions
diff --git a/src/battle/mechanic/btl_turn_actions_management.erl b/src/battle/mechanic/btl_turn_actions_management.erl index d33fbad..eefe812 100644 --- a/src/battle/mechanic/btl_turn_actions_management.erl +++ b/src/battle/mechanic/btl_turn_actions_management.erl @@ -37,17 +37,48 @@ deactivate_character (Update) -> S1Update. --spec handle_action -( - btl_action:type(), - btl_character_turn_update:type() -) --> btl_character_turn_update:type(). -handle_action (BattleAction, Update) -> - case btl_action:get_category(BattleAction) of - move -> btl_turn_actions_move:handle(BattleAction, Update); - switch_weapon -> btl_turn_actions_switch_weapon:handle(Update); - attack -> btl_turn_actions_attack:handle(BattleAction, Update) +-spec main_character_is_alive + ( + btl_character_turn_update:type() + ) + -> {boolean(), btl_character_turn_update:type()}. +main_character_is_alive (Update) -> + {S0Update, MainCharacter} = btl_character_turn_update:get_character(Update), + {btl_character:get_is_alive(MainCharacter), S0Update}. + +-spec handle_actions + ( + list(btl_action:type()), + btl_character_turn_update:type() + ) + -> btl_character_turn_update:type(). +handle_actions ([], Update) -> Update; +handle_actions ([BattleAction|FutureBattleActions], Update) -> + {MainCharacterIsAlive, S0Update} = main_character_is_alive(Update), + + ActionResult = + case {MainCharacterIsAlive, btl_action:get_category(BattleAction)} of + {false, _} -> {ok, S0Update}; + {true, move} -> btl_turn_actions_move:handle(BattleAction, S0Update); + {true, switch_weapon} -> + btl_turn_actions_switch_weapon:handle(S0Update); + {true, attack} -> + btl_turn_actions_attack:handle(BattleAction, S0Update); + {true, interrupted_move} -> + btl_turn_actions_move:handle(BattleAction, S0Update); + {true, defend} -> + % TODO: Attack of Opportunity + Update + end, + + case ActionResult of + {ok, NewUpdate} -> handle_actions(FutureBattleActions, NewUpdate); + {events, NewEvents, NewUpdate} -> + handle_actions + ( + (NewEvents ++ FutureBattleActions), + NewUpdate + ) end. -spec update_timeline @@ -98,7 +129,7 @@ update_timeline (Update) -> handle (Update, Request) -> Actions = btl_character_turn_request:get_actions(Request), - S0Update = lists:foldl(fun handle_action/2, Update, Actions), + S0Update = handle_actions(Actions, Update), S1Update = deactivate_character(S0Update), S2Update = update_timeline(S1Update), S3Update = btl_turn_progression:handle(S2Update), diff --git a/src/battle/mechanic/turn_action/btl_turn_actions_attack.erl b/src/battle/mechanic/turn_action/btl_turn_actions_attack.erl index e36c7e3..af4c53b 100644 --- a/src/battle/mechanic/turn_action/btl_turn_actions_attack.erl +++ b/src/battle/mechanic/turn_action/btl_turn_actions_attack.erl @@ -151,7 +151,7 @@ get_attack_sequence (Character, TargetCharacter) -> btl_action:type(), btl_character_turn_update:type() ) - -> btl_character_turn_update:type(). + -> {ok, btl_character_turn_update:type()}. handle (BattleAction, Update) -> {S0Update, Battle} = btl_character_turn_update:get_battle(Update), {S1Update, Character} = btl_character_turn_update:get_character(S0Update), @@ -336,4 +336,4 @@ handle (BattleAction, Update) -> ) end, - S6Update. + {ok, S6Update}. diff --git a/src/battle/mechanic/turn_action/btl_turn_actions_move.erl b/src/battle/mechanic/turn_action/btl_turn_actions_move.erl index a0cd138..70b42c9 100644 --- a/src/battle/mechanic/turn_action/btl_turn_actions_move.erl +++ b/src/battle/mechanic/turn_action/btl_turn_actions_move.erl @@ -18,16 +18,23 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -spec cross ( + non_neg_integer(), shr_map:type(), list(shr_location:type()), list(shr_direction:enum()), non_neg_integer(), shr_location:type() ) - -> {shr_location:type(), non_neg_integer()}. -cross (_Map, _ForbiddenLocations, [], Cost, Location) -> - {Location, Cost}; -cross (Map, ForbiddenLocations, [Step|NextSteps], Cost, Location) -> + -> + { + shr_location:type(), + list(shr_direction:type()), + non_neg_integer(), + list(shr_map_marker:type()) + }. +cross (_PlayerIX, _Map, _ForbiddenLocations, [], Cost, Location) -> + {Location, [], Cost, []}; +cross (PlayerIX, Map, ForbiddenLocations, [Step|NextSteps], Cost, Location) -> NextLocation = shr_location:apply_direction(Step, Location), NextTileInstance = shr_map:get_tile_instance(NextLocation, Map), NextTileClassID = shr_tile_instance:get_tile_id(NextTileInstance), @@ -43,20 +50,60 @@ cross (Map, ForbiddenLocations, [Step|NextSteps], Cost, Location) -> ForbiddenLocations ), - IsForbidden = false, + false = IsForbidden, + + Interruptions = + list:foldl + ( + fun (MarkerName, CurrentInterruptions) -> + case shr_map:get_marker(MarkerName, Map) of + {ok, Marker} -> + case shr_map_marker:interrupts_movement(PlayerIX, Marker) of + true -> [Marker|CurrentInterruptions]; + _ -> CurrentInterruptions + end; + + error -> + %% TODO: Error. + CurrentInterruptions + end + end, + [], + shr_tile_instance:get_triggers(NextTileInstance) + ), + + case Interruptions of + [] -> + cross + ( + PlayerIX, + Map, + ForbiddenLocations, + NextSteps, + NextCost, + NextLocation + ); - cross(Map, ForbiddenLocations, NextSteps, NextCost, NextLocation). + _ -> {NextLocation, NextSteps, NextCost, Interruptions} + end. -spec cross ( + non_neg_integer(), shr_map:type(), list(shr_location:type()), list(shr_direction:enum()), shr_location:type() ) - -> {shr_location:type(), non_neg_integer()}. -cross (Map, ForbiddenLocations, Path, Location) -> - cross(Map, ForbiddenLocations, Path, 0, Location). + -> + { + shr_location:type(), + list(shr_direction:type()), + non_neg_integer(), + list(shr_map_marker:type()) + }. +cross (PlayerIX, Map, ForbiddenLocations, Path, Location) -> + cross(PlayerIX, Map, ForbiddenLocations, Path, 0, Location). -spec get_path_cost_and_destination ( @@ -67,6 +114,8 @@ cross (Map, ForbiddenLocations, Path, Location) -> { non_neg_integer(), shr_location:type(), + list(shr_direction:type()), + list(shr_map_marker:type()), btl_character_turn_update:type() }. get_path_cost_and_destination (Update, Path) -> @@ -75,6 +124,9 @@ get_path_cost_and_destination (Update, Path) -> CharacterIX = btl_character_turn_update:get_character_ix(S1Update), Map = btl_battle:get_map(Battle), + % FIXME: This is recalculated at every move action, despite there be no need + % to: The client will not allow the character to go somewhere that would + % only be freed because of an event. ForbiddenLocations = orddict:fold ( @@ -91,42 +143,35 @@ get_path_cost_and_destination (Update, Path) -> btl_battle:get_characters(Battle) ), - {NewLocation, Cost} = + {NewLocation, RemainingPath, Cost, Interruptions} = cross ( + btl_character:get_player_index(Character), Map, ForbiddenLocations, Path, btl_character:get_location(Character) ), - {Cost, NewLocation, S1Update}. + {Cost, NewLocation, RemainingPath, Interruptions, S1Update}. --spec assert_character_can_move +-spec get_movement_points ( - btl_character:type(), - non_neg_integer() + btl_action:type(), + btl_character:type() ) - -> ('ok' | 'error'). -assert_character_can_move (Char, Cost) -> - CharacterMovementPoints = - shr_statistics:get_movement_points - ( - shr_character:get_statistics + -> non_neg_integer(). +get_movement_points (Action, Char) -> + case btl_action:get_category(Action) of + interrupted_move -> btl_action:get_movement_points(Action); + _ -> + shr_statistics:get_movement_points ( - btl_character:get_base_character(Char) + shr_character:get_statistics + ( + btl_character:get_base_character(Char) + ) ) - ), - - case (Cost =< CharacterMovementPoints) of - true -> ok; - false -> - io:format - ( - "~n[E] Character trying to move ~p dist with ~p points.~n", - [Cost, CharacterMovementPoints] - ), - error end. -spec commit_move @@ -183,14 +228,51 @@ commit_move (Character, Update, Path, NewLocation) -> btl_action:type(), btl_character_turn_update:type() ) - -> btl_character_turn_update:type(). + -> + ( + {'ok', btl_character_turn_update:type()} + | {'events', list(btl_action:type()), btl_character_turn_update:type()} + ). handle (BattleAction, Update) -> {S0Update, Character} = btl_character_turn_update:get_character(Update), + Path = btl_action:get_path(BattleAction), - {PathCost, NewLocation, S1Update} = + {PathCost, NewLocation, RemainingPath, Interruptions, S1Update} = get_path_cost_and_destination(S0Update, Path), - ok = assert_character_can_move(Character, PathCost), + MovementPoints = get_movement_points(BattleAction, Character), + + true = (MovementPoints >= PathCost), + + S2Update = commit_move(Character, S1Update, Path, NewLocation), - commit_move(Character, S1Update, Path, NewLocation). + case RemainingPath of + [] -> {ok, S2Update}; + _ -> + {events, + ( + lists:foldl + ( + fun (Marker, CurrentActions) -> + ( + btl_action:from_map_marker(Character, Marker) + ++ + CurrentActions + ) + end, + [], + Interruptions + ) + ++ + [ + btl_action:new_interrupted_move + ( + RemainingPath, + (MovementPoints - PathCost) + ) + ] + ), + S2Update + } + end. diff --git a/src/battle/mechanic/turn_action/btl_turn_actions_switch_weapon.erl b/src/battle/mechanic/turn_action/btl_turn_actions_switch_weapon.erl index 24b361a..8e4aeab 100644 --- a/src/battle/mechanic/turn_action/btl_turn_actions_switch_weapon.erl +++ b/src/battle/mechanic/turn_action/btl_turn_actions_switch_weapon.erl @@ -24,7 +24,7 @@ ( btl_character_turn_update:type() ) - -> btl_character_turn_update:type(). + -> {'ok', btl_character_turn_update:type()}. handle (Update) -> {S0Update, Character} = btl_character_turn_update:get_character(Update), CharacterIX = btl_character_turn_update:get_character_ix(S0Update), @@ -52,4 +52,4 @@ handle (Update) -> S1Update ), - S2Update. + {ok, S2Update}. |