| summaryrefslogtreecommitdiff | 
diff options
| author | nsensfel <SpamShield0@noot-noot.org> | 2018-02-28 17:46:41 +0100 | 
|---|---|---|
| committer | nsensfel <SpamShield0@noot-noot.org> | 2018-02-28 17:46:41 +0100 | 
| commit | 1b59bdfc0d923a1ebfcebf4d6efceb2f2f4579a4 (patch) | |
| tree | d000a796fd61b27d8031cbdf691f1be73fdb5cb0 | |
| parent | 5235345620c0d4a6669ccc6badc387902ea8c92a (diff) | |
Moved the mess from 'character_turn' into 'attack'.
| -rw-r--r-- | src/battlemap/attack.erl | 279 | ||||
| -rw-r--r-- | src/query/character_turn.erl | 146 | ||||
| -rw-r--r-- | src/query/character_turn/handle_character_instance_attacking_2.erl | 383 | ||||
| -rw-r--r-- | src/struct/weapon.erl | 4 | 
4 files changed, 428 insertions, 384 deletions
| diff --git a/src/battlemap/attack.erl b/src/battlemap/attack.erl new file mode 100644 index 0000000..7384f78 --- /dev/null +++ b/src/battlemap/attack.erl @@ -0,0 +1,279 @@ +-module(attack). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% TODO: find better names for those types. +-type hits() :: ('misses' | 'grazes' | 'hits'). +-type critical() :: ('critical' | 'basic'). +-type attack_order() :: 'first' | 'second' | 'counter'. +-type attack_order_with_parry() :: {attack_order(), boolean()}. +-type attack_category() :: +   ( +      attack_order() +      | {attack_order(), 'parry'} +   ). +-type attack_effect() :: {hits(), critical(), non_neg_integer()}. +-type attack_desc() :: +   ( +      {attack_category(), attack_effect()} +      | 'nothing' +   ). + +-export_type +( +   [ +      hits/0, +      critical/0, +      attack_category/0, +      attack_effect/0, +      attack_desc/0 +   ] +). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export +( +   [ +      get_sequence/3, +      get_description_of/3, +      apply_to_healths/3 +   ] +). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec roll_hits +   ( +      statistics:struct(), +      statistics:struct() +   ) +   -> hits(). +roll_hits (AttackerStatistics, DefenderStatistics) -> +   DefenderDodges = statistics:get_dodges(DefenderStatistics), +   AttackerAccuracy = statistics:get_accuracy(AttackerStatistics), +   MissChance = max(0, (DefenderDodges - AttackerAccuracy)), +   case roll:percentage() of +      X when (X =< MissChance) -> misses; +      X when (X =< (MissChance * 2)) -> grazes; +      _ -> hits +   end. + +-spec roll_damage +   ( +      statistics:struct(), +      statistics:struct() +   ) +   -> {critical(), non_neg_integer()}. +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. + +-spec effect_of_attack +   ( +      statistics:struct(), +      statistics:struct() +   ) +   -> attack_effect(). +effect_of_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 -> {Hits, Critical, Damage} +   end. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +-spec get_description_of +   ( +      attack_order_with_parry(), +      statistics:struct(), +      statistics:struct() +   ) +   -> attack_desc(). +get_description_of +( +   {first, DefenderCanParry}, +   AttackerStatistics, +   DefenderStatistics +) -> +   DefenderParryChance = statistics:get_parries(DefenderStatistics), +   ParryRoll = +      case DefenderCanParry of +         true -> roll:percentage(); +         _ -> 101 +      end, +   if +      (ParryRoll =< DefenderParryChance) -> +            { +               {first, parry}, +               effect_of_attack(DefenderStatistics, AttackerStatistics) +            }; + +      true -> +         {first, effect_of_attack(AttackerStatistics, DefenderStatistics)} +   end; +get_description_of +( +   {second, DefenderCanParry}, +   AttackerStatistics, +   DefenderStatistics +) -> +   DefenderParryChance = statistics:get_parries(DefenderStatistics), +   ParryRoll = +      case DefenderCanParry of +         true -> roll:percentage(); +         _ -> 101 +      end, +   AttackerDoubleAttackChange = statistics:get_double_hits(AttackerStatistics), +   DoubleAttackRoll = roll:percentage(), +   if +      (DoubleAttackRoll > AttackerDoubleAttackChange) -> +         nothing; + +      (ParryRoll =< DefenderParryChance) -> +            { +               {second, parry}, +               effect_of_attack(DefenderStatistics, AttackerStatistics) +            }; + +      true -> +         {second, effect_of_attack(AttackerStatistics, DefenderStatistics)} +   end; +get_description_of +( +   {counter, AttackerCanParry}, +   AttackerStatistics, +   DefenderStatistics +) -> +   AttackerParryChance = statistics:get_parries(AttackerStatistics), +   ParryRoll = +      case AttackerCanParry of +         true -> roll:percentage(); +         _ -> 101 +      end, +   if +      (ParryRoll =< AttackerParryChance) -> +            { +               {counter, parry}, +               effect_of_attack(AttackerStatistics, DefenderStatistics) +            }; + +      true -> +         {counter, effect_of_attack(DefenderStatistics, AttackerStatistics)} +   end. + +-spec apply_to_healths +   ( +      attack_desc(), +      non_neg_integer(), +      non_neg_integer() +   ) +   -> {attack_desc(), non_neg_integer(), non_neg_integer()}. +apply_to_healths +( +   nothing, +   AttackerHealth, +   DefenderHealth +) -> +   {nothing, AttackerHealth, DefenderHealth}; +apply_to_healths +( +   {Attack, Effect}, +   AttackerHealth, +   DefenderHealth +) +when +( +   (Attack == first) +   or (Attack == second) +   or (Attack == {counter, parry}) +) -> +   {_Hits, _Critical, Damage} = Effect, +   case AttackerHealth of +      0 -> +         {nothing, AttackerHealth, DefenderHealth}; + +      _ -> +         { +            {Attack, Effect}, +            AttackerHealth, +            max(0, (DefenderHealth - Damage)) +         } +   end; +apply_to_healths +( +   {Attack, Effect}, +   AttackerHealth, +   DefenderHealth +) +when +( +   (Attack == {first, parry}) +   or (Attack == {second, parry}) +   or (Attack == counter) +) -> +   {_Hits, _Critical, Damage} = Effect, +   case DefenderHealth of +      0 -> +         {nothing, AttackerHealth, DefenderHealth}; + +      _ -> +         { +            {Attack, Effect}, +            max(0, (AttackerHealth - Damage)), +            DefenderHealth +         } +   end. + +-spec get_sequence +   ( +      non_neg_integer(), +      weapon:struct(), +      weapon:struct() +   ) +   -> list(attack_order_with_parry()). +get_sequence (AttackRange, AttackerWeapon, DefenderWeapon) -> +   {AttackerDefenseRange, AttackerAttackRange} = +      weapon:get_ranges(AttackerWeapon), +   {DefenderDefenseRange, DefenderAttackRange} = +      weapon:get_ranges(DefenderWeapon), + +   AttackerCanAttack = (AttackRange =< AttackerAttackRange), +   AttackerCanDefend = +      (AttackerCanAttack and (AttackRange > AttackerDefenseRange)), +   AttackerCanParry = +      (AttackerCanDefend and weapon:can_parry(AttackerWeapon)), + +   DefenderCanAttack = (AttackRange =< DefenderAttackRange), +   DefenderCanDefend = +      (DefenderCanAttack and (AttackRange > DefenderDefenseRange)), +   DefenderCanParry = +      (DefenderCanDefend and weapon:can_parry(DefenderWeapon)), + +   First = {first, DefenderCanParry}, +   Second = {second, DefenderCanParry}, +   Counter = {counter, AttackerCanParry}, + +   if +      (not AttackerCanAttack) -> +         []; + +      (not DefenderCanDefend) -> +         [First, Second]; + +      true -> +         [First, Counter, Second] +   end. diff --git a/src/query/character_turn.erl b/src/query/character_turn.erl index c920745..b24e038 100644 --- a/src/query/character_turn.erl +++ b/src/query/character_turn.erl @@ -233,7 +233,151 @@ handle_character_instance_switching_weapons (QueryState, Input) ->        UpdatedQueryState     }. --include("character_turn/handle_character_instance_attacking_2.erl"). +-spec set_new_healths_in_query_state +   ( +      non_neg_integer(), +      non_neg_integer(), +      query_state(), +      input() +   ) +   -> query_state(). +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 +               ( +                  RemainingDefenderHealth, +                  TargettedCharacterInstance +               ), +               CharacterInstances +            ), +            BattlemapInstance +         ), +      character_instance = +         character_instance:set_current_health +         ( +            RemainingAttackerHealth, +            ControlledCharacterInstance +         ) +   }. + +-spec handle_character_instance_attacking +   ( +      query_state(), +      input() +   ) +   -> {list(attack:attack_desc()), query_state()}. +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), +   {DefendingWeaponID, _} = character:get_weapon_ids(TargettedCharacter), +   DefendingWeapon = weapon:from_id(DefendingWeaponID), +   BaseAttackerHealth = +      character_instance:get_current_health(ControlledCharacterInstance), +   BaseDefenderHealth = +      character_instance:get_current_health(TargettedCharacterInstance), + +   AttackSequence = +      attack:get_sequence(RequiredRange, AttackingWeapon, DefendingWeapon), + +   AttackEffects = +      lists:map +      ( +         fun (AttackOrder) -> +            attack:get_description_of +            ( +               AttackOrder, +               ControlledCharacterStatistics, +               TargettedCharacterStatistics +            ) +         end, +         AttackSequence +      ), + +   {AttackSummary, RemainingAttackerHealth, RemainingDefenderHealth} = +      lists:foldl +      ( +         fun +         ( +            AttackEffect, +            { +               CurrentAttackEffects, +               CurrentAttackerHealth, +               CurrentDefenderHealth +            } +         ) -> +            {AttackTrueEffect, NewAttackerHealth, NewDefenderHealth} = +               attack:apply_to_healths +               ( +                  AttackEffect, +                  CurrentAttackerHealth, +                  CurrentDefenderHealth +               ), +            { +               [AttackTrueEffect|CurrentAttackEffects], +               NewAttackerHealth, +               NewDefenderHealth +            } +         end, +         {[], BaseAttackerHealth, BaseDefenderHealth}, +         AttackEffects +      ), + +   { +      AttackSummary, +      set_new_healths_in_query_state +      ( +         RemainingAttackerHealth, +         RemainingDefenderHealth, +         QueryState, +         Input +      ) +   }.  -spec get_type_of_turn (input()) -> list(atom()).  get_type_of_turn (Input) -> diff --git a/src/query/character_turn/handle_character_instance_attacking_2.erl b/src/query/character_turn/handle_character_instance_attacking_2.erl deleted file mode 100644 index 6995c4c..0000000 --- a/src/query/character_turn/handle_character_instance_attacking_2.erl +++ /dev/null @@ -1,383 +0,0 @@ -% TODO: put all of that into separate modules. It's kind of a mess here. --type hits() :: ('misses' | 'grazes' | 'hits'). --type critical() :: ('critical' | 'basic'). --type attack_category() :: -   ( -      'first' -      | 'second' -      | 'counter' -      | {'first', 'parry'} -      | {'second', 'parry'} -   ). --type attack_effect() :: {hits(), critical(), non_neg_integer()}. --type attack_desc() :: {attack_category(), attack_effect()}. - --spec roll_hits -   ( -      statistics:struct(), -      statistics:struct() -   ) -   -> hits(). -roll_hits (AttackerStatistics, DefenderStatistics) -> -   DefenderDodges = statistics:get_dodges(DefenderStatistics), -   AttackerAccuracy = statistics:get_accuracy(AttackerStatistics), -   MissChance = max(0, (DefenderDodges - AttackerAccuracy)), -   case roll:percentage() of -      X when (X =< MissChance) -> misses; -      X when (X =< (MissChance * 2)) -> grazes; -      _ -> hits -   end. - --spec roll_damage -   ( -      statistics:struct(), -      statistics:struct() -   ) -   -> {critical(), non_neg_integer()}. -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. - --spec handle_attack -   ( -      statistics:struct(), -      statistics:struct() -   ) -   -> {hits(), critical(), non_neg_integer()}. -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 -> {Hits, Critical, Damage} -   end. - --spec handle_attacks -   ( -      list(attack_category()), -      statistics:struct(), -      statistics:struct(), -      list(attack_desc()) -   ) -   -> list(attack_desc()). -handle_attacks ([], _AttackerStatistics, _DefenderStatistics, Results) -> -   Results; -handle_attacks -( -   [first|Next], -   AttackerStatistics, -   DefenderStatistics, -   Results -) -> -   AttackResult = handle_attack(AttackerStatistics, DefenderStatistics), -   handle_attacks -   ( -      Next, -      AttackerStatistics, -      DefenderStatistics, -      [{first, AttackResult} | Results] -   ); -handle_attacks -( -   [second|Next], -   AttackerStatistics, -   DefenderStatistics, -   Results -) -> -   SecondHitChance = statistics:get_double_hits(AttackerStatistics), -   UpdatedResults = -      case roll:percentage() of -         X when (X =< SecondHitChance) -> -            [ -               {second, handle_attack(AttackerStatistics, DefenderStatistics)} -               | -               Results -            ]; - -         _ -> -            Results -      end, -   handle_attacks(Next, AttackerStatistics, DefenderStatistics, UpdatedResults); -handle_attacks -( -   [{first, parry}|Next], -   AttackerStatistics, -   DefenderStatistics, -   Results -) -> -   ParryChance = statistics:get_parries(DefenderStatistics), -   AttackResult = -      case roll:percentage() of -         X when (X =< ParryChance) -> -            { -               {first, parry}, -               handle_attack(DefenderStatistics, AttackerStatistics) -            }; - -         _ -> -            {first, handle_attack(AttackerStatistics, DefenderStatistics)} -      end, -   handle_attacks -   ( -      Next, -      AttackerStatistics, -      DefenderStatistics, -      [AttackResult|Results] -   ); -handle_attacks -( -   [{second, parry}|Next], -   AttackerStatistics, -   DefenderStatistics, -   Results -) -> -   SecondHitChance = statistics:get_double_hits(AttackerStatistics), -   ParryChance = statistics:get_parries(DefenderStatistics), -   AttackResult = -      case roll:percentage() of -         X when (X =< SecondHitChance) -> -            case roll:percentage() of -               Y when (Y =< ParryChance) -> -                  { -                     {second, parry}, -                     handle_attack(DefenderStatistics, AttackerStatistics) -                  }; - -               _ -> -                  { -                     second, -                     handle_attack(AttackerStatistics, DefenderStatistics) -                  } -            end; - -         _ -> nothing -      end, -   handle_attacks -   ( -      Next, -      AttackerStatistics, -      DefenderStatistics, -      case AttackResult of -         nothing -> Results; -         _ -> [AttackResult|Results] -      end -   ); -handle_attacks -( -   [counter|Next], -   AttackerStatistics, -   DefenderStatistics, -   Results -) -> -   handle_attacks -   ( -      Next, -      AttackerStatistics, -      DefenderStatistics, -      [ -         {counter, handle_attack(DefenderStatistics, AttackerStatistics)} -         | -         Results -      ] -   ). - --spec apply_attacks_to_healths -   ( -      list(attack_desc()), -      non_neg_integer(), -      non_neg_integer(), -      list(attack_desc()) -   ) -   -> {list(attack_desc()), non_neg_integer(), non_neg_integer()}. -apply_attacks_to_healths ([], AttackerHealth, DefenderHealth, ValidEffects) -> -   {ValidEffects, AttackerHealth, DefenderHealth}; -apply_attacks_to_healths -( -   [{Action, Effect}|Next], -   AttackerHealth, -   DefenderHealth, -   ValidEffects -) -when ((Action == first) or (Action == second)) -> -   {_Hit, _Critical, Damage} = Effect, -   case (AttackerHealth > 0) of -      true -> -         apply_attacks_to_healths -         ( -            Next, -            AttackerHealth, -            max(0, (DefenderHealth - Damage)), -            [{Action, Effect}|ValidEffects] -         ); - -      false -> -         {ValidEffects, AttackerHealth, DefenderHealth} -   end; -apply_attacks_to_healths -( -   [{Action, Effect}|Next], -   AttackerHealth, -   DefenderHealth, -   ValidEffects -) -when -( -   (Action == counter) -   or (Action == {first, parry}) -   or (Action == {second, parry}) -) -> -   {_Hit, _Critical, Damage} = Effect, -   case (DefenderHealth > 0) of -      true -> -         apply_attacks_to_healths -         ( -            Next, -            max(0, (AttackerHealth - Damage)), -            DefenderHealth, -            [{Action, Effect}|ValidEffects] -         ); - -      false -> -         {ValidEffects, AttackerHealth, DefenderHealth} -   end. - --spec set_new_healths_in_query_state -   ( -      non_neg_integer(), -      non_neg_integer(), -      query_state(), -      input() -   ) -   -> query_state(). -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 -               ( -                  RemainingDefenderHealth, -                  TargettedCharacterInstance -               ), -               CharacterInstances -            ), -            BattlemapInstance -         ), -      character_instance = -         character_instance:set_current_health -         ( -            RemainingAttackerHealth, -            ControlledCharacterInstance -         ) -   }. - --spec handle_character_instance_attacking -   ( -      query_state(), -      input() -   ) -   -> {list(attack_desc()), query_state()}. -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, parry}, counter, {first, parry}]; -         {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 -      ( -         RemainingAttackerHealth, -         RemainingDefenderHealth, -         QueryState, -         Input -      ) -   }. diff --git a/src/struct/weapon.erl b/src/struct/weapon.erl index d96886c..80cb925 100644 --- a/src/struct/weapon.erl +++ b/src/struct/weapon.erl @@ -55,6 +55,7 @@     [        random_id/0,        from_id/1, +      can_parry/1,        apply_to_attributes/2     ]  ). @@ -102,6 +103,9 @@ get_ranges (Wp) ->  get_damages (Wp) ->     damages_of_type(Wp#weapon.range_type, Wp#weapon.damage_mod). +-spec can_parry (struct()) -> boolean(). +can_parry (Wp) -> (Wp#weapon.range_type == melee). +  -spec from_id (id()) -> struct().  from_id (0) ->     #weapon{ | 


