| summaryrefslogtreecommitdiff | 
diff options
| -rw-r--r-- | include/tacticians/attributes.hrl.m4 (renamed from include/base_attributes.hrl) | 20 | ||||
| -rw-r--r-- | include/tacticians/damage_types.hrl.m4 (renamed from include/damage_types.hrl.m4) | 0 | ||||
| -rw-r--r-- | src/balancer/blc_attribute.erl | 100 | ||||
| -rw-r--r-- | src/balancer/struct/blc_armor.erl | 11 | ||||
| -rw-r--r-- | src/balancer/struct/blc_error.erl | 24 | ||||
| -rw-r--r-- | src/balancer/struct/blc_glyph.erl | 451 | ||||
| -rw-r--r-- | src/balancer/struct/blc_weapon.erl | 414 | ||||
| -rw-r--r-- | src/shared/struct/shr_attributes.erl | 110 | ||||
| -rw-r--r-- | src/shared/struct/shr_damage_type.erl | 2 | ||||
| -rw-r--r-- | src/shared/struct/shr_omnimods.erl | 115 | 
10 files changed, 1179 insertions, 68 deletions
diff --git a/include/base_attributes.hrl b/include/tacticians/attributes.hrl.m4 index 09bc136..3c0e731 100644 --- a/include/base_attributes.hrl +++ b/include/tacticians/attributes.hrl.m4 @@ -1,48 +1,60 @@ +m4_include(__MAKEFILE_DATA_DIR/names.m4.conf) + +-define(ATTRIBUTE_DAMAGE_MODIFIER,           __SN_DAMAGE_MODIFIER).  -define(ATTRIBUTE_DAMAGE_MODIFIER_MIN,       0).  -define(ATTRIBUTE_DAMAGE_MODIFIER_MAX,       300).  -define(ATTRIBUTE_DAMAGE_MODIFIER_DEFAULT,   100).  -define(ATTRIBUTE_DAMAGE_MODIFIER_COST,      1). +-define(ATTRIBUTE_MOVEMENT_POINTS,           __SN_MOVEMENT_POINTS).  -define(ATTRIBUTE_MOVEMENT_POINTS_MIN,       8).  -define(ATTRIBUTE_MOVEMENT_POINTS_MAX,       200).  -define(ATTRIBUTE_MOVEMENT_POINTS_DEFAULT,   32).  -define(ATTRIBUTE_MOVEMENT_POINTS_COST,      1). +-define(ATTRIBUTE_HEALTH,           __SN_MAX_HEALTH).  -define(ATTRIBUTE_HEALTH_MIN,       1).  -define(ATTRIBUTE_HEALTH_MAX,       500).  -define(ATTRIBUTE_HEALTH_DEFAULT,   100).  -define(ATTRIBUTE_HEALTH_COST,      1). --define(ATTRIBUTE_DODGE_CHANCE_MIN,     0). --define(ATTRIBUTE_DODGE_CHANCE_MAX,     175). --define(ATTRIBUTE_DODGE_CHANCE_DEFAULT, 50). --define(ATTRIBUTE_DODGE_CHANCE_COST,    1). +-define(ATTRIBUTE_DODGE_CHANCE,           __SN_DODGE). +-define(ATTRIBUTE_DODGE_CHANCE_MIN,       0). +-define(ATTRIBUTE_DODGE_CHANCE_MAX,       175). +-define(ATTRIBUTE_DODGE_CHANCE_DEFAULT,   50). +-define(ATTRIBUTE_DODGE_CHANCE_COST,      1). +-define(ATTRIBUTE_PARRY_CHANCE,         __SN_PARRY).  -define(ATTRIBUTE_PARRY_CHANCE_MIN,     0).  -define(ATTRIBUTE_PARRY_CHANCE_MAX,     100).  -define(ATTRIBUTE_PARRY_CHANCE_DEFAULT, 5).  -define(ATTRIBUTE_PARRY_CHANCE_COST,    1). +-define(ATTRIBUTE_ACCURACY,         __SN_ACCURACY).  -define(ATTRIBUTE_ACCURACY_MIN,     0).  -define(ATTRIBUTE_ACCURACY_MAX,     100).  -define(ATTRIBUTE_ACCURACY_DEFAULT, 50).  -define(ATTRIBUTE_ACCURACY_COST,    1). +-define(ATTRIBUTE_DOUBLE_HIT_CHANCE,         __SN_DOUBLE_HITS).  -define(ATTRIBUTE_DOUBLE_HIT_CHANCE_MIN,     0).  -define(ATTRIBUTE_DOUBLE_HIT_CHANCE_MAX,     100).  -define(ATTRIBUTE_DOUBLE_HIT_CHANCE_DEFAULT, 5).  -define(ATTRIBUTE_DOUBLE_HIT_CHANCE_COST,    1). +-define(ATTRIBUTE_CRITICAL_HIT_CHANCE,          __SN_CRITICAL_HIT).  -define(ATTRIBUTE_CRITICAL_HIT_CHANCE_MIN,      0).  -define(ATTRIBUTE_CRITICAL_HIT_CHANCE_MAX,      100).  -define(ATTRIBUTE_CRITICAL_HIT_CHANCE_DEFAULT,  10).  -define(ATTRIBUTE_CRITICAL_HIT_CHANCE_COST,     1). +-define(ATTRIBUTE_DEFENSE_SCORE,          def_score).  -define(ATTRIBUTE_DEFENSE_SCORE_MIN,      0).  -define(ATTRIBUTE_DEFENSE_SCORE_MAX,      300).  -define(ATTRIBUTE_DEFENSE_SCORE_DEFAULT,  50).  -define(ATTRIBUTE_DEFENSE_SCORE_COST,     1). +-define(ATTRIBUTE_ATTACK_SCORE,           atk_score).  -define(ATTRIBUTE_ATTACK_SCORE_MIN,       0).  -define(ATTRIBUTE_ATTACK_SCORE_MAX,       300).  -define(ATTRIBUTE_ATTACK_SCORE_DEFAULT,   50). diff --git a/include/damage_types.hrl.m4 b/include/tacticians/damage_types.hrl.m4 index df82e59..df82e59 100644 --- a/include/damage_types.hrl.m4 +++ b/include/tacticians/damage_types.hrl.m4 diff --git a/src/balancer/blc_attribute.erl b/src/balancer/blc_attribute.erl new file mode 100644 index 0000000..55becfa --- /dev/null +++ b/src/balancer/blc_attribute.erl @@ -0,0 +1,100 @@ +-module(blc_attribute). + +-include("tacticians/attributes.hrl"). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export +( +   [ +      get_info/1 +   ] +). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec get_info +   ( +      shr_attributes:meta_enum() +   ) +   -> +   { +      non_neg_integer(), +      non_neg_integer(), +      non_neg_integer(), +      non_neg_integer() +   }. +get_info (?ATTRIBUTE_ACCURACY) -> +   { +      ?ATTRIBUTE_ACCURACY_MIN, +      ?ATTRIBUTE_ACCURACY_DEFAULT, +      ?ATTRIBUTE_ACCURACY_MAX, +      ?ATTRIBUTE_ACCURACY_COST +   }; +get_info (?ATTRIBUTE_ATTACK_SCORE) -> +   { +      ?ATTRIBUTE_ATTACK_SCORE_MIN, +      ?ATTRIBUTE_ATTACK_SCORE_DEFAULT, +      ?ATTRIBUTE_ATTACK_SCORE_MAX, +      ?ATTRIBUTE_ATTACK_SCORE_COST +   }; +get_info (?ATTRIBUTE_CRITICAL_HIT_CHANCE) -> +   { +      ?ATTRIBUTE_CRITICAL_HIT_CHANCE_MIN, +      ?ATTRIBUTE_CRITICAL_HIT_CHANCE_DEFAULT, +      ?ATTRIBUTE_CRITICAL_HIT_CHANCE_MAX, +      ?ATTRIBUTE_CRITICAL_HIT_CHANCE_COST +   }; +get_info (?ATTRIBUTE_DEFENSE_SCORE) -> +   { +      ?ATTRIBUTE_DEFENSE_SCORE_MIN, +      ?ATTRIBUTE_DEFENSE_SCORE_DEFAULT, +      ?ATTRIBUTE_DEFENSE_SCORE_MAX, +      ?ATTRIBUTE_DEFENSE_SCORE_COST +   }; +get_info (?ATTRIBUTE_DODGE_CHANCE) -> +   { +      ?ATTRIBUTE_DODGE_CHANCE_MIN, +      ?ATTRIBUTE_DODGE_CHANCE_DEFAULT, +      ?ATTRIBUTE_DODGE_CHANCE_MAX, +      ?ATTRIBUTE_DODGE_CHANCE_COST +   }; +get_info (?ATTRIBUTE_DOUBLE_HIT_CHANCE) -> +   { +      ?ATTRIBUTE_DOUBLE_HIT_CHANCE_MIN, +      ?ATTRIBUTE_DOUBLE_HIT_CHANCE_DEFAULT, +      ?ATTRIBUTE_DOUBLE_HIT_CHANCE_MAX, +      ?ATTRIBUTE_DOUBLE_HIT_CHANCE_COST +   }; +get_info (?ATTRIBUTE_HEALTH) -> +   { +      ?ATTRIBUTE_HEALTH_MIN, +      ?ATTRIBUTE_HEALTH_DEFAULT, +      ?ATTRIBUTE_HEALTH_MAX, +      ?ATTRIBUTE_HEALTH_COST +   }; +get_info (?ATTRIBUTE_MOVEMENT_POINTS) -> +   { +      ?ATTRIBUTE_MOVEMENT_POINTS_MIN, +      ?ATTRIBUTE_MOVEMENT_POINTS_DEFAULT, +      ?ATTRIBUTE_MOVEMENT_POINTS_MAX, +      ?ATTRIBUTE_MOVEMENT_POINTS_COST +   }; +get_info (?ATTRIBUTE_PARRY_CHANCE) -> +   { +      ?ATTRIBUTE_PARRY_CHANCE_MIN, +      ?ATTRIBUTE_PARRY_CHANCE_DEFAULT, +      ?ATTRIBUTE_PARRY_CHANCE_MAX, +      ?ATTRIBUTE_PARRY_CHANCE_COST +   }. diff --git a/src/balancer/struct/blc_armor.erl b/src/balancer/struct/blc_armor.erl index 46189d2..9677f88 100644 --- a/src/balancer/struct/blc_armor.erl +++ b/src/balancer/struct/blc_armor.erl @@ -1,6 +1,6 @@  -module(blc_armor). --include("base_attributes.hrl"). +-include("tacticians/attributes.hrl").  -define  ( @@ -57,7 +57,6 @@  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  -export_type([proto_armor/0]). -% FIXME: quick debug  -export  (     [ @@ -97,7 +96,7 @@     )     -> {proto_armor(), non_neg_integer()}.  increase_health_by (Amount, Armor) -> -   NewHealth = Armor#proto_armor.health + Amount, +   NewHealth = (Armor#proto_armor.health + Amount),     case (NewHealth > ?ATTRIBUTE_HEALTH_MAX) of        true ->           { @@ -122,7 +121,7 @@ increase_health_by (Amount, Armor) ->     )     -> {proto_armor(), non_neg_integer()}.  increase_damage_modifier_by (Amount, Armor) -> -   NewDamageModifier = Armor#proto_armor.damage_modifier + Amount, +   NewDamageModifier = (Armor#proto_armor.damage_modifier + Amount),     case (NewDamageModifier > ?ATTRIBUTE_DAMAGE_MODIFIER_MAX) of        true ->           { @@ -153,7 +152,7 @@ increase_damage_modifier_by (Amount, Armor) ->     )     -> {proto_armor(), non_neg_integer()}.  increase_dodge_chance_by (Amount, Armor) -> -   NewDodgeChance = Armor#proto_armor.dodge + Amount, +   NewDodgeChance = (Armor#proto_armor.dodge + Amount),     case (NewDodgeChance > ?ATTRIBUTE_DODGE_CHANCE_MAX) of        true ->           { @@ -178,7 +177,7 @@ increase_dodge_chance_by (Amount, Armor) ->     )     -> {proto_armor(), non_neg_integer()}.  increase_movement_points_by (Amount, Armor) -> -   NewMvtPoints = Armor#proto_armor.mvt_points + Amount, +   NewMvtPoints = (Armor#proto_armor.mvt_points + Amount),     case (NewMvtPoints > ?ATTRIBUTE_MOVEMENT_POINTS_MAX) of        true ->           { diff --git a/src/balancer/struct/blc_error.erl b/src/balancer/struct/blc_error.erl new file mode 100644 index 0000000..9bd3548 --- /dev/null +++ b/src/balancer/struct/blc_error.erl @@ -0,0 +1,24 @@ +-module(blc_error). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +-type type() :: +   ( +      {error, balance, non_neg_integer(), non_neg_integer()} +      | {error, incompatible} +   ). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export_type([type/0]). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/balancer/struct/blc_glyph.erl b/src/balancer/struct/blc_glyph.erl new file mode 100644 index 0000000..9b43f88 --- /dev/null +++ b/src/balancer/struct/blc_glyph.erl @@ -0,0 +1,451 @@ +-module(blc_glyph). + +-include("tacticians/attributes.hrl"). + +-define(SPENDABLE_GLYPH_POINTS, 100). +-define(NEGATIVE_POINTS_MODIFIER, 0.75). +-define(NEGATIVE_POINTS_MULTIPLIER, (2 - ?NEGATIVE_POINTS_MODIFIER)). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-record +( +   proto_glyph, +   { +      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_score :: non_neg_integer(), +      defense_sign :: integer(), +      attack_score :: non_neg_integer(), +      attack_sign :: integer() +   } +). + +-opaque type() :: #proto_glyph{}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export_type([type/0]). + +-export +( +   [ +      increase_attribute_by/3, +      decrease_attribute_by/3, +      increase_attribute_for/3, +      decrease_attribute_for/3, +      set_attack_coefficients/2, +      set_defense_coefficients/2 +   ] +). + +-export +( +   [ +      new/2, +      get_remaining_positive_points/1, +      get_points_balance/1 +   ] +). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec increase_attribute_by +   ( +      shr_attributes:meta_enum(), +      non_neg_integer(), +      type() +   ) +   -> ({ok, type()} | blc_error:type()). +increase_attribute_by (?ATTRIBUTE_ATTACK_SCORE, S0Amount, Glyph) -> +   S0NewAttackScore = (Glyph#proto_glyph.attack_score + S0Amount), +   {S1NewAttackScore, S1Amount} = +      case (S0NewAttackScore > ?ATTRIBUTE_ATTACK_SCORE_MAX) of +         true -> +            { +               ?ATTRIBUTE_ATTACK_SCORE_MAX, +               (?ATTRIBUTE_ATTACK_SCORE_MAX - Glyph#proto_glyph.attack_score) +            }; + +         false -> {S0NewAttackScore, S0Amount} +      end, + +   Cost = (S1Amount * ?ATTRIBUTE_ATTACK_SCORE_COST), + +   if +      (Glyph#proto_glyph.attack_sign == -1) -> {error, incompatible}; +      (Cost > (Glyph#proto_glyph.remaining_positive_points)) -> +         {error, balance, Glyph#proto_glyph.remaining_positive_points, Cost}; + +      true -> +         { +            ok, +            Glyph#proto_glyph +            { +               attack_score = S1NewAttackScore, +               attack_sign = 1, +               omnimods = +                  shr_omnimods:set_attack_modifiers +                  ( +                     blc_damage_type:generate_entries_from_score +                     ( +                        S1NewAttackScore, +                        Glyph#proto_glyph.attack_coef +                     ), +                     Glyph#proto_glyph.omnimods +                  ), +               remaining_positive_points = +                  (Glyph#proto_glyph.remaining_positive_points - Cost), +               points_balance = (Glyph#proto_glyph.points_balance - Cost) +            } +         } +   end; +increase_attribute_by (?ATTRIBUTE_DEFENSE_SCORE, S0Amount, Glyph) -> +   S0NewDefenseScore = (Glyph#proto_glyph.defense_score + S0Amount), +   {S1NewDefenseScore, S1Amount} = +      case (S0NewDefenseScore > ?ATTRIBUTE_DEFENSE_SCORE_MAX) of +         true -> +            { +               ?ATTRIBUTE_DEFENSE_SCORE_MAX, +               (?ATTRIBUTE_DEFENSE_SCORE_MAX - Glyph#proto_glyph.defense_score) +            }; + +         false -> {S0NewDefenseScore, S0Amount} +      end, + +   Cost = (S1Amount * ?ATTRIBUTE_DEFENSE_SCORE_COST), + +   if +      (Glyph#proto_glyph.defense_sign == -1) -> {error, incompatible}; +      (Cost > (Glyph#proto_glyph.remaining_positive_points)) -> +         {error, balance, Glyph#proto_glyph.remaining_positive_points, Cost}; + +      true -> +         { +            ok, +            Glyph#proto_glyph +            { +               defense_score = S1NewDefenseScore, +               defense_sign = 1, +               omnimods = +                  shr_omnimods:set_defense_modifiers +                  ( +                     blc_damage_type:generate_entries_from_score +                     ( +                        S1NewDefenseScore, +                        Glyph#proto_glyph.defense_coef +                     ), +                     Glyph#proto_glyph.omnimods +                  ), +               remaining_positive_points = +                  (Glyph#proto_glyph.remaining_positive_points - Cost), +               points_balance = (Glyph#proto_glyph.points_balance - Cost) +            } +         } +   end; +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), + +   S1Amount = +      case ((CurrentValue + S0Amount) > AttMax) of +         true -> (AttMax - CurrentValue); +         false -> S0Amount +      end, + +   Cost = (S1Amount * AttCost), + +   if +      (CurrentValue < 0) -> {error, incompatible}; +      (Cost > (Glyph#proto_glyph.remaining_positive_points)) -> +         {error, balance, Glyph#proto_glyph.remaining_positive_points, Cost}; + +      true -> +         { +            ok, +            Glyph#proto_glyph +            { +               omnimods = +                  shr_omnimods:mod_attribute +                  ( +                     Attribute, +                     S1Amount, +                     CurrentOmnimods +                  ), +               remaining_positive_points = +                  (Glyph#proto_glyph.remaining_positive_points - Cost), +               points_balance = (Glyph#proto_glyph.points_balance - Cost) +            } +         } +   end. + +-spec decrease_attribute_by +   ( +      shr_attributes:meta_enum(), +      non_neg_integer(), +      type() +   ) +   -> ({ok, type()} | blc_error:type()). +decrease_attribute_by (?ATTRIBUTE_ATTACK_SCORE, Amount, Glyph) -> +   NewAttackScore = (Glyph#proto_glyph.attack_score + Amount), + +   Cost = +      trunc +      ( +         (Amount * ?ATTRIBUTE_ATTACK_SCORE_COST) +         * ?NEGATIVE_POINTS_MULTIPLIER +      ), + +   if +      (Glyph#proto_glyph.attack_sign == -1) -> {error, incompatible}; +      true -> +         { +            ok, +            Glyph#proto_glyph +            { +               attack_score = NewAttackScore, +               attack_sign = -1, +               omnimods = +                  shr_omnimods:set_attack_modifiers +                  ( +                     lists:map +                     ( +                        fun ({Name, Value}) -> {Name, (-1 * Value)} end, +                        blc_damage_type:generate_entries_from_score +                        ( +                           NewAttackScore, +                           Glyph#proto_glyph.attack_coef +                        ) +                     ), +                     Glyph#proto_glyph.omnimods +                  ), +               points_balance = (Glyph#proto_glyph.points_balance + Cost) +            } +         } +   end; +decrease_attribute_by (?ATTRIBUTE_DEFENSE_SCORE, Amount, Glyph) -> +   NewDefenseScore = (Glyph#proto_glyph.defense_score + Amount), + +   Cost = +      trunc +      ( +         (Amount * ?ATTRIBUTE_DEFENSE_SCORE_COST) +         * ?NEGATIVE_POINTS_MULTIPLIER +      ), + +   if +      (Glyph#proto_glyph.defense_sign == -1) -> {error, incompatible}; +      true -> +         { +            ok, +            Glyph#proto_glyph +            { +               defense_score = NewDefenseScore, +               defense_sign = -1, +               omnimods = +                  shr_omnimods:set_defense_modifiers +                  ( +                     lists:map +                     ( +                        fun ({Name, Value}) -> {Name, (-1 * Value)} end, +                        blc_damage_type:generate_entries_from_score +                        ( +                           NewDefenseScore, +                           Glyph#proto_glyph.defense_coef +                        ) +                     ), +                     Glyph#proto_glyph.omnimods +                  ), +               points_balance = (Glyph#proto_glyph.points_balance + Cost) +            } +         } +   end; +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), + +   Cost = ((Amount * AttCost) * ?NEGATIVE_POINTS_MULTIPLIER), + +   if +      (CurrentValue > 0) -> {error, incompatible}; + +      true -> +         { +            ok, +            Glyph#proto_glyph +            { +               omnimods = +                  shr_omnimods:mod_attribute +                  ( +                     Attribute, +                     (-1 * Amount), +                     CurrentOmnimods +                  ), +               points_balance = (Glyph#proto_glyph.points_balance + Cost) +            } +         } +   end. + +-spec set_attack_coefficients +   ( +      list(blc_damage_type:coefficient()), +      type() +   ) +   -> type(). +set_attack_coefficients (Coefficients, Glyph) -> +   NewGlyph = +      Glyph#proto_glyph +      { +         attack_coef = blc_damage_type:sort_entries(Coefficients) +      }, + +   case (NewGlyph#proto_glyph.attack_sign) of +      0 -> NewGlyph; +      1 -> +         NewGlyph#proto_glyph +         { +            omnimods = +               shr_omnimods:set_attack_modifiers +               ( +                  blc_damage_type:generate_entries_from_score +                  ( +                     NewGlyph#proto_glyph.attack_score, +                     NewGlyph#proto_glyph.attack_coef +                  ), +                  NewGlyph#proto_glyph.omnimods +               ) +         }; +      -1 -> +         NewGlyph#proto_glyph +         { +            omnimods = +               shr_omnimods:set_attack_modifiers +               ( +                  lists:map +                  ( +                     fun ({Name, Value}) -> {Name, (-1 * Value)} end, +                     blc_damage_type:generate_entries_from_score +                     ( +                        NewGlyph#proto_glyph.attack_score, +                        NewGlyph#proto_glyph.attack_coef +                     ) +                  ), +                  NewGlyph#proto_glyph.omnimods +               ) +         } +   end. + +-spec set_defense_coefficients +   ( +      list(blc_damage_type:coefficient()), +      type() +   ) +   -> type(). +set_defense_coefficients (Coefficients, Glyph) -> +   NewGlyph = +      Glyph#proto_glyph +      { +         defense_coef = blc_damage_type:sort_entries(Coefficients) +      }, + +   case (NewGlyph#proto_glyph.defense_sign) of +      0 -> NewGlyph; +      1 -> +         NewGlyph#proto_glyph +         { +            omnimods = +               shr_omnimods:set_defense_modifiers +               ( +                  blc_damage_type:generate_entries_from_score +                  ( +                     NewGlyph#proto_glyph.defense_score, +                     NewGlyph#proto_glyph.defense_coef +                  ), +                  NewGlyph#proto_glyph.omnimods +               ) +         }; +      -1 -> +         NewGlyph#proto_glyph +         { +            omnimods = +               shr_omnimods:set_defense_modifiers +               ( +                  lists:map +                  ( +                     fun ({Name, Value}) -> {Name, (-1 * Value)} end, +                     blc_damage_type:generate_entries_from_score +                     ( +                        NewGlyph#proto_glyph.defense_score, +                        NewGlyph#proto_glyph.defense_coef +                     ) +                  ), +                  NewGlyph#proto_glyph.omnimods +               ) +         } +   end. + +-spec new +   ( +      list(blc_damage_type:coefficient()), +      list(blc_damage_type:coefficient()) +   ) +   -> type(). +new (AttackCoefficients, DefenseCoefficients) -> +   #proto_glyph +   { +      remaining_positive_points = ?SPENDABLE_GLYPH_POINTS, +      points_balance = 0, +      omnimods = omnimods:new(), +      attack_coef = blc_damage_type:sort_entries(AttackCoefficients), +      attack_score = 0, +      attack_sign = 0, +      defense_coef = blc_damage_type:sort_entries(DefenseCoefficients), +      defense_score = 0, +      defense_sign = 0 +   }. + +-spec increase_attribute_for +   ( +      shr_attributes:meta_enum(), +      non_neg_integer(), +      type() +   ) +   -> ({ok, type} | blc_error:type()). +increase_attribute_for (Attribute, GivenPoints, Glyph) -> +   {_AttMin, _AttDef, _AttMax, AttCost} = blc_attribute:get_info(Attribute), +   AmountOfIncrease = trunc(GivenPoints / AttCost), +   increase_attribute_by(Attribute, AmountOfIncrease, Glyph). + +-spec decrease_attribute_for +   ( +      shr_attributes:meta_enum(), +      non_neg_integer(), +      type() +   ) +   -> ({ok, type} | blc_error:type()). +decrease_attribute_for (Attribute, GivenPoints, Glyph) -> +   {_AttMin, _AttDef, _AttMax, AttCost} = blc_attribute:get_info(Attribute), +   AmountOfDecrease = +      trunc((GivenPoints * ?NEGATIVE_POINTS_MULTIPLIER) / AttCost), + +   increase_attribute_by(Attribute, AmountOfDecrease, Glyph). + +-spec get_remaining_positive_points (type()) -> non_neg_integer(). +get_remaining_positive_points (Glyph) -> +   Glyph#proto_glyph.remaining_positive_points. + +-spec get_points_balance (type()) -> non_neg_integer(). +get_points_balance (Glyph) -> +   Glyph#proto_glyph.points_balance. diff --git a/src/balancer/struct/blc_weapon.erl b/src/balancer/struct/blc_weapon.erl new file mode 100644 index 0000000..0edeb35 --- /dev/null +++ b/src/balancer/struct/blc_weapon.erl @@ -0,0 +1,414 @@ +-module(blc_weapon). + +-include("tacticians/attributes.hrl"). + +-define(WEAPON_ATTRIBUTE_RANGE_MIN,       0). +-define(WEAPON_ATTRIBUTE_RANGE_MAX,       2). +-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, +   ( +      ( +         ?ATTRIBUTE_ACCURACY_COST +         * (?ATTRIBUTE_ACCURACY_DEFAULT - ?ATTRIBUTE_ACCURACY_MIN) +      ) +      + +      ( +         ?ATTRIBUTE_CRITICAL_HIT_CHANCE_COST +         * +         ( +            ?ATTRIBUTE_CRITICAL_HIT_CHANCE_DEFAULT +            - ?ATTRIBUTE_CRITICAL_HIT_CHANCE_MIN +         ) +      ) +      + +      ( +         ?ATTRIBUTE_DOUBLE_HIT_CHANCE_COST +         * +         ( +            ?ATTRIBUTE_DOUBLE_HIT_CHANCE_DEFAULT +            - ?ATTRIBUTE_DOUBLE_HIT_CHANCE_MIN +         ) +      ) +      + +      ( +         ?ATTRIBUTE_ATTACK_SCORE_COST +         * (?ATTRIBUTE_ATTACK_SCORE_DEFAULT - ?ATTRIBUTE_ATTACK_SCORE_MIN) +      ) +      + +      ( +         ?WEAPON_ATTRIBUTE_RANGE_COST +         * (?WEAPON_ATTRIBUTE_RANGE_DEFAULT - ?WEAPON_ATTRIBUTE_RANGE_MIN) +      ) +   ) +). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-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()), +      attack_coef :: list(blc_damage_type:coefficient()), +      attack_score :: non_neg_integer() +   } +). + +-opaque proto_weapon() :: #proto_weapon{}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export_type([proto_weapon/0]). + +-export +( +   [ +      increase_range_by/2, +      increase_type_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_accuracy_for/2, +      increase_critical_hit_chance_for/2, +      increase_double_hit_chance_for/2, +      increase_attack_score_for/2, +      set_attack_coefficients/2 +   ] +). + +-export +( +   [ +      new/1, +      get_spendable_points/0 +   ] +). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec increase_accuracy_by +   ( +      non_neg_integer(), +      proto_weapon() +   ) +   -> {proto_weapon(), non_neg_integer()}. +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. + +-spec increase_range_by +   ( +      non_neg_integer(), +      proto_weapon() +   ) +   -> {proto_weapon(), non_neg_integer()}. +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 +            ) +         }; + +      false -> +         { +            Weapon#proto_weapon{ range = NewDamageModifier }, +            (Amount * ?WEAPON_ATTRIBUTE_RANGE_COST) +         } +   end. + +-spec increase_type_by +   ( +      non_neg_integer(), +      proto_weapon() +   ) +   -> {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) +         } +   end. + +-spec increase_critical_hit_chance_by +   ( +      non_neg_integer(), +      proto_weapon() +   ) +   -> {proto_weapon(), non_neg_integer()}. +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. + +-spec increase_double_hit_chance_by +   ( +      non_neg_integer(), +      proto_weapon() +   ) +   -> {proto_weapon(), non_neg_integer()}. +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. + + +-spec increase_attack_score_by +   ( +      non_neg_integer(), +      proto_weapon() +   ) +   -> {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 +            { +               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 +            ) +         }; + +      false -> +         { +            Weapon#proto_weapon +            { +               attack_score = NewAttackScore, +               attack = +                  blc_damage_type:generate_entries_from_score +                  ( +                     NewAttackScore, +                     Weapon#proto_weapon.attack_coef +                  ) +            }, +            (Amount * ?ATTRIBUTE_ATTACK_SCORE_COST) +         } +   end. + +-spec set_attack_coefficients +   ( +      list(blc_damage_type:coefficient()), +      proto_weapon() +   ) +   -> proto_weapon(). +set_attack_coefficients (Coefficients, Weapon) -> +   {Result, 0} = +      increase_attack_score_by +      ( +         0, +         Weapon#proto_weapon +         { +            attack_coef = blc_damage_type:sort_entries(Coefficients) +         } +      ), + +   Result. + +-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 +         } +      ), + +   Result. + +-spec increase_range_for +   ( +      non_neg_integer(), +      proto_weapon() +   ) +   -> {proto_weapon(), non_neg_integer()}. +increase_range_for (GivenPoints, Weapon) -> +   AmountOfIncrease = trunc(GivenPoints / ?WEAPON_ATTRIBUTE_RANGE_COST), +   {Result, SpentPoints} = increase_range_by(AmountOfIncrease, Weapon), +   {Result, (GivenPoints - SpentPoints)}. + +-spec increase_type_for +   ( +      non_neg_integer(), +      proto_weapon() +   ) +   -> {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)}. + +-spec increase_accuracy_for +   ( +      non_neg_integer(), +      proto_weapon() +   ) +   -> {proto_weapon(), non_neg_integer()}. +increase_accuracy_for (GivenPoints, Weapon) -> +   AmountOfIncrease = trunc(GivenPoints / ?ATTRIBUTE_ACCURACY_COST), +   {Result, SpentPoints} = increase_accuracy_by(AmountOfIncrease, Weapon), +   {Result, (GivenPoints - SpentPoints)}. + +-spec increase_critical_hit_chance_for +   ( +      non_neg_integer(), +      proto_weapon() +   ) +   -> {proto_weapon(), non_neg_integer()}. +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)}. + +-spec increase_double_hit_chance_for +   ( +      non_neg_integer(), +      proto_weapon() +   ) +   -> {proto_weapon(), non_neg_integer()}. +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)}. + + +-spec increase_attack_score_for +   ( +      non_neg_integer(), +      proto_weapon() +   ) +   -> {proto_weapon(), non_neg_integer()}. +increase_attack_score_for (GivenPoints, Weapon) -> +   AmountOfIncrease = trunc(GivenPoints / ?ATTRIBUTE_ATTACK_SCORE_COST), +   {Result, SpentPoints} = increase_attack_score_by(AmountOfIncrease, Weapon), +   {Result, (GivenPoints - SpentPoints)}. + + +-spec get_spendable_points () -> non_neg_integer(). +get_spendable_points () -> ?SPENDABLE_WEAPON_POINTS. diff --git a/src/shared/struct/shr_attributes.erl b/src/shared/struct/shr_attributes.erl index cd3aedf..44d2e04 100644 --- a/src/shared/struct/shr_attributes.erl +++ b/src/shared/struct/shr_attributes.erl @@ -1,5 +1,7 @@  -module(shr_attributes). +-include("tacticians/attributes.hrl"). +  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -9,18 +11,36 @@     {        movement_points :: non_neg_integer(),        health :: non_neg_integer(), -      dodges :: integer(), -      parries :: integer(), +      dodge_chance :: integer(), +      parry_chance :: integer(),        accuracy :: integer(), -      double_hits :: integer(), -      critical_hits :: integer(), +      double_hit_chance :: integer(), +      critical_hit_chance :: integer(),        damage_modifier :: integer()     }  ).  -opaque type() :: #attributes{}. - --export_type([type/0]). +-type enum() :: +   ( +      ?ATTRIBUTE_ACCURACY +      | ?ATTRIBUTE_CRITICAL_HIT_CHANCE +      | ?ATTRIBUTE_DAMAGE_MODIFIER +      | ?ATTRIBUTE_DODGE_CHANCE +      | ?ATTRIBUTE_DOUBLE_HIT_CHANCE +      | ?ATTRIBUTE_HEALTH +      | ?ATTRIBUTE_MOVEMENT_POINTS +      | ?ATTRIBUTE_PARRY_CHANCE +   ). + +-type meta_enum() :: +   ( +      enum() +      | ?ATTRIBUTE_ATTACK_SCORE +      | ?ATTRIBUTE_DEFENSE_SCORE +   ). + +-export_type([type/0,enum/0,meta_enum/0]).  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -31,11 +51,11 @@     [        get_movement_points/1,        get_health/1, -      get_dodges/1, -      get_parries/1, +      get_dodge_chance/1, +      get_parry_chance/1,        get_accuracy/1, -      get_double_hits/1, -      get_critical_hits/1, +      get_double_hit_chance/1, +      get_critical_hit_chance/1,        get_damage_modifier/1,        get_damage_multiplier/1, @@ -64,25 +84,25 @@ mod_movement_points (Mod, Atts) ->  mod_health (Mod, Atts) ->     Atts#attributes{ health = (Atts#attributes.health + Mod) }. --spec mod_dodges (integer(), type()) -> type(). -mod_dodges (Mod, Atts) -> -   Atts#attributes{ dodges = (Atts#attributes.dodges + Mod) }. +-spec mod_dodge_chance (integer(), type()) -> type(). +mod_dodge_chance (Mod, Atts) -> +   Atts#attributes{ dodge_chance = (Atts#attributes.dodge_chance + Mod) }. --spec mod_parries (integer(), type()) -> type(). -mod_parries (Mod, Atts) -> -   Atts#attributes{ parries = (Atts#attributes.parries + Mod) }. +-spec mod_parry_chance (integer(), type()) -> type(). +mod_parry_chance (Mod, Atts) -> +   Atts#attributes{ parry_chance = (Atts#attributes.parry_chance + Mod) }.  -spec mod_accuracy (integer(), type()) -> type().  mod_accuracy (Mod, Atts) ->     Atts#attributes{ accuracy = (Atts#attributes.accuracy + Mod) }. --spec mod_double_hits (integer(), type()) -> type(). -mod_double_hits (Mod, Atts) -> -   Atts#attributes{ double_hits = (Atts#attributes.double_hits + Mod) }. +-spec mod_double_hit_chance (integer(), type()) -> type(). +mod_double_hit_chance (Mod, Atts) -> +   Atts#attributes{ double_hit_chance = (Atts#attributes.double_hit_chance + Mod) }. --spec mod_critical_hits (integer(), type()) -> type(). -mod_critical_hits (Mod, Atts) -> -   Atts#attributes{ critical_hits = (Atts#attributes.critical_hits + Mod) }. +-spec mod_critical_hit_chance (integer(), type()) -> type(). +mod_critical_hit_chance (Mod, Atts) -> +   Atts#attributes{ critical_hit_chance = (Atts#attributes.critical_hit_chance + Mod) }.  -spec mod_damage_modifier (integer(), type()) -> type().  mod_damage_modifier (Mod, Atts) -> @@ -101,20 +121,20 @@ get_movement_points (Atts) -> max(0, Atts#attributes.movement_points).  -spec get_health (type()) -> non_neg_integer().  get_health (Atts) -> max(1, Atts#attributes.health). --spec get_dodges (type()) -> non_neg_integer(). -get_dodges (Atts) -> max(0, Atts#attributes.dodges). +-spec get_dodge_chance (type()) -> non_neg_integer(). +get_dodge_chance (Atts) -> max(0, Atts#attributes.dodge_chance). --spec get_parries (type()) -> non_neg_integer(). -get_parries (Atts) -> max(0, Atts#attributes.parries). +-spec get_parry_chance (type()) -> non_neg_integer(). +get_parry_chance (Atts) -> max(0, Atts#attributes.parry_chance).  -spec get_accuracy (type()) -> non_neg_integer().  get_accuracy (Atts) -> max(0, Atts#attributes.accuracy). --spec get_double_hits (type()) -> non_neg_integer(). -get_double_hits (Atts) -> max(0, Atts#attributes.double_hits). +-spec get_double_hit_chance (type()) -> non_neg_integer(). +get_double_hit_chance (Atts) -> max(0, Atts#attributes.double_hit_chance). --spec get_critical_hits (type()) -> non_neg_integer(). -get_critical_hits (Atts) -> max(0, Atts#attributes.critical_hits). +-spec get_critical_hit_chance (type()) -> non_neg_integer(). +get_critical_hit_chance (Atts) -> max(0, Atts#attributes.critical_hit_chance).  -spec get_damage_modifier (type()) -> non_neg_integer().  get_damage_modifier (Atts) -> max(0, Atts#attributes.damage_modifier). @@ -128,20 +148,24 @@ default () ->     {        movement_points = 0,        health = 1, -      dodges = 0, -      parries = 0, +      dodge_chance = 0, +      parry_chance = 0,        accuracy = 0, -      double_hits = 0, -      critical_hits = 0, +      double_hit_chance = 0, +      critical_hit_chance = 0,        damage_modifier = 100     }. --spec apply_mod (atom(), integer(), type()) -> type(). -apply_mod(mheal, Value, Atts) -> mod_health(Value, Atts); -apply_mod(mpts, Value, Atts) -> mod_movement_points(Value, Atts); -apply_mod(dodg, Value, Atts) -> mod_dodges(Value, Atts); -apply_mod(pary, Value, Atts) -> mod_parries(Value, Atts); -apply_mod(accu, Value, Atts) -> mod_accuracy(Value, Atts); -apply_mod(dhit, Value, Atts) -> mod_double_hits(Value, Atts); -apply_mod(crit, Value, Atts) -> mod_critical_hits(Value, Atts); -apply_mod(dmgm, Value, Atts) -> mod_damage_modifier(Value, Atts). +-spec apply_mod (enum(), integer(), type()) -> type(). +apply_mod(?ATTRIBUTE_HEALTH, Mod, Atts) -> mod_health(Mod, Atts); +apply_mod(?ATTRIBUTE_DODGE_CHANCE, Mod, Atts) -> mod_dodge_chance(Mod, Atts); +apply_mod(?ATTRIBUTE_PARRY_CHANCE, Mod, Atts) -> mod_parry_chance(Mod, Atts); +apply_mod(?ATTRIBUTE_ACCURACY, Mod, Atts) -> mod_accuracy(Mod, Atts); +apply_mod(?ATTRIBUTE_MOVEMENT_POINTS, Mod, Atts) -> +   mod_movement_points(Mod, Atts); +apply_mod(?ATTRIBUTE_DOUBLE_HIT_CHANCE, Mod, Atts) -> +   mod_double_hit_chance(Mod, Atts); +apply_mod(?ATTRIBUTE_CRITICAL_HIT_CHANCE, Mod, Atts) -> +   mod_critical_hit_chance(Mod, Atts); +apply_mod(?ATTRIBUTE_DAMAGE_MODIFIER, Mod, Atts) -> +   mod_damage_modifier(Mod, Atts). diff --git a/src/shared/struct/shr_damage_type.erl b/src/shared/struct/shr_damage_type.erl index 9bcd79f..d739514 100644 --- a/src/shared/struct/shr_damage_type.erl +++ b/src/shared/struct/shr_damage_type.erl @@ -1,6 +1,6 @@  -module(shr_damage_type). --include("damage_types.hrl"). +-include("tacticians/damage_types.hrl").  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/shared/struct/shr_omnimods.erl b/src/shared/struct/shr_omnimods.erl index 7602e1f..e4993c8 100644 --- a/src/shared/struct/shr_omnimods.erl +++ b/src/shared/struct/shr_omnimods.erl @@ -3,22 +3,36 @@  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --type entry() :: {atom(), integer()}. --type mods() :: dict:dict(atom(), integer()). +-type attribute_entry() :: {shr_attributes:enum(), integer()}. +-type attribute_mods() :: dict:dict(shr_attributes:enum(), integer()). + +-type damage_type_entry() :: {shr_damage_type:type(), integer()}. +-type damage_type_mods() :: dict:dict(shr_damage_type:type(), integer()). + +-type entry() :: (attribute_entry() | damage_type_entry()). +-type mods() :: (attribute_mods() | damage_type_mods()).  -record  (     omnimods,     { -      attmods :: mods(), -      atkmods :: mods(), -      defmods :: mods() +      attmods :: attribute_mods(), +      atkmods :: damage_type_mods(), +      defmods :: damage_type_mods()     }  ).  -opaque type() :: #omnimods{}. --export_type([type/0, entry/0]). +-export_type +( +   [ +      type/0, +      attribute_entry/0, +      damage_type_entry/0, +      entry/0 +   ] +).  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -27,7 +41,7 @@  -export  (     [ -      default/0, +      new/0,        new/3     ]  ). @@ -37,7 +51,10 @@  (     [        merge/2, -      apply_coefficient/2 +      apply_coefficient/2, +      set_attribute_modifiers/2, +      set_attack_modifiers/2, +      set_defense_modifiers/2     ]  ). @@ -46,7 +63,13 @@  (     [        apply_to_attributes/2, -      get_attack_damage/3 +      get_attack_damage/3, +      get_attribute_modifier/2, +      get_attack_modifier/2, +      get_defense_modifier/2, +      get_attribute_modifiers/1, +      get_attack_modifiers/1, +      get_defense_modifiers/1     ]  ). @@ -61,11 +84,15 @@  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec apply_coefficient_to_mods (float(), mods()) -> mods(). +-spec apply_coefficient_to_mods +   (float(), attribute_mods()) -> attribute_mods(); +   (float(), damage_type_mods()) -> damage_type_mods().  apply_coefficient_to_mods (Coef, Mods) ->     dict:map(fun (_Name, Val) -> shr_math_util:ceil(Coef * Val) end, Mods). --spec merge_mods (mods(), mods()) -> mods(). +-spec merge_mods +   (attribute_mods(), attribute_mods()) -> attribute_mods(); +   (damage_type_mods(), damage_type_mods()) -> damage_type_mods().  merge_mods (ModsA, ModsB) ->     dict:merge(fun (_Name, ValA, ValB) -> (ValA + ValB) end, ModsA, ModsB). @@ -88,7 +115,13 @@ encode_mods (Mods) ->  %% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%% Creation --spec new (list(entry()), list(entry()), list(entry())) -> type(). +-spec new +   ( +      list(attribute_entry()), +      list(damage_type_entry()), +      list(damage_type_entry()) +   ) +   -> type().  new (AttributeMods, AttackMods, DefenseMods) ->     #omnimods     { @@ -97,8 +130,8 @@ new (AttributeMods, AttackMods, DefenseMods) ->        defmods = dict:from_list(DefenseMods)     }. --spec default () -> type(). -default () -> new([], [], []). +-spec new () -> type(). +new () -> new([], [], []).  %%% Modification  -spec merge (type(), type()) -> type(). @@ -119,6 +152,28 @@ apply_coefficient (Coef, Omnimods) ->        defmods = apply_coefficient_to_mods(Coef, Omnimods#omnimods.defmods)     }. +-spec set_attribute_modifiers (list(attribute_entry()), type()) -> type(). +set_attribute_modifiers (NewAttributeModifiers, Omnimods) -> +   Omnimods#omnimods +   { +      attmods = dict:from_list(NewAttributeModifiers) +   }. + +-spec set_defense_modifiers (list(damage_type_entry()), type()) -> type(). +set_defense_modifiers (NewDefenseModifiers, Omnimods) -> +   Omnimods#omnimods +   { +      defmods = dict:from_list(NewDefenseModifiers) +   }. + +-spec set_attack_modifiers (list(damage_type_entry()), type()) -> type(). +set_attack_modifiers (NewAttackModifiers, Omnimods) -> +   Omnimods#omnimods +   { +      atkmods = dict:from_list(NewAttackModifiers) +   }. + +%%%% Access  -spec apply_to_attributes     (        type(), @@ -133,6 +188,7 @@ apply_to_attributes (Omnimods, Attributes) ->        Omnimods#omnimods.attmods     ). +% FIXME: 'base' is no longer used.  -spec get_attack_damage (float(), type(), type()) -> non_neg_integer().  get_attack_damage (AttackModifier, AttackerOmnimods, DefenderOmnimods) ->     AttackerOmnimodsAttmods = AttackerOmnimods#omnimods.atkmods, @@ -191,6 +247,37 @@ get_attack_damage (AttackModifier, AttackerOmnimods, DefenderOmnimods) ->     Result. +-spec get_attribute_modifier (shr_attributes:enum(), type()) -> integer(). +get_attribute_modifier (Attribute, Omnimods) -> +   case dict:find(Attribute, Omnimods#omnimods.attmods) of +      {ok, Value} -> Value; +      error -> 0 +   end. + +-spec get_attack_modifier (shr_damage_type:type(), type()) -> integer(). +get_attack_modifier (DamageType, Omnimods) -> +   case dict:find(DamageType, Omnimods#omnimods.atkmods) of +      {ok, Value} -> Value; +      error -> 0 +   end. + +-spec get_defense_modifier (shr_damage_type:type(), type()) -> integer(). +get_defense_modifier (DamageType, Omnimods) -> +   case dict:find(DamageType, Omnimods#omnimods.defmods) of +      {ok, Value} -> Value; +      error -> 0 +   end. + +-spec get_attribute_modifiers (type()) -> list(attribute_entry()). +get_attribute_modifiers (Omnimods) -> lists:to_list(Omnimods#omnimods.attmods). + +-spec get_attack_modifiers (type()) -> list(damage_type_entry()). +get_attack_modifiers (Omnimods) -> lists:to_list(Omnimods#omnimods.atkmods). + +-spec get_defense_modifiers (type()) -> list(damage_type_entry()). +get_defense_modifiers (Omnimods) -> lists:to_list(Omnimods#omnimods.defmods). + +  %%% Export  -spec encode (type()) -> {list(any())}.  encode (Omnimods) ->  | 


