summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/battlemap/game-logic')
-rw-r--r--src/battlemap/game-logic/bm_movement.erl58
-rw-r--r--src/battlemap/game-logic/bm_next_turn.erl135
-rw-r--r--src/battlemap/game-logic/bm_roll.erl32
-rw-r--r--src/battlemap/game-logic/bm_turn_actions.erl364
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.