summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/balancer/blc_attribute.erl7
-rw-r--r--src/balancer/struct/blc_armor.erl320
-rw-r--r--src/balancer/struct/blc_glyph.erl18
-rw-r--r--src/balancer/struct/blc_weapon.erl422
-rw-r--r--src/battle/mechanic/action/btl_action_attack.erl8
-rw-r--r--src/shared/struct/shr_omnimods.erl71
6 files changed, 433 insertions, 413 deletions
diff --git a/src/balancer/blc_attribute.erl b/src/balancer/blc_attribute.erl
index 55becfa..14cfe8f 100644
--- a/src/balancer/blc_attribute.erl
+++ b/src/balancer/blc_attribute.erl
@@ -56,6 +56,13 @@ get_info (?ATTRIBUTE_CRITICAL_HIT_CHANCE) ->
?ATTRIBUTE_CRITICAL_HIT_CHANCE_MAX,
?ATTRIBUTE_CRITICAL_HIT_CHANCE_COST
};
+get_info (?ATTRIBUTE_DAMAGE_MODIFIER) ->
+ {
+ ?ATTRIBUTE_DAMAGE_MODIFIER_MIN,
+ ?ATTRIBUTE_DAMAGE_MODIFIER_DEFAULT,
+ ?ATTRIBUTE_DAMAGE_MODIFIER_MAX,
+ ?ATTRIBUTE_DAMAGE_MODIFIER_COST
+ };
get_info (?ATTRIBUTE_DEFENSE_SCORE) ->
{
?ATTRIBUTE_DEFENSE_SCORE_MIN,
diff --git a/src/balancer/struct/blc_armor.erl b/src/balancer/struct/blc_armor.erl
index 9677f88..cc23415 100644
--- a/src/balancer/struct/blc_armor.erl
+++ b/src/balancer/struct/blc_armor.erl
@@ -40,22 +40,19 @@
(
proto_armor,
{
- health :: non_neg_integer(),
- damage_modifier :: non_neg_integer(),
- dodge :: non_neg_integer(),
- mvt_points :: non_neg_integer(),
- defense :: list(blc_damage_type:entry()),
+ omnimods :: shr_omnimods:type(),
defense_coef :: list(blc_damage_type:coefficient()),
- defense_score :: non_neg_integer()
+ defense_score :: non_neg_integer(),
+ remaining_points :: non_neg_integer()
}
).
--opaque proto_armor() :: #proto_armor{}.
+-opaque type() :: #proto_armor{}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--export_type([proto_armor/0]).
+-export_type([type/0]).
-export
(
@@ -78,13 +75,54 @@
(
[
new/1,
- get_spendable_points/0
+ get_remaining_points/1
]
).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-spec increase_attribute_by
+ (
+ shr_attributes:enum(),
+ non_neg_integer(),
+ type()
+ )
+ -> ({ok, type()} | blc_error:type()).
+increase_attribute_by (Attribute, S0Amount, Armor) ->
+ CurrentOmnimods = Armor#proto_armor.omnimods,
+ CurrentValue =
+ shr_omnimods:get_attribute_modifier(Attribute, CurrentOmnimods),
+
+ {_AttMin, _AttDef, AttMax, AttCost} = blc_attribute:get_info(Attribute),
+
+ S1Amount =
+ case ((CurrentValue + S0Amount) > AttMax) of
+ true -> (AttMax - CurrentValue);
+ false -> S0Amount
+ end,
+
+ Cost = (S1Amount * AttCost),
+ RemainingPoints = Armor#proto_armor.remaining_points,
+
+ case (Cost > RemainingPoints) of
+ true -> {error, balance, RemainingPoints, Cost};
+ false ->
+ {
+ ok,
+ Armor#proto_armor
+ {
+ remaining_points = (RemainingPoints - Cost),
+ omnimods =
+ shr_omnimods:mod_attribute_modifier
+ (
+ Attribute,
+ S1Amount,
+ Armor#proto_armor.omnimods
+ )
+ }
+ }
+ end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -92,246 +130,186 @@
-spec increase_health_by
(
non_neg_integer(),
- proto_armor()
+ type()
)
- -> {proto_armor(), non_neg_integer()}.
+ -> ({ok, type()} | blc_error:type()).
increase_health_by (Amount, Armor) ->
- NewHealth = (Armor#proto_armor.health + Amount),
- case (NewHealth > ?ATTRIBUTE_HEALTH_MAX) of
- true ->
- {
- Armor#proto_armor{ health = ?ATTRIBUTE_HEALTH_MAX },
- (
- (?ATTRIBUTE_HEALTH_MAX - Armor#proto_armor.health)
- * ?ATTRIBUTE_HEALTH_COST
- )
- };
-
- false ->
- {
- Armor#proto_armor{ health = NewHealth },
- (Amount * ?ATTRIBUTE_HEALTH_COST)
- }
- end.
+ increase_attribute_by(?ATTRIBUTE_HEALTH, Amount, Armor).
-spec increase_damage_modifier_by
(
non_neg_integer(),
- proto_armor()
+ type()
)
- -> {proto_armor(), non_neg_integer()}.
+ -> ({ok, type()} | blc_error:type()).
increase_damage_modifier_by (Amount, Armor) ->
- NewDamageModifier = (Armor#proto_armor.damage_modifier + Amount),
- case (NewDamageModifier > ?ATTRIBUTE_DAMAGE_MODIFIER_MAX) of
- true ->
- {
- Armor#proto_armor
- {
- damage_modifier = ?ATTRIBUTE_DAMAGE_MODIFIER_MAX
- },
- (
- (
- ?ATTRIBUTE_DAMAGE_MODIFIER_MAX
- - Armor#proto_armor.damage_modifier
- )
- * ?ATTRIBUTE_DAMAGE_MODIFIER_COST
- )
- };
-
- false ->
- {
- Armor#proto_armor{ damage_modifier = NewDamageModifier },
- (Amount * ?ATTRIBUTE_DAMAGE_MODIFIER_COST)
- }
- end.
+ increase_attribute_by(?ATTRIBUTE_DAMAGE_MODIFIER, Amount, Armor).
-spec increase_dodge_chance_by
(
non_neg_integer(),
- proto_armor()
+ type()
)
- -> {proto_armor(), non_neg_integer()}.
+ -> ({ok, type()} | blc_error:type()).
increase_dodge_chance_by (Amount, Armor) ->
- NewDodgeChance = (Armor#proto_armor.dodge + Amount),
- case (NewDodgeChance > ?ATTRIBUTE_DODGE_CHANCE_MAX) of
- true ->
- {
- Armor#proto_armor{ dodge = ?ATTRIBUTE_DODGE_CHANCE_MAX },
- (
- (?ATTRIBUTE_DODGE_CHANCE_MAX - Armor#proto_armor.dodge)
- * ?ATTRIBUTE_DODGE_CHANCE_COST
- )
- };
-
- false ->
- {
- Armor#proto_armor{ dodge = NewDodgeChance },
- (Amount * ?ATTRIBUTE_DODGE_CHANCE_COST)
- }
- end.
+ increase_attribute_by(?ATTRIBUTE_DODGE_CHANCE, Amount, Armor).
-spec increase_movement_points_by
(
non_neg_integer(),
- proto_armor()
+ type()
)
- -> {proto_armor(), non_neg_integer()}.
+ -> ({ok, type()} | blc_error:type()).
increase_movement_points_by (Amount, Armor) ->
- NewMvtPoints = (Armor#proto_armor.mvt_points + Amount),
- case (NewMvtPoints > ?ATTRIBUTE_MOVEMENT_POINTS_MAX) of
- true ->
- {
- Armor#proto_armor{ mvt_points = ?ATTRIBUTE_MOVEMENT_POINTS_MAX },
- (
- (?ATTRIBUTE_MOVEMENT_POINTS_MAX - Armor#proto_armor.mvt_points)
- * ?ATTRIBUTE_MOVEMENT_POINTS_COST
- )
- };
-
- false ->
- {
- Armor#proto_armor{ mvt_points = NewMvtPoints },
- (Amount * ?ATTRIBUTE_MOVEMENT_POINTS_COST)
- }
- end.
+ increase_attribute_by(?ATTRIBUTE_MOVEMENT_POINTS, Amount, Armor).
-spec increase_defense_score_by
(
non_neg_integer(),
- proto_armor()
+ type()
)
- -> {proto_armor(), non_neg_integer()}.
-increase_defense_score_by (Amount, Armor) ->
- NewDefenseScore = (Armor#proto_armor.defense_score + Amount),
- case (NewDefenseScore > ?ATTRIBUTE_DEFENSE_SCORE_MAX) of
- true ->
- {
- Armor#proto_armor
+ -> ({ok, type()} | blc_error:type()).
+increase_defense_score_by (S0Amount, Armor) ->
+ CurrentValue = Armor#proto_armor.defense_score,
+ S0NewValue = CurrentValue + S0Amount,
+ {S1Amount, S1NewValue} =
+ case (S0NewValue > ?ATTRIBUTE_DEFENSE_SCORE_MAX) of
+ false -> {S0Amount, S0NewValue};
+ true ->
{
- defense_score = ?ATTRIBUTE_DEFENSE_SCORE_MAX,
- defense =
- blc_damage_type:generate_entries_from_score
- (
- NewDefenseScore,
- Armor#proto_armor.defense_coef
- )
- },
- (
- (?ATTRIBUTE_DEFENSE_SCORE_MAX - Armor#proto_armor.defense_score)
- * Amount
- )
- };
+ (?ATTRIBUTE_DEFENSE_SCORE_MAX - CurrentValue),
+ ?ATTRIBUTE_DEFENSE_SCORE_MAX
+ }
+ end,
+
+ Cost = (S1Amount * ?ATTRIBUTE_DEFENSE_SCORE_COST),
+ RemainingPoints = Armor#proto_armor.remaining_points,
+ case (Cost > RemainingPoints) of
+ true -> {error, balance, RemainingPoints, Cost};
false ->
{
+ ok,
Armor#proto_armor
{
- defense_score = NewDefenseScore,
- defense =
- blc_damage_type:generate_entries_from_score
+ remaining_points = (RemainingPoints - Cost),
+ defense_score = S1NewValue,
+ omnimods =
+ shr_omnimods:set_defense_modifiers
(
- NewDefenseScore,
- Armor#proto_armor.defense_coef
+ blc_damage_type:generate_entries_from_score
+ (
+ S1NewValue,
+ Armor#proto_armor.defense_coef
+ ),
+ Armor#proto_armor.omnimods
)
- },
- (Amount * ?ATTRIBUTE_DEFENSE_SCORE_COST)
+ }
}
end.
-spec set_defense_coefficients
(
list(blc_damage_type:coefficient()),
- proto_armor()
+ type()
)
- -> proto_armor().
+ -> type().
set_defense_coefficients (Coefficients, Armor) ->
- {Result, 0} =
- increase_defense_score_by
- (
- 0,
- Armor#proto_armor
- {
- defense_coef = blc_damage_type:sort_entries(Coefficients)
- }
- ),
+ NewCoefs = blc_damage_type:sort_entries(Coefficients),
+
+ Armor#proto_armor
+ {
+ defense_coef = NewCoefs,
+ omnimods =
+ shr_omnimods:set_defense_modifiers
+ (
+ blc_damage_type:generate_entries_from_score
+ (
+ Armor#proto_armor.defense_score,
+ NewCoefs
+ ),
+ Armor#proto_armor.omnimods
+ )
+ }.
- Result.
--spec new (list(blc_damage_type:coefficient())) -> proto_armor().
+-spec new (list(blc_damage_type:coefficient())) -> type().
new (Coefficients) ->
- {Result, _DefenseScoreIncreaseCost} =
- increase_defense_score_by
- (
- ?ATTRIBUTE_DEFENSE_SCORE_MIN,
- #proto_armor
- {
- health = ?ATTRIBUTE_HEALTH_MIN,
- damage_modifier = ?ATTRIBUTE_DAMAGE_MODIFIER_MIN,
- dodge = ?ATTRIBUTE_DODGE_CHANCE_MIN,
- mvt_points = ?ATTRIBUTE_MOVEMENT_POINTS_MIN,
- defense = [],
- defense_coef = blc_damage_type:sort_entries(Coefficients),
- defense_score = 0
- }
- ),
+ SortedCoefficients = blc_damage_type:sort_entries(Coefficients),
+
+ #proto_armor
+ {
+ omnimods =
+ shr_omnimods:new
+ (
+ [
+ {?ATTRIBUTE_HEALTH, ?ATTRIBUTE_HEALTH_MIN},
+ {?ATTRIBUTE_DAMAGE_MODIFIER, ?ATTRIBUTE_DAMAGE_MODIFIER_MIN},
+ {?ATTRIBUTE_DODGE_CHANCE, ?ATTRIBUTE_DODGE_CHANCE_MIN},
+ {?ATTRIBUTE_MOVEMENT_POINTS, ?ATTRIBUTE_MOVEMENT_POINTS_MIN}
+ ],
+ [],
+ blc_damage_type:generate_entries_from_score
+ (
+ ?ATTRIBUTE_DEFENSE_SCORE_MIN,
+ SortedCoefficients
+ )
+ ),
- Result.
+ defense_coef = SortedCoefficients,
+ defense_score = ?ATTRIBUTE_DEFENSE_SCORE_MIN,
+ remaining_points = ?SPENDABLE_ARMOR_POINTS
+ }.
-spec increase_health_for
(
non_neg_integer(),
- proto_armor()
+ type()
)
- -> {proto_armor(), non_neg_integer()}.
+ -> ({ok, type()} | blc_error:type()).
increase_health_for (GivenPoints, Armor) ->
AmountOfIncrease = trunc(GivenPoints / ?ATTRIBUTE_HEALTH_COST),
- {Result, SpentPoints} = increase_health_by(AmountOfIncrease, Armor),
- {Result, (GivenPoints - SpentPoints)}.
+ increase_health_by(AmountOfIncrease, Armor).
-spec increase_damage_modifier_for
(
non_neg_integer(),
- proto_armor()
+ type()
)
- -> {proto_armor(), non_neg_integer()}.
+ -> ({ok, type()} | blc_error:type()).
increase_damage_modifier_for (GivenPoints, Armor) ->
AmountOfIncrease = trunc(GivenPoints / ?ATTRIBUTE_DAMAGE_MODIFIER_COST),
- {Result, SpentPoints} = increase_damage_modifier_by(AmountOfIncrease, Armor),
- {Result, (GivenPoints - SpentPoints)}.
+ increase_damage_modifier_by(AmountOfIncrease, Armor).
-spec increase_dodge_chance_for
(
non_neg_integer(),
- proto_armor()
+ type()
)
- -> {proto_armor(), non_neg_integer()}.
+ -> ({ok, type()} | blc_error:type()).
increase_dodge_chance_for (GivenPoints, Armor) ->
AmountOfIncrease = trunc(GivenPoints / ?ATTRIBUTE_DODGE_CHANCE_COST),
- {Result, SpentPoints} = increase_dodge_chance_by(AmountOfIncrease, Armor),
- {Result, (GivenPoints - SpentPoints)}.
+ increase_dodge_chance_by(AmountOfIncrease, Armor).
-spec increase_movement_points_for
(
non_neg_integer(),
- proto_armor()
+ type()
)
- -> {proto_armor(), non_neg_integer()}.
+ -> ({ok, type()} | blc_error:type()).
increase_movement_points_for (GivenPoints, Armor) ->
AmountOfIncrease = trunc(GivenPoints / ?ATTRIBUTE_MOVEMENT_POINTS_COST),
- {Result, SpentPoints} = increase_movement_points_by(AmountOfIncrease, Armor),
- {Result, (GivenPoints - SpentPoints)}.
+ increase_movement_points_by(AmountOfIncrease, Armor).
-spec increase_defense_score_for
(
non_neg_integer(),
- proto_armor()
+ type()
)
- -> {proto_armor(), non_neg_integer()}.
+ -> ({ok, type()} | blc_error:type()).
increase_defense_score_for (GivenPoints, Armor) ->
AmountOfIncrease = trunc(GivenPoints / ?ATTRIBUTE_DEFENSE_SCORE_COST),
- {Result, SpentPoints} = increase_defense_score_by(AmountOfIncrease, Armor),
- {Result, (GivenPoints - SpentPoints)}.
-
+ increase_defense_score_by(AmountOfIncrease, Armor).
--spec get_spendable_points () -> non_neg_integer().
-get_spendable_points () -> ?SPENDABLE_ARMOR_POINTS.
+-spec get_remaining_points (type()) -> non_neg_integer().
+get_remaining_points (Armor) -> Armor#proto_armor.remaining_points.
diff --git a/src/balancer/struct/blc_glyph.erl b/src/balancer/struct/blc_glyph.erl
index 9b43f88..894dd9f 100644
--- a/src/balancer/struct/blc_glyph.erl
+++ b/src/balancer/struct/blc_glyph.erl
@@ -16,8 +16,8 @@
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_coef :: list(blc_damage_type:coefficient()),
+ attack_coef :: list(blc_damage_type:coefficient()),
defense_score :: non_neg_integer(),
defense_sign :: integer(),
attack_score :: non_neg_integer(),
@@ -156,7 +156,8 @@ increase_attribute_by (?ATTRIBUTE_DEFENSE_SCORE, S0Amount, Glyph) ->
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),
+ CurrentValue =
+ shr_omnimods:get_attribute_modifier(Attribute, CurrentOmnimods),
S1Amount =
case ((CurrentValue + S0Amount) > AttMax) of
@@ -177,7 +178,7 @@ increase_attribute_by (Attribute, S0Amount, Glyph) ->
Glyph#proto_glyph
{
omnimods =
- shr_omnimods:mod_attribute
+ shr_omnimods:mod_attribute_modifier
(
Attribute,
S1Amount,
@@ -274,9 +275,10 @@ decrease_attribute_by (?ATTRIBUTE_DEFENSE_SCORE, Amount, Glyph) ->
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),
+ CurrentValue =
+ shr_omnimods:get_attribute_modifier(Attribute, CurrentOmnimods),
- Cost = ((Amount * AttCost) * ?NEGATIVE_POINTS_MULTIPLIER),
+ Cost = trunc((Amount * AttCost) * ?NEGATIVE_POINTS_MULTIPLIER),
if
(CurrentValue > 0) -> {error, incompatible};
@@ -287,7 +289,7 @@ decrease_attribute_by (Attribute, Amount, Glyph) ->
Glyph#proto_glyph
{
omnimods =
- shr_omnimods:mod_attribute
+ shr_omnimods:mod_attribute_modifier
(
Attribute,
(-1 * Amount),
@@ -407,7 +409,7 @@ new (AttackCoefficients, DefenseCoefficients) ->
{
remaining_positive_points = ?SPENDABLE_GLYPH_POINTS,
points_balance = 0,
- omnimods = omnimods:new(),
+ omnimods = shr_omnimods:new(),
attack_coef = blc_damage_type:sort_entries(AttackCoefficients),
attack_score = 0,
attack_sign = 0,
diff --git a/src/balancer/struct/blc_weapon.erl b/src/balancer/struct/blc_weapon.erl
index 0edeb35..970c4e5 100644
--- a/src/balancer/struct/blc_weapon.erl
+++ b/src/balancer/struct/blc_weapon.erl
@@ -7,15 +7,9 @@
-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,
+ BASE_SPENDABLE_WEAPON_POINTS,
(
(
?ATTRIBUTE_ACCURACY_COST
@@ -52,42 +46,57 @@
)
).
+-define
+(
+ MELEE_SPENDABLE_WEAPON_POINTS,
+ (
+ ?BASE_SPENDABLE_WEAPON_POINTS
+ +
+ (
+ ?ATTRIBUTE_PARRY_CHANCE_COST
+ * (?ATTRIBUTE_PARRY_CHANCE_DEFAULT - ?ATTRIBUTE_PARRY_CHANCE_MIN)
+ )
+ )
+).
+
+-define(RANGED_SPENDABLE_WEAPON_POINTS, ?BASE_SPENDABLE_WEAPON_POINTS).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-type range_type() :: (melee | ranged).
+
-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()),
+ range_type :: range_type(),
+ omnimods :: shr_omnimods:type(),
attack_coef :: list(blc_damage_type:coefficient()),
- attack_score :: non_neg_integer()
+ attack_score :: non_neg_integer(),
+ remaining_points :: non_neg_integer()
}
).
--opaque proto_weapon() :: #proto_weapon{}.
+-opaque type() :: #proto_weapon{}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--export_type([proto_weapon/0]).
+-export_type([type/0,range_type/0]).
-export
(
[
increase_range_by/2,
- increase_type_by/2,
+ increase_parry_chance_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_parry_chance_for/2,
increase_accuracy_for/2,
increase_critical_hit_chance_for/2,
increase_double_hit_chance_for/2,
@@ -99,14 +108,55 @@
-export
(
[
- new/1,
- get_spendable_points/0
+ new/2,
+ get_remaining_points/1
]
).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-spec increase_attribute_by
+ (
+ shr_attributes:enum(),
+ non_neg_integer(),
+ type()
+ )
+ -> ({ok, type()} | blc_error:type()).
+increase_attribute_by (Attribute, S0Amount, Weapon) ->
+ CurrentOmnimods = Weapon#proto_weapon.omnimods,
+ CurrentValue =
+ shr_omnimods:get_attribute_modifier(Attribute, CurrentOmnimods),
+
+ {_AttMin, _AttDef, AttMax, AttCost} = blc_attribute:get_info(Attribute),
+
+ S1Amount =
+ case ((CurrentValue + S0Amount) > AttMax) of
+ true -> (AttMax - CurrentValue);
+ false -> S0Amount
+ end,
+
+ Cost = (S1Amount * AttCost),
+ RemainingPoints = Weapon#proto_weapon.remaining_points,
+
+ case (Cost > RemainingPoints) of
+ true -> {error, balance, RemainingPoints, Cost};
+ false ->
+ {
+ ok,
+ Weapon#proto_weapon
+ {
+ remaining_points = (RemainingPoints - Cost),
+ omnimods =
+ shr_omnimods:mod_attribute_modifier
+ (
+ Attribute,
+ S1Amount,
+ Weapon#proto_weapon.omnimods
+ )
+ }
+ }
+ end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -114,301 +164,221 @@
-spec increase_accuracy_by
(
non_neg_integer(),
- proto_weapon()
+ type()
)
- -> {proto_weapon(), non_neg_integer()}.
+ -> ({ok, type()} | blc_error:type()).
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.
+ increase_attribute_by(?ATTRIBUTE_ACCURACY, Amount, Weapon).
-spec increase_range_by
(
non_neg_integer(),
- proto_weapon()
+ type()
)
- -> {proto_weapon(), non_neg_integer()}.
+ -> ({ok, type()} | blc_error:type()).
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
- )
- };
+ increase_attribute_by(?ATTRIBUTE_ACCURACY, Amount, Weapon).
- false ->
- {
- Weapon#proto_weapon{ range = NewDamageModifier },
- (Amount * ?WEAPON_ATTRIBUTE_RANGE_COST)
- }
- end.
-
--spec increase_type_by
+-spec increase_parry_chance_by
(
non_neg_integer(),
- proto_weapon()
+ type()
)
- -> {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)
- }
+ -> ({ok, type()} | blc_error:type()).
+increase_parry_chance_by (Amount, Weapon) ->
+ case (Weapon#proto_weapon.range_type) of
+ ranged -> {error, incompatible};
+ _ -> increase_attribute_by(?ATTRIBUTE_PARRY_CHANCE, Amount, Weapon)
end.
-spec increase_critical_hit_chance_by
(
non_neg_integer(),
- proto_weapon()
+ type()
)
- -> {proto_weapon(), non_neg_integer()}.
+ -> ({ok, type()} | blc_error:type()).
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.
+ increase_attribute_by(?ATTRIBUTE_CRITICAL_HIT_CHANCE, Amount, Weapon).
-spec increase_double_hit_chance_by
(
non_neg_integer(),
- proto_weapon()
+ type()
)
- -> {proto_weapon(), non_neg_integer()}.
+ -> ({ok, type()} | blc_error:type()).
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.
-
+ increase_attribute_by(?ATTRIBUTE_DOUBLE_HIT_CHANCE, Amount, Weapon).
-spec increase_attack_score_by
(
non_neg_integer(),
- proto_weapon()
+ type()
)
- -> {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
+ -> ({ok, type()} | blc_error:type()).
+increase_attack_score_by (S0Amount, Weapon) ->
+ CurrentValue = Weapon#proto_weapon.attack_score,
+ S0NewValue = CurrentValue + S0Amount,
+ {S1Amount, S1NewValue} =
+ case (S0NewValue > ?ATTRIBUTE_ATTACK_SCORE_MAX) of
+ false -> {S0Amount, S0NewValue};
+ true ->
{
- 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
- )
- };
+ (?ATTRIBUTE_ATTACK_SCORE_MAX - CurrentValue),
+ ?ATTRIBUTE_ATTACK_SCORE_MAX
+ }
+ end,
+ Cost = (S1Amount * ?ATTRIBUTE_ATTACK_SCORE_COST),
+ RemainingPoints = Weapon#proto_weapon.remaining_points,
+
+ case (Cost > RemainingPoints) of
+ true -> {error, balance, RemainingPoints, Cost};
false ->
{
+ ok,
Weapon#proto_weapon
{
- attack_score = NewAttackScore,
- attack =
- blc_damage_type:generate_entries_from_score
+ remaining_points = (RemainingPoints - Cost),
+ attack_score = S1NewValue,
+ omnimods =
+ shr_omnimods:set_attack_modifiers
(
- NewAttackScore,
- Weapon#proto_weapon.attack_coef
+ blc_damage_type:generate_entries_from_score
+ (
+ S1NewValue,
+ Weapon#proto_weapon.attack_coef
+ ),
+ Weapon#proto_weapon.omnimods
)
- },
- (Amount * ?ATTRIBUTE_ATTACK_SCORE_COST)
+ }
}
end.
-spec set_attack_coefficients
(
list(blc_damage_type:coefficient()),
- proto_weapon()
+ type()
)
- -> proto_weapon().
+ -> type().
set_attack_coefficients (Coefficients, Weapon) ->
- {Result, 0} =
- increase_attack_score_by
- (
- 0,
- Weapon#proto_weapon
- {
- attack_coef = blc_damage_type:sort_entries(Coefficients)
- }
- ),
+ NewCoefs = blc_damage_type:sort_entries(Coefficients),
- Result.
+ Weapon#proto_weapon
+ {
+ attack_coef = NewCoefs,
+ omnimods =
+ shr_omnimods:set_attack_modifiers
+ (
+ blc_damage_type:generate_entries_from_score
+ (
+ Weapon#proto_weapon.attack_score,
+ NewCoefs
+ ),
+ Weapon#proto_weapon.omnimods
+ )
+ }.
--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
- }
- ),
+-spec new (range_type(), list(blc_damage_type:coefficient())) -> type().
+new (RangeType, Coefficients) ->
+ SortedCoefficients = blc_damage_type:sort_entries(Coefficients),
- Result.
+ #proto_weapon
+ {
+ range = ?WEAPON_ATTRIBUTE_RANGE_MIN,
+ range_type = RangeType,
+ omnimods =
+ shr_omnimods:new
+ (
+ [
+ {?ATTRIBUTE_ACCURACY, ?ATTRIBUTE_ACCURACY_MIN},
+ {?ATTRIBUTE_PARRY_CHANCE, ?ATTRIBUTE_PARRY_CHANCE_MIN},
+ {
+ ?ATTRIBUTE_CRITICAL_HIT_CHANCE,
+ ?ATTRIBUTE_CRITICAL_HIT_CHANCE_MIN
+ },
+ {
+ ?ATTRIBUTE_DOUBLE_HIT_CHANCE,
+ ?ATTRIBUTE_DOUBLE_HIT_CHANCE_MIN
+ }
+ ],
+ blc_damage_type:generate_entries_from_score
+ (
+ ?ATTRIBUTE_ATTACK_SCORE_MIN,
+ SortedCoefficients
+ ),
+ []
+ ),
+
+ attack_coef = SortedCoefficients,
+ attack_score = ?ATTRIBUTE_ATTACK_SCORE_MIN,
+ remaining_points =
+ case RangeType of
+ melee -> ?MELEE_SPENDABLE_WEAPON_POINTS;
+ ranged -> ?RANGED_SPENDABLE_WEAPON_POINTS
+ end
+ }.
-spec increase_range_for
(
non_neg_integer(),
- proto_weapon()
+ type()
)
- -> {proto_weapon(), non_neg_integer()}.
+ -> ({ok, type()} | blc_error:type()).
increase_range_for (GivenPoints, Weapon) ->
AmountOfIncrease = trunc(GivenPoints / ?WEAPON_ATTRIBUTE_RANGE_COST),
- {Result, SpentPoints} = increase_range_by(AmountOfIncrease, Weapon),
- {Result, (GivenPoints - SpentPoints)}.
+ increase_range_by(AmountOfIncrease, Weapon).
--spec increase_type_for
+-spec increase_parry_chance_for
(
non_neg_integer(),
- proto_weapon()
+ type()
)
- -> {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)}.
+ -> ({ok, type()} | blc_error:type()).
+increase_parry_chance_for (GivenPoints, Weapon) ->
+ AmountOfIncrease = trunc(GivenPoints / ?ATTRIBUTE_PARRY_CHANCE_COST),
+ increase_parry_chance_by(AmountOfIncrease, Weapon).
-spec increase_accuracy_for
(
non_neg_integer(),
- proto_weapon()
+ type()
)
- -> {proto_weapon(), non_neg_integer()}.
+ -> ({ok, type()} | blc_error:type()).
increase_accuracy_for (GivenPoints, Weapon) ->
AmountOfIncrease = trunc(GivenPoints / ?ATTRIBUTE_ACCURACY_COST),
- {Result, SpentPoints} = increase_accuracy_by(AmountOfIncrease, Weapon),
- {Result, (GivenPoints - SpentPoints)}.
+ increase_accuracy_by(AmountOfIncrease, Weapon).
-spec increase_critical_hit_chance_for
(
non_neg_integer(),
- proto_weapon()
+ type()
)
- -> {proto_weapon(), non_neg_integer()}.
+ -> ({ok, type()} | blc_error:type()).
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)}.
+ increase_critical_hit_chance_by(AmountOfIncrease, Weapon).
-spec increase_double_hit_chance_for
(
non_neg_integer(),
- proto_weapon()
+ type()
)
- -> {proto_weapon(), non_neg_integer()}.
+ -> ({ok, type()} | blc_error:type()).
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)}.
+ increase_double_hit_chance_by(AmountOfIncrease, Weapon).
-spec increase_attack_score_for
(
non_neg_integer(),
- proto_weapon()
+ type()
)
- -> {proto_weapon(), non_neg_integer()}.
+ -> ({ok, type()} | blc_error:type()).
increase_attack_score_for (GivenPoints, Weapon) ->
AmountOfIncrease = trunc(GivenPoints / ?ATTRIBUTE_ATTACK_SCORE_COST),
- {Result, SpentPoints} = increase_attack_score_by(AmountOfIncrease, Weapon),
- {Result, (GivenPoints - SpentPoints)}.
+ increase_attack_score_by(AmountOfIncrease, Weapon).
--spec get_spendable_points () -> non_neg_integer().
-get_spendable_points () -> ?SPENDABLE_WEAPON_POINTS.
+-spec get_remaining_points (type()) -> non_neg_integer().
+get_remaining_points (Weapon) -> Weapon#proto_weapon.remaining_points.
diff --git a/src/battle/mechanic/action/btl_action_attack.erl b/src/battle/mechanic/action/btl_action_attack.erl
index 04becc8..62c58f8 100644
--- a/src/battle/mechanic/action/btl_action_attack.erl
+++ b/src/battle/mechanic/action/btl_action_attack.erl
@@ -24,7 +24,7 @@
)
-> {float(), integer(), integer()}.
roll_precision_modifier (Attributes, TargetAttributes, TargetLuck) ->
- TargetDodges = shr_attributes:get_dodges(TargetAttributes),
+ TargetDodges = shr_attributes:get_dodge_chance(TargetAttributes),
Accuracy = shr_attributes:get_accuracy(Attributes),
MissChance = max(0, (TargetDodges - Accuracy)),
@@ -48,7 +48,7 @@ roll_precision_modifier (Attributes, TargetAttributes, TargetLuck) ->
)
-> {float(), integer(), integer()}.
roll_critical_modifier (Attributes, Luck) ->
- CriticalHitChance = shr_attributes:get_critical_hits(Attributes),
+ CriticalHitChance = shr_attributes:get_critical_hit_chance(Attributes),
{_Roll, IsSuccess, PositiveModifier, NegativeModifier} =
shr_roll:percentage_with_luck(CriticalHitChance, Luck),
@@ -68,7 +68,7 @@ roll_critical_modifier (Attributes, Luck) ->
)
-> {boolean(), integer(), integer()}.
roll_parry (DefenderAttributes, DefenderLuck) ->
- DefenderParryChance = shr_attributes:get_parries(DefenderAttributes),
+ DefenderParryChance = shr_attributes:get_parry_chance(DefenderAttributes),
{_Roll, IsSuccess, PositiveModifier, NegativeModifier} =
shr_roll:percentage_with_luck(DefenderParryChance, DefenderLuck),
@@ -518,7 +518,7 @@ handle_attack_sequence
(
btl_character:get_base_character(S0Character)
),
- DoubleAttackChance = shr_attributes:get_double_hits(Attributes),
+ DoubleAttackChance = shr_attributes:get_double_hit_chance(Attributes),
{_Roll, IsSuccessful, PositiveModifier, NegativeModifier} =
shr_roll:percentage_with_luck(DoubleAttackChance, S0PlayerLuck),
diff --git a/src/shared/struct/shr_omnimods.erl b/src/shared/struct/shr_omnimods.erl
index e4993c8..ae8ba44 100644
--- a/src/shared/struct/shr_omnimods.erl
+++ b/src/shared/struct/shr_omnimods.erl
@@ -54,7 +54,10 @@
apply_coefficient/2,
set_attribute_modifiers/2,
set_attack_modifiers/2,
- set_defense_modifiers/2
+ set_defense_modifiers/2,
+ mod_attribute_modifier/3,
+ mod_attack_modifier/3,
+ mod_defense_modifier/3
]
).
@@ -173,6 +176,66 @@ set_attack_modifiers (NewAttackModifiers, Omnimods) ->
atkmods = dict:from_list(NewAttackModifiers)
}.
+-spec mod_attribute_modifier
+ (
+ shr_attributes:enum(),
+ integer(),
+ type()
+ )
+ -> type().
+mod_attribute_modifier (Attribute, Mod, Omnimods) ->
+ Omnimods#omnimods
+ {
+ attmods =
+ dict:update
+ (
+ Attribute,
+ fun (Current) -> (Current + Mod) end,
+ Mod,
+ Omnimods#omnimods.attmods
+ )
+ }.
+
+-spec mod_attack_modifier
+ (
+ shr_damage_type:type(),
+ integer(),
+ type()
+ )
+ -> type().
+mod_attack_modifier (DamageType, Mod, Omnimods) ->
+ Omnimods#omnimods
+ {
+ atkmods =
+ dict:update
+ (
+ DamageType,
+ fun (Current) -> (Current + Mod) end,
+ Mod,
+ Omnimods#omnimods.atkmods
+ )
+ }.
+
+-spec mod_defense_modifier
+ (
+ shr_damage_type:type(),
+ integer(),
+ type()
+ )
+ -> type().
+mod_defense_modifier (DamageType, Mod, Omnimods) ->
+ Omnimods#omnimods
+ {
+ defmods =
+ dict:update
+ (
+ DamageType,
+ fun (Current) -> (Current + Mod) end,
+ Mod,
+ Omnimods#omnimods.defmods
+ )
+ }.
+
%%%% Access
-spec apply_to_attributes
(
@@ -269,13 +332,13 @@ get_defense_modifier (DamageType, Omnimods) ->
end.
-spec get_attribute_modifiers (type()) -> list(attribute_entry()).
-get_attribute_modifiers (Omnimods) -> lists:to_list(Omnimods#omnimods.attmods).
+get_attribute_modifiers (Omnimods) -> dict:to_list(Omnimods#omnimods.attmods).
-spec get_attack_modifiers (type()) -> list(damage_type_entry()).
-get_attack_modifiers (Omnimods) -> lists:to_list(Omnimods#omnimods.atkmods).
+get_attack_modifiers (Omnimods) -> dict:to_list(Omnimods#omnimods.atkmods).
-spec get_defense_modifiers (type()) -> list(damage_type_entry()).
-get_defense_modifiers (Omnimods) -> lists:to_list(Omnimods#omnimods.defmods).
+get_defense_modifiers (Omnimods) -> dict:to_list(Omnimods#omnimods.defmods).
%%% Export