| summaryrefslogtreecommitdiff | 
diff options
Diffstat (limited to 'src/query')
| -rw-r--r-- | src/query/character_turn.erl | 200 | ||||
| -rw-r--r-- | src/query/character_turn/handle_character_attacking_2.erl | 59 | ||||
| -rw-r--r-- | src/query/character_turn/handle_character_instance_attacking_2.erl | 358 | 
3 files changed, 469 insertions, 148 deletions
| diff --git a/src/query/character_turn.erl b/src/query/character_turn.erl index d71c64a..19b6cff 100644 --- a/src/query/character_turn.erl +++ b/src/query/character_turn.erl @@ -12,9 +12,9 @@        player_id,        session_token,        battlemap_instance_id, -      character_instance_id, +      character_instance_ix,        path, -      target_id +      target_ix     }  ). @@ -23,8 +23,17 @@     query_state,     {        battlemap_instance, -      character_instance, -      rolls +      character_instance +   } +). + +-record +( +   query_result, +   { +      is_new_turn, +      updated_character_instance_ixs, +      updated_battlemap_instance     }  ). @@ -38,16 +47,16 @@  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  parse_input (Req) ->     JSONReqMap = jiffy:decode(Req, [return_maps]), -   CharacterInstanceID = binary_to_integer(maps:get(<<"cid">>, JSONReqMap)), -   TargetID = binary_to_integer(maps:get(<<"tid">>, JSONReqMap)), +   CharacterInstanceIX = binary_to_integer(maps:get(<<"cix">>, JSONReqMap)), +   TargetIX = binary_to_integer(maps:get(<<"tix">>, JSONReqMap)),     #input     {        player_id = maps:get(<<"pid">>, JSONReqMap),        session_token = maps:get(<<"stk">>, JSONReqMap),        battlemap_instance_id = maps:get(<<"bmp">>, JSONReqMap), -      character_instance_id = CharacterInstanceID, +      character_instance_ix = CharacterInstanceIX,        path = maps:get(<<"p">>, JSONReqMap), -      target_id = TargetID +      target_ix = TargetIX     }.  fetch_data (Input) -> @@ -61,17 +70,16 @@ fetch_data (Input) ->     CharacterInstance =        array:get        ( -         Input#input.character_instance_id, +         Input#input.character_instance_ix,           battlemap_instance:get_character_instances(BattlemapInstance)        ),     #query_state     {        battlemap_instance = BattlemapInstance, -      character_instance = CharacterInstance, -      rolls = [] +      character_instance = CharacterInstance     }. -assert_character_can_be_played (QueryState, Input) -> +assert_character_instance_can_be_played (QueryState, Input) ->     %%% Var     BattlemapInstance = QueryState#query_state.battlemap_instance,     PlayerID = Input#input.player_id, @@ -80,20 +88,20 @@ assert_character_can_be_played (QueryState, Input) ->     PlayerID =        arrays:get        ( -         player_turn:get_player_id +         player_turn:get_player_ix           (              battlemap_instance:get_player_turn(BattlemapInstance)           ), -         battlemap_instance:get_players(BattlemapInstance) +         battlemap_instance:get_player_ids(BattlemapInstance)        ),     PlayerID = -      character:get_owner +      character:get_owner_id        (           character_instance:get_character(ControlledCharacterInstance)        ), -   true = character_instance:is_active(ControlledCharacterInstance). +   true = character_instance:get_is_active(ControlledCharacterInstance). -handle_character_moving (QueryState, Input) -> +handle_character_instance_moving (QueryState, Input) ->     BattlemapInstance = QueryState#query_state.battlemap_instance,     ControlledCharacterInstance = QueryState#query_state.character_instance,     ControlledCharacter = @@ -130,10 +138,12 @@ handle_character_moving (QueryState, Input) ->           )     }. -handle_character_switching_weapons (QueryState) -> +handle_character_instance_switching_weapons (QueryState) ->     ControlledCharacterInstance = QueryState#query_state.character_instance,     ControlledCharacter =        character_instance:get_character(ControlledCharacterInstance), +   {PrimaryWeapon, SecondaryWeapon} = +      character:get_weapons(ControlledCharacter),     QueryState#query_state     {        character_instance = @@ -141,20 +151,17 @@ handle_character_switching_weapons (QueryState) ->           (              character:set_weapons              ( -               weapon_set:switch -               ( -                  character:get_weapons(ControlledCharacter) -               ), +               {SecondaryWeapon, PrimaryWeapon},                 ControlledCharacter              ),              ControlledCharacterInstance           )     }. --include("character_turn/handle_character_attacking_2.erl"). +-include("character_turn/handle_character_instance_attacking_2.erl").  get_type_of_turn (Input) -> -   case {Input#input.path, Input#input.target_id} of +   case {Input#input.path, Input#input.target_ix} of        {[], -1} -> [nothing, nothing];        {[], _} -> [nothing, attack];        {[<<"S">>], -1} -> [switch, nothing]; @@ -174,131 +181,137 @@ finalize_character_instance (QueryState, Input) ->     QueryState#query_state     {        battlemap_instance = -         battlemap_instance:set_characters +         battlemap_instance:set_character_instances           (              array:set              ( -               Input#input.character_instance_id, +               Input#input.character_instance_ix,                 FinalizedCharacterInstance, -               battlemap_instance:get_characters(BattlemapInstance) +               battlemap_instance:get_character_instances(BattlemapInstance)              ),              BattlemapInstance           ),        character_instance = FinalizedCharacterInstance     }. -unnamed_function (IDs, CharacterInstances, _Owner, -1) -> -   {IDs, CharacterInstances}; -unnamed_function (IDs, CharacterInstances, Owner, I) -> -   CharacterInstance = array:get(I, CharacterInstances), +activate_relevant_character_instances (IXs, CharacterInstances, _Owner, -1) -> +   {IXs, CharacterInstances}; +activate_relevant_character_instances (IXs, CharacterInstances, Owner, IX) -> +   CharacterInstance = array:get(IX, CharacterInstances),     Character = character_instance:get_character(CharacterInstance), -   case character:get_owner(Character) of +   case character:get_owner_id(Character) of        OwnerID when (OwnerID == Owner) -> -         unnamed_function +         activate_relevant_character_instances           ( -            [I|IDs], +            [IX|IXs],              array:set              ( -               I, +               IX,                 character_instance:set_is_active(true, CharacterInstance),                 CharacterInstances              ),              Owner, -            (I - 1) +            (IX - 1)           );        _ -> -         unnamed_function +         activate_relevant_character_instances           ( -            IDs, +            IXs,              CharacterInstances,              Owner, -            (I - 1) +            (IX - 1)           )     end.  start_next_players_turn (QueryState, Input) ->     BattlemapInstance = QueryState#query_state.battlemap_instance, -   Players = battlemap_instance:get_players(BattlemapInstance), +   PlayerIDs = battlemap_instance:get_player_ids(BattlemapInstance),     PlayerTurn = battlemap_instance:get_player_turn(BattlemapInstance), -   CurrentPlayerID = player_turn:get_player_id(PlayerTurn), +   CurrentPlayerIX = player_turn:get_player_ix(PlayerTurn),     CurrentTurnNumber = player_turn:get_number(PlayerTurn),     CharacterInstances =        battlemap_instance:get_character_instances(BattlemapInstance), -   NextPlayer = ((CurrentPlayerID + 1) rem (array:size(Players))), +   NextPlayerIX = ((CurrentPlayerIX + 1) rem (array:size(PlayerIDs))),     NextPlayerTurn =        player_turn:new        ( -         case NextPlayer of +         case NextPlayerIX of              0 -> (CurrentTurnNumber + 1);              _ -> CurrentTurnNumber           end, -         NextPlayer +         NextPlayerIX        ), -   {ActivatedCharacterInstancesID, UpdatedCharacterInstances} = -      unnamed_function +   {ActivatedCharacterInstanceIXs, UpdatedCharacterInstances} = +      activate_relevant_character_instances        (           [],           CharacterInstances, -         array:get(NextPlayer, Players), +         array:get(NextPlayerIX, PlayerIDs),           array:size(CharacterInstances)        ), -   { -      ActivatedCharacterInstancesID, -      QueryState#query_state -      { -         battlemap_instance = -            battlemap_instance:set_character_instances -            ( -               UpdatedCharacterInstances, -               battlemap_instance:set_player_turn -               ( -                  NextPlayerTurn, -                  BattlemapInstance -               ) -            ) -      } -   }. +   UpdatedBattlemapInstance = +      battlemap_instance:set_character_instances +      ( +         UpdatedCharacterInstances, +         battlemap_instance:set_player_turn +         ( +            NextPlayerTurn, +            BattlemapInstance +         ) +      ), +   {ActivatedCharacterInstanceIXs, UpdatedBattlemapInstance}.  finalize_character_turn (QueryState, Input) ->     BattlemapInstance = QueryState#query_state.battlemap_instance, -   Players = battlemap_instance:get_players(BattlemapInstance), +   CharacterInstances = +      battlemap_instance:get_character_instances(BattlemapInstance), -   CharacterInstanceRemains = +   AnActiveCharacterInstanceRemains =        array:foldl        ( -         fun (_I, CharacterInstance, Prev) -> +         fun (_IX, CharacterInstance, Prev) ->              (Prev or character_instance:get_is_active(CharacterInstance))           end, -         Players +         CharacterInstances        ), -   case CharacterInstanceRemains of -      true -> {false, {[], QueryState}}; -      false -> {true, start_next_players_turn(QueryState, Input)} +   case AnActiveCharacterInstanceRemains of +      true -> +         #query_result +         { +            is_new_turn = false, +            updated_character_instance_ixs = [], +            updated_battlemap_instance = BattlemapInstance +         }; +      false -> +         {UpdatedCharacterInstanceIXs, UpdatedBattlemapInstance} = +            start_next_players_turn(QueryState, Input), +         #query_result +         { +            is_new_turn = true, +            updated_character_instance_ixs = UpdatedCharacterInstanceIXs, +            updated_battlemap_instance = UpdatedBattlemapInstance +         }     end. -play (QueryState, [], Input) -> -   finalize_character_turn -   ( -      finalize_character_instance(QueryState, Input), -      Input -   ); +play (QueryState, [], _Input) -> +   QueryState;  play (QueryState, [nothing|Next], Input) ->     play(QueryState, Next, Input);  play (QueryState, [move|Next], Input) ->     play     ( -      handle_character_moving(QueryState, Input), +      handle_character_instance_moving(QueryState, Input),        Next,        Input     );  play (QueryState, [switch|Next], Input) ->     play     ( -      handle_character_switching_weapons(QueryState), +      handle_character_instance_switching_weapons(QueryState),        Next,        Input     ); @@ -306,32 +319,41 @@ play (QueryState, [switch|Next], Input) ->  play (QueryState, [attack|Next], Input) ->     play     ( -      handle_character_attacking(QueryState, Input), +      handle_character_instance_attacking(QueryState, Input),        Next,        Input     ). -send_to_database (QueryState, TurnType, Input) -> +send_to_database (QueryResult, TurnType, Input) ->     unimplemented. -update_cache (QueryState, TurnType, Input) -> +update_cache (QueryResult, TurnType, Input) ->     unimplemented. -generate_reply (QueryState, TurnType, Input) -> +generate_reply (QueryResult, TurnType, Input) ->     jiffy:encode([[<<"ok">>]]).  handle (Req) ->     Input = parse_input(Req),     security:assert_identity(Req#input.player_id, Req#input.session_token), +   security:lock_queries(Req#input.player_id),     QueryState = fetch_data(Input), -   assert_character_can_be_played(Input, QueryState), +   assert_character_instance_can_be_played(Input, QueryState),     TurnType = get_type_of_turn(Input), -   {IsNewTurn, {UpdatedCharacterInstancesID, PostPlayQueryState}} = -      play(QueryState, TurnType, Input), -   send_to_database(PostPlayQueryState, TurnType, Input), -   update_cache(PostPlayQueryState, TurnType, Input), -   generate_reply(PostPlayQueryState, TurnType, Input). - +   QueryResult = +      finalize_character_turn +      ( +         finalize_character_instance +         ( +            play(QueryState, TurnType, Input), +            Input +         ), +         Input +      ), +   send_to_database(QueryResult, TurnType, Input), +   update_cache(QueryResult, TurnType, Input), +   security:unlock_queries(Req#input.player_id), +   generate_reply(QueryResult, TurnType, Input).  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/query/character_turn/handle_character_attacking_2.erl b/src/query/character_turn/handle_character_attacking_2.erl deleted file mode 100644 index 3fd2687..0000000 --- a/src/query/character_turn/handle_character_attacking_2.erl +++ /dev/null @@ -1,59 +0,0 @@ -roll_hits (AttackerStatistics, DefenderStatistics) -> -   MissChance = -      max -      ( -         0, -         ( -            statistics:get_dodges(DefenderStatistics) -            - -            statistics:get_accuracy(AttackerStatistics) -         ) -      ), -   case roll:percentage() of -      X when (X < MissChance) -> misses; -      X when (X < (MissChance * 2)) -> grazes; -      _ -> hits -   end. - -roll_damage (AttackerStatistics, _DefenderStatistics) -> -   {MinimumDamage, MaximumDamage} = statistics:get_damages(AttackerStatistics), -   MaximumRoll = max(1, MaximumDamage - MinimumDamage), -   MinimumDamage + (rand:uniform(MaximumRoll) - 1). - -handle_character_attacking (QueryState, Input) -> -   BattlemapInstance = QueryState#query_state.battlemap_instance, -   ControlledCharacterInstance = QueryState#query_state.character_instance, -   ControlledCharacter = -      character_instance:get_character(ControlledCharacterInstance), -   ControlledCharacterStatistics = -      character:get_statistics(ControlledCharacter), -   TargettedCharacterInstance = -      array:get -      ( -         Input#input.target_id, -         battlemap_instance:get_characters(BattlemapInstance) -      ), -   TargettedCharacter = -      character_instance:get_character(TargettedCharacterInstance), -   TargettedCharacterStatistics = character:get_statistics(TargettedCharacter), -   RequiredRange = -      movement:steps_between -      ( -         character_instance:get_location(ControlledCharacterInstance), -         character_instance:get_location(TargettedCharacterInstance) -      ), -   {AttackingWeaponID, _} = character:get_weapon_ids(ControlledCharacter), -   AttackingWeapon = weapon:from_id(AttackingWeaponID), -   {_, AttackingWeaponRange} = weapon:get_ranges(AttackingWeapon), -   {DefendingWeaponID, _} = character:get_weapon_ids(TargettedCharacter), -   DefendingWeapon = weapon:from_id(DefendingWeaponID), -   {DefendingWeaponRange, _} = weapon:get_ranges(DefendingWeapon), - -   true = (RequiredRange =< AttackingWeaponRange), - -   {Rolls, HealthMod} = -      handle_attack -      ( -         ControlledCharacterStatistics, -         TargettedCharacterStatistics -      ). diff --git a/src/query/character_turn/handle_character_instance_attacking_2.erl b/src/query/character_turn/handle_character_instance_attacking_2.erl new file mode 100644 index 0000000..be2ac99 --- /dev/null +++ b/src/query/character_turn/handle_character_instance_attacking_2.erl @@ -0,0 +1,358 @@ +roll_hits (AttackerStatistics, DefenderStatistics) -> +   MissChance = +      max +      ( +         0, +         ( +            statistics:get_dodges(DefenderStatistics) +            - +            statistics:get_accuracy(AttackerStatistics) +         ) +      ), +   case roll:percentage() of +      X when (X =< MissChance) -> misses; +      X when (X =< (MissChance * 2)) -> grazes; +      _ -> hits +   end. + +roll_damage (AttackerStatistics, _DefenderStatistics) -> +   {MinimumDamage, MaximumDamage} = statistics:get_damages(AttackerStatistics), +   MaximumRoll = max(1, MaximumDamage - MinimumDamage), +   BaseDamage = MinimumDamage + (rand:uniform(MaximumRoll) - 1), +   CriticalHitChance = statistics:get_critical_hits(AttackerStatistics), +   case roll:percentage() of +      X when (X =< CriticalHitChance) -> +         {critical, (BaseDamage * 2)}; +      _ -> +         {basic, BaseDamage} +   end. + +handle_attack (AttackerStatistics, DefenderStatistics) -> +   Hits = roll_hits(AttackerStatistics, DefenderStatistics), +   {Critical, Damage} = roll_damage(AttackerStatistics, DefenderStatistics), +   case Hits of +      misses -> +         {Hits, Critical, 0}; + +      grazes -> +         { +            Hits, +            Critical, +            trunc(Damage / 2) +         }; + +      _ -> +         { +            Hits, +            Critical, +            Damage +         } +   end. + +handle_parry (AttackerStatistics, DefenderStatistics) -> +   ParryChance = statistics:get_parries(DefenderStatistics), +   case roll:percentage() of +      X when (X =< ParryChance) -> +         [{parry, handle_attack(DefenderStatistics, AttackerStatistics)}]; +      _ -> +         [] +   end. + +handle_attacks ([], _AttackerStatistics, _DefenderStatistics, Results) -> +   Results; +handle_attacks +( +   [nothing|Next], +   AttackerStatistics, +   DefenderStatistics, +   Results +) -> +   handle_attacks +   ( +      Next, +      AttackerStatistics, +      DefenderStatistics, +      Results +   ); +handle_attacks +( +   [first|Next], +   AttackerStatistics, +   DefenderStatistics, +   Results +) -> +   handle_attacks +   ( +      Next, +      AttackerStatistics, +      DefenderStatistics, +      [ +         { +            first, +            handle_attack(AttackerStatistics, DefenderStatistics) +         } +         | +         Results +      ] +   ); +handle_attacks +( +   [second|Next], +   AttackerStatistics, +   DefenderStatistics, +   Results +) -> +   handle_attacks +   ( +      Next, +      AttackerStatistics, +      DefenderStatistics, +      [ +         { +            second, +            handle_attack(AttackerStatistics, DefenderStatistics) +         } +         | +         Results +      ] +   ); +handle_attacks +( +   [parry|Next], +   AttackerStatistics, +   DefenderStatistics, +   Results +) -> +   handle_attacks +   ( +      Next, +      AttackerStatistics, +      DefenderStatistics, +      ( +         handle_parry(AttackerStatistics, DefenderStatistics) +         ++ +         Results +      ) +   ); +handle_attacks +( +   [counter|Next], +   AttackerStatistics, +   DefenderStatistics, +   Results +) -> +   handle_attacks +   ( +      Next, +      AttackerStatistics, +      DefenderStatistics, +      [ +         { +            counter, +            handle_attack(DefenderStatistics, AttackerStatistics) +         } +         | +         Results +      ] +   ). + +apply_attacks_to_healths ([], AttackerHealth, DefenderHealth, ValidEffects) -> +   {ValidEffects, AttackerHealth, DefenderHealth}; +apply_attacks_to_healths +( +   [{first, Effect}|Next], +   AttackerHealth, +   DefenderHealth, +   ValidEffects +) -> +   {_Hit, _Critical, Damage} = Effect, +   case (AttackerHealth > 0) of +      true -> +         apply_attacks_to_healths +         ( +            Next, +            AttackerHealth, +            max(0, (DefenderHealth - Damage)), +            [{first, Effect}|ValidEffects] +         ); +      false -> +         ValidEffects +   end; +apply_attacks_to_healths +( +   [{second, Effect}|Next], +   AttackerHealth, +   DefenderHealth, +   ValidEffects +) -> +   {_Hit, _Critical, Damage} = Effect, +   case (AttackerHealth > 0) of +      true -> +         apply_attacks_to_healths +         ( +            Next, +            AttackerHealth, +            max(0, (DefenderHealth - Damage)), +            [{second, Effect}|ValidEffects] +         ); +      false -> +         ValidEffects +   end; +apply_attacks_to_healths +( +   [{counter, Effect}|Next], +   AttackerHealth, +   DefenderHealth, +   ValidEffects +) -> +   {_Hit, _Critical, Damage} = Effect, +   case (DefenderHealth > 0) of +      true -> +         apply_attacks_to_healths +         ( +            Next, +            max(0, (AttackerHealth - Damage)), +            DefenderHealth, +            [{counter, Effect}|ValidEffects] +         ); +      false -> +         ValidEffects +   end; +apply_attacks_to_healths +( +   [{parry, Effect}|Next], +   AttackerHealth, +   DefenderHealth, +   ValidEffects +) -> +   {_Hit, _Critical, Damage} = Effect, +   case (DefenderHealth > 0) of +      true -> +         apply_attacks_to_healths +         ( +            Next, +            max(0, (AttackerHealth - Damage)), +            DefenderHealth, +            [{parry, Effect}|ValidEffects] +         ); +      false -> +         ValidEffects +   end. + +set_new_healths_in_query_state +( +   RemainingAttackerHealth, +   RemainingDefenderHealth, +   QueryState, +   Input +) -> +   BattlemapInstance = QueryState#query_state.battlemap_instance, +   ControlledCharacterInstance = QueryState#query_state.character_instance, +   CharacterInstances = +      battlemap_instance:get_character_instances(BattlemapInstance), +   TargettedCharacterInstanceIX = Input#input.target_ix, +   TargettedCharacterInstance = +      array:get +      ( +         TargettedCharacterInstanceIX, +         CharacterInstances +      ), + +   QueryState#query_state +   { +      battlemap_instance = +         battlemap_instance:set_character_instances +         ( +            array:set +            ( +               TargettedCharacterInstanceIX, +               character_instance:set_current_health +               ( +                  TargettedCharacterInstance, +                  RemainingDefenderHealth +               ) +            ) +         ), +      character_instance = +         character_instance:set_current_health +         ( +            ControlledCharacterInstance, +            RemainingAttackerHealth +         ) +   }. + +handle_character_instance_attacking (QueryState, Input) -> +   BattlemapInstance = QueryState#query_state.battlemap_instance, +   ControlledCharacterInstance = QueryState#query_state.character_instance, +   ControlledCharacter = +      character_instance:get_character(ControlledCharacterInstance), +   ControlledCharacterStatistics = +      character:get_statistics(ControlledCharacter), +   TargettedCharacterInstance = +      array:get +      ( +         Input#input.target_ix, +         battlemap_instance:get_character_instances(BattlemapInstance) +      ), +   TargettedCharacter = +      character_instance:get_character(TargettedCharacterInstance), +   TargettedCharacterStatistics = character:get_statistics(TargettedCharacter), +   RequiredRange = +      movement:steps_between +      ( +         character_instance:get_location(ControlledCharacterInstance), +         character_instance:get_location(TargettedCharacterInstance) +      ), +   {AttackingWeaponID, _} = character:get_weapon_ids(ControlledCharacter), +   AttackingWeapon = weapon:from_id(AttackingWeaponID), +   {_, AttackingWeaponRange} = weapon:get_ranges(AttackingWeapon), +   {DefendingWeaponID, _} = character:get_weapon_ids(TargettedCharacter), +   DefendingWeapon = weapon:from_id(DefendingWeaponID), +   {DefendingWeaponDefRange, DefendingWeaponAtkRange} = +      weapon:get_ranges(DefendingWeapon), + +   true = (RequiredRange =< AttackingWeaponRange), + +   CanDefend = +      ( +         (RequiredRange > DefendingWeaponDefRange) +         and +         (RequiredRange =< DefendingWeaponAtkRange) +      ), +   CanParry = (weapon:get_range_type(DefendingWeapon) == melee), +   Actions = +      case {CanDefend, CanParry} of +         {true, true} -> +            [second, counter, parry, first]; +         {true, false} -> +            [second, counter, first]; +         {false, _} -> +            [second, first] +      end, +   Effects = +      handle_attacks +      ( +         Actions, +         ControlledCharacterStatistics, +         TargettedCharacterStatistics, +         [] +      ), +   {RemainingEffects, RemainingAttackerHealth, RemainingDefenderHealth} = +      apply_attacks_to_healths +      ( +         Effects, +         character_instance:get_current_health(ControlledCharacterInstance), +         character_instance:get_current_health(TargettedCharacterInstance), +         [] +      ), + +   { +      RemainingEffects, +      set_new_healths_in_query_state +      ( +         QueryState, +         RemainingAttackerHealth, +         RemainingDefenderHealth, +         Input +      ) +   }. | 


