| summaryrefslogtreecommitdiff | 
diff options
Diffstat (limited to 'src/battlemap/game-logic')
| -rw-r--r-- | src/battlemap/game-logic/bm_movement.erl | 58 | ||||
| -rw-r--r-- | src/battlemap/game-logic/bm_next_turn.erl | 135 | ||||
| -rw-r--r-- | src/battlemap/game-logic/bm_roll.erl | 32 | ||||
| -rw-r--r-- | src/battlemap/game-logic/bm_turn_actions.erl | 364 | 
4 files changed, 589 insertions, 0 deletions
diff --git a/src/battlemap/game-logic/bm_movement.erl b/src/battlemap/game-logic/bm_movement.erl new file mode 100644 index 0000000..ed4c38c --- /dev/null +++ b/src/battlemap/game-logic/bm_movement.erl @@ -0,0 +1,58 @@ +-module(bm_movement). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export([cross/4]). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec cross +   ( +      bm_battlemap:type(), +      list(bm_location:type()), +      list(bm_direction:enum()), +      non_neg_integer(), +      bm_location:type() +   ) +   -> {bm_location:type(), non_neg_integer()}. +cross (_Battlemap, _ForbiddenLocations, [], Cost, Location) -> +   {Location, Cost}; +cross (Battlemap, ForbiddenLocations, [Step|NextSteps], Cost, Location) -> +   NextLocation = bm_location:apply_direction(Step, Location), +   NextTile = bm_battlemap:get_tile_id(NextLocation, Battlemap), +   NextCost = (Cost + bm_tile:get_cost(NextTile)), +   IsForbidden = +      lists:foldl +      ( +         fun (ForbiddenLocation, Prev) -> +            (Prev or (NextLocation == ForbiddenLocation)) +         end, +         false, +         ForbiddenLocations +      ), + +   IsForbidden = false, + +   cross(Battlemap, ForbiddenLocations, NextSteps, NextCost, NextLocation). + +-spec cross +   ( +      bm_battlemap:type(), +      list(bm_location:type()), +      list(bm_direction:enum()), +      bm_location:type() +   ) +   -> {bm_location:type(), non_neg_integer()}. +cross (Battlemap, ForbiddenLocations, Path, Location) -> +   cross(Battlemap, ForbiddenLocations, Path, 0, Location). diff --git a/src/battlemap/game-logic/bm_next_turn.erl b/src/battlemap/game-logic/bm_next_turn.erl new file mode 100644 index 0000000..3628111 --- /dev/null +++ b/src/battlemap/game-logic/bm_next_turn.erl @@ -0,0 +1,135 @@ +-module(bm_next_turn). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export +( +   [ +      update_if_needed/1 +   ] +). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec set_player_turn_to_next (bm_battle:type()) -> bm_battle:type(). +set_player_turn_to_next (Battle) -> +   Players = bm_battle:get_players(Battle), +   CurrentPlayerTurn = bm_battle:get_current_player_turn(Battle), + +   NextPlayerTurn = bm_player_turn:next(array:size(Players), CurrentPlayerTurn), + +   bm_battle:set_current_player_turn(NextPlayerTurn, Battle). + +-spec reset_next_player_timeline +   ( +      bm_battle:type() +   ) +   -> {bm_battle:type(), bm_player:type()}. +reset_next_player_timeline (Battle) -> +   NextPlayerTurn = bm_battle:get_current_player_turn(Battle), +   NextPlayerIX = bm_player_turn:get_player_ix(NextPlayerTurn), +   NextPlayer = bm_battle:get_player(NextPlayerIX, Battle), + +   UpdatedNextPlayer = bm_player:reset_timeline(NextPlayer), +   UpdatedBattle = +      bm_battle:set_player(NextPlayerIX, UpdatedNextPlayer, Battle), + +   {UpdatedBattle, UpdatedNextPlayer}. + + +-spec activate_next_players_characters +   ( +      bm_battle:type(), +      bm_player:type() +   ) +   -> {bm_battle:type(), list(non_neg_integer())}. +activate_next_players_characters (Battle, NextPlayer) -> +   NextPlayerID = bm_player:get_id(NextPlayer), +   Characters = bm_battle:get_characters(Battle), + +   {UpdatedCharacters, ModifiedIXs} = +      array_util:mapiff +      ( +         fun (Character) -> +            (bm_character:get_owner_id(Character) == NextPlayerID) +         end, +         fun (Character) -> +            bm_character:set_is_active(true, Character) +         end, +         Characters +      ), + +   UpdatedBattle = bm_battle:set_characters(UpdatedCharacters, Battle), + +   {UpdatedBattle, ModifiedIXs}. + +-spec add_activation_updates +   ( +      list(non_neg_integer()), +      bm_character_turn_update:type() +   ) +   -> bm_character_turn_update:type(). +add_activation_updates ([], Update) -> +   Update; +add_activation_updates ([IX|NextIXs], Update) -> +   add_activation_updates +   ( +      NextIXs, +      bm_character_turn_update:add_to_db +      ( +         sh_db_query:update_indexed +         ( +            bm_battle:get_characters_field(), +            IX, +            [sh_db_query:set_field(bm_character:get_active_field(), true)] +         ), +         Update +      ) +   ). + +-spec update +   ( +      bm_character_turn_update:type() +   ) +   -> bm_character_turn_update:type(). +update (Update) -> +   Data = bm_character_turn_update:get_data(Update), +   Battle = bm_character_turn_data:get_battle(Data), + +   S0Battle = set_player_turn_to_next(Battle), +   {S1Battle, NextPlayer} = reset_next_player_timeline(S0Battle), +   {S2Battle, ActivatedCharactersIX} = +      activate_next_players_characters(S1Battle, NextPlayer), + +   S0Update = add_activation_updates(ActivatedCharactersIX, Update), + +   UpdatedData = bm_character_turn_data:set_battle(S2Battle, Data), + +   bm_character_turn_update:set_data(UpdatedData, S0Update). + +-spec requires_update (bm_character_turn_update:type()) -> boolean(). +requires_update (Update) -> +   Data = bm_character_turn_update:get_data(Update), +   Battle = bm_character_turn_data:get_battle(Data), +   Characters = bm_battle:get_characters(Battle), + +   array_util:none(fun bm_character:get_is_active/1, Characters). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec update_if_needed +   ( +      bm_character_turn_update:type() +   ) +   -> character_turn_update:type(). +update_if_needed (Update) -> +   case requires_update(Update) of +      true -> update(Update); +      _ -> Update +   end. diff --git a/src/battlemap/game-logic/bm_roll.erl b/src/battlemap/game-logic/bm_roll.erl new file mode 100644 index 0000000..be1cb9d --- /dev/null +++ b/src/battlemap/game-logic/bm_roll.erl @@ -0,0 +1,32 @@ +-module(bm_roll). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export +( +   [ +      percentage/0, +      between/2 +   ] +). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec between (non_neg_integer(), non_neg_integer()) -> non_neg_integer(). +between (Min, Max) -> +   Diff = (Max - Min), +   (Min + (rand:uniform(Diff + 1) - 1)). + +-spec percentage () -> 0..100. +percentage () -> +   between(0, 100). diff --git a/src/battlemap/game-logic/bm_turn_actions.erl b/src/battlemap/game-logic/bm_turn_actions.erl new file mode 100644 index 0000000..9664283 --- /dev/null +++ b/src/battlemap/game-logic/bm_turn_actions.erl @@ -0,0 +1,364 @@ +-module(bm_turn_actions). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export +( +   [ +      handle/2 +   ] +). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%% SWITCHING WEAPON %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec handle_switch_weapon +   ( +      bm_character_turn_update:type() +   ) +   -> bm_character_turn_update:type(). +handle_switch_weapon (Update) -> +   Data = bm_character_turn_update:get_data(Update), +   Character = bm_character_turn_data:get_character(Data), +   CharacterIX = bm_character_turn_data:get_character_ix(Data), +   CharacterAttributes = bm_character:get_attributes(Character), +   {PrimaryWeaponID, SecondaryWeaponID} = bm_character:get_weapon_ids(Character), + +   UpdatedWeaponIDs = {SecondaryWeaponID, PrimaryWeaponID}, +   UpdatedCharacterStatistics = +      bm_statistics:new(CharacterAttributes, UpdatedWeaponIDs), +   UpdatedCharacter = +      bm_character:set_statistics +      ( +         UpdatedCharacterStatistics, +         bm_character:set_weapon_ids(UpdatedWeaponIDs, Character) +      ), + +   DBQuery = +      sh_db_query:update_indexed +      ( +         bm_battle:get_characters_field(), +         CharacterIX, +         [ +            sh_db_query:set_field +            ( +               bm_character:get_weapons_field(), +               UpdatedWeaponIDs +            ) +         ] +      ), + +   UpdatedData = bm_character_turn_data:set_character(UpdatedCharacter, Data), + +   S0Update = bm_character_turn_update:set_data(UpdatedData, Update), +   S1Update = +      bm_character_turn_update:add_to_timeline +      ( +         bm_turn_result:new_character_switched_weapons(CharacterIX), +         S0Update +      ), + +   bm_character_turn_update:add_to_db(DBQuery, S1Update). + +%%%% MOVING %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec get_path_cost_and_destination +   ( +      bm_character_turn_data:type(), +      list(bm_direction:type()) +   ) +   -> {non_neg_integer(), bm_location:type()}. +get_path_cost_and_destination (Data, Path) -> +   Character = bm_character_turn_data:get_character(Data), +   CharacterIX = bm_character_turn_data:get_character_ix(Data), +   Battle = bm_character_turn_data:get_battle(Data), +   Battlemap = bm_battle:get_battlemap(Battle), + +   ForbiddenLocations = +      array:foldl +      ( +         fun (IX, Char, Prev) -> +            IsAlive = bm_character:get_is_alive(Char), +            if +               (IX == CharacterIX) -> Prev; +               (not IsAlive) -> Prev; +               true -> [bm_character:get_location(Char)|Prev] +            end +         end, +         [], +         bm_battle:get_characters(Battle) +      ), + +   {NewLocation, Cost} = +      bm_movement:cross +      ( +         Battlemap, +         ForbiddenLocations, +         Path, +         bm_character:get_location(Character) +      ), + +   {Cost, NewLocation}. + +-spec assert_character_can_move +   ( +      bm_character_turn_data:type(), +      non_neg_integer() +   ) +   -> 'ok'. +assert_character_can_move (Data, Cost) -> +   Character = bm_character_turn_data:get_character(Data), +   CharacterStatistics = bm_character:get_statistics(Character), +   CharacterMovementPoints = +      bm_statistics:get_movement_points(CharacterStatistics), + +   true = (Cost =< CharacterMovementPoints), + +   ok. + +-spec commit_move +   ( +      bm_character_turn_update:type(), +      list(bm_direction:type()), +      bm_location:type() +   ) +   -> bm_character_turn_update:type(). +commit_move (Update, Path, NewLocation) -> +   Data = bm_character_turn_update:get_data(Update), +   Character = bm_character_turn_data:get_character(Data), +   CharacterIX = bm_character_turn_data:get_character_ix(Data), + +   UpdatedCharacter = bm_character:set_location(NewLocation, Character), + +   UpdatedData = bm_character_turn_data:set_character(UpdatedCharacter, Data), + +   S0Update = +      bm_character_turn_update:add_to_timeline +      ( +         bm_turn_result:new_character_moved(CharacterIX, Path, NewLocation), +         Update +      ), + +   S1Update = +      bm_character_turn_update:add_to_db +      ( +         sh_db_query:update_indexed +         ( +            bm_battle:get_characters_field(), +            CharacterIX, +            [ +               sh_db_query:set_field +               ( +                  bm_character:get_location_field(), +                  NewLocation +               ) +            ] +         ), +         S0Update +      ), + +   bm_character_turn_update:set_data(UpdatedData, S1Update). + +-spec handle_move +   ( +      bm_battle_action:type(), +      bm_character_turn_update:type() +   ) +   -> bm_character_turn_update:type(). +handle_move (BattleAction, Update) -> +   Data = bm_character_turn_update:get_data(Update), +   Path = bm_battle_action:get_path(BattleAction), + +   {PathCost, NewLocation} = get_path_cost_and_destination(Data, Path), +   assert_character_can_move(Data, PathCost), + +   commit_move(Update, Path, NewLocation). + +%%%% ATTACKING %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec handle_attack_sequence +   ( +      bm_character:type(), +      bm_character:type(), +      list(bm_attack:step()) +   ) +   -> {list(bm_attack:type()), non_neg_integer(), non_neg_integer()}. +handle_attack_sequence +( +   Character, +   TargetCharacter, +   AttackSequence +) -> +   CharacterStatistics = bm_character:get_statistics(Character), +   TargetCharacterStatistics = bm_character:get_statistics(TargetCharacter), + +   AttackPlannedEffects = +      lists:map +      ( +         fun (AttackStep) -> +            bm_attack:get_description_of +            ( +               AttackStep, +               CharacterStatistics, +               TargetCharacterStatistics +            ) +         end, +         AttackSequence +      ), + +   lists:foldl +   ( +      fun +      ( +         AttackEffectCandidate, +         {AttackValidEffects, AttackerHealth, DefenderHealth} +      ) -> +         {AttackResult, NewAttackerHealth, NewDefenderHealth} = +            bm_attack:apply_to_healths +            ( +               AttackEffectCandidate, +               AttackerHealth, +               DefenderHealth +            ), +         case AttackResult of +            nothing -> {AttackValidEffects, AttackerHealth, DefenderHealth}; +            _ -> +               { +                  (AttackValidEffects ++ [AttackResult]), +                  NewAttackerHealth, +                  NewDefenderHealth +               } +         end +      end, +      { +         [], +         bm_character:get_current_health(Character), +         bm_character:get_current_health(TargetCharacter) +      }, +      AttackPlannedEffects +   ). + +-spec get_attack_sequence +   ( +      bm_character:type(), +      bm_character:type() +   ) +   -> list(attack:step()). +get_attack_sequence (Character, TargetCharacter) -> +   Range = +      location:dist +      ( +         bm_character:get_location(Character), +         bm_character:get_location(TargetCharacter) +      ), + +   {AttackingWeaponID, _} = bm_character:get_weapon_ids(Character), +   {DefendingWeaponID, _} = bm_character:get_weapon_ids(TargetCharacter), + +   AttackingWeapon = bm_weapon:from_id(AttackingWeaponID), +   DefendingWeapon = bm_weapon:from_id(DefendingWeaponID), + +   bm_attack:get_sequence(Range, AttackingWeapon, DefendingWeapon). + + +-spec handle_attack +   ( +      bm_battle_action:type(), +      bm_character_turn_update:type() +   ) +   -> bm_character_turn_update:type(). +handle_attack (BattleAction, Update) -> +   Data = bm_character_turn_update:get_data(Update), +   Battle = bm_character_turn_data:get_battle(Data), +   Character = bm_character_turn_data:get_character(Data), +   CharacterIX = bm_character_turn_data:get_character_ix(Data), +   TargetIX = bm_battle_action:get_target_ix(BattleAction), +   TargetCharacter = bm_battle:get_character(TargetIX, Battle), + +   AttackSequence = get_attack_sequence(Character, TargetCharacter), + +   {AttackEffects, RemainingAttackerHealth, RemainingDefenderHealth} = +      handle_attack_sequence +      ( +         Character, +         TargetCharacter, +         AttackSequence +      ), + +   UpdatedCharacter = +      bm_character:set_current_health +      ( +         RemainingAttackerHealth, +         Character +      ), + +   UpdatedBattle = +      bm_battle:set_character +      ( +         TargetIX, +         bm_character:set_current_health +         ( +            RemainingDefenderHealth, +            TargetCharacter +         ), +         Battle +      ), + + +   S0Data = bm_character_turn_data:set_battle(UpdatedBattle, Data), +   S1Data = +      bm_character_turn_data:set_character +      ( +         UpdatedCharacter, +         S0Data +      ), + + +   S0Update = +      bm_character_turn_update:add_to_timeline +      ( +         bm_turn_result:new_character_attacked +         ( +            CharacterIX, +            TargetIX, +            AttackEffects +         ), +         Update +      ), +   S1Update = bm_character_turn_update:set_data(S1Data, S0Update), + +   DBQuery = +      sh_db_query:update_indexed +      ( +         bm_battle:get_characters_field(), +         TargetIX, +         [ +            sh_db_query:set_field +            ( +               bm_character:get_current_health_field(), +               RemainingDefenderHealth +            ) +         ] +      ), + +   bm_character_turn_update:add_to_db(DBQuery, S1Update). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec handle +( +   bm_battle_action:type(), +   bm_character_turn_update:type() +) +-> bm_character_turn_update:type(). +handle (BattleAction, Update) -> +   case bm_battle_action:get_category(BattleAction) of +      move -> handle_move(BattleAction, Update); +      switch_weapon -> handle_switch_weapon(Update); +      attack -> handle_attack(BattleAction, Update) +   end.  | 


