summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared/struct')
-rw-r--r--src/shared/struct/sh_db_item.erl12
-rw-r--r--src/shared/struct/sh_db_query.erl157
-rw-r--r--src/shared/struct/sh_db_user.erl5
-rw-r--r--src/shared/struct/sh_statistics.erl29
-rw-r--r--src/shared/struct/sh_weapon.erl360
5 files changed, 544 insertions, 19 deletions
diff --git a/src/shared/struct/sh_db_item.erl b/src/shared/struct/sh_db_item.erl
index e499634..98a1cb4 100644
--- a/src/shared/struct/sh_db_item.erl
+++ b/src/shared/struct/sh_db_item.erl
@@ -3,7 +3,17 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--include("../include/db_item.hrl").
+-record
+(
+ db_item,
+ {
+ id :: any(),
+ perm :: sh_db_user:permission(),
+ val :: any()
+ }
+).
+
+-type db_item() :: #db_item{}.
-type type() :: db_item().
diff --git a/src/shared/struct/sh_db_query.erl b/src/shared/struct/sh_db_query.erl
index 998568e..4eb50ba 100644
--- a/src/shared/struct/sh_db_query.erl
+++ b/src/shared/struct/sh_db_query.erl
@@ -3,7 +3,65 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--include("../include/db_query.hrl").
+-record
+(
+ set_field,
+ {
+ field :: non_neg_integer(),
+ value :: any()
+ }
+).
+
+-record
+(
+ add_to_field,
+ {
+ field :: non_neg_integer(),
+ values :: list(any()),
+ head :: boolean()
+ }
+).
+
+-record
+(
+ update_indexed,
+ {
+ field :: non_neg_integer(),
+ ix :: non_neg_integer(),
+ ops :: list(db_query_op())
+ }
+).
+
+-record
+(
+ set_perm,
+ {
+ perm :: sh_db_user:permission()
+ }
+).
+
+-record
+(
+ set_val,
+ {
+ val :: any()
+ }
+).
+
+-record
+(
+ db_query,
+ {
+ db :: atom(),
+ id :: any(),
+ user :: db_user:user(),
+ ops :: list(db_query_master_op())
+ }
+).
+
+-type db_query_op() :: (#set_field{} | #add_to_field{} | #update_indexed{}).
+-type db_query_master_op() :: (db_query_op() | #set_perm{} | #set_val{}).
+-type db_query() :: #db_query{}.
-opaque op() :: db_query_op().
-opaque type() :: db_query().
@@ -22,10 +80,84 @@
update_indexed/3
]
).
+-export
+(
+ [
+ get_database/1,
+ get_entry_id/1
+ ]
+).
+-export([apply_to/2]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-spec get_user (db_query()) -> sh_db_user:user().
+get_user (#db_query{ user = Result }) -> Result.
+
+-spec apply_update_indexed (#update_indexed{}, any()) -> any().
+apply_update_indexed (Op, Elem) ->
+ FieldNumber = Op#update_indexed.field,
+ IX = Op#update_indexed.ix,
+ Ops = Op#update_indexed.ops,
+
+ IndexedFieldValue = element(FieldNumber, Elem),
+ ArrayValue = array:get(IX, IndexedFieldValue),
+ UpdatedArrayValue = lists:foldl(fun apply_op_to/2, ArrayValue, Ops),
+ UpdatedIndexedFieldValue =
+ array:set(IX, UpdatedArrayValue, IndexedFieldValue),
+
+ setelement(FieldNumber, Elem, UpdatedIndexedFieldValue).
+
+-spec apply_add_to_field (#add_to_field{}, any()) -> any().
+apply_add_to_field (Op, Elem) ->
+ FieldNumber = Op#add_to_field.field,
+ NewValues = Op#add_to_field.values,
+ AddToHead = Op#add_to_field.head,
+
+ CurrentValues = element(FieldNumber, Elem),
+ UpdatedValues =
+ case AddToHead of
+ true -> (NewValues ++ CurrentValues);
+ _ -> (CurrentValues ++ NewValues)
+ end,
+
+ setelement(FieldNumber, Elem, UpdatedValues).
+
+-spec apply_set_field (#set_field{}, any()) -> any().
+apply_set_field (Op, Elem) ->
+ FieldNumber = Op#set_field.field,
+ NewValue = Op#set_field.value,
+
+ setelement(FieldNumber, Elem, NewValue).
+
+-spec apply_op_to (db_query_op(), any()) -> any().
+apply_op_to (Op, Elem) when is_record(Op, set_field) ->
+ apply_set_field(Op, Elem);
+apply_op_to (Op, Elem) when is_record(Op, add_to_field) ->
+ apply_add_to_field(Op, Elem);
+apply_op_to (Op, Elem) when is_record(Op, update_indexed) ->
+ apply_update_indexed(Op, Elem).
+
+-spec apply_master_op_to
+ (
+ db_query_master_op(),
+ sh_db_item:type()
+ )
+ -> sh_db_item:type().
+apply_master_op_to (MOp, Elem) when is_record(MOp, set_perm) ->
+ NewPerm = MOp#set_perm.perm,
+
+ sh_db_item:set_perm(NewPerm, Elem);
+apply_master_op_to (MOp, Elem) when is_record(MOp, set_val) ->
+ NewVal = MOp#set_val.val,
+
+ sh_db_item:set_value(NewVal, Elem);
+apply_master_op_to (MOp, Elem) ->
+ OldValue = sh_db_item:get_value(Elem),
+ NewValue = apply_op_to(MOp, OldValue),
+
+ sh_db_item:set_value(NewValue, Elem).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -57,3 +189,26 @@ add_to_field (Field, Values) ->
-> op().
update_indexed (Field, IX, Updates) ->
#update_indexed { field = Field, ix = IX, ops = Updates}.
+
+-spec get_database (db_query()) -> atom().
+get_database (#db_query{ db = Result }) -> Result.
+
+-spec get_entry_id (db_query()) -> any().
+get_entry_id (#db_query{ id = Result }) -> Result.
+
+-spec apply_to
+ (
+ db_query(),
+ sh_db_item:type()
+ )
+ -> ({'ok', sh_db_item:type()} | 'error').
+apply_to (DBQuery, DBItem) ->
+ true =
+ sh_db_user:can_access
+ (
+ sh_db_item:get_permission(DBItem),
+ get_user(DBQuery)
+ ),
+ MOps = DBQuery#db_query.ops,
+ {ok, lists:foldl(fun apply_master_op_to/2, DBItem, MOps)}.
+
diff --git a/src/shared/struct/sh_db_user.erl b/src/shared/struct/sh_db_user.erl
index 40a46d3..f2d4dfe 100644
--- a/src/shared/struct/sh_db_user.erl
+++ b/src/shared/struct/sh_db_user.erl
@@ -3,7 +3,10 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--include("../include/db_user.hrl").
+-type db_named_user() :: {'user', any()}.
+-type db_user() :: (db_named_user() | 'admin' | 'any').
+-type db_permission() :: (list(db_named_user()) | 'any').
+
-type user() :: db_user().
-type permission() :: db_permission().
diff --git a/src/shared/struct/sh_statistics.erl b/src/shared/struct/sh_statistics.erl
index 7cf2b06..92cd8d6 100644
--- a/src/shared/struct/sh_statistics.erl
+++ b/src/shared/struct/sh_statistics.erl
@@ -54,17 +54,14 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--spec ceil (float()) -> integer().
-ceil (F) ->
+-spec float_to_int (float()) -> integer().
+float_to_int (F) ->
I = trunc(F),
case (F > I) of
true -> (I + 1);
_ -> I
end.
--spec float_to_int (float()) -> integer().
-float_to_int (F) -> ceil(F).
-
-spec min_max (number(), number(), number()) -> number().
min_max (Min, Max, V) -> min(Max, max(Min, V)).
@@ -146,21 +143,21 @@ get_damages (Stats) ->
-spec new
(
- attributes:type(),
- {weapon:id(), weapon:id()}
+ sh_attributes:type(),
+ {sh_weapon:id(), sh_weapon:id()}
)
-> type().
new (BaseAttributes, WeaponIDs) ->
{ActiveWeaponID, _} = WeaponIDs,
- ActiveWeapon = weapon:from_id(ActiveWeaponID),
- {MinDamage, MaxDamage} = weapon:get_damages(ActiveWeapon),
- Attributes = weapon:apply_to_attributes(BaseAttributes, ActiveWeapon),
- Constitution = attributes:get_constitution(Attributes),
- Dexterity = attributes:get_dexterity(Attributes),
- Intelligence = attributes:get_intelligence(Attributes),
- Mind = attributes:get_mind(Attributes),
- Speed = attributes:get_speed(Attributes),
- Strength = attributes:get_strength(Attributes),
+ ActiveWeapon = sh_weapon:from_id(ActiveWeaponID),
+ {MinDamage, MaxDamage} = sh_weapon:get_damages(ActiveWeapon),
+ Attributes = sh_weapon:apply_to_attributes(BaseAttributes, ActiveWeapon),
+ Constitution = sh_attributes:get_constitution(Attributes),
+ Dexterity = sh_attributes:get_dexterity(Attributes),
+ Intelligence = sh_attributes:get_intelligence(Attributes),
+ Mind = sh_attributes:get_mind(Attributes),
+ Speed = sh_attributes:get_speed(Attributes),
+ Strength = sh_attributes:get_strength(Attributes),
DamageBaseModifier = damage_base_modifier(Strength),
#statistics
diff --git a/src/shared/struct/sh_weapon.erl b/src/shared/struct/sh_weapon.erl
new file mode 100644
index 0000000..30943b9
--- /dev/null
+++ b/src/shared/struct/sh_weapon.erl
@@ -0,0 +1,360 @@
+-module(sh_weapon).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-opaque id() :: non_neg_integer().
+
+-type range_type() :: 'ranged' | 'melee'.
+-type range_mod() :: 'long' | 'short'.
+-type damage_type() :: 'slash' | 'pierce' | 'blunt'.
+-type damage_mod() :: 'heavy' | 'light'.
+
+-record
+(
+ weapon,
+ {
+ id :: id(),
+ name :: binary(),
+ range_type :: range_type(),
+ range_mod :: range_mod(),
+ damage_type :: damage_type(),
+ damage_mod :: damage_mod()
+ }
+).
+
+-opaque type() :: #weapon{}.
+
+-export_type([type/0, id/0]).
+-export_type
+(
+ [
+ range_type/0,
+ range_mod/0,
+ damage_type/0,
+ damage_mod/0
+ ]
+).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%% Accessors
+-export
+(
+ [
+ get_id/1,
+ get_range_type/1,
+ get_ranges/1,
+ get_damages/1
+ ]
+).
+
+-export
+(
+ [
+ random_id/0,
+ from_id/1,
+ can_parry/1,
+ apply_to_attributes/2
+ ]
+).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-spec ranges_of_type
+ (
+ range_type(),
+ range_mod()
+ )
+ -> {non_neg_integer(), non_neg_integer()}.
+ranges_of_type (ranged, long) -> {2, 6};
+ranges_of_type (ranged, short) -> {1, 4};
+ranges_of_type (melee, long) -> {0, 2};
+ranges_of_type (melee, short) -> {0, 1}.
+
+-spec damages_of_type
+ (
+ range_type(),
+ damage_mod()
+ )
+ -> {non_neg_integer(), non_neg_integer()}.
+damages_of_type (ranged, heavy) -> {10, 25};
+damages_of_type (ranged, light) -> {5, 20};
+damages_of_type (melee, heavy) -> {20, 35};
+damages_of_type (melee, light) -> {15, 30}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%% Accessors
+-spec get_id (type()) -> id().
+get_id (Wp) -> Wp#weapon.id.
+
+-spec get_range_type (type()) -> range_type().
+get_range_type (Wp) -> Wp#weapon.range_type.
+
+-spec get_ranges (type()) -> {non_neg_integer(), non_neg_integer()}.
+get_ranges (Wp) ->
+ ranges_of_type(Wp#weapon.range_type, Wp#weapon.range_mod).
+
+-spec get_damages (type()) -> {non_neg_integer(), non_neg_integer()}.
+get_damages (Wp) ->
+ damages_of_type(Wp#weapon.range_type, Wp#weapon.damage_mod).
+
+-spec can_parry (type()) -> boolean().
+can_parry (Wp) -> (Wp#weapon.range_type == melee).
+
+-spec from_id (id()) -> type().
+from_id (0) ->
+ #weapon{
+ id = 0,
+ name = <<"None">>,
+ range_type = melee,
+ range_mod = short,
+ damage_type = blunt,
+ damage_mod = light
+ };
+from_id (1) ->
+ #weapon{
+ id = 1,
+ name = <<"Dagger">>,
+ range_type = melee,
+ range_mod = short,
+ damage_type = slash,
+ damage_mod = light
+ };
+from_id (2) ->
+ #weapon{
+ id = 2,
+ name = <<"Sword">>,
+ range_type = melee,
+ range_mod = short,
+ damage_type = slash,
+ damage_mod = heavy
+ };
+from_id (3) ->
+ #weapon{
+ id = 3,
+ name = <<"Claymore">>,
+ range_type = melee,
+ range_mod = long,
+ damage_type = slash,
+ damage_mod = light
+ };
+from_id (4) ->
+ #weapon{
+ id = 4,
+ name = <<"Bardiche">>,
+ range_type = melee,
+ range_mod = long,
+ damage_type = slash,
+ damage_mod = heavy
+ };
+from_id (5) ->
+ #weapon{
+ id = 5,
+ name = <<"Stiletto">>,
+ range_type = melee,
+ range_mod = short,
+ damage_type = pierce,
+ damage_mod = light
+ };
+from_id (6) ->
+ #weapon{
+ id = 6,
+ name = <<"Pickaxe">>,
+ range_type = melee,
+ range_mod = short,
+ damage_type = pierce,
+ damage_mod = heavy
+ };
+from_id (7) ->
+ #weapon{
+ id = 7,
+ name = <<"Rapier">>,
+ range_type = melee,
+ range_mod = long,
+ damage_type = pierce,
+ damage_mod = light
+ };
+from_id (8) ->
+ #weapon{
+ id = 8,
+ name = <<"Pike">>,
+ range_type = melee,
+ range_mod = long,
+ damage_type = pierce,
+ damage_mod = heavy
+ };
+from_id (9) ->
+ #weapon{
+ id = 9,
+ name = <<"Club">>,
+ range_type = melee,
+ range_mod = short,
+ damage_type = blunt,
+ damage_mod = light
+ };
+from_id (10) ->
+ #weapon{
+ id = 10,
+ name = <<"Mace">>,
+ range_type = melee,
+ range_mod = short,
+ damage_type = blunt,
+ damage_mod = heavy
+ };
+from_id (11) ->
+ #weapon{
+ id = 11,
+ name = <<"Staff">>,
+ range_type = melee,
+ range_mod = long,
+ damage_type = blunt,
+ damage_mod = light
+ };
+from_id (12) ->
+ #weapon{
+ id = 12,
+ name = <<"War Hammer">>,
+ range_type = melee,
+ range_mod = long,
+ damage_type = blunt,
+ damage_mod = heavy
+ };
+from_id (13) ->
+ #weapon{
+ id = 13,
+ name = <<"Short Bow (Broadhead)">>,
+ range_type = ranged,
+ range_mod = short,
+ damage_type = slash,
+ damage_mod = light
+ };
+from_id (14) ->
+ #weapon{
+ id = 14,
+ name = <<"Short Bow (Blunt)">>,
+ range_type = ranged,
+ range_mod = short,
+ damage_type = blunt,
+ damage_mod = light
+ };
+from_id (15) ->
+ #weapon{
+ id = 15,
+ name = <<"Short Bow (Bodkin Point)">>,
+ range_type = ranged,
+ range_mod = short,
+ damage_type = pierce,
+ damage_mod = light
+ };
+from_id (16) ->
+ #weapon{
+ id = 16,
+ name = <<"Long Bow (Broadhead)">>,
+ range_type = ranged,
+ range_mod = long,
+ damage_type = slash,
+ damage_mod = light
+ };
+from_id (17) ->
+ #weapon{
+ id = 17,
+ name = <<"Long Bow (Blunt)">>,
+ range_type = ranged,
+ range_mod = long,
+ damage_type = blunt,
+ damage_mod = light
+ };
+from_id (18) ->
+ #weapon{
+ id = 18,
+ name = <<"Long Bow (Bodkin Point)">>,
+ range_type = ranged,
+ range_mod = long,
+ damage_type = pierce,
+ damage_mod = light
+ };
+from_id (19) ->
+ #weapon{
+ id = 19,
+ name = <<"Crossbow (Broadhead)">>,
+ range_type = ranged,
+ range_mod = short,
+ damage_type = slash,
+ damage_mod = heavy
+ };
+from_id (20) ->
+ #weapon{
+ id = 20,
+ name = <<"Crossbow (Blunt)">>,
+ range_type = ranged,
+ range_mod = short,
+ damage_type = blunt,
+ damage_mod = heavy
+ };
+from_id (21) ->
+ #weapon{
+ id = 21,
+ name = <<"Crossbow (Bodkin Point)">>,
+ range_type = ranged,
+ range_mod = short,
+ damage_type = pierce,
+ damage_mod = heavy
+ };
+from_id (22) ->
+ #weapon{
+ id = 22,
+ name = <<"Arbalest (Broadhead)">>,
+ range_type = ranged,
+ range_mod = long,
+ damage_type = slash,
+ damage_mod = heavy
+ };
+from_id (23) ->
+ #weapon{
+ id = 23,
+ name = <<"Arbalest (Blunt)">>,
+ range_type = ranged,
+ range_mod = long,
+ damage_type = blunt,
+ damage_mod = heavy
+ };
+from_id (24) ->
+ #weapon{
+ id = 24,
+ name = <<"Arbalest (Bodkin Point)">>,
+ range_type = ranged,
+ range_mod = long,
+ damage_type = pierce,
+ damage_mod = heavy
+ }.
+
+-spec random_id () -> id().
+random_id () -> sh_roll:between(0, 24).
+
+-spec apply_to_attributes
+ (
+ sh_attributes:type(),
+ type()
+ )
+ -> sh_attributes:type().
+apply_to_attributes (Attributes, Weapon) ->
+ Dexterity = sh_attributes:get_dexterity(Attributes),
+ Speed = sh_attributes:get_speed(Attributes),
+ RangeModifier = Weapon#weapon.range_mod,
+ DamageModifier = Weapon#weapon.damage_mod,
+ WithRangeModifier =
+ case RangeModifier of
+ long ->
+ sh_attributes:set_dexterity(max(0, (Dexterity - 20)), Attributes);
+ _ -> Attributes
+ end,
+ case DamageModifier of
+ heavy -> sh_attributes:set_speed(max(0, (Speed - 20)), WithRangeModifier);
+ _ -> WithRangeModifier
+ end.
+