summaryrefslogtreecommitdiff |
diff options
Diffstat (limited to 'src/balancer/struct/blc_glyph.erl')
-rw-r--r-- | src/balancer/struct/blc_glyph.erl | 451 |
1 files changed, 451 insertions, 0 deletions
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. |