| summaryrefslogtreecommitdiff | 
diff options
| author | nsensfel <SpamShield0@noot-noot.org> | 2019-06-05 17:52:58 +0200 | 
|---|---|---|
| committer | nsensfel <SpamShield0@noot-noot.org> | 2019-06-05 17:52:58 +0200 | 
| commit | 9e7dcabc164eacb7024387e060623993b48c60b4 (patch) | |
| tree | 50df2a6143eb2eca18b2588383630c81bb11c1b6 /src/battle/mechanic/action/btl_action_move.erl | |
| parent | 1afb69a11b0e291c7bfd6c24bdd8e55742e61889 (diff) | |
[Broken] ...
Diffstat (limited to 'src/battle/mechanic/action/btl_action_move.erl')
| -rw-r--r-- | src/battle/mechanic/action/btl_action_move.erl | 291 | 
1 files changed, 291 insertions, 0 deletions
| diff --git a/src/battle/mechanic/action/btl_action_move.erl b/src/battle/mechanic/action/btl_action_move.erl new file mode 100644 index 0000000..a32a40f --- /dev/null +++ b/src/battle/mechanic/action/btl_action_move.erl @@ -0,0 +1,291 @@ +-module(btl_action_move). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export +( +   [ +      handle/3 +   ] +). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-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(), +      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), +   NextTile = shr_tile:from_id(NextTileClassID), +   NextCost = (Cost + shr_tile:get_cost(NextTile)), +   IsForbidden = +      lists:foldl +      ( +         fun (ForbiddenLocation, Prev) -> +            (Prev or (NextLocation == ForbiddenLocation)) +         end, +         false, +         ForbiddenLocations +      ), + +   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 +         ); + +      _ -> {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(), +      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 +   ( +      non_neg_integer(), +      btl_character:type(), +      btl_character_turn_update:type(), +      list(shr_direction:type()) +   ) +   -> +   { +      non_neg_integer(), +      shr_location:type(), +      list(shr_direction:type()), +      list(shr_map_marker:type()) +   }. +get_path_cost_and_destination (CharacterIX, Character, Update, Path) -> +   Battle = btl_character_turn_update:get_battle(Update), +   Map = btl_battle:get_map(Battle), + +   % [TODO][OPTIMIZATION] Redundant calculations. +   % 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 +      ( +         fun (IX, Char, Prev) -> +            IsAlive = btl_character:get_is_alive(Char), +            if +               (IX == CharacterIX) -> Prev; +               (not IsAlive) -> Prev; +               true -> +                  ordsets:add_element(btl_character:get_location(Char), Prev) +            end +         end, +         ordsets:new(), +         btl_battle:get_characters(Battle) +      ), + +   {NewLocation, RemainingPath, Cost, Interruptions} = +      cross +      ( +         btl_character:get_player_index(Character), +         Map, +         ForbiddenLocations, +         Path, +         btl_character:get_location(Character) +      ), + +   {Cost, NewLocation, RemainingPath, Interruptions}. + +-spec get_movement_points +   ( +      btl_action:type(), +      btl_character:type() +   ) +   -> non_neg_integer(). +get_movement_points (Action, Character) -> +   case btl_action:get_movement_points(Action) of +      -1 -> +         shr_statistics:get_movement_points +         ( +            shr_character:get_statistics +            ( +               btl_character:get_base_character(Character) +            ) +         ); + +      Other -> Other +   end. + +-spec commit_move +   ( +      non_neg_integer(), +      btl_character:type(), +      btl_character_turn_update:type(), +      list(shr_direction:type()), +      shr_location:type() +   ) +   -> btl_character_turn_update:type(). +commit_move (CharacterIX, Character, S0Update, Path, NewLocation) -> +   S0Battle = btl_character_turn_update:get_battle(S0Update), + +   Map = btl_battle:get_map(S0Battle), + +   TileOmnimods = +      shr_tile:get_omnimods +      ( +         shr_tile:from_id +         ( +            shr_tile_instance:get_tile_id +            ( +               shr_map:get_tile_instance(NewLocation, Map) +            ) +         ) +      ), + +   {UpdatedCharacter, CharacterAtaxiaUpdate} = +      btl_character:ataxia_set_location(NewLocation, TileOmnimods, Character), + +   {UpdatedBattle, BattleAtaxiaUpdate} = +      btl_battle:ataxia_set_character +      ( +         CharacterIX, +         UpdatedCharacter, +         CharacterAtaxiaUpdate, +         S0Battle +      ), + +   TimelineItem = +      btl_turn_result:new_character_moved(CharacterIX, Path, NewLocation), + +   S1Update = btl_character_turn_update:add_to_timeline(TimelineItem, S0Update), +   S2Update = +      btl_character_turn_update:ataxia_set_battle +      ( +         UpdatedBattle, +         BattleAtaxiaUpdate, +         S1Update +      ), + +   S2Update. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec handle +   ( +      btl_action:type(), +      btl_character:type(), +      btl_character_turn_update:type() +   ) +   -> +   ( +      {'ok', btl_character_turn_update:type()} +      | {'events', list(btl_action:type()), btl_character_turn_update:type()} +   ). +handle (Action, Character, S0Update) -> +   Path = btl_action:get_path(Action), +   CharacterIX = btl_action:get_actor_index(Action), + +   {PathCost, NewLocation, RemainingPath, Interruptions} = +      get_path_cost_and_destination(CharacterIX, Character, S0Update, Path), + +   MovementPoints = get_movement_points(Action, Character), + +   true = (MovementPoints >= PathCost), + +   S1Update = commit_move(CharacterIX, Character, S0Update, Path, NewLocation), + +   case RemainingPath of +      [] -> {ok, S1Update}; +      _ -> +         {events, +            ( +               lists:foldl +               ( +                  fun (Marker, CurrentActions) -> +                     ( +                        btl_action:from_map_marker +                        ( +                           CharacterIX, +                           Character, +                           Marker +                        ) +                        ++ +                        CurrentActions +                     ) +                  end, +                  [], +                  Interruptions +               ) +               ++ +               [ +                  btl_action:new_move +                  ( +                     CharacterIX, +                     RemainingPath, +                     (MovementPoints - PathCost) +                  ) +               ] +            ), +            S1Update +         } +   end. | 


