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. |