From 14e79da8b8d45ef242aee34cf4376d220846f690 Mon Sep 17 00:00:00 2001 From: nsensfel Date: Wed, 23 Jan 2019 18:43:13 +0100 Subject: Cleaning up a bit... --- src/battle/game-logic/btl_movement.erl | 60 ------ src/battle/game-logic/btl_next_turn.erl | 184 ----------------- src/battle/game-logic/btl_turn_actions.erl | 99 --------- src/battle/game-logic/btl_turn_actions_attack.erl | 225 --------------------- src/battle/game-logic/btl_turn_actions_move.erl | 140 ------------- .../game-logic/btl_turn_actions_switch_weapon.erl | 68 ------- src/battle/game-logic/btl_victory.erl | 208 ------------------- src/battle/mechanic/btl_next_turn.erl | 184 +++++++++++++++++ src/battle/mechanic/btl_turn_actions.erl | 83 ++++++++ src/battle/mechanic/btl_victory.erl | 208 +++++++++++++++++++ .../turn_action/btl_turn_actions_attack.erl | 225 +++++++++++++++++++++ .../mechanic/turn_action/btl_turn_actions_move.erl | 186 +++++++++++++++++ .../turn_action/btl_turn_actions_stats_change.erl | 85 ++++++++ .../turn_action/btl_turn_actions_switch_weapon.erl | 68 +++++++ src/battle/query/btl_character_turn.erl | 65 +----- 15 files changed, 1046 insertions(+), 1042 deletions(-) delete mode 100644 src/battle/game-logic/btl_movement.erl delete mode 100644 src/battle/game-logic/btl_next_turn.erl delete mode 100644 src/battle/game-logic/btl_turn_actions.erl delete mode 100644 src/battle/game-logic/btl_turn_actions_attack.erl delete mode 100644 src/battle/game-logic/btl_turn_actions_move.erl delete mode 100644 src/battle/game-logic/btl_turn_actions_switch_weapon.erl delete mode 100644 src/battle/game-logic/btl_victory.erl create mode 100644 src/battle/mechanic/btl_next_turn.erl create mode 100644 src/battle/mechanic/btl_turn_actions.erl create mode 100644 src/battle/mechanic/btl_victory.erl create mode 100644 src/battle/mechanic/turn_action/btl_turn_actions_attack.erl create mode 100644 src/battle/mechanic/turn_action/btl_turn_actions_move.erl create mode 100644 src/battle/mechanic/turn_action/btl_turn_actions_stats_change.erl create mode 100644 src/battle/mechanic/turn_action/btl_turn_actions_switch_weapon.erl (limited to 'src') diff --git a/src/battle/game-logic/btl_movement.erl b/src/battle/game-logic/btl_movement.erl deleted file mode 100644 index dd7eff9..0000000 --- a/src/battle/game-logic/btl_movement.erl +++ /dev/null @@ -1,60 +0,0 @@ --module(btl_movement). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --export([cross/4]). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec cross - ( - btl_map:type(), - list(btl_location:type()), - list(btl_direction:enum()), - non_neg_integer(), - btl_location:type() - ) - -> {btl_location:type(), non_neg_integer()}. -cross (_Map, _ForbiddenLocations, [], Cost, Location) -> - {Location, Cost}; -cross (Map, ForbiddenLocations, [Step|NextSteps], Cost, Location) -> - NextLocation = btl_location:apply_direction(Step, Location), - NextTileInstance = btl_map:get_tile_instance(NextLocation, Map), - NextTileClassID = shr_tile:extract_main_class_id(NextTileInstance), - NextTile = shr_tile:from_class_id(NextTileClassID), - NextCost = (Cost + shr_tile:get_cost(NextTile)), - IsForbidden = - lists:foldl - ( - fun (ForbiddenLocation, Prev) -> - (Prev or (NextLocation == ForbiddenLocation)) - end, - false, - ForbiddenLocations - ), - - IsForbidden = false, - - cross(Map, ForbiddenLocations, NextSteps, NextCost, NextLocation). - --spec cross - ( - btl_map:type(), - list(btl_location:type()), - list(btl_direction:enum()), - btl_location:type() - ) - -> {btl_location:type(), non_neg_integer()}. -cross (Map, ForbiddenLocations, Path, Location) -> - cross(Map, ForbiddenLocations, Path, 0, Location). diff --git a/src/battle/game-logic/btl_next_turn.erl b/src/battle/game-logic/btl_next_turn.erl deleted file mode 100644 index 886916d..0000000 --- a/src/battle/game-logic/btl_next_turn.erl +++ /dev/null @@ -1,184 +0,0 @@ --module(btl_next_turn). -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --export -( - [ - update_if_needed/1 - ] -). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec set_player_turn_to_next (btl_battle:type()) - -> {btl_battle:type(), ataxic:basic()}. -set_player_turn_to_next (Battle) -> - Players = btl_battle:get_players(Battle), - CurrentPlayerTurn = btl_battle:get_current_player_turn(Battle), - - NextPlayerTurn = btl_player_turn:next(Players, CurrentPlayerTurn), - - UpdatedBattle = btl_battle:set_current_player_turn(NextPlayerTurn, Battle), - - DBQuery = - ataxic:update_field - ( - btl_battle:get_current_player_turn_field(), - ataxic:constant(NextPlayerTurn) - ), - - {UpdatedBattle, DBQuery}. - --spec reset_next_player_timeline (btl_battle:type()) - -> {btl_battle:type(), btl_player:type(), ataxic:basic()}. -reset_next_player_timeline (Battle) -> - NextPlayerTurn = btl_battle:get_current_player_turn(Battle), - NextPlayerIX = btl_player_turn:get_player_ix(NextPlayerTurn), - NextPlayer = btl_battle:get_player(NextPlayerIX, Battle), - - UpdatedNextPlayer = btl_player:reset_timeline(NextPlayer), - UpdatedBattle = - btl_battle:set_player(NextPlayerIX, UpdatedNextPlayer, Battle), - - DBQuery = - ataxic:update_field - ( - btl_battle:get_players_field(), - ataxic_sugar:update_orddict_element - ( - NextPlayerIX, - ataxic:update_field - ( - btl_player:get_timeline_field(), - ataxic:constant([]) - ) - ) - ), - - {UpdatedBattle, UpdatedNextPlayer, DBQuery}. - - --spec activate_next_players_characters (btl_battle:type(), btl_player:type()) - -> {btl_battle:type(), ataxic:basic()}. -activate_next_players_characters (Battle, NextPlayer) -> - NextPlayerIX = btl_player:get_index(NextPlayer), - Characters = btl_battle:get_characters(Battle), - - {UpdatedCharacters, AtaxicUpdates} = - orddict:fold - ( - fun (IX, Character, {Prev, Updates}) -> - case (btl_character:get_player_index(Character) == NextPlayerIX) of - true -> - { - orddict:store - ( - IX, - btl_character:set_is_active(true, Character), - Prev - ), - [ - ataxic_sugar:update_orddict_element - ( - IX, - ataxic:update_field - ( - btl_character:get_is_active_field(), - ataxic:constant(true) - ) - )|Updates - ] - }; - - false -> {Prev, Updates} - end - end, - {Characters, []}, - Characters - ), - - DBQuery = - ataxic:update_field - ( - btl_battle:get_characters_field(), - ataxic:sequence(AtaxicUpdates) - ), - - UpdatedBattle = btl_battle:set_characters(UpdatedCharacters, Battle), - - {UpdatedBattle, DBQuery}. - --spec update - ( - btl_character_turn_update:type() - ) - -> btl_character_turn_update:type(). -update (Update) -> - Data = btl_character_turn_update:get_data(Update), - Battle = btl_character_turn_data:get_battle(Data), - - {S0Battle, DBQuery0} = set_player_turn_to_next(Battle), - {S1Battle, NextPlayer, DBQuery1} = reset_next_player_timeline(S0Battle), - {S2Battle, DBQuery2} = - activate_next_players_characters(S1Battle, NextPlayer), - - S0Data = btl_character_turn_data:set_battle(S2Battle, Data), - S0Update = - btl_character_turn_update:add_to_timeline - ( - btl_turn_result:new_player_turn_started - ( - btl_player:get_index(NextPlayer) - ), - DBQuery0, - Update - ), - - S1Update = btl_character_turn_update:set_data(S0Data, S0Update), - - S2Update = - lists:foldl - ( - fun btl_character_turn_update:add_to_db/2, - S1Update, - [DBQuery1,DBQuery2] - ), - - S2Update. - --spec requires_update (btl_character_turn_update:type()) -> boolean(). -requires_update (Update) -> - Data = btl_character_turn_update:get_data(Update), - Battle = btl_character_turn_data:get_battle(Data), - Characters = btl_battle:get_characters(Battle), - - (not - (lists:any - ( - fun ({_IX, Char}) -> - btl_character:get_is_active(Char) - end, - orddict:to_list(Characters) - ) - ) - ). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec update_if_needed - ( - btl_character_turn_update:type() - ) - -> btl_character_turn_update:type(). -update_if_needed (Update) -> - case requires_update(Update) of - true -> update(Update); - _ -> Update - end. diff --git a/src/battle/game-logic/btl_turn_actions.erl b/src/battle/game-logic/btl_turn_actions.erl deleted file mode 100644 index 4e469f1..0000000 --- a/src/battle/game-logic/btl_turn_actions.erl +++ /dev/null @@ -1,99 +0,0 @@ --module(btl_turn_actions). -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --export -( - [ - handle/2, - handle_max_health_changes/2 - ] -). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec mod_current_health - ( - non_neg_integer(), - non_neg_integer(), - btl_character_turn_update:type() - ) - -> btl_character_turn_update:type(). -mod_current_health (CurrentMaxHealth, PreviousMaxHealth, Update) -> - Data = btl_character_turn_update:get_data(Update), - Character = btl_character_turn_data:get_character(Data), - CharacterIX = btl_character_turn_data:get_character_ix(Data), - PreviousHealth = btl_character:get_current_health(Character), - - PreviousHealthRatio = (PreviousHealth / PreviousMaxHealth), - NewHealth = - min - ( - CurrentMaxHealth, - max(1, round(PreviousHealthRatio * CurrentMaxHealth)) - ), - - UpdatedCharacter = btl_character:set_current_health(NewHealth, Character), - UpdatedData = btl_character_turn_data:set_character(UpdatedCharacter, Data), - S0Update = btl_character_turn_update:set_data(UpdatedData, Update), - - DBQuery = - ataxic:update_field - ( - btl_battle:get_characters_field(), - ataxic_sugar:update_orddict_element - ( - CharacterIX, - ataxic:update_field - ( - btl_character:get_current_health_field(), - ataxic:constant(NewHealth) - ) - ) - ), - - S1Update = btl_character_turn_update:add_to_db(DBQuery, S0Update), - - S1Update. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec handle -( - btl_battle_action:type(), - btl_character_turn_update:type() -) --> btl_character_turn_update:type(). -handle (BattleAction, Update) -> - case btl_battle_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) - end. - --spec handle_max_health_changes - ( - btl_character_current_data:type(), - btl_character_turn_update:type() - ) - -> btl_character_turn_update:type(). -handle_max_health_changes (PreviousData, Update) -> - Data = btl_character_turn_update:get_data(Update), - CurrentData = btl_character_turn_data:get_character_current_data(Data), - CurrentStats = btl_character_current_data:get_statistics(CurrentData), - PreviousStats = btl_character_current_data:get_statistics(PreviousData), - - CurrentMaxHealth = shr_statistics:get_health(CurrentStats), - PreviousMaxHealth = shr_statistics:get_health(PreviousStats), - - case (CurrentMaxHealth == PreviousMaxHealth) of - true -> Update; - _ -> mod_current_health(CurrentMaxHealth, PreviousMaxHealth, Update) - end. diff --git a/src/battle/game-logic/btl_turn_actions_attack.erl b/src/battle/game-logic/btl_turn_actions_attack.erl deleted file mode 100644 index 52dd3fb..0000000 --- a/src/battle/game-logic/btl_turn_actions_attack.erl +++ /dev/null @@ -1,225 +0,0 @@ --module(btl_turn_actions_attack). -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --export -( - [ - handle/2 - ] -). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec handle_attack_sequence - ( - btl_character_current_data:type(), - non_neg_integer(), - btl_character_current_data:type(), - non_neg_integer(), - list(btl_attack:step()) - ) - -> {list(btl_attack:type()), non_neg_integer(), non_neg_integer()}. -handle_attack_sequence -( - CharacterCurrentData, - CharacterCurrentHealth, - TargetCurrentData, - TargetCurrentHealth, - AttackSequence -) -> - AttackPlannedEffects = - lists:map - ( - fun (AttackStep) -> - btl_attack:get_description_of - ( - AttackStep, - CharacterCurrentData, - TargetCurrentData - ) - end, - AttackSequence - ), - - lists:foldl - ( - fun - ( - AttackEffectCandidate, - {AttackValidEffects, AttackerHealth, DefenderHealth} - ) -> - {AttackResult, NewAttackerHealth, NewDefenderHealth} = - btl_attack:apply_to_healths - ( - AttackEffectCandidate, - AttackerHealth, - DefenderHealth - ), - case AttackResult of - nothing -> {AttackValidEffects, AttackerHealth, DefenderHealth}; - _ -> - { - (AttackValidEffects ++ [AttackResult]), - NewAttackerHealth, - NewDefenderHealth - } - end - end, - { - [], - CharacterCurrentHealth, - TargetCurrentHealth - }, - AttackPlannedEffects - ). - --spec get_attack_sequence - ( - btl_character:type(), - btl_character:type() - ) - -> list(btl_attack:step()). -get_attack_sequence (Character, TargetCharacter) -> - Range = - btl_location:dist - ( - btl_character:get_location(Character), - btl_character:get_location(TargetCharacter) - ), - - {AttackingWeaponID, _} = btl_character:get_weapon_ids(Character), - {DefendingWeaponID, _} = btl_character:get_weapon_ids(TargetCharacter), - - AttackingWeapon = shr_weapon:from_id(AttackingWeaponID), - DefendingWeapon = shr_weapon:from_id(DefendingWeaponID), - - btl_attack:get_sequence(Range, AttackingWeapon, DefendingWeapon). - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec handle - ( - btl_battle_action:type(), - btl_character_turn_update:type() - ) - -> btl_character_turn_update:type(). -handle (BattleAction, Update) -> - Data = btl_character_turn_update:get_data(Update), - Battle = btl_character_turn_data:get_battle(Data), - Character = btl_character_turn_data:get_character(Data), - CharacterIX = btl_character_turn_data:get_character_ix(Data), - CharacterCurrentData = - btl_character_turn_data:get_character_current_data(Data), - - Map = btl_battle:get_map(Battle), - TargetIX = btl_battle_action:get_target_ix(BattleAction), - TargetCharacter = btl_battle:get_character(TargetIX, Battle), - TargetCurrentData = btl_character_current_data:new(TargetCharacter, Map), - - true = btl_character:get_is_alive(TargetCharacter), - - AttackSequence = get_attack_sequence(Character, TargetCharacter), - - {AttackEffects, RemainingAttackerHealth, RemainingDefenderHealth} = - handle_attack_sequence - ( - CharacterCurrentData, - btl_character:get_current_health(Character), - TargetCurrentData, - btl_character:get_current_health(TargetCharacter), - AttackSequence - ), - - UpdatedCharacter = - btl_character:set_current_health(RemainingAttackerHealth, Character), - - UpdatedBattle = - btl_battle:set_character - ( - TargetIX, - btl_character:set_current_health - ( - RemainingDefenderHealth, - TargetCharacter - ), - Battle - ), - - S0Data = btl_character_turn_data:set_battle(UpdatedBattle, Data), - S1Data = btl_character_turn_data:set_character(UpdatedCharacter, S0Data), - - TimelineItem = - btl_turn_result:new_character_attacked - ( - CharacterIX, - TargetIX, - AttackEffects - ), - - DBQuery0 = - ataxic:update_field - ( - btl_battle:get_characters_field(), - ataxic_sugar:update_orddict_element - ( - TargetIX, - ataxic:update_field - ( - btl_character:get_current_health_field(), - ataxic:constant(RemainingDefenderHealth) - ) - ) - ), - - DBQuery1 = - ataxic:update_field - ( - btl_battle:get_characters_field(), - ataxic_sugar:update_orddict_element - ( - CharacterIX, - ataxic:update_field - ( - btl_character:get_current_health_field(), - ataxic:constant(RemainingAttackerHealth) - ) - ) - ), - - S0Update = - btl_character_turn_update:add_to_timeline - ( - TimelineItem, - DBQuery0, - Update - ), - - S1Update = btl_character_turn_update:add_to_db(DBQuery1, S0Update), - S2Update = btl_character_turn_update:set_data(S1Data, S1Update), - - S3Update = - btl_victory:handle_character_lost_health - ( - CharacterIX, - RemainingAttackerHealth, - S2Update - ), - - S4Update = - btl_victory:handle_character_lost_health - ( - TargetIX, - RemainingDefenderHealth, - S3Update - ), - - S4Update. diff --git a/src/battle/game-logic/btl_turn_actions_move.erl b/src/battle/game-logic/btl_turn_actions_move.erl deleted file mode 100644 index 80e5170..0000000 --- a/src/battle/game-logic/btl_turn_actions_move.erl +++ /dev/null @@ -1,140 +0,0 @@ --module(btl_turn_actions_move). -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --export -( - [ - handle/2 - ] -). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec get_path_cost_and_destination - ( - btl_character_turn_data:type(), - list(btl_direction:type()) - ) - -> {non_neg_integer(), btl_location:type()}. -get_path_cost_and_destination (Data, Path) -> - Character = btl_character_turn_data:get_character(Data), - CharacterIX = btl_character_turn_data:get_character_ix(Data), - Battle = btl_character_turn_data:get_battle(Data), - Map = btl_battle:get_map(Battle), - - 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, Cost} = - btl_movement:cross - ( - Map, - ForbiddenLocations, - Path, - btl_character:get_location(Character) - ), - - {Cost, NewLocation}. - --spec assert_character_can_move - ( - btl_character_turn_data:type(), - non_neg_integer() - ) - -> 'ok'. -assert_character_can_move (Data, Cost) -> - CharacterData = btl_character_turn_data:get_character_current_data(Data), - CharacterStats= btl_character_current_data:get_statistics(CharacterData), - CharacterMovementPoints = shr_statistics:get_movement_points(CharacterStats), - - true = (Cost =< CharacterMovementPoints), - - ok. - --spec commit_move - ( - btl_character_current_data:type(), - btl_character_turn_update:type(), - list(btl_direction:type()), - btl_location:type() - ) - -> btl_character_turn_update:type(). -commit_move (PreviousCurrentData, Update, Path, NewLocation) -> - Data = btl_character_turn_update:get_data(Update), - Character = btl_character_turn_data:get_character(Data), - CharacterIX = btl_character_turn_data:get_character_ix(Data), - - UpdatedCharacter = btl_character:set_location(NewLocation, Character), - S0Data = btl_character_turn_data:set_character(UpdatedCharacter, Data), - S1Data = btl_character_turn_data:refresh_character_current_data(S0Data), - - S0Update = btl_character_turn_update:set_data(S1Data, Update), - S1Update = - btl_turn_actions:handle_max_health_changes(PreviousCurrentData, S0Update), - - TimelineItem = - btl_turn_result:new_character_moved(CharacterIX, Path, NewLocation), - - DBQuery = - ataxic:update_field - ( - btl_battle:get_characters_field(), - ataxic_sugar:update_orddict_element - ( - CharacterIX, - ataxic:update_field - ( - btl_character:get_location_field(), - ataxic:constant(NewLocation) - ) - ) - ), - - S2Update = - btl_character_turn_update:add_to_timeline - ( - TimelineItem, - DBQuery, - S1Update - ), - - S2Update. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec handle - ( - btl_battle_action:type(), - btl_character_turn_update:type() - ) - -> btl_character_turn_update:type(). -handle (BattleAction, Update) -> - Data = btl_character_turn_update:get_data(Update), - CharacterCurrentData = - btl_character_turn_data:get_character_current_data(Data), - Path = btl_battle_action:get_path(BattleAction), - - {PathCost, NewLocation} = get_path_cost_and_destination(Data, Path), - assert_character_can_move(Data, PathCost), - - commit_move(CharacterCurrentData, Update, Path, NewLocation). diff --git a/src/battle/game-logic/btl_turn_actions_switch_weapon.erl b/src/battle/game-logic/btl_turn_actions_switch_weapon.erl deleted file mode 100644 index 990f91f..0000000 --- a/src/battle/game-logic/btl_turn_actions_switch_weapon.erl +++ /dev/null @@ -1,68 +0,0 @@ --module(btl_turn_actions_switch_weapon). -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --export -( - [ - handle/1 - ] -). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec handle - ( - btl_character_turn_update:type() - ) - -> btl_character_turn_update:type(). -handle (Update) -> - Data = btl_character_turn_update:get_data(Update), - Character = btl_character_turn_data:get_character(Data), - CharacterCurrentData = - btl_character_turn_data:get_character_current_data(Data), - CharacterIX = btl_character_turn_data:get_character_ix(Data), - - {PrimaryWeaponID, SecondaryWeaponID} = btl_character:get_weapon_ids(Character), - - UpdatedWeaponIDs = {SecondaryWeaponID, PrimaryWeaponID}, - UpdatedCharacter = btl_character:set_weapon_ids(UpdatedWeaponIDs, Character), - - S0Data = btl_character_turn_data:set_character(UpdatedCharacter, Data), - S1Data = btl_character_turn_data:refresh_character_current_data(S0Data), - - S0Update = btl_character_turn_update:set_data(S1Data, Update), - S1Update = - btl_turn_actions:handle_max_health_changes - ( - CharacterCurrentData, - S0Update - ), - - TimelineItem = btl_turn_result:new_character_switched_weapons(CharacterIX), - - DBQuery = - ataxic:update_field - ( - btl_battle:get_characters_field(), - ataxic_sugar:update_orddict_element - ( - CharacterIX, - ataxic:update_field - ( - btl_character:get_weapons_field(), - ataxic:constant(UpdatedWeaponIDs) - ) - ) - ), - - btl_character_turn_update:add_to_timeline(TimelineItem, DBQuery, S1Update). diff --git a/src/battle/game-logic/btl_victory.erl b/src/battle/game-logic/btl_victory.erl deleted file mode 100644 index 089af81..0000000 --- a/src/battle/game-logic/btl_victory.erl +++ /dev/null @@ -1,208 +0,0 @@ --module(btl_victory). -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --export -( - [ - handle_character_lost_health/3 - ] -). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - --spec mark_players_characters_as_defeated - ( - non_neg_integer(), - orddict:orddict(non_neg_integer(), btl_character:type()) - ) - -> - { - orddict:orddict(non_neg_integer(), btl_character:type()), - list(ataxic:basic()) - }. -mark_players_characters_as_defeated (PlayerIX, Characters) -> - orddict:fold - ( - fun (IX, Character, {Dict, Updates}) -> - case (btl_character:get_player_index(Character) == PlayerIX) of - false -> {Dict, Updates}; - true -> - { - orddict:store - ( - IX, - btl_character:set_is_defeated(true, Character), - Dict - ), - [ - ataxic_sugar:update_orddict_element - ( - IX, - ataxic:update_field - ( - btl_character:get_is_defeated_field(), - ataxic:constant(true) - ) - ) - ] - } - end - end, - {Characters, []}, - Characters - ). - --spec handle_player_defeat - ( - non_neg_integer(), - btl_character_turn_update:type() - ) - -> btl_character_turn_update:type(). -handle_player_defeat (PlayerIX, Update) -> - Data = btl_character_turn_update:get_data(Update), - Battle = btl_character_turn_data:get_battle(Data), - Characters = btl_battle:get_characters(Battle), - - %% FIXME [FUNCTION: battle][MEDIUM]: The controlled character might slip - %% through. - {UpdatedCharacters, AtaxicUpdates} = - mark_players_characters_as_defeated(PlayerIX, Characters), - - S0Battle = btl_battle:set_characters(UpdatedCharacters, Battle), - S1Battle = - btl_battle:set_player - ( - PlayerIX, - btl_player:set_is_active - ( - false, - btl_battle:get_player(PlayerIX, S0Battle) - ), - S0Battle - ), - - UpdatedData = btl_character_turn_data:set_battle(S1Battle, Data), - S0Update = btl_character_turn_update:set_data(UpdatedData, Update), - - DBQuery = - ataxic:sequence - ( - [ - ataxic:update_field - ( - btl_battle:get_players_field(), - ataxic_sugar:update_orddict_element - ( - PlayerIX, - ataxic:update_field - ( - btl_player:get_is_active_field(), - ataxic:constant(false) - ) - ) - ), - ataxic:update_field - ( - btl_battle:get_characters_field(), - ataxic:sequence(AtaxicUpdates) - ) - ] - ), - - S1Update = - btl_character_turn_update:add_to_timeline - ( - btl_turn_result:new_player_lost(PlayerIX), - DBQuery, - S0Update - ), - - S1Update. - - --spec actually_handle_character_lost_health - ( - non_neg_integer(), - btl_character_turn_update:type() - ) - -> btl_character_turn_update:type(). -actually_handle_character_lost_health (CharIX, Update) -> - Data = btl_character_turn_update:get_data(Update), - Battle = btl_character_turn_data:get_battle(Data), - Character = btl_battle:get_character(CharIX, Battle), - Characters = btl_battle:get_characters(Battle), - CharacterPlayerIX = btl_character:get_player_index(Character), - - case btl_character:get_rank(Character) of - optional -> - %% Let's not assume there is a commander - StillHasAliveChar = - lists:any - ( - fun ({IX, Char}) -> - ( - (CharacterPlayerIX == btl_character:get_player_index(Char)) - and (IX /= CharIX) - and btl_character:get_is_alive(Char) - ) - end, - orddict:to_list(Characters) - ), - - case StillHasAliveChar of - true -> Update; - _ -> handle_player_defeat(CharacterPlayerIX, Update) - end; - - commander -> handle_player_defeat(CharacterPlayerIX, Update); - - target -> - StillHasAliveChar = - lists:any - ( - fun ({IX, Char}) -> - ( - (CharacterPlayerIX == btl_character:get_player_index(Char)) - and (IX /= CharIX) - and btl_character:get_is_alive(Char) - ) - end, - orddict:to_list(Characters) - ), - - case StillHasAliveChar of - true -> Update; - _ -> handle_player_defeat(CharacterPlayerIX, Update) - end - end. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec handle_character_lost_health - ( - non_neg_integer(), - integer(), - btl_character_turn_update:type() - ) - -> btl_character_turn_update:type(). -handle_character_lost_health (_, Health, Update) when (Health > 0) -> Update; -handle_character_lost_health (CharIX, _Health, Update) -> - Data = btl_character_turn_update:get_data(Update), - S1Data = btl_character_turn_data:clean_battle(Data), - S1Update = btl_character_turn_update:set_data(S1Data, Update), - - S2Update = actually_handle_character_lost_health(CharIX, S1Update), - - S2Data = btl_character_turn_update:get_data(S2Update), - S3Data = btl_character_turn_data:refreshr_character(S2Data), - S3Update = btl_character_turn_update:set_data(S3Data, S2Update), - - S3Update. diff --git a/src/battle/mechanic/btl_next_turn.erl b/src/battle/mechanic/btl_next_turn.erl new file mode 100644 index 0000000..886916d --- /dev/null +++ b/src/battle/mechanic/btl_next_turn.erl @@ -0,0 +1,184 @@ +-module(btl_next_turn). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export +( + [ + update_if_needed/1 + ] +). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec set_player_turn_to_next (btl_battle:type()) + -> {btl_battle:type(), ataxic:basic()}. +set_player_turn_to_next (Battle) -> + Players = btl_battle:get_players(Battle), + CurrentPlayerTurn = btl_battle:get_current_player_turn(Battle), + + NextPlayerTurn = btl_player_turn:next(Players, CurrentPlayerTurn), + + UpdatedBattle = btl_battle:set_current_player_turn(NextPlayerTurn, Battle), + + DBQuery = + ataxic:update_field + ( + btl_battle:get_current_player_turn_field(), + ataxic:constant(NextPlayerTurn) + ), + + {UpdatedBattle, DBQuery}. + +-spec reset_next_player_timeline (btl_battle:type()) + -> {btl_battle:type(), btl_player:type(), ataxic:basic()}. +reset_next_player_timeline (Battle) -> + NextPlayerTurn = btl_battle:get_current_player_turn(Battle), + NextPlayerIX = btl_player_turn:get_player_ix(NextPlayerTurn), + NextPlayer = btl_battle:get_player(NextPlayerIX, Battle), + + UpdatedNextPlayer = btl_player:reset_timeline(NextPlayer), + UpdatedBattle = + btl_battle:set_player(NextPlayerIX, UpdatedNextPlayer, Battle), + + DBQuery = + ataxic:update_field + ( + btl_battle:get_players_field(), + ataxic_sugar:update_orddict_element + ( + NextPlayerIX, + ataxic:update_field + ( + btl_player:get_timeline_field(), + ataxic:constant([]) + ) + ) + ), + + {UpdatedBattle, UpdatedNextPlayer, DBQuery}. + + +-spec activate_next_players_characters (btl_battle:type(), btl_player:type()) + -> {btl_battle:type(), ataxic:basic()}. +activate_next_players_characters (Battle, NextPlayer) -> + NextPlayerIX = btl_player:get_index(NextPlayer), + Characters = btl_battle:get_characters(Battle), + + {UpdatedCharacters, AtaxicUpdates} = + orddict:fold + ( + fun (IX, Character, {Prev, Updates}) -> + case (btl_character:get_player_index(Character) == NextPlayerIX) of + true -> + { + orddict:store + ( + IX, + btl_character:set_is_active(true, Character), + Prev + ), + [ + ataxic_sugar:update_orddict_element + ( + IX, + ataxic:update_field + ( + btl_character:get_is_active_field(), + ataxic:constant(true) + ) + )|Updates + ] + }; + + false -> {Prev, Updates} + end + end, + {Characters, []}, + Characters + ), + + DBQuery = + ataxic:update_field + ( + btl_battle:get_characters_field(), + ataxic:sequence(AtaxicUpdates) + ), + + UpdatedBattle = btl_battle:set_characters(UpdatedCharacters, Battle), + + {UpdatedBattle, DBQuery}. + +-spec update + ( + btl_character_turn_update:type() + ) + -> btl_character_turn_update:type(). +update (Update) -> + Data = btl_character_turn_update:get_data(Update), + Battle = btl_character_turn_data:get_battle(Data), + + {S0Battle, DBQuery0} = set_player_turn_to_next(Battle), + {S1Battle, NextPlayer, DBQuery1} = reset_next_player_timeline(S0Battle), + {S2Battle, DBQuery2} = + activate_next_players_characters(S1Battle, NextPlayer), + + S0Data = btl_character_turn_data:set_battle(S2Battle, Data), + S0Update = + btl_character_turn_update:add_to_timeline + ( + btl_turn_result:new_player_turn_started + ( + btl_player:get_index(NextPlayer) + ), + DBQuery0, + Update + ), + + S1Update = btl_character_turn_update:set_data(S0Data, S0Update), + + S2Update = + lists:foldl + ( + fun btl_character_turn_update:add_to_db/2, + S1Update, + [DBQuery1,DBQuery2] + ), + + S2Update. + +-spec requires_update (btl_character_turn_update:type()) -> boolean(). +requires_update (Update) -> + Data = btl_character_turn_update:get_data(Update), + Battle = btl_character_turn_data:get_battle(Data), + Characters = btl_battle:get_characters(Battle), + + (not + (lists:any + ( + fun ({_IX, Char}) -> + btl_character:get_is_active(Char) + end, + orddict:to_list(Characters) + ) + ) + ). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec update_if_needed + ( + btl_character_turn_update:type() + ) + -> btl_character_turn_update:type(). +update_if_needed (Update) -> + case requires_update(Update) of + true -> update(Update); + _ -> Update + end. diff --git a/src/battle/mechanic/btl_turn_actions.erl b/src/battle/mechanic/btl_turn_actions.erl new file mode 100644 index 0000000..d4a81fc --- /dev/null +++ b/src/battle/mechanic/btl_turn_actions.erl @@ -0,0 +1,83 @@ +-module(btl_turn_actions). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export +( + [ + apply_requested_actions/2 + ] +). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Move elsewhere + +%%%% TODO: move this elsewhere +-spec finalize_character + ( + btl_character_turn_update:type() + ) + -> btl_character_turn_update:type(). +finalize_character (Update) -> + Data = btl_character_turn_update:get_data(Update), + Character = btl_character_turn_data:get_character(Data), + + DisabledCharacter = btl_character:set_is_active(false, Character), + UpdatedData = btl_character_turn_data:set_character(DisabledCharacter, Data), + FinalizedData = btl_character_turn_data:clean_battle(UpdatedData), + + DBQuery = + ataxic:update_field + ( + btl_battle:get_characters_field(), + ataxic_sugar:update_orddict_element + ( + btl_character_turn_data:get_character_ix(Data), + ataxic:update_field + ( + btl_character:get_is_active_field(), + ataxic:constant(false) + ) + ) + ), + + S0Update = btl_character_turn_update:set_data(FinalizedData, Update), + S1Update = btl_character_turn_update:add_to_db(DBQuery, S0Update), + + S1Update. + +-spec handle +( + btl_battle_action:type(), + btl_character_turn_update:type() +) +-> btl_character_turn_update:type(). +handle (BattleAction, Update) -> + case btl_battle_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) + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec apply_requested_actions + ( + btl_character_turn_data:type(), + btl_character_turn_request:type() + ) + -> btl_character_turn_update:type(). +apply_requested_actions (Data, Request) -> + Actions = btl_character_turn_request:get_actions(Request), + + EmptyUpdate = btl_character_turn_update:new(Data), + PostActionsUpdate = lists:foldl(fun handle/2, EmptyUpdate, Actions), + + finalize_character(PostActionsUpdate). diff --git a/src/battle/mechanic/btl_victory.erl b/src/battle/mechanic/btl_victory.erl new file mode 100644 index 0000000..089af81 --- /dev/null +++ b/src/battle/mechanic/btl_victory.erl @@ -0,0 +1,208 @@ +-module(btl_victory). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export +( + [ + handle_character_lost_health/3 + ] +). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +-spec mark_players_characters_as_defeated + ( + non_neg_integer(), + orddict:orddict(non_neg_integer(), btl_character:type()) + ) + -> + { + orddict:orddict(non_neg_integer(), btl_character:type()), + list(ataxic:basic()) + }. +mark_players_characters_as_defeated (PlayerIX, Characters) -> + orddict:fold + ( + fun (IX, Character, {Dict, Updates}) -> + case (btl_character:get_player_index(Character) == PlayerIX) of + false -> {Dict, Updates}; + true -> + { + orddict:store + ( + IX, + btl_character:set_is_defeated(true, Character), + Dict + ), + [ + ataxic_sugar:update_orddict_element + ( + IX, + ataxic:update_field + ( + btl_character:get_is_defeated_field(), + ataxic:constant(true) + ) + ) + ] + } + end + end, + {Characters, []}, + Characters + ). + +-spec handle_player_defeat + ( + non_neg_integer(), + btl_character_turn_update:type() + ) + -> btl_character_turn_update:type(). +handle_player_defeat (PlayerIX, Update) -> + Data = btl_character_turn_update:get_data(Update), + Battle = btl_character_turn_data:get_battle(Data), + Characters = btl_battle:get_characters(Battle), + + %% FIXME [FUNCTION: battle][MEDIUM]: The controlled character might slip + %% through. + {UpdatedCharacters, AtaxicUpdates} = + mark_players_characters_as_defeated(PlayerIX, Characters), + + S0Battle = btl_battle:set_characters(UpdatedCharacters, Battle), + S1Battle = + btl_battle:set_player + ( + PlayerIX, + btl_player:set_is_active + ( + false, + btl_battle:get_player(PlayerIX, S0Battle) + ), + S0Battle + ), + + UpdatedData = btl_character_turn_data:set_battle(S1Battle, Data), + S0Update = btl_character_turn_update:set_data(UpdatedData, Update), + + DBQuery = + ataxic:sequence + ( + [ + ataxic:update_field + ( + btl_battle:get_players_field(), + ataxic_sugar:update_orddict_element + ( + PlayerIX, + ataxic:update_field + ( + btl_player:get_is_active_field(), + ataxic:constant(false) + ) + ) + ), + ataxic:update_field + ( + btl_battle:get_characters_field(), + ataxic:sequence(AtaxicUpdates) + ) + ] + ), + + S1Update = + btl_character_turn_update:add_to_timeline + ( + btl_turn_result:new_player_lost(PlayerIX), + DBQuery, + S0Update + ), + + S1Update. + + +-spec actually_handle_character_lost_health + ( + non_neg_integer(), + btl_character_turn_update:type() + ) + -> btl_character_turn_update:type(). +actually_handle_character_lost_health (CharIX, Update) -> + Data = btl_character_turn_update:get_data(Update), + Battle = btl_character_turn_data:get_battle(Data), + Character = btl_battle:get_character(CharIX, Battle), + Characters = btl_battle:get_characters(Battle), + CharacterPlayerIX = btl_character:get_player_index(Character), + + case btl_character:get_rank(Character) of + optional -> + %% Let's not assume there is a commander + StillHasAliveChar = + lists:any + ( + fun ({IX, Char}) -> + ( + (CharacterPlayerIX == btl_character:get_player_index(Char)) + and (IX /= CharIX) + and btl_character:get_is_alive(Char) + ) + end, + orddict:to_list(Characters) + ), + + case StillHasAliveChar of + true -> Update; + _ -> handle_player_defeat(CharacterPlayerIX, Update) + end; + + commander -> handle_player_defeat(CharacterPlayerIX, Update); + + target -> + StillHasAliveChar = + lists:any + ( + fun ({IX, Char}) -> + ( + (CharacterPlayerIX == btl_character:get_player_index(Char)) + and (IX /= CharIX) + and btl_character:get_is_alive(Char) + ) + end, + orddict:to_list(Characters) + ), + + case StillHasAliveChar of + true -> Update; + _ -> handle_player_defeat(CharacterPlayerIX, Update) + end + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec handle_character_lost_health + ( + non_neg_integer(), + integer(), + btl_character_turn_update:type() + ) + -> btl_character_turn_update:type(). +handle_character_lost_health (_, Health, Update) when (Health > 0) -> Update; +handle_character_lost_health (CharIX, _Health, Update) -> + Data = btl_character_turn_update:get_data(Update), + S1Data = btl_character_turn_data:clean_battle(Data), + S1Update = btl_character_turn_update:set_data(S1Data, Update), + + S2Update = actually_handle_character_lost_health(CharIX, S1Update), + + S2Data = btl_character_turn_update:get_data(S2Update), + S3Data = btl_character_turn_data:refreshr_character(S2Data), + S3Update = btl_character_turn_update:set_data(S3Data, S2Update), + + S3Update. diff --git a/src/battle/mechanic/turn_action/btl_turn_actions_attack.erl b/src/battle/mechanic/turn_action/btl_turn_actions_attack.erl new file mode 100644 index 0000000..52dd3fb --- /dev/null +++ b/src/battle/mechanic/turn_action/btl_turn_actions_attack.erl @@ -0,0 +1,225 @@ +-module(btl_turn_actions_attack). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export +( + [ + handle/2 + ] +). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec handle_attack_sequence + ( + btl_character_current_data:type(), + non_neg_integer(), + btl_character_current_data:type(), + non_neg_integer(), + list(btl_attack:step()) + ) + -> {list(btl_attack:type()), non_neg_integer(), non_neg_integer()}. +handle_attack_sequence +( + CharacterCurrentData, + CharacterCurrentHealth, + TargetCurrentData, + TargetCurrentHealth, + AttackSequence +) -> + AttackPlannedEffects = + lists:map + ( + fun (AttackStep) -> + btl_attack:get_description_of + ( + AttackStep, + CharacterCurrentData, + TargetCurrentData + ) + end, + AttackSequence + ), + + lists:foldl + ( + fun + ( + AttackEffectCandidate, + {AttackValidEffects, AttackerHealth, DefenderHealth} + ) -> + {AttackResult, NewAttackerHealth, NewDefenderHealth} = + btl_attack:apply_to_healths + ( + AttackEffectCandidate, + AttackerHealth, + DefenderHealth + ), + case AttackResult of + nothing -> {AttackValidEffects, AttackerHealth, DefenderHealth}; + _ -> + { + (AttackValidEffects ++ [AttackResult]), + NewAttackerHealth, + NewDefenderHealth + } + end + end, + { + [], + CharacterCurrentHealth, + TargetCurrentHealth + }, + AttackPlannedEffects + ). + +-spec get_attack_sequence + ( + btl_character:type(), + btl_character:type() + ) + -> list(btl_attack:step()). +get_attack_sequence (Character, TargetCharacter) -> + Range = + btl_location:dist + ( + btl_character:get_location(Character), + btl_character:get_location(TargetCharacter) + ), + + {AttackingWeaponID, _} = btl_character:get_weapon_ids(Character), + {DefendingWeaponID, _} = btl_character:get_weapon_ids(TargetCharacter), + + AttackingWeapon = shr_weapon:from_id(AttackingWeaponID), + DefendingWeapon = shr_weapon:from_id(DefendingWeaponID), + + btl_attack:get_sequence(Range, AttackingWeapon, DefendingWeapon). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec handle + ( + btl_battle_action:type(), + btl_character_turn_update:type() + ) + -> btl_character_turn_update:type(). +handle (BattleAction, Update) -> + Data = btl_character_turn_update:get_data(Update), + Battle = btl_character_turn_data:get_battle(Data), + Character = btl_character_turn_data:get_character(Data), + CharacterIX = btl_character_turn_data:get_character_ix(Data), + CharacterCurrentData = + btl_character_turn_data:get_character_current_data(Data), + + Map = btl_battle:get_map(Battle), + TargetIX = btl_battle_action:get_target_ix(BattleAction), + TargetCharacter = btl_battle:get_character(TargetIX, Battle), + TargetCurrentData = btl_character_current_data:new(TargetCharacter, Map), + + true = btl_character:get_is_alive(TargetCharacter), + + AttackSequence = get_attack_sequence(Character, TargetCharacter), + + {AttackEffects, RemainingAttackerHealth, RemainingDefenderHealth} = + handle_attack_sequence + ( + CharacterCurrentData, + btl_character:get_current_health(Character), + TargetCurrentData, + btl_character:get_current_health(TargetCharacter), + AttackSequence + ), + + UpdatedCharacter = + btl_character:set_current_health(RemainingAttackerHealth, Character), + + UpdatedBattle = + btl_battle:set_character + ( + TargetIX, + btl_character:set_current_health + ( + RemainingDefenderHealth, + TargetCharacter + ), + Battle + ), + + S0Data = btl_character_turn_data:set_battle(UpdatedBattle, Data), + S1Data = btl_character_turn_data:set_character(UpdatedCharacter, S0Data), + + TimelineItem = + btl_turn_result:new_character_attacked + ( + CharacterIX, + TargetIX, + AttackEffects + ), + + DBQuery0 = + ataxic:update_field + ( + btl_battle:get_characters_field(), + ataxic_sugar:update_orddict_element + ( + TargetIX, + ataxic:update_field + ( + btl_character:get_current_health_field(), + ataxic:constant(RemainingDefenderHealth) + ) + ) + ), + + DBQuery1 = + ataxic:update_field + ( + btl_battle:get_characters_field(), + ataxic_sugar:update_orddict_element + ( + CharacterIX, + ataxic:update_field + ( + btl_character:get_current_health_field(), + ataxic:constant(RemainingAttackerHealth) + ) + ) + ), + + S0Update = + btl_character_turn_update:add_to_timeline + ( + TimelineItem, + DBQuery0, + Update + ), + + S1Update = btl_character_turn_update:add_to_db(DBQuery1, S0Update), + S2Update = btl_character_turn_update:set_data(S1Data, S1Update), + + S3Update = + btl_victory:handle_character_lost_health + ( + CharacterIX, + RemainingAttackerHealth, + S2Update + ), + + S4Update = + btl_victory:handle_character_lost_health + ( + TargetIX, + RemainingDefenderHealth, + S3Update + ), + + S4Update. diff --git a/src/battle/mechanic/turn_action/btl_turn_actions_move.erl b/src/battle/mechanic/turn_action/btl_turn_actions_move.erl new file mode 100644 index 0000000..bf023d5 --- /dev/null +++ b/src/battle/mechanic/turn_action/btl_turn_actions_move.erl @@ -0,0 +1,186 @@ +-module(btl_turn_actions_move). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export +( + [ + handle/2 + ] +). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec cross + ( + btl_map:type(), + list(btl_location:type()), + list(btl_direction:enum()), + non_neg_integer(), + btl_location:type() + ) + -> {btl_location:type(), non_neg_integer()}. +cross (_Map, _ForbiddenLocations, [], Cost, Location) -> + {Location, Cost}; +cross (Map, ForbiddenLocations, [Step|NextSteps], Cost, Location) -> + NextLocation = btl_location:apply_direction(Step, Location), + NextTileInstance = btl_map:get_tile_instance(NextLocation, Map), + NextTileClassID = shr_tile:extract_main_class_id(NextTileInstance), + NextTile = shr_tile:from_class_id(NextTileClassID), + NextCost = (Cost + shr_tile:get_cost(NextTile)), + IsForbidden = + lists:foldl + ( + fun (ForbiddenLocation, Prev) -> + (Prev or (NextLocation == ForbiddenLocation)) + end, + false, + ForbiddenLocations + ), + + IsForbidden = false, + + cross(Map, ForbiddenLocations, NextSteps, NextCost, NextLocation). + +-spec cross + ( + btl_map:type(), + list(btl_location:type()), + list(btl_direction:enum()), + btl_location:type() + ) + -> {btl_location:type(), non_neg_integer()}. +cross (Map, ForbiddenLocations, Path, Location) -> + cross(Map, ForbiddenLocations, Path, 0, Location). + +-spec get_path_cost_and_destination + ( + btl_character_turn_data:type(), + list(btl_direction:type()) + ) + -> {non_neg_integer(), btl_location:type()}. +get_path_cost_and_destination (Data, Path) -> + Character = btl_character_turn_data:get_character(Data), + CharacterIX = btl_character_turn_data:get_character_ix(Data), + Battle = btl_character_turn_data:get_battle(Data), + Map = btl_battle:get_map(Battle), + + 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, Cost} = + cross + ( + Map, + ForbiddenLocations, + Path, + btl_character:get_location(Character) + ), + + {Cost, NewLocation}. + +-spec assert_character_can_move + ( + btl_character_turn_data:type(), + non_neg_integer() + ) + -> 'ok'. +assert_character_can_move (Data, Cost) -> + CharacterData = btl_character_turn_data:get_character_current_data(Data), + CharacterStats= btl_character_current_data:get_statistics(CharacterData), + CharacterMovementPoints = shr_statistics:get_movement_points(CharacterStats), + + true = (Cost =< CharacterMovementPoints), + + ok. + +-spec commit_move + ( + btl_character_current_data:type(), + btl_character_turn_update:type(), + list(btl_direction:type()), + btl_location:type() + ) + -> btl_character_turn_update:type(). +commit_move (PreviousCurrentData, Update, Path, NewLocation) -> + Data = btl_character_turn_update:get_data(Update), + Character = btl_character_turn_data:get_character(Data), + CharacterIX = btl_character_turn_data:get_character_ix(Data), + + UpdatedCharacter = btl_character:set_location(NewLocation, Character), + S0Data = btl_character_turn_data:set_character(UpdatedCharacter, Data), + S1Data = btl_character_turn_data:refresh_character_current_data(S0Data), + + S0Update = btl_character_turn_update:set_data(S1Data, Update), + S1Update = + btl_turn_actions_stats_change:handle_max_health_changes + ( + PreviousCurrentData, + S0Update + ), + + TimelineItem = + btl_turn_result:new_character_moved(CharacterIX, Path, NewLocation), + + DBQuery = + ataxic:update_field + ( + btl_battle:get_characters_field(), + ataxic_sugar:update_orddict_element + ( + CharacterIX, + ataxic:update_field + ( + btl_character:get_location_field(), + ataxic:constant(NewLocation) + ) + ) + ), + + S2Update = + btl_character_turn_update:add_to_timeline + ( + TimelineItem, + DBQuery, + S1Update + ), + + S2Update. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec handle + ( + btl_battle_action:type(), + btl_character_turn_update:type() + ) + -> btl_character_turn_update:type(). +handle (BattleAction, Update) -> + Data = btl_character_turn_update:get_data(Update), + CharacterCurrentData = + btl_character_turn_data:get_character_current_data(Data), + Path = btl_battle_action:get_path(BattleAction), + + {PathCost, NewLocation} = get_path_cost_and_destination(Data, Path), + assert_character_can_move(Data, PathCost), + + commit_move(CharacterCurrentData, Update, Path, NewLocation). diff --git a/src/battle/mechanic/turn_action/btl_turn_actions_stats_change.erl b/src/battle/mechanic/turn_action/btl_turn_actions_stats_change.erl new file mode 100644 index 0000000..5fe5444 --- /dev/null +++ b/src/battle/mechanic/turn_action/btl_turn_actions_stats_change.erl @@ -0,0 +1,85 @@ +-module(btl_turn_actions_stats_change). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export +( + [ + handle_max_health_changes/2 + ] +). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec mod_current_health + ( + non_neg_integer(), + non_neg_integer(), + btl_character_turn_update:type() + ) + -> btl_character_turn_update:type(). +mod_current_health (CurrentMaxHealth, PreviousMaxHealth, Update) -> + Data = btl_character_turn_update:get_data(Update), + Character = btl_character_turn_data:get_character(Data), + CharacterIX = btl_character_turn_data:get_character_ix(Data), + PreviousHealth = btl_character:get_current_health(Character), + + PreviousHealthRatio = (PreviousHealth / PreviousMaxHealth), + NewHealth = + min + ( + CurrentMaxHealth, + max(1, round(PreviousHealthRatio * CurrentMaxHealth)) + ), + + UpdatedCharacter = btl_character:set_current_health(NewHealth, Character), + UpdatedData = btl_character_turn_data:set_character(UpdatedCharacter, Data), + S0Update = btl_character_turn_update:set_data(UpdatedData, Update), + + DBQuery = + ataxic:update_field + ( + btl_battle:get_characters_field(), + ataxic_sugar:update_orddict_element + ( + CharacterIX, + ataxic:update_field + ( + btl_character:get_current_health_field(), + ataxic:constant(NewHealth) + ) + ) + ), + + S1Update = btl_character_turn_update:add_to_db(DBQuery, S0Update), + + S1Update. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec handle_max_health_changes + ( + btl_character_current_data:type(), + btl_character_turn_update:type() + ) + -> btl_character_turn_update:type(). +handle_max_health_changes (PreviousData, Update) -> + Data = btl_character_turn_update:get_data(Update), + CurrentData = btl_character_turn_data:get_character_current_data(Data), + CurrentStats = btl_character_current_data:get_statistics(CurrentData), + PreviousStats = btl_character_current_data:get_statistics(PreviousData), + + CurrentMaxHealth = shr_statistics:get_health(CurrentStats), + PreviousMaxHealth = shr_statistics:get_health(PreviousStats), + + case (CurrentMaxHealth == PreviousMaxHealth) of + true -> Update; + _ -> mod_current_health(CurrentMaxHealth, PreviousMaxHealth, Update) + 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 new file mode 100644 index 0000000..119dbe7 --- /dev/null +++ b/src/battle/mechanic/turn_action/btl_turn_actions_switch_weapon.erl @@ -0,0 +1,68 @@ +-module(btl_turn_actions_switch_weapon). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export +( + [ + handle/1 + ] +). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec handle + ( + btl_character_turn_update:type() + ) + -> btl_character_turn_update:type(). +handle (Update) -> + Data = btl_character_turn_update:get_data(Update), + Character = btl_character_turn_data:get_character(Data), + CharacterCurrentData = + btl_character_turn_data:get_character_current_data(Data), + CharacterIX = btl_character_turn_data:get_character_ix(Data), + + {PrimaryWeaponID, SecondaryWeaponID} = btl_character:get_weapon_ids(Character), + + UpdatedWeaponIDs = {SecondaryWeaponID, PrimaryWeaponID}, + UpdatedCharacter = btl_character:set_weapon_ids(UpdatedWeaponIDs, Character), + + S0Data = btl_character_turn_data:set_character(UpdatedCharacter, Data), + S1Data = btl_character_turn_data:refresh_character_current_data(S0Data), + + S0Update = btl_character_turn_update:set_data(S1Data, Update), + S1Update = + btl_turn_actions_stats_change:handle_max_health_changes + ( + CharacterCurrentData, + S0Update + ), + + TimelineItem = btl_turn_result:new_character_switched_weapons(CharacterIX), + + DBQuery = + ataxic:update_field + ( + btl_battle:get_characters_field(), + ataxic_sugar:update_orddict_element + ( + CharacterIX, + ataxic:update_field + ( + btl_character:get_weapons_field(), + ataxic:constant(UpdatedWeaponIDs) + ) + ) + ), + + btl_character_turn_update:add_to_timeline(TimelineItem, DBQuery, S1Update). diff --git a/src/battle/query/btl_character_turn.erl b/src/battle/query/btl_character_turn.erl index 32ec9be..90afba8 100644 --- a/src/battle/query/btl_character_turn.erl +++ b/src/battle/query/btl_character_turn.erl @@ -113,54 +113,8 @@ assert_user_permissions (Data, Request) -> ok. %%%% QUERY LOGIC HANDLING %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec finalize_character - ( - btl_character_turn_update:type() - ) - -> btl_character_turn_update:type(). -finalize_character (Update) -> - Data = btl_character_turn_update:get_data(Update), - Character = btl_character_turn_data:get_character(Data), - - DisabledCharacter = btl_character:set_is_active(false, Character), - UpdatedData = btl_character_turn_data:set_character(DisabledCharacter, Data), - FinalizedData = btl_character_turn_data:clean_battle(UpdatedData), - - DBQuery = - ataxic:update_field - ( - btl_battle:get_characters_field(), - ataxic_sugar:update_orddict_element - ( - btl_character_turn_data:get_character_ix(Data), - ataxic:update_field - ( - btl_character:get_is_active_field(), - ataxic:constant(false) - ) - ) - ), - - S0Update = btl_character_turn_update:set_data(FinalizedData, Update), - S1Update = btl_character_turn_update:add_to_db(DBQuery, S0Update), - - S1Update. - --spec handle_actions - ( - btl_character_turn_data:type(), - btl_character_turn_request:type() - ) - -> btl_character_turn_update:type(). -handle_actions (Data, Request) -> - Actions = btl_character_turn_request:get_actions(Request), - - EmptyUpdate = btl_character_turn_update:new(Data), - PostActionsUpdate = - lists:foldl(fun btl_turn_actions:handle/2, EmptyUpdate, Actions), - - finalize_character(PostActionsUpdate). +%%%% TODO: move this elsewhere -spec update_timeline ( btl_character_turn_update:type() @@ -214,7 +168,7 @@ update_timeline (Update) -> ) -> btl_character_turn_update:type(). update_data (Data, Request) -> - PostActionsUpdate = handle_actions(Data, Request), + PostActionsUpdate = btl_turn_actions:apply_requested_actions(Data, Request), PostCharacterTurnUpdate = update_timeline(PostActionsUpdate), btl_next_turn:update_if_needed(PostCharacterTurnUpdate). @@ -276,15 +230,6 @@ commit_update (Update, Request) -> ok. -%%%% USER DISCONNECTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec disconnect_user (btl_character_turn_request:type()) -> 'ok'. -disconnect_user (Request) -> - PlayerID = btl_character_turn_request:get_player_id(Request), - - shr_security:unlock_queries(PlayerID), - - ok. - %%%% REPLY GENERATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -spec generate_reply (btl_character_turn_update:type()) -> binary(). generate_reply (Update) -> @@ -301,12 +246,16 @@ handle (EncodedRequest) -> case authenticate_user(Request) of ok -> PlayerID = btl_character_turn_request:get_player_id(Request), + shr_security:lock_queries(PlayerID), + Data = fetch_data(Request), assert_user_permissions(Data, Request), Update = update_data(Data, Request), commit_update(Update, Request), - disconnect_user(Request), + + shr_security:unlock_queries(PlayerID), + generate_reply(Update); error -> jiffy:encode([shr_disconnected:generate()]) -- cgit v1.2.3-70-g09d2