From 5266e24e01611fc8026dfa0498ee87d7fba65e88 Mon Sep 17 00:00:00 2001 From: Nathanael Sensfelder Date: Sun, 18 Aug 2019 16:05:23 +0200 Subject: ... --- include/base_attributes.hrl | 49 ---- include/damage_types.hrl.m4 | 16 -- include/tacticians/attributes.hrl.m4 | 61 +++++ include/tacticians/damage_types.hrl.m4 | 16 ++ src/balancer/blc_attribute.erl | 100 ++++++++ src/balancer/struct/blc_armor.erl | 11 +- src/balancer/struct/blc_error.erl | 24 ++ src/balancer/struct/blc_glyph.erl | 451 +++++++++++++++++++++++++++++++++ src/balancer/struct/blc_weapon.erl | 414 ++++++++++++++++++++++++++++++ src/shared/struct/shr_attributes.erl | 110 ++++---- src/shared/struct/shr_damage_type.erl | 2 +- src/shared/struct/shr_omnimods.erl | 115 ++++++++- 12 files changed, 1240 insertions(+), 129 deletions(-) delete mode 100644 include/base_attributes.hrl delete mode 100644 include/damage_types.hrl.m4 create mode 100644 include/tacticians/attributes.hrl.m4 create mode 100644 include/tacticians/damage_types.hrl.m4 create mode 100644 src/balancer/blc_attribute.erl create mode 100644 src/balancer/struct/blc_error.erl create mode 100644 src/balancer/struct/blc_glyph.erl create mode 100644 src/balancer/struct/blc_weapon.erl diff --git a/include/base_attributes.hrl b/include/base_attributes.hrl deleted file mode 100644 index 09bc136..0000000 --- a/include/base_attributes.hrl +++ /dev/null @@ -1,49 +0,0 @@ --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_MIN, 8). --define(ATTRIBUTE_MOVEMENT_POINTS_MAX, 200). --define(ATTRIBUTE_MOVEMENT_POINTS_DEFAULT, 32). --define(ATTRIBUTE_MOVEMENT_POINTS_COST, 1). - --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_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_MIN, 0). --define(ATTRIBUTE_ACCURACY_MAX, 100). --define(ATTRIBUTE_ACCURACY_DEFAULT, 50). --define(ATTRIBUTE_ACCURACY_COST, 1). - --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_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_MIN, 0). --define(ATTRIBUTE_DEFENSE_SCORE_MAX, 300). --define(ATTRIBUTE_DEFENSE_SCORE_DEFAULT, 50). --define(ATTRIBUTE_DEFENSE_SCORE_COST, 1). - --define(ATTRIBUTE_ATTACK_SCORE_MIN, 0). --define(ATTRIBUTE_ATTACK_SCORE_MAX, 300). --define(ATTRIBUTE_ATTACK_SCORE_DEFAULT, 50). --define(ATTRIBUTE_ATTACK_SCORE_COST, 1). diff --git a/include/damage_types.hrl.m4 b/include/damage_types.hrl.m4 deleted file mode 100644 index df82e59..0000000 --- a/include/damage_types.hrl.m4 +++ /dev/null @@ -1,16 +0,0 @@ -m4_include(__MAKEFILE_DATA_DIR/names.m4.conf) - --define(DAMAGE_TYPE_SLASH, __SN_SLASH). --define(DAMAGE_TYPE_PIERCE, __SN_PIERCE). --define(DAMAGE_TYPE_BLUNT, __SN_BLUNT). - -% Synonyms for blunt damage. --define(DAMAGE_TYPE_BLUDGEONING, ?DAMAGE_TYPE_BLUNT). --define(DAMAGE_TYPE_IMPACT, ?DAMAGE_TYPE_BLUNT). - -% Synonyms for pierce damage. --define(DAMAGE_TYPE_PIERCING, ?DAMAGE_TYPE_PIERCE). --define(DAMAGE_TYPE_PUNCTURE, ?DAMAGE_TYPE_PIERCE). - -% Synonyms for slash damage. --define(DAMAGE_TYPE_SLASHING, ?DAMAGE_TYPE_SLASH). diff --git a/include/tacticians/attributes.hrl.m4 b/include/tacticians/attributes.hrl.m4 new file mode 100644 index 0000000..3c0e731 --- /dev/null +++ b/include/tacticians/attributes.hrl.m4 @@ -0,0 +1,61 @@ +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, __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). +-define(ATTRIBUTE_ATTACK_SCORE_COST, 1). diff --git a/include/tacticians/damage_types.hrl.m4 b/include/tacticians/damage_types.hrl.m4 new file mode 100644 index 0000000..df82e59 --- /dev/null +++ b/include/tacticians/damage_types.hrl.m4 @@ -0,0 +1,16 @@ +m4_include(__MAKEFILE_DATA_DIR/names.m4.conf) + +-define(DAMAGE_TYPE_SLASH, __SN_SLASH). +-define(DAMAGE_TYPE_PIERCE, __SN_PIERCE). +-define(DAMAGE_TYPE_BLUNT, __SN_BLUNT). + +% Synonyms for blunt damage. +-define(DAMAGE_TYPE_BLUDGEONING, ?DAMAGE_TYPE_BLUNT). +-define(DAMAGE_TYPE_IMPACT, ?DAMAGE_TYPE_BLUNT). + +% Synonyms for pierce damage. +-define(DAMAGE_TYPE_PIERCING, ?DAMAGE_TYPE_PIERCE). +-define(DAMAGE_TYPE_PUNCTURE, ?DAMAGE_TYPE_PIERCE). + +% Synonyms for slash damage. +-define(DAMAGE_TYPE_SLASHING, ?DAMAGE_TYPE_SLASH). 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) -> -- cgit v1.2.3-70-g09d2