summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/balancer/struct/blc_glyph.erl')
-rw-r--r--src/balancer/struct/blc_glyph.erl451
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.