summaryrefslogtreecommitdiff |
diff options
author | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2019-08-18 16:05:23 +0200 |
---|---|---|
committer | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2019-08-18 16:05:23 +0200 |
commit | 5266e24e01611fc8026dfa0498ee87d7fba65e88 (patch) | |
tree | 72c73402dc959f5d618ac850b54d8eb724f60145 /src/balancer | |
parent | dc742fd9190eadd5eed2e45dd36262ea06550172 (diff) |
...
Diffstat (limited to 'src/balancer')
-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 |
5 files changed, 994 insertions, 6 deletions
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. |