summaryrefslogtreecommitdiff |
diff options
-rw-r--r-- | src/struct/attack.erl (renamed from src/battle/attack.erl) | 235 |
1 files changed, 115 insertions, 120 deletions
diff --git a/src/battle/attack.erl b/src/struct/attack.erl index f1ef048..b27ff48 100644 --- a/src/battle/attack.erl +++ b/src/struct/attack.erl @@ -3,38 +3,28 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-type order() :: ('first' | 'second' | 'counter'). +-type precision() :: ('misses' | 'grazes' | 'hits'). -% 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' - ). +-record +( + attack, + { + order :: order(), + precision :: precision(), + is_critical :: boolean(), + is_parry :: boolean(), + damage :: non_neg_integer() + } +). +-opaque struct() :: #attack{}. +-type maybe_struct() :: ('nothing' | struct()). +-opaque step() :: {order(), boolean()}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --export_type -( - [ - hits/0, - critical/0, - attack_category/0, - attack_effect/0, - attack_desc/0, - attack_order_with_parry/0 - ] -). +-export_type([struct/0, maybe_struct/0, step/0]). -export ( @@ -55,13 +45,13 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec roll_hits +-spec roll_precision ( statistics:struct(), statistics:struct() ) - -> hits(). -roll_hits (AttackerStatistics, DefenderStatistics) -> + -> precision(). +roll_precision (AttackerStatistics, DefenderStatistics) -> DefenderDodges = statistics:get_dodges(DefenderStatistics), AttackerAccuracy = statistics:get_accuracy(AttackerStatistics), MissChance = max(0, (DefenderDodges - AttackerAccuracy)), @@ -76,121 +66,120 @@ roll_hits (AttackerStatistics, DefenderStatistics) -> statistics:struct(), statistics:struct() ) - -> {critical(), non_neg_integer()}. + -> {non_neg_integer(), boolean()}. 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} + X when (X =< CriticalHitChance) -> {(BaseDamage * 2), true}; + _ -> {BaseDamage, false} end. +-spec roll_parry (statistics:struct()) -> boolean(). +roll_parry (DefenderStatistics) -> + DefenderParryChance = statistics:get_parries(DefenderStatistics), + (roll:percentage() =< DefenderParryChance). + -spec effect_of_attack ( + order(), statistics:struct(), - statistics:struct() + statistics:struct(), + boolean() ) - -> 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. + -> struct(). +effect_of_attack (Order, AttackerStatistics, DefenderStatistics, CanParry) -> + ParryIsSuccessful = (CanParry and roll_parry(DefenderStatistics)), + {ActualAtkStatistics, ActualDefStatistics} = + case ParryIsSuccessful of + true -> {DefenderStatistics, AttackerStatistics}; + false -> {AttackerStatistics, DefenderStatistics} + end, + + Precision = roll_precision(ActualAtkStatistics, ActualDefStatistics), + {Damage, IsCritical} = roll_damage(ActualAtkStatistics, ActualDefStatistics), + ActualDamage = + case Precision of + misses -> 0; + grazes -> trunc(Damage / 2); + hits -> Damage + end, + + #attack + { + order = Order, + precision = Precision, + is_critical = IsCritical, + is_parry = ParryIsSuccessful, + damage = ActualDamage + }. + +-spec encode_order (order()) -> binary(). +encode_order (first) -> <<"f">>; +encode_order (counter) -> <<"c">>; +encode_order (second) -> <<"s">>. + +-spec encode_precision (precision()) -> binary(). +encode_precision (hits) -> <<"h">>; +encode_precision (grazes) -> <<"g">>; +encode_precision (misses) -> <<"m">>. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -spec get_description_of ( - attack_order_with_parry(), + step(), statistics:struct(), statistics:struct() ) - -> attack_desc(). + -> maybe_struct(). get_description_of ( - {first, DefenderCanParry}, + {first, CanParry}, 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; + effect_of_attack(first, AttackerStatistics, DefenderStatistics, CanParry); get_description_of ( - {second, DefenderCanParry}, + {second, CanParry}, 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) - }; + case roll:percentage() of + X when (X =< AttackerDoubleAttackChange) -> + effect_of_attack + ( + second, + AttackerStatistics, + DefenderStatistics, + CanParry + ); - true -> - {second, effect_of_attack(AttackerStatistics, DefenderStatistics)} + _ -> + nothing end; get_description_of ( - {counter, AttackerCanParry}, + {counter, CanParry}, 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. + effect_of_attack(counter, DefenderStatistics, AttackerStatistics, CanParry). -spec apply_to_healths ( - attack_desc(), + maybe_struct(), non_neg_integer(), non_neg_integer() ) - -> {attack_desc(), non_neg_integer(), non_neg_integer()}. + -> {maybe_struct(), non_neg_integer(), non_neg_integer()}. apply_to_healths ( nothing, @@ -200,24 +189,25 @@ apply_to_healths {nothing, AttackerHealth, DefenderHealth}; apply_to_healths ( - {Attack, Effect}, + Attack, AttackerHealth, DefenderHealth ) when ( - (Attack == first) - or (Attack == second) - or (Attack == {counter, parry}) + (Attack#attack.order == first) + or (Attack#attack.order == second) + or ((Attack#attack.order == counter) and Attack#attack.is_parry) ) -> - {_Hits, _Critical, Damage} = Effect, + Damage = Attack#attack.damage, + case AttackerHealth of 0 -> {nothing, AttackerHealth, DefenderHealth}; _ -> { - {Attack, Effect}, + Attack, AttackerHealth, max(0, (DefenderHealth - Damage)) } @@ -230,9 +220,12 @@ apply_to_healths ) when ( - (Attack == {first, parry}) - or (Attack == {second, parry}) - or (Attack == counter) + (Attack#attack.order == counter) + or + ( + (Attack#attack.is_parry) + and ((Attack#attack.order == first) or (Attack#attack.order == second)) + ) ) -> {_Hits, _Critical, Damage} = Effect, case DefenderHealth of @@ -253,7 +246,7 @@ when weapon:struct(), weapon:struct() ) - -> list(attack_order_with_parry()). + -> list(step()). get_sequence (AttackRange, AttackerWeapon, DefenderWeapon) -> {AttackerDefenseRange, AttackerAttackRange} = weapon:get_ranges(AttackerWeapon), @@ -287,22 +280,24 @@ get_sequence (AttackRange, AttackerWeapon, DefenderWeapon) -> [First, Counter, Second] end. --spec encode (attack_desc()) -> binary(). +-spec encode (struct()) -> binary(). % This shouldn't be a possibility. Types in this module are a mess... -encode ({AttackCategory, AttackEffect}) -> +encode (Attack) -> + Order = Attack#attack.order, + Precision = Attack#attack.precision, + IsCritical = Attack#attack.is_critical, + IsParry = Attack#attack.is_parry, + Damage = Attack#attack.damage, + jiffy:encode ( { [ - <<"attack">>, - list_to_binary - ( - io_lib:format - ( - "~p", - [{AttackCategory, AttackEffect}] - ) - ) + {<<"ord">>, encode_order(Order)}, + {<<"pre">>, encode_precision(Precision)}, + {<<"cri">>, IsCritical}, + {<<"par">>, IsParry}, + {<<"dmg">>, Damage} ] } ). |