From acb9dd3220a3edcac93aa11d1d74d008e2fb23ed Mon Sep 17 00:00:00 2001 From: nsensfel Date: Wed, 11 Jul 2018 18:02:26 +0200 Subject: "sh_" -> "shr_". --- src/shared/struct/shr_statistics.erl | 200 +++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 src/shared/struct/shr_statistics.erl (limited to 'src/shared/struct/shr_statistics.erl') diff --git a/src/shared/struct/shr_statistics.erl b/src/shared/struct/shr_statistics.erl new file mode 100644 index 0000000..cf48d96 --- /dev/null +++ b/src/shared/struct/shr_statistics.erl @@ -0,0 +1,200 @@ +-module(shr_statistics). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-record +( + statistics, + { + movement_points :: non_neg_integer(), + health :: non_neg_integer(), + dodges :: non_neg_integer(), + parries :: non_neg_integer(), + damage_min :: non_neg_integer(), + damage_max :: non_neg_integer(), + accuracy :: non_neg_integer(), + double_hits :: non_neg_integer(), + critical_hits :: non_neg_integer() + } +). + +-opaque type() :: #statistics{}. + +-export_type([type/0]). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%% Accessors +-export +( + [ + get_movement_points/1, + get_health/1, + get_dodges/1, + get_parries/1, + get_damage_min/1, + get_damage_max/1, + get_accuracy/1, + get_double_hits/1, + get_critical_hits/1, + + get_damages/1 + ] +). + +-export +( + [ + new/3 + ] +). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec float_to_int (float()) -> integer(). +float_to_int (F) -> + I = trunc(F), + case (F > I) of + true -> (I + 1); + _ -> I + end. + +-spec min_max (number(), number(), number()) -> number(). +min_max (Min, Max, V) -> min(Max, max(Min, V)). + +-spec average (list(number())) -> number(). +%average ([]) -> 0; +average (L) -> lists:sum(L) / length(L). + +% V | 010 | 030 | 050 | 070 | 100 | +% F | 004 | 023 | 058 | 104 | 200 | +-spec gentle_squared_growth (number()) -> non_neg_integer(). +gentle_squared_growth (V) -> float_to_int(math:pow(V, 1.8) / 20.0). + +% V | 010 | 030 | 050 | 070 | 100 | +% F | 001 | 005 | 018 | 041 | 100 | +-spec sudden_squared_growth (number()) -> non_neg_integer(). +sudden_squared_growth (V) -> float_to_int(math:pow(V, 2.5) / 1000.0). + +% V | 010 | 030 | 050 | 070 | 100 | +% F | 002 | 006 | 016 | 049 | 256 | +-spec sudden_exp_growth (number()) -> non_neg_integer(). +sudden_exp_growth (V) -> float_to_int(math:pow(4.0, V / 25.0)). + +% V | 010 | 030 | 050 | 070 | 100 | +% F | 040 | 066 | 079 | 088 | 099 | +% Seems too generous, values for attributes below 50 should dip faster and +% lower. +%-spec already_high_slow_growth (non_neg_integer()) -> non_neg_integer(). +%already_high_slow_growth (V) -> float_to_int(30 * math:log((V + 5)/4)). + +-spec damage_base_modifier (non_neg_integer()) -> float(). +damage_base_modifier (Strength) -> ((math:pow(Strength, 1.8) / 2000.0) - 0.75). + +-spec apply_damage_base_modifier + ( + float(), + non_neg_integer() + ) + -> non_neg_integer(). +apply_damage_base_modifier (Modifier, BaseValue) -> + max(0, float_to_int(BaseValue + (BaseValue * Modifier))). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%% Accessors +-spec get_movement_points (type()) -> non_neg_integer(). +get_movement_points (Stats) -> Stats#statistics.movement_points. + +-spec get_health (type()) -> non_neg_integer(). +get_health (Stats) -> Stats#statistics.health. + +-spec get_dodges (type()) -> non_neg_integer(). +get_dodges (Stats) -> Stats#statistics.dodges. + +-spec get_parries (type()) -> non_neg_integer(). +get_parries (Stats) -> Stats#statistics.parries. + +-spec get_damage_min (type()) -> non_neg_integer(). +get_damage_min (Stats) -> Stats#statistics.damage_min. + +-spec get_damage_max (type()) -> non_neg_integer(). +get_damage_max (Stats) -> Stats#statistics.damage_max. + +-spec get_accuracy (type()) -> non_neg_integer(). +get_accuracy (Stats) -> Stats#statistics.accuracy. + +-spec get_double_hits (type()) -> non_neg_integer(). +get_double_hits (Stats) -> Stats#statistics.double_hits. + +-spec get_critical_hits (type()) -> non_neg_integer(). +get_critical_hits (Stats) -> Stats#statistics.critical_hits. + +-spec get_damages (type()) -> {non_neg_integer(), non_neg_integer()}. +get_damages (Stats) -> + { + Stats#statistics.damage_min, + Stats#statistics.damage_max + }. + +-spec new + ( + shr_attributes:type(), + {shr_weapon:id(), shr_weapon:id()}, + shr_armor:id() + ) + -> type(). +new (BaseAttributes, WeaponIDs, ArmorID) -> + {ActiveWeaponID, _} = WeaponIDs, + ActiveWeapon = shr_weapon:from_id(ActiveWeaponID), + {MinDamage, MaxDamage} = shr_weapon:get_damages(ActiveWeapon), + Armor = shr_armor:from_id(ArmorID), + Attributes = + shr_armor:apply_to_attributes + ( + Armor, + shr_weapon:apply_to_attributes(ActiveWeapon, BaseAttributes) + ), + Constitution = shr_attributes:get_constitution(Attributes), + Dexterity = shr_attributes:get_dexterity(Attributes), + Intelligence = shr_attributes:get_intelligence(Attributes), + Mind = shr_attributes:get_mind(Attributes), + Speed = shr_attributes:get_speed(Attributes), + Strength = shr_attributes:get_strength(Attributes), + DamageBaseModifier = damage_base_modifier(Strength), + + #statistics + { + movement_points = + gentle_squared_growth + ( + average([Mind, Constitution, Constitution, Speed, Speed, Speed]) + ), + health = + gentle_squared_growth + ( + average([Constitution, Constitution, Constitution, Mind]) + ), + dodges = + min_max(0, 100, sudden_exp_growth(average([Dexterity, Mind, Speed]))), + parries = + min_max + ( + 0, + 75, + sudden_exp_growth + ( + average([Dexterity, Intelligence, Speed, Strength]) + ) + ), + damage_min = apply_damage_base_modifier(DamageBaseModifier, MinDamage), + damage_max = apply_damage_base_modifier(DamageBaseModifier, MaxDamage), + accuracy = min_max(0, 100, sudden_squared_growth(Dexterity)), + double_hits = + min_max(0, 100, sudden_squared_growth(average([Mind, Speed]))), + critical_hits = min_max(0, 100, sudden_squared_growth(Intelligence)) + }. -- cgit v1.2.3-70-g09d2