summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/struct/statistics.erl')
-rw-r--r--src/struct/statistics.erl157
1 files changed, 157 insertions, 0 deletions
diff --git a/src/struct/statistics.erl b/src/struct/statistics.erl
new file mode 100644
index 0000000..0668fea
--- /dev/null
+++ b/src/struct/statistics.erl
@@ -0,0 +1,157 @@
+-module(statistics).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-record
+(
+ statistics,
+ {
+ movement_points,
+ health,
+ dodges,
+ parries,
+ damage_min,
+ damage_max,
+ accuracy,
+ double_hits,
+ critical_hits
+ }
+).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% 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
+ ]
+).
+
+-export
+(
+ [
+ calc_for/2
+ ]
+).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ceil (F) ->
+ I = trunc(F),
+ case (F > I) of
+ true -> (I + 1);
+ _ -> I
+ end.
+
+float_to_int (F) -> trunc(ceil(F)).
+min_max (Min, Max, V) -> min(Max, max(Min, V)).
+
+average ([]) -> 0;
+average (L) -> lists:sum(L) / length(L).
+
+% V | 010 | 030 | 050 | 070 | 100 |
+% F | 004 | 023 | 058 | 104 | 200 |
+gentle_squared_growth (V) -> float_to_int(math:pow(V, 1.8) / 20).
+
+% V | 010 | 030 | 050 | 070 | 100 |
+% F | 001 | 005 | 018 | 041 | 100 |
+sudden_squared_growth (V) -> float_to_int(math:pow(V, 2.5) / 1000).
+
+% V | 010 | 030 | 050 | 070 | 100 |
+% F | 002 | 006 | 016 | 049 | 256 |
+sudden_exp_growth (V) -> float_to_int(math:pow(4, V / 25)).
+
+% 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.
+already_high_slow_growth (V) -> float_to_int(30 * math:log((V + 5)/4)).
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%% Accessors
+get_movement_points (Stats) -> Stats#statistics.movement_points.
+get_health (Stats) -> Stats#statistics.health.
+get_dodges (Stats) -> Stats#statistics.dodges.
+get_parries (Stats) -> Stats#statistics.parries.
+get_damage_min (Stats) -> Stats#statistics.damage_min.
+get_damage_max (Stats) -> Stats#statistics.damage_max.
+get_accuracy (Stats) -> Stats#statistics.accuracy.
+get_double_hits (Stats) -> Stats#statistics.double_hits.
+get_critical_hits (Stats) -> Stats#statistics.critical_hits.
+
+calc_for (Att, _Wp) ->
+ #statistics
+ {
+ movement_points = gentle_squared_growth(attributes:get_speed(Att)),
+ health = gentle_squared_growth(attributes:get_constitution(Att)),
+ dodges =
+ min_max
+ (
+ 0,
+ 100,
+ sudden_exp_growth
+ (
+ average
+ (
+ [
+ attributes:get_dexterity(Att),
+ attributes:get_mind(Att),
+ attributes:get_speed(Att)
+ ]
+ )
+ )
+ ),
+ parries =
+ min_max
+ (
+ 0,
+ 75,
+ sudden_exp_growth
+ (
+ average
+ (
+ [
+ attributes:get_dexterity(Att),
+ attributes:get_speed(Att),
+ attributes:get_strength(Att)
+ ]
+ )
+ )
+ ),
+ damage_min = 0,
+ damage_max = 100,
+ accuracy =
+ % Hitting should involve this stat (not with this formula though), but
+ % also the target's dodge stat, with three possible results:
+ % - Missed
+ % - Grazed (Halved damage)
+ % - Hit
+ % Stat = (target.dodge - char.accuracy)
+ % Roll = RAND(0, 100)
+ % if (Roll >= (Stat * 2)): Hit
+ % else if (Roll >= Stat): Grazed
+ % else: Missed.
+ min_max
+ (
+ 0,
+ 100,
+ sudden_squared_growth(attributes:get_dexterity(Att))
+ ),
+ double_hits =
+ min_max(0, 100, sudden_squared_growth(attributes:get_speed(Att))),
+ critical_hits =
+ min_max(0, 100, sudden_squared_growth(attributes:get_intelligence(Att)))
+ }.