| summaryrefslogtreecommitdiff | 
diff options
| -rw-r--r-- | src/balancer/blc_attribute.erl | 7 | ||||
| -rw-r--r-- | src/balancer/struct/blc_armor.erl | 320 | ||||
| -rw-r--r-- | src/balancer/struct/blc_glyph.erl | 18 | ||||
| -rw-r--r-- | src/balancer/struct/blc_weapon.erl | 422 | ||||
| -rw-r--r-- | src/battle/mechanic/action/btl_action_attack.erl | 8 | ||||
| -rw-r--r-- | src/shared/struct/shr_omnimods.erl | 71 | 
6 files changed, 433 insertions, 413 deletions
| diff --git a/src/balancer/blc_attribute.erl b/src/balancer/blc_attribute.erl index 55becfa..14cfe8f 100644 --- a/src/balancer/blc_attribute.erl +++ b/src/balancer/blc_attribute.erl @@ -56,6 +56,13 @@ get_info (?ATTRIBUTE_CRITICAL_HIT_CHANCE) ->        ?ATTRIBUTE_CRITICAL_HIT_CHANCE_MAX,        ?ATTRIBUTE_CRITICAL_HIT_CHANCE_COST     }; +get_info (?ATTRIBUTE_DAMAGE_MODIFIER) -> +   { +      ?ATTRIBUTE_DAMAGE_MODIFIER_MIN, +      ?ATTRIBUTE_DAMAGE_MODIFIER_DEFAULT, +      ?ATTRIBUTE_DAMAGE_MODIFIER_MAX, +      ?ATTRIBUTE_DAMAGE_MODIFIER_COST +   };  get_info (?ATTRIBUTE_DEFENSE_SCORE) ->     {        ?ATTRIBUTE_DEFENSE_SCORE_MIN, diff --git a/src/balancer/struct/blc_armor.erl b/src/balancer/struct/blc_armor.erl index 9677f88..cc23415 100644 --- a/src/balancer/struct/blc_armor.erl +++ b/src/balancer/struct/blc_armor.erl @@ -40,22 +40,19 @@  (     proto_armor,     { -      health :: non_neg_integer(), -      damage_modifier :: non_neg_integer(), -      dodge :: non_neg_integer(), -      mvt_points :: non_neg_integer(), -      defense :: list(blc_damage_type:entry()), +      omnimods :: shr_omnimods:type(),        defense_coef :: list(blc_damage_type:coefficient()), -      defense_score :: non_neg_integer() +      defense_score :: non_neg_integer(), +      remaining_points :: non_neg_integer()     }  ). --opaque proto_armor() :: #proto_armor{}. +-opaque type() :: #proto_armor{}.  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --export_type([proto_armor/0]). +-export_type([type/0]).  -export  ( @@ -78,13 +75,54 @@  (     [        new/1, -      get_spendable_points/0 +      get_remaining_points/1     ]  ).  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec increase_attribute_by +   ( +      shr_attributes:enum(), +      non_neg_integer(), +      type() +   ) +   -> ({ok, type()} | blc_error:type()). +increase_attribute_by (Attribute, S0Amount, Armor) -> +   CurrentOmnimods = Armor#proto_armor.omnimods, +   CurrentValue = +      shr_omnimods:get_attribute_modifier(Attribute, CurrentOmnimods), + +   {_AttMin, _AttDef, AttMax, AttCost} = blc_attribute:get_info(Attribute), + +   S1Amount = +      case ((CurrentValue + S0Amount) > AttMax) of +         true -> (AttMax - CurrentValue); +         false -> S0Amount +      end, + +   Cost = (S1Amount * AttCost), +   RemainingPoints = Armor#proto_armor.remaining_points, + +   case (Cost > RemainingPoints) of +      true -> {error, balance, RemainingPoints, Cost}; +      false -> +         { +            ok, +            Armor#proto_armor +            { +               remaining_points = (RemainingPoints - Cost), +               omnimods = +                  shr_omnimods:mod_attribute_modifier +                  ( +                     Attribute, +                     S1Amount, +                     Armor#proto_armor.omnimods +                  ) +            } +         } +   end.  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -92,246 +130,186 @@  -spec increase_health_by     (        non_neg_integer(), -      proto_armor() +      type()     ) -   -> {proto_armor(), non_neg_integer()}. +   -> ({ok, type()} | blc_error:type()).  increase_health_by (Amount, Armor) -> -   NewHealth = (Armor#proto_armor.health + Amount), -   case (NewHealth > ?ATTRIBUTE_HEALTH_MAX) of -      true -> -         { -            Armor#proto_armor{ health = ?ATTRIBUTE_HEALTH_MAX }, -            ( -               (?ATTRIBUTE_HEALTH_MAX - Armor#proto_armor.health) -               * ?ATTRIBUTE_HEALTH_COST -            ) -         }; - -      false -> -         { -            Armor#proto_armor{ health = NewHealth }, -            (Amount * ?ATTRIBUTE_HEALTH_COST) -         } -   end. +   increase_attribute_by(?ATTRIBUTE_HEALTH, Amount, Armor).  -spec increase_damage_modifier_by     (        non_neg_integer(), -      proto_armor() +      type()     ) -   -> {proto_armor(), non_neg_integer()}. +   -> ({ok, type()} | blc_error:type()).  increase_damage_modifier_by (Amount, Armor) -> -   NewDamageModifier = (Armor#proto_armor.damage_modifier + Amount), -   case (NewDamageModifier > ?ATTRIBUTE_DAMAGE_MODIFIER_MAX) of -      true -> -         { -            Armor#proto_armor -            { -               damage_modifier = ?ATTRIBUTE_DAMAGE_MODIFIER_MAX -            }, -            ( -               ( -                  ?ATTRIBUTE_DAMAGE_MODIFIER_MAX -                  - Armor#proto_armor.damage_modifier -               ) -               * ?ATTRIBUTE_DAMAGE_MODIFIER_COST -            ) -         }; - -      false -> -         { -            Armor#proto_armor{ damage_modifier = NewDamageModifier }, -            (Amount * ?ATTRIBUTE_DAMAGE_MODIFIER_COST) -         } -   end. +   increase_attribute_by(?ATTRIBUTE_DAMAGE_MODIFIER, Amount, Armor).  -spec increase_dodge_chance_by     (        non_neg_integer(), -      proto_armor() +      type()     ) -   -> {proto_armor(), non_neg_integer()}. +   -> ({ok, type()} | blc_error:type()).  increase_dodge_chance_by (Amount, Armor) -> -   NewDodgeChance = (Armor#proto_armor.dodge + Amount), -   case (NewDodgeChance > ?ATTRIBUTE_DODGE_CHANCE_MAX) of -      true -> -         { -            Armor#proto_armor{ dodge = ?ATTRIBUTE_DODGE_CHANCE_MAX }, -            ( -               (?ATTRIBUTE_DODGE_CHANCE_MAX - Armor#proto_armor.dodge) -               * ?ATTRIBUTE_DODGE_CHANCE_COST -            ) -         }; - -      false -> -         { -            Armor#proto_armor{ dodge = NewDodgeChance }, -            (Amount * ?ATTRIBUTE_DODGE_CHANCE_COST) -         } -   end. +   increase_attribute_by(?ATTRIBUTE_DODGE_CHANCE, Amount, Armor).  -spec increase_movement_points_by     (        non_neg_integer(), -      proto_armor() +      type()     ) -   -> {proto_armor(), non_neg_integer()}. +   -> ({ok, type()} | blc_error:type()).  increase_movement_points_by (Amount, Armor) -> -   NewMvtPoints = (Armor#proto_armor.mvt_points + Amount), -   case (NewMvtPoints > ?ATTRIBUTE_MOVEMENT_POINTS_MAX) of -      true -> -         { -            Armor#proto_armor{ mvt_points = ?ATTRIBUTE_MOVEMENT_POINTS_MAX }, -            ( -               (?ATTRIBUTE_MOVEMENT_POINTS_MAX - Armor#proto_armor.mvt_points) -               * ?ATTRIBUTE_MOVEMENT_POINTS_COST -            ) -         }; - -      false -> -         { -            Armor#proto_armor{ mvt_points = NewMvtPoints }, -            (Amount * ?ATTRIBUTE_MOVEMENT_POINTS_COST) -         } -   end. +   increase_attribute_by(?ATTRIBUTE_MOVEMENT_POINTS, Amount, Armor).  -spec increase_defense_score_by     (        non_neg_integer(), -      proto_armor() +      type()     ) -   -> {proto_armor(), non_neg_integer()}. -increase_defense_score_by (Amount, Armor) -> -   NewDefenseScore = (Armor#proto_armor.defense_score + Amount), -   case (NewDefenseScore > ?ATTRIBUTE_DEFENSE_SCORE_MAX) of -      true -> -         { -            Armor#proto_armor +   -> ({ok, type()} | blc_error:type()). +increase_defense_score_by (S0Amount, Armor) -> +   CurrentValue = Armor#proto_armor.defense_score, +   S0NewValue = CurrentValue + S0Amount, +   {S1Amount, S1NewValue} = +      case (S0NewValue > ?ATTRIBUTE_DEFENSE_SCORE_MAX) of +         false -> {S0Amount, S0NewValue}; +         true ->              { -               defense_score = ?ATTRIBUTE_DEFENSE_SCORE_MAX, -               defense = -                  blc_damage_type:generate_entries_from_score -                  ( -                     NewDefenseScore, -                     Armor#proto_armor.defense_coef -                  ) -            }, -            ( -               (?ATTRIBUTE_DEFENSE_SCORE_MAX - Armor#proto_armor.defense_score) -               * Amount -            ) -         }; +               (?ATTRIBUTE_DEFENSE_SCORE_MAX - CurrentValue), +               ?ATTRIBUTE_DEFENSE_SCORE_MAX +            } +      end, + +   Cost = (S1Amount * ?ATTRIBUTE_DEFENSE_SCORE_COST), +   RemainingPoints = Armor#proto_armor.remaining_points, +   case (Cost > RemainingPoints) of +      true -> {error, balance, RemainingPoints, Cost};        false ->           { +            ok,              Armor#proto_armor              { -               defense_score = NewDefenseScore, -               defense = -                  blc_damage_type:generate_entries_from_score +               remaining_points = (RemainingPoints - Cost), +               defense_score = S1NewValue, +               omnimods = +                  shr_omnimods:set_defense_modifiers                    ( -                     NewDefenseScore, -                     Armor#proto_armor.defense_coef +                     blc_damage_type:generate_entries_from_score +                     ( +                        S1NewValue, +                        Armor#proto_armor.defense_coef +                     ), +                     Armor#proto_armor.omnimods                    ) -            }, -            (Amount * ?ATTRIBUTE_DEFENSE_SCORE_COST) +            }           }     end.  -spec set_defense_coefficients     (        list(blc_damage_type:coefficient()), -      proto_armor() +      type()     ) -   -> proto_armor(). +   -> type().  set_defense_coefficients (Coefficients, Armor) -> -   {Result, 0} = -      increase_defense_score_by -      ( -         0, -         Armor#proto_armor -         { -            defense_coef = blc_damage_type:sort_entries(Coefficients) -         } -      ), +   NewCoefs = blc_damage_type:sort_entries(Coefficients), + +   Armor#proto_armor +   { +      defense_coef = NewCoefs, +      omnimods = +         shr_omnimods:set_defense_modifiers +         ( +            blc_damage_type:generate_entries_from_score +            ( +               Armor#proto_armor.defense_score, +               NewCoefs +            ), +            Armor#proto_armor.omnimods +         ) +   }. -   Result. --spec new (list(blc_damage_type:coefficient())) -> proto_armor(). +-spec new (list(blc_damage_type:coefficient())) -> type().  new (Coefficients) -> -   {Result, _DefenseScoreIncreaseCost} = -      increase_defense_score_by -      ( -         ?ATTRIBUTE_DEFENSE_SCORE_MIN, -         #proto_armor -         { -            health = ?ATTRIBUTE_HEALTH_MIN, -            damage_modifier = ?ATTRIBUTE_DAMAGE_MODIFIER_MIN, -            dodge = ?ATTRIBUTE_DODGE_CHANCE_MIN, -            mvt_points = ?ATTRIBUTE_MOVEMENT_POINTS_MIN, -            defense = [], -            defense_coef = blc_damage_type:sort_entries(Coefficients), -            defense_score = 0 -         } -      ), +   SortedCoefficients = blc_damage_type:sort_entries(Coefficients), + +   #proto_armor +   { +      omnimods = +         shr_omnimods:new +         ( +            [ +               {?ATTRIBUTE_HEALTH, ?ATTRIBUTE_HEALTH_MIN}, +               {?ATTRIBUTE_DAMAGE_MODIFIER, ?ATTRIBUTE_DAMAGE_MODIFIER_MIN}, +               {?ATTRIBUTE_DODGE_CHANCE, ?ATTRIBUTE_DODGE_CHANCE_MIN}, +               {?ATTRIBUTE_MOVEMENT_POINTS, ?ATTRIBUTE_MOVEMENT_POINTS_MIN} +            ], +            [], +            blc_damage_type:generate_entries_from_score +            ( +               ?ATTRIBUTE_DEFENSE_SCORE_MIN, +               SortedCoefficients +            ) +         ), -   Result. +      defense_coef = SortedCoefficients, +      defense_score = ?ATTRIBUTE_DEFENSE_SCORE_MIN, +      remaining_points = ?SPENDABLE_ARMOR_POINTS +   }.  -spec increase_health_for     (        non_neg_integer(), -      proto_armor() +      type()     ) -   -> {proto_armor(), non_neg_integer()}. +   -> ({ok, type()} | blc_error:type()).  increase_health_for (GivenPoints, Armor) ->     AmountOfIncrease = trunc(GivenPoints / ?ATTRIBUTE_HEALTH_COST), -   {Result, SpentPoints} = increase_health_by(AmountOfIncrease, Armor), -   {Result, (GivenPoints - SpentPoints)}. +   increase_health_by(AmountOfIncrease, Armor).  -spec increase_damage_modifier_for     (        non_neg_integer(), -      proto_armor() +      type()     ) -   -> {proto_armor(), non_neg_integer()}. +   -> ({ok, type()} | blc_error:type()).  increase_damage_modifier_for (GivenPoints, Armor) ->     AmountOfIncrease = trunc(GivenPoints / ?ATTRIBUTE_DAMAGE_MODIFIER_COST), -   {Result, SpentPoints} = increase_damage_modifier_by(AmountOfIncrease, Armor), -   {Result, (GivenPoints - SpentPoints)}. +   increase_damage_modifier_by(AmountOfIncrease, Armor).  -spec increase_dodge_chance_for     (        non_neg_integer(), -      proto_armor() +      type()     ) -   -> {proto_armor(), non_neg_integer()}. +   -> ({ok, type()} | blc_error:type()).  increase_dodge_chance_for (GivenPoints, Armor) ->     AmountOfIncrease = trunc(GivenPoints / ?ATTRIBUTE_DODGE_CHANCE_COST), -   {Result, SpentPoints} = increase_dodge_chance_by(AmountOfIncrease, Armor), -   {Result, (GivenPoints - SpentPoints)}. +   increase_dodge_chance_by(AmountOfIncrease, Armor).  -spec increase_movement_points_for     (        non_neg_integer(), -      proto_armor() +      type()     ) -   -> {proto_armor(), non_neg_integer()}. +   -> ({ok, type()} | blc_error:type()).  increase_movement_points_for (GivenPoints, Armor) ->     AmountOfIncrease = trunc(GivenPoints / ?ATTRIBUTE_MOVEMENT_POINTS_COST), -   {Result, SpentPoints} = increase_movement_points_by(AmountOfIncrease, Armor), -   {Result, (GivenPoints - SpentPoints)}. +   increase_movement_points_by(AmountOfIncrease, Armor).  -spec increase_defense_score_for     (        non_neg_integer(), -      proto_armor() +      type()     ) -   -> {proto_armor(), non_neg_integer()}. +   -> ({ok, type()} | blc_error:type()).  increase_defense_score_for (GivenPoints, Armor) ->     AmountOfIncrease = trunc(GivenPoints / ?ATTRIBUTE_DEFENSE_SCORE_COST), -   {Result, SpentPoints} = increase_defense_score_by(AmountOfIncrease, Armor), -   {Result, (GivenPoints - SpentPoints)}. - +   increase_defense_score_by(AmountOfIncrease, Armor). --spec get_spendable_points () -> non_neg_integer(). -get_spendable_points () -> ?SPENDABLE_ARMOR_POINTS. +-spec get_remaining_points (type()) -> non_neg_integer(). +get_remaining_points (Armor) -> Armor#proto_armor.remaining_points. diff --git a/src/balancer/struct/blc_glyph.erl b/src/balancer/struct/blc_glyph.erl index 9b43f88..894dd9f 100644 --- a/src/balancer/struct/blc_glyph.erl +++ b/src/balancer/struct/blc_glyph.erl @@ -16,8 +16,8 @@        remaining_positive_points :: non_neg_integer(),        points_balance :: integer(),        omnimods :: shr_omnimods:type(), -      defense_coef :: blc_damage_type:coefficient(), -      attack_coef :: blc_damage_type:coefficient(), +      defense_coef :: list(blc_damage_type:coefficient()), +      attack_coef :: list(blc_damage_type:coefficient()),        defense_score :: non_neg_integer(),        defense_sign :: integer(),        attack_score :: non_neg_integer(), @@ -156,7 +156,8 @@ increase_attribute_by (?ATTRIBUTE_DEFENSE_SCORE, S0Amount, Glyph) ->  increase_attribute_by (Attribute, S0Amount, Glyph) ->     {_AttMin, _AttDef, AttMax, AttCost} = blc_attribute:get_info(Attribute),     CurrentOmnimods = Glyph#proto_glyph.omnimods, -   CurrentValue = shr_omnimods:get_attribute(Attribute, CurrentOmnimods), +   CurrentValue = +      shr_omnimods:get_attribute_modifier(Attribute, CurrentOmnimods),     S1Amount =        case ((CurrentValue + S0Amount) > AttMax) of @@ -177,7 +178,7 @@ increase_attribute_by (Attribute, S0Amount, Glyph) ->              Glyph#proto_glyph              {                 omnimods = -                  shr_omnimods:mod_attribute +                  shr_omnimods:mod_attribute_modifier                    (                       Attribute,                       S1Amount, @@ -274,9 +275,10 @@ decrease_attribute_by (?ATTRIBUTE_DEFENSE_SCORE, Amount, Glyph) ->  decrease_attribute_by (Attribute, Amount, Glyph) ->     {_AttMin, _AttDef, _AttMax, AttCost} = blc_attribute:get_info(Attribute),     CurrentOmnimods = Glyph#proto_glyph.omnimods, -   CurrentValue = shr_omnimods:get_attribute(Attribute, CurrentOmnimods), +   CurrentValue = +      shr_omnimods:get_attribute_modifier(Attribute, CurrentOmnimods), -   Cost = ((Amount * AttCost) * ?NEGATIVE_POINTS_MULTIPLIER), +   Cost = trunc((Amount * AttCost) * ?NEGATIVE_POINTS_MULTIPLIER),     if        (CurrentValue > 0) -> {error, incompatible}; @@ -287,7 +289,7 @@ decrease_attribute_by (Attribute, Amount, Glyph) ->              Glyph#proto_glyph              {                 omnimods = -                  shr_omnimods:mod_attribute +                  shr_omnimods:mod_attribute_modifier                    (                       Attribute,                       (-1 * Amount), @@ -407,7 +409,7 @@ new (AttackCoefficients, DefenseCoefficients) ->     {        remaining_positive_points = ?SPENDABLE_GLYPH_POINTS,        points_balance = 0, -      omnimods = omnimods:new(), +      omnimods = shr_omnimods:new(),        attack_coef = blc_damage_type:sort_entries(AttackCoefficients),        attack_score = 0,        attack_sign = 0, diff --git a/src/balancer/struct/blc_weapon.erl b/src/balancer/struct/blc_weapon.erl index 0edeb35..970c4e5 100644 --- a/src/balancer/struct/blc_weapon.erl +++ b/src/balancer/struct/blc_weapon.erl @@ -7,15 +7,9 @@  -define(WEAPON_ATTRIBUTE_RANGE_DEFAULT,   0).  -define(WEAPON_ATTRIBUTE_RANGE_COST,      1). --define(WEAPON_ATTRIBUTE_TYPE_MIN,     0). --define(WEAPON_ATTRIBUTE_TYPE_MAX,     1). --define(WEAPON_ATTRIBUTE_TYPE_DEFAULT, 0). --define(WEAPON_ATTRIBUTE_TYPE_COST,    100). - -  -define  ( -   SPENDABLE_WEAPON_POINTS, +   BASE_SPENDABLE_WEAPON_POINTS,     (        (           ?ATTRIBUTE_ACCURACY_COST @@ -52,42 +46,57 @@     )  ). +-define +( +   MELEE_SPENDABLE_WEAPON_POINTS, +   ( +      ?BASE_SPENDABLE_WEAPON_POINTS +      + +      ( +         ?ATTRIBUTE_PARRY_CHANCE_COST +         * (?ATTRIBUTE_PARRY_CHANCE_DEFAULT - ?ATTRIBUTE_PARRY_CHANCE_MIN) +      ) +   ) +). + +-define(RANGED_SPENDABLE_WEAPON_POINTS, ?BASE_SPENDABLE_WEAPON_POINTS). +  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-type range_type() :: (melee | ranged). +  -record  (     proto_weapon,     {        range :: non_neg_integer(), -      type :: non_neg_integer(), -      accuracy :: non_neg_integer(), -      critical_hit_chance :: non_neg_integer(), -      double_hit_chance :: non_neg_integer(), -      attack :: list(blc_damage_type:entry()), +      range_type :: range_type(), +      omnimods :: shr_omnimods:type(),        attack_coef :: list(blc_damage_type:coefficient()), -      attack_score :: non_neg_integer() +      attack_score :: non_neg_integer(), +      remaining_points :: non_neg_integer()     }  ). --opaque proto_weapon() :: #proto_weapon{}. +-opaque type() :: #proto_weapon{}.  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --export_type([proto_weapon/0]). +-export_type([type/0,range_type/0]).  -export  (     [        increase_range_by/2, -      increase_type_by/2, +      increase_parry_chance_by/2,        increase_accuracy_by/2,        increase_critical_hit_chance_by/2,        increase_double_hit_chance_by/2,        increase_attack_score_by/2,        increase_range_for/2, -      increase_type_for/2, +      increase_parry_chance_for/2,        increase_accuracy_for/2,        increase_critical_hit_chance_for/2,        increase_double_hit_chance_for/2, @@ -99,14 +108,55 @@  -export  (     [ -      new/1, -      get_spendable_points/0 +      new/2, +      get_remaining_points/1     ]  ).  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec increase_attribute_by +   ( +      shr_attributes:enum(), +      non_neg_integer(), +      type() +   ) +   -> ({ok, type()} | blc_error:type()). +increase_attribute_by (Attribute, S0Amount, Weapon) -> +   CurrentOmnimods = Weapon#proto_weapon.omnimods, +   CurrentValue = +      shr_omnimods:get_attribute_modifier(Attribute, CurrentOmnimods), + +   {_AttMin, _AttDef, AttMax, AttCost} = blc_attribute:get_info(Attribute), + +   S1Amount = +      case ((CurrentValue + S0Amount) > AttMax) of +         true -> (AttMax - CurrentValue); +         false -> S0Amount +      end, + +   Cost = (S1Amount * AttCost), +   RemainingPoints = Weapon#proto_weapon.remaining_points, + +   case (Cost > RemainingPoints) of +      true -> {error, balance, RemainingPoints, Cost}; +      false -> +         { +            ok, +            Weapon#proto_weapon +            { +               remaining_points = (RemainingPoints - Cost), +               omnimods = +                  shr_omnimods:mod_attribute_modifier +                  ( +                     Attribute, +                     S1Amount, +                     Weapon#proto_weapon.omnimods +                  ) +            } +         } +   end.  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -114,301 +164,221 @@  -spec increase_accuracy_by     (        non_neg_integer(), -      proto_weapon() +      type()     ) -   -> {proto_weapon(), non_neg_integer()}. +   -> ({ok, type()} | blc_error:type()).  increase_accuracy_by (Amount, Weapon) -> -   NewAccuracy = (Weapon#proto_weapon.accuracy + Amount), -   case (NewAccuracy > ?ATTRIBUTE_ACCURACY_MAX) of -      true -> -         { -            Weapon#proto_weapon{ accuracy = ?ATTRIBUTE_ACCURACY_MAX }, -            ( -               (?ATTRIBUTE_ACCURACY_MAX - Weapon#proto_weapon.accuracy) -               * ?ATTRIBUTE_ACCURACY_COST -            ) -         }; - -      false -> -         { -            Weapon#proto_weapon{ accuracy = NewAccuracy }, -            (Amount * ?ATTRIBUTE_ACCURACY_COST) -         } -   end. +   increase_attribute_by(?ATTRIBUTE_ACCURACY, Amount, Weapon).  -spec increase_range_by     (        non_neg_integer(), -      proto_weapon() +      type()     ) -   -> {proto_weapon(), non_neg_integer()}. +   -> ({ok, type()} | blc_error:type()).  increase_range_by (Amount, Weapon) -> -   NewDamageModifier = Weapon#proto_weapon.range + Amount, -   case (NewDamageModifier > ?WEAPON_ATTRIBUTE_RANGE_MAX) of -      true -> -         { -            Weapon#proto_weapon -            { -               range = ?WEAPON_ATTRIBUTE_RANGE_MAX -            }, -            ( -               ( -                  ?WEAPON_ATTRIBUTE_RANGE_MAX -                  - Weapon#proto_weapon.range -               ) -               * ?WEAPON_ATTRIBUTE_RANGE_COST -            ) -         }; +   increase_attribute_by(?ATTRIBUTE_ACCURACY, Amount, Weapon). -      false -> -         { -            Weapon#proto_weapon{ range = NewDamageModifier }, -            (Amount * ?WEAPON_ATTRIBUTE_RANGE_COST) -         } -   end. - --spec increase_type_by +-spec increase_parry_chance_by     (        non_neg_integer(), -      proto_weapon() +      type()     ) -   -> {proto_weapon(), non_neg_integer()}. -increase_type_by (Amount, Weapon) -> -   NewType = Weapon#proto_weapon.type + Amount, -   case (NewType > ?WEAPON_ATTRIBUTE_TYPE_MAX) of -      true -> -         { -            Weapon#proto_weapon { type = ?WEAPON_ATTRIBUTE_TYPE_MAX }, -            ( -               (?WEAPON_ATTRIBUTE_TYPE_MAX - Weapon#proto_weapon.type) -               * ?WEAPON_ATTRIBUTE_TYPE_COST -            ) -         }; - -      false -> -         { -            Weapon#proto_weapon{ type = NewType }, -            (Amount * ?WEAPON_ATTRIBUTE_TYPE_COST) -         } +   -> ({ok, type()} | blc_error:type()). +increase_parry_chance_by (Amount, Weapon) -> +   case (Weapon#proto_weapon.range_type) of +      ranged -> {error, incompatible}; +      _ -> increase_attribute_by(?ATTRIBUTE_PARRY_CHANCE, Amount, Weapon)     end.  -spec increase_critical_hit_chance_by     (        non_neg_integer(), -      proto_weapon() +      type()     ) -   -> {proto_weapon(), non_neg_integer()}. +   -> ({ok, type()} | blc_error:type()).  increase_critical_hit_chance_by (Amount, Weapon) -> -   NewCriticalHitChance = (Weapon#proto_weapon.critical_hit_chance + Amount), -   case (NewCriticalHitChance > ?ATTRIBUTE_CRITICAL_HIT_CHANCE_MAX) of -      true -> -         { -            Weapon#proto_weapon -            { -               critical_hit_chance = ?ATTRIBUTE_CRITICAL_HIT_CHANCE_MAX -            }, -            ( -               ( -                  ?ATTRIBUTE_CRITICAL_HIT_CHANCE_MAX -                  - Weapon#proto_weapon.critical_hit_chance -               ) -               * ?ATTRIBUTE_CRITICAL_HIT_CHANCE_COST -            ) -         }; - -      false -> -         { -            Weapon#proto_weapon{ critical_hit_chance = NewCriticalHitChance }, -            (Amount * ?ATTRIBUTE_CRITICAL_HIT_CHANCE_COST) -         } -   end. +   increase_attribute_by(?ATTRIBUTE_CRITICAL_HIT_CHANCE, Amount, Weapon).  -spec increase_double_hit_chance_by     (        non_neg_integer(), -      proto_weapon() +      type()     ) -   -> {proto_weapon(), non_neg_integer()}. +   -> ({ok, type()} | blc_error:type()).  increase_double_hit_chance_by (Amount, Weapon) -> -   NewDoubleHitChance = Weapon#proto_weapon.double_hit_chance + Amount, -   case (NewDoubleHitChance > ?ATTRIBUTE_DOUBLE_HIT_CHANCE_MAX) of -      true -> -         { -            Weapon#proto_weapon -            { -               double_hit_chance = ?ATTRIBUTE_DOUBLE_HIT_CHANCE_MAX -            }, -            ( -               ( -                  ?ATTRIBUTE_DOUBLE_HIT_CHANCE_MAX -                  - Weapon#proto_weapon.double_hit_chance -               ) -               * ?ATTRIBUTE_DOUBLE_HIT_CHANCE_COST -            ) -         }; - -      false -> -         { -            Weapon#proto_weapon{ double_hit_chance = NewDoubleHitChance }, -            (Amount * ?ATTRIBUTE_DOUBLE_HIT_CHANCE_COST) -         } -   end. - +   increase_attribute_by(?ATTRIBUTE_DOUBLE_HIT_CHANCE, Amount, Weapon).  -spec increase_attack_score_by     (        non_neg_integer(), -      proto_weapon() +      type()     ) -   -> {proto_weapon(), non_neg_integer()}. -increase_attack_score_by (Amount, Weapon) -> -   NewAttackScore = (Weapon#proto_weapon.attack_score + Amount), -   case (NewAttackScore > ?ATTRIBUTE_ATTACK_SCORE_MAX) of -      true -> -         { -            Weapon#proto_weapon +   -> ({ok, type()} | blc_error:type()). +increase_attack_score_by (S0Amount, Weapon) -> +   CurrentValue = Weapon#proto_weapon.attack_score, +   S0NewValue = CurrentValue + S0Amount, +   {S1Amount, S1NewValue} = +      case (S0NewValue > ?ATTRIBUTE_ATTACK_SCORE_MAX) of +         false -> {S0Amount, S0NewValue}; +         true ->              { -               attack_score = ?ATTRIBUTE_ATTACK_SCORE_MAX, -               attack = -                  blc_damage_type:generate_entries_from_score -                  ( -                     NewAttackScore, -                     Weapon#proto_weapon.attack_coef -                  ) -            }, -            ( -               (?ATTRIBUTE_ATTACK_SCORE_MAX - Weapon#proto_weapon.attack_score) -               * Amount -            ) -         }; +               (?ATTRIBUTE_ATTACK_SCORE_MAX - CurrentValue), +               ?ATTRIBUTE_ATTACK_SCORE_MAX +            } +      end, +   Cost = (S1Amount * ?ATTRIBUTE_ATTACK_SCORE_COST), +   RemainingPoints = Weapon#proto_weapon.remaining_points, + +   case (Cost > RemainingPoints) of +      true -> {error, balance, RemainingPoints, Cost};        false ->           { +            ok,              Weapon#proto_weapon              { -               attack_score = NewAttackScore, -               attack = -                  blc_damage_type:generate_entries_from_score +               remaining_points = (RemainingPoints - Cost), +               attack_score = S1NewValue, +               omnimods = +                  shr_omnimods:set_attack_modifiers                    ( -                     NewAttackScore, -                     Weapon#proto_weapon.attack_coef +                     blc_damage_type:generate_entries_from_score +                     ( +                        S1NewValue, +                        Weapon#proto_weapon.attack_coef +                     ), +                     Weapon#proto_weapon.omnimods                    ) -            }, -            (Amount * ?ATTRIBUTE_ATTACK_SCORE_COST) +            }           }     end.  -spec set_attack_coefficients     (        list(blc_damage_type:coefficient()), -      proto_weapon() +      type()     ) -   -> proto_weapon(). +   -> type().  set_attack_coefficients (Coefficients, Weapon) -> -   {Result, 0} = -      increase_attack_score_by -      ( -         0, -         Weapon#proto_weapon -         { -            attack_coef = blc_damage_type:sort_entries(Coefficients) -         } -      ), +   NewCoefs = blc_damage_type:sort_entries(Coefficients), -   Result. +   Weapon#proto_weapon +   { +      attack_coef = NewCoefs, +      omnimods = +         shr_omnimods:set_attack_modifiers +         ( +            blc_damage_type:generate_entries_from_score +            ( +               Weapon#proto_weapon.attack_score, +               NewCoefs +            ), +            Weapon#proto_weapon.omnimods +         ) +   }. --spec new (list(blc_damage_type:coefficient())) -> proto_weapon(). -new (Coefficients) -> -   {Result, _AttackScoreIncreaseCost} = -      increase_attack_score_by -      ( -         ?ATTRIBUTE_ATTACK_SCORE_MIN, -         #proto_weapon -         { -            range = ?WEAPON_ATTRIBUTE_RANGE_MIN, -            type = ?WEAPON_ATTRIBUTE_TYPE_MIN, -            accuracy = ?ATTRIBUTE_ACCURACY_MIN, -            critical_hit_chance = ?ATTRIBUTE_CRITICAL_HIT_CHANCE_MIN, -            double_hit_chance = ?ATTRIBUTE_DOUBLE_HIT_CHANCE_MIN, -            attack = [], -            attack_coef = blc_damage_type:sort_entries(Coefficients), -            attack_score = 0 -         } -      ), +-spec new (range_type(), list(blc_damage_type:coefficient())) -> type(). +new (RangeType, Coefficients) -> +   SortedCoefficients = blc_damage_type:sort_entries(Coefficients), -   Result. +   #proto_weapon +   { +      range = ?WEAPON_ATTRIBUTE_RANGE_MIN, +      range_type = RangeType, +      omnimods = +         shr_omnimods:new +         ( +            [ +               {?ATTRIBUTE_ACCURACY, ?ATTRIBUTE_ACCURACY_MIN}, +               {?ATTRIBUTE_PARRY_CHANCE, ?ATTRIBUTE_PARRY_CHANCE_MIN}, +               { +                  ?ATTRIBUTE_CRITICAL_HIT_CHANCE, +                  ?ATTRIBUTE_CRITICAL_HIT_CHANCE_MIN +               }, +               { +                  ?ATTRIBUTE_DOUBLE_HIT_CHANCE, +                  ?ATTRIBUTE_DOUBLE_HIT_CHANCE_MIN +               } +            ], +            blc_damage_type:generate_entries_from_score +            ( +               ?ATTRIBUTE_ATTACK_SCORE_MIN, +               SortedCoefficients +            ), +            [] +         ), + +      attack_coef = SortedCoefficients, +      attack_score = ?ATTRIBUTE_ATTACK_SCORE_MIN, +      remaining_points = +         case RangeType of +            melee -> ?MELEE_SPENDABLE_WEAPON_POINTS; +            ranged -> ?RANGED_SPENDABLE_WEAPON_POINTS +         end +   }.  -spec increase_range_for     (        non_neg_integer(), -      proto_weapon() +      type()     ) -   -> {proto_weapon(), non_neg_integer()}. +   -> ({ok, type()} | blc_error:type()).  increase_range_for (GivenPoints, Weapon) ->     AmountOfIncrease = trunc(GivenPoints / ?WEAPON_ATTRIBUTE_RANGE_COST), -   {Result, SpentPoints} = increase_range_by(AmountOfIncrease, Weapon), -   {Result, (GivenPoints - SpentPoints)}. +   increase_range_by(AmountOfIncrease, Weapon). --spec increase_type_for +-spec increase_parry_chance_for     (        non_neg_integer(), -      proto_weapon() +      type()     ) -   -> {proto_weapon(), non_neg_integer()}. -increase_type_for (GivenPoints, Weapon) -> -   AmountOfIncrease = trunc(GivenPoints / ?WEAPON_ATTRIBUTE_TYPE_COST), -   {Result, SpentPoints} = increase_type_by(AmountOfIncrease, Weapon), -   {Result, (GivenPoints - SpentPoints)}. +   -> ({ok, type()} | blc_error:type()). +increase_parry_chance_for (GivenPoints, Weapon) -> +   AmountOfIncrease = trunc(GivenPoints / ?ATTRIBUTE_PARRY_CHANCE_COST), +   increase_parry_chance_by(AmountOfIncrease, Weapon).  -spec increase_accuracy_for     (        non_neg_integer(), -      proto_weapon() +      type()     ) -   -> {proto_weapon(), non_neg_integer()}. +   -> ({ok, type()} | blc_error:type()).  increase_accuracy_for (GivenPoints, Weapon) ->     AmountOfIncrease = trunc(GivenPoints / ?ATTRIBUTE_ACCURACY_COST), -   {Result, SpentPoints} = increase_accuracy_by(AmountOfIncrease, Weapon), -   {Result, (GivenPoints - SpentPoints)}. +   increase_accuracy_by(AmountOfIncrease, Weapon).  -spec increase_critical_hit_chance_for     (        non_neg_integer(), -      proto_weapon() +      type()     ) -   -> {proto_weapon(), non_neg_integer()}. +   -> ({ok, type()} | blc_error:type()).  increase_critical_hit_chance_for (GivenPoints, Weapon) ->     AmountOfIncrease = trunc(GivenPoints / ?ATTRIBUTE_CRITICAL_HIT_CHANCE_COST), -   {Result, SpentPoints} = -      increase_critical_hit_chance_by(AmountOfIncrease, Weapon), - -   {Result, (GivenPoints - SpentPoints)}. +   increase_critical_hit_chance_by(AmountOfIncrease, Weapon).  -spec increase_double_hit_chance_for     (        non_neg_integer(), -      proto_weapon() +      type()     ) -   -> {proto_weapon(), non_neg_integer()}. +   -> ({ok, type()} | blc_error:type()).  increase_double_hit_chance_for (GivenPoints, Weapon) ->     AmountOfIncrease = trunc(GivenPoints / ?ATTRIBUTE_DOUBLE_HIT_CHANCE_COST), -   {Result, SpentPoints} = -      increase_double_hit_chance_by(AmountOfIncrease, Weapon), - -   {Result, (GivenPoints - SpentPoints)}. +   increase_double_hit_chance_by(AmountOfIncrease, Weapon).  -spec increase_attack_score_for     (        non_neg_integer(), -      proto_weapon() +      type()     ) -   -> {proto_weapon(), non_neg_integer()}. +   -> ({ok, type()} | blc_error:type()).  increase_attack_score_for (GivenPoints, Weapon) ->     AmountOfIncrease = trunc(GivenPoints / ?ATTRIBUTE_ATTACK_SCORE_COST), -   {Result, SpentPoints} = increase_attack_score_by(AmountOfIncrease, Weapon), -   {Result, (GivenPoints - SpentPoints)}. +   increase_attack_score_by(AmountOfIncrease, Weapon). --spec get_spendable_points () -> non_neg_integer(). -get_spendable_points () -> ?SPENDABLE_WEAPON_POINTS. +-spec get_remaining_points (type()) -> non_neg_integer(). +get_remaining_points (Weapon) -> Weapon#proto_weapon.remaining_points. diff --git a/src/battle/mechanic/action/btl_action_attack.erl b/src/battle/mechanic/action/btl_action_attack.erl index 04becc8..62c58f8 100644 --- a/src/battle/mechanic/action/btl_action_attack.erl +++ b/src/battle/mechanic/action/btl_action_attack.erl @@ -24,7 +24,7 @@     )     -> {float(), integer(), integer()}.  roll_precision_modifier (Attributes, TargetAttributes, TargetLuck) -> -   TargetDodges = shr_attributes:get_dodges(TargetAttributes), +   TargetDodges = shr_attributes:get_dodge_chance(TargetAttributes),     Accuracy = shr_attributes:get_accuracy(Attributes),     MissChance = max(0, (TargetDodges - Accuracy)), @@ -48,7 +48,7 @@ roll_precision_modifier (Attributes, TargetAttributes, TargetLuck) ->     )     -> {float(), integer(), integer()}.  roll_critical_modifier (Attributes, Luck) -> -   CriticalHitChance = shr_attributes:get_critical_hits(Attributes), +   CriticalHitChance = shr_attributes:get_critical_hit_chance(Attributes),     {_Roll, IsSuccess, PositiveModifier, NegativeModifier} =        shr_roll:percentage_with_luck(CriticalHitChance, Luck), @@ -68,7 +68,7 @@ roll_critical_modifier (Attributes, Luck) ->     )     -> {boolean(), integer(), integer()}.  roll_parry (DefenderAttributes, DefenderLuck) -> -   DefenderParryChance = shr_attributes:get_parries(DefenderAttributes), +   DefenderParryChance = shr_attributes:get_parry_chance(DefenderAttributes),     {_Roll, IsSuccess, PositiveModifier, NegativeModifier} =        shr_roll:percentage_with_luck(DefenderParryChance, DefenderLuck), @@ -518,7 +518,7 @@ handle_attack_sequence              (                 btl_character:get_base_character(S0Character)              ), -         DoubleAttackChance = shr_attributes:get_double_hits(Attributes), +         DoubleAttackChance = shr_attributes:get_double_hit_chance(Attributes),           {_Roll, IsSuccessful, PositiveModifier, NegativeModifier} =              shr_roll:percentage_with_luck(DoubleAttackChance, S0PlayerLuck), diff --git a/src/shared/struct/shr_omnimods.erl b/src/shared/struct/shr_omnimods.erl index e4993c8..ae8ba44 100644 --- a/src/shared/struct/shr_omnimods.erl +++ b/src/shared/struct/shr_omnimods.erl @@ -54,7 +54,10 @@        apply_coefficient/2,        set_attribute_modifiers/2,        set_attack_modifiers/2, -      set_defense_modifiers/2 +      set_defense_modifiers/2, +      mod_attribute_modifier/3, +      mod_attack_modifier/3, +      mod_defense_modifier/3     ]  ). @@ -173,6 +176,66 @@ set_attack_modifiers (NewAttackModifiers, Omnimods) ->        atkmods = dict:from_list(NewAttackModifiers)     }. +-spec mod_attribute_modifier +   ( +      shr_attributes:enum(), +      integer(), +      type() +   ) +   -> type(). +mod_attribute_modifier (Attribute, Mod, Omnimods) -> +   Omnimods#omnimods +   { +      attmods = +         dict:update +         ( +            Attribute, +            fun (Current) -> (Current + Mod) end, +            Mod, +            Omnimods#omnimods.attmods +         ) +   }. + +-spec mod_attack_modifier +   ( +      shr_damage_type:type(), +      integer(), +      type() +   ) +   -> type(). +mod_attack_modifier (DamageType, Mod, Omnimods) -> +   Omnimods#omnimods +   { +      atkmods = +         dict:update +         ( +            DamageType, +            fun (Current) -> (Current + Mod) end, +            Mod, +            Omnimods#omnimods.atkmods +         ) +   }. + +-spec mod_defense_modifier +   ( +      shr_damage_type:type(), +      integer(), +      type() +   ) +   -> type(). +mod_defense_modifier (DamageType, Mod, Omnimods) -> +   Omnimods#omnimods +   { +      defmods = +         dict:update +         ( +            DamageType, +            fun (Current) -> (Current + Mod) end, +            Mod, +            Omnimods#omnimods.defmods +         ) +   }. +  %%%% Access  -spec apply_to_attributes     ( @@ -269,13 +332,13 @@ get_defense_modifier (DamageType, Omnimods) ->     end.  -spec get_attribute_modifiers (type()) -> list(attribute_entry()). -get_attribute_modifiers (Omnimods) -> lists:to_list(Omnimods#omnimods.attmods). +get_attribute_modifiers (Omnimods) -> dict:to_list(Omnimods#omnimods.attmods).  -spec get_attack_modifiers (type()) -> list(damage_type_entry()). -get_attack_modifiers (Omnimods) -> lists:to_list(Omnimods#omnimods.atkmods). +get_attack_modifiers (Omnimods) -> dict:to_list(Omnimods#omnimods.atkmods).  -spec get_defense_modifiers (type()) -> list(damage_type_entry()). -get_defense_modifiers (Omnimods) -> lists:to_list(Omnimods#omnimods.defmods). +get_defense_modifiers (Omnimods) -> dict:to_list(Omnimods#omnimods.defmods).  %%% Export | 


